Compare commits
536 Commits
Author | SHA1 | Date | |
---|---|---|---|
a3f3082bf0 | |||
0570c240e4 | |||
398118f708 | |||
dcc3f6d74d | |||
0af95332e9 | |||
f9a76a7d06 | |||
832a54ee42 | |||
e8f4294e7f | |||
ce448f4341 | |||
847eaa0fa3 | |||
3e80f0e526 | |||
f3dd6c224c | |||
863acb6c21 | |||
989e8a1f99 | |||
84d1ba792b | |||
b32126c335 | |||
d5e09f4d62 | |||
c25c57c3a3 | |||
692e34d4a2 | |||
071348eb72 | |||
8803f9f4dc | |||
aa816d3887 | |||
a5ba40a78b | |||
cb83b8a887 | |||
8bb726e899 | |||
88662a540d | |||
9b32a5917c | |||
ffd1691ba9 | |||
afd4417a7b | |||
2f53bbba20 | |||
a4f99f4de9 | |||
0711128d28 | |||
25f79ba73e | |||
2590a9b535 | |||
f68a1d3708 | |||
89f7f63e18 | |||
ca2b4bcd4b | |||
f6cfc9294b | |||
5b87c67aed | |||
f5b9d87913 | |||
3acebdcf5d | |||
02aca135bd | |||
32109dc414 | |||
c9acb7b7e2 | |||
545444d86f | |||
7f111491a8 | |||
ee5123f5dc | |||
3dfaf56fdd | |||
432a688edf | |||
42a649d80f | |||
47fbfb37bf | |||
4107abba2d | |||
1d26bc544e | |||
ef7b70a375 | |||
deb290bc2c | |||
5c8b7d2c64 | |||
f5d5bac076 | |||
ad16e2f97a | |||
d0191a7397 | |||
016a41b14d | |||
7a527b4f95 | |||
fd28f0c219 | |||
7342b1ecdf | |||
58f4b3ad80 | |||
3974312c3a | |||
db897f4f7a | |||
77093c21b7 | |||
415131413d | |||
df01a82fa2 | |||
1912fa34ba | |||
db5e1de07a | |||
84661eac64 | |||
629203f17a | |||
2ab8e88924 | |||
a91dd2e42a | |||
6eca80b4aa | |||
cea46786a2 | |||
9c5fc1693a | |||
42f5770b7b | |||
01db37435f | |||
07a003352d | |||
ac009d293d | |||
eb8f8c93c8 | |||
18a5117d1e | |||
ff72da60d3 | |||
d4a723a464 | |||
9c2f0b8ac4 | |||
dc081fb0bf | |||
f882099f9d | |||
24498eb416 | |||
4c2cdc682b | |||
1cb66bb39f | |||
7ff5ef27c7 | |||
03d8e317c4 | |||
1de4fe5dbf | |||
879ff08f0e | |||
a15d7ac1da | |||
4a6abbdfc6 | |||
78eb5f6777 | |||
0cdb5231c2 | |||
5af845d049 | |||
a5c28497b5 | |||
801ad62ae3 | |||
7d4d2e29b0 | |||
c33f719ddc | |||
69fc6b4f75 | |||
5ec4c02a43 | |||
f0489ee72a | |||
d0f625305b | |||
c15a58fa2b | |||
3d67d1970b | |||
ce08a3c8c7 | |||
bc29712271 | |||
cc48b5c066 | |||
deba0e21f1 | |||
0469d9240a | |||
cdda60a430 | |||
7570356bfa | |||
c4a97d822e | |||
fc4dfc5eb1 | |||
25d95dae6d | |||
1c4fcce2a1 | |||
6e73faaed7 | |||
41c9910613 | |||
aaddef213d | |||
02f3aee1db | |||
c27ba96093 | |||
c5a474cb54 | |||
d5264f5645 | |||
0cd4b87021 | |||
b1e7775a8a | |||
87f5feff11 | |||
c3ddc3d6b1 | |||
cec39a7d16 | |||
c6c8e15813 | |||
752fd14fe5 | |||
776067cd43 | |||
e87a46be21 | |||
89a7ff3ada | |||
3d6e50dc02 | |||
264950bbf2 | |||
84c5be0b5b | |||
eda8f2f8b9 | |||
cc52945d00 | |||
07f184a69d | |||
a123ef58b1 | |||
024126dde4 | |||
4275c34818 | |||
c4e6f585c5 | |||
7467fd36b9 | |||
aca01985fd | |||
eb5e14e6e0 | |||
b8af10902f | |||
f411c9e5b9 | |||
7f455e6eec | |||
e36caafa52 | |||
5e89d98876 | |||
200dbd4860 | |||
c90952884a | |||
7c2d8fc672 | |||
a50a688aaf | |||
6ec7297e43 | |||
f264cd1cb8 | |||
fc17bddcde | |||
0765626761 | |||
f146b34042 | |||
f899d6ea44 | |||
c18d7a1469 | |||
2c7ff82f31 | |||
3f8f3a2daa | |||
f5eeb1a714 | |||
2af3d9c040 | |||
4664acce50 | |||
3797861dfe | |||
d6d3984524 | |||
c17f5c10cc | |||
9cb318f5a2 | |||
b026dd8b52 | |||
0ebc316311 | |||
dc412c5f02 | |||
e80278cf02 | |||
307699ac89 | |||
4df0b7e9de | |||
371831f9cb | |||
8e305e7099 | |||
481df830ad | |||
14b4718cc2 | |||
7b6e73cb98 | |||
f2ca4634e2 | |||
d30cf2f9d6 | |||
e9cb6fbe87 | |||
99960a98d2 | |||
9ac3383d01 | |||
06ac75724f | |||
a1d691ecc8 | |||
6e329721be | |||
739bf5c325 | |||
ee340b7c6c | |||
17ddab98fb | |||
4f65f473e4 | |||
527a04d21e | |||
f2ee468d76 | |||
0320096538 | |||
7abb48adfe | |||
b40d3c0817 | |||
0e5617152a | |||
dba402344f | |||
13d176302b | |||
e3b801053a | |||
6626739798 | |||
396033da80 | |||
02ee9d2938 | |||
a4c7f183d7 | |||
d690eec88f | |||
10e4dfae27 | |||
f8d948b46b | |||
9cf78d5701 | |||
45471dbbd6 | |||
387e8386d1 | |||
eec6e4be7a | |||
b711f25892 | |||
788f0453f7 | |||
45b1775a53 | |||
53e4ff72d2 | |||
7813a7d129 | |||
c0ced6dc2d | |||
8157ee87b0 | |||
ab051aba27 | |||
5a61ef0c49 | |||
c451dbda9f | |||
0d38288078 | |||
2e9b953e9d | |||
a94383f168 | |||
75c40ddd61 | |||
86a75a0670 | |||
c776825fdd | |||
1cc9383d91 | |||
8ed1e53e99 | |||
7833c88ac4 | |||
12f177399f | |||
5be32366be | |||
5b7d2eeabf | |||
6cd10a1b10 | |||
822652aa0d | |||
cf47ace493 | |||
0595f11950 | |||
35df312ea4 | |||
489eb8519e | |||
b76a2dc2cb | |||
f2f5f7fc6e | |||
8ee23ba67b | |||
ecb422b360 | |||
60389d5441 | |||
b186db70db | |||
324b6f1b1a | |||
cdba1d37a4 | |||
dc42c97ee4 | |||
bc00e8d312 | |||
720b71d01f | |||
1132b07c53 | |||
9230194794 | |||
d724896f04 | |||
29866dfb91 | |||
a249622159 | |||
9f2393fb80 | |||
d5f8040d0a | |||
e0b8ea136b | |||
879b2273c1 | |||
f24972b1b1 | |||
d2886b3bb4 | |||
f296fea112 | |||
2605fc46e7 | |||
9d54b3a14b | |||
d09a6283ed | |||
1c168c3a44 | |||
0f74479c47 | |||
790bb949f6 | |||
2adcad6dd2 | |||
242ef1ace1 | |||
842b6a1247 | |||
98335529eb | |||
ca7ee794bf | |||
f9f2ba6faf | |||
aea1d211d4 | |||
57a518a36d | |||
29b83189b0 | |||
1d3df7885d | |||
fd06ffa2af | |||
36a1622dd1 | |||
7a91b23cb5 | |||
4b90b6a226 | |||
b13daa4cdf | |||
0c6f026828 | |||
a2520bd267 | |||
b928a209a4 | |||
89e16ed6a5 | |||
1a1f99af37 | |||
df2cd37ed2 | |||
12a71bc6bc | |||
7d270c235a | |||
b0b7248504 | |||
78460c1848 | |||
75b119eafc | |||
64b0ae93f7 | |||
7c0b25f5a6 | |||
07b5df3a19 | |||
e7023726f4 | |||
a9ccd9254c | |||
335f3271d2 | |||
7f93f7ef47 | |||
cf46a87fcd | |||
ad6680f602 | |||
5e287f67af | |||
ecfe6e0609 | |||
df9790dd11 | |||
67cfc4c9bc | |||
a68e623c80 | |||
9e3915ba48 | |||
ba2de61748 | |||
a9a4edebe2 | |||
64f2ffa166 | |||
13020b9cc2 | |||
96b96fba0f | |||
2cbe53a9ba | |||
48755114e5 | |||
a5d5f67be7 | |||
dfb58c44a2 | |||
69948ce919 | |||
3190ccf3b2 | |||
a8ea8173aa | |||
e13a49d1f0 | |||
2f0b8f675a | |||
c2aed033ba | |||
0f8a780b0d | |||
c5bc2e77c8 | |||
079310dc7c | |||
0d2cdf6165 | |||
436dde271f | |||
96891a076f | |||
9ce0067bdf | |||
345940bbc1 | |||
c49507b289 | |||
c730142508 | |||
27aa00b15f | |||
36a00a255b | |||
0e3249c89b | |||
920019ab70 | |||
82c8b44db7 | |||
bb3a307d5a | |||
dcb0ddaf5e | |||
4c1edd52c5 | |||
d512e27979 | |||
0619d82e0b | |||
a4038d5b94 | |||
e3d5e1fab7 | |||
035036308a | |||
0d29259d9b | |||
26b0f3dc96 | |||
5c9306b0fe | |||
3befb0e4b9 | |||
97bb88f10b | |||
6c7467a58b | |||
c579a85c12 | |||
400fdd08fd | |||
c1fe6c9c81 | |||
c58a0bea91 | |||
88a934b93c | |||
cde5cced69 | |||
472bedd3ea | |||
d8a06d03bd | |||
32020f9fb3 | |||
d574b14934 | |||
00c5d89e7d | |||
d2c8aefe64 | |||
ba796bbdd3 | |||
a0bb2ba7b7 | |||
f9fa3b5b6c | |||
f89d438116 | |||
1abe791d46 | |||
1502ae78b6 | |||
bad6e719de | |||
8c7129f3d2 | |||
dbff6f71e1 | |||
fcd934ccf6 | |||
45a8f340d9 | |||
5856513405 | |||
01fa3ee5c3 | |||
b8d69ffdf3 | |||
7ef60ec2a9 | |||
83f905c0e1 | |||
72ba3a3918 | |||
df10597da4 | |||
5db2e794a9 | |||
486aa06747 | |||
01ce1b32df | |||
c78b0b2c51 | |||
9ade1c3ea3 | |||
315a4cfcd4 | |||
11c04027ab | |||
eabe3b4c39 | |||
d471454675 | |||
bf57776b59 | |||
a32579ae5b | |||
780601d27a | |||
c909e731d7 | |||
9b8eb42354 | |||
0757174e8e | |||
3a43cdefe8 | |||
38c48beddd | |||
ad5749fb04 | |||
f6a838e9ee | |||
a6d1f4aaf1 | |||
eca8d11ee2 | |||
a195b7dbe4 | |||
083d7ec902 | |||
9d2d0cae6d | |||
c2f4a9bf71 | |||
231095fe8a | |||
28a532483a | |||
83853a215d | |||
8248307a99 | |||
67bd88b19a | |||
9f698b4de0 | |||
742f3d6787 | |||
323651bd38 | |||
9d397eb5a1 | |||
6114cd2bd4 | |||
d494f7bd5e | |||
ec6a7ab721 | |||
ad6d2b4619 | |||
c093390010 | |||
acd69f2be2 | |||
5d2f341653 | |||
420d1c35f5 | |||
08647267bb | |||
215d50d2f6 | |||
bf2cb6fa48 | |||
e97a2d4123 | |||
585e3f6adc | |||
7f77ce1a48 | |||
a1616ce181 | |||
1c22dff714 | |||
8d1d6e8f70 | |||
e7f4aba5a3 | |||
fdbe9f5d9f | |||
8bead6bfdd | |||
52dda73dbb | |||
31b3888a2f | |||
6f938470c2 | |||
776c4afc03 | |||
536dd647c6 | |||
51d581ab27 | |||
75294e7dad | |||
04bada7a9d | |||
2349143477 | |||
e9bff5fe9f | |||
411cb0cb92 | |||
53e1fb3554 | |||
2cb3b66640 | |||
5af3144330 | |||
e4043cbb3a | |||
fff424a35f | |||
b5d1c8b05a | |||
d713e33cc4 | |||
3d327d25f0 | |||
077283bf0f | |||
9ec25ea036 | |||
878cfe669c | |||
5f0be3cb2e | |||
9e28e14c08 | |||
954d002884 | |||
0a48591e53 | |||
d37c723951 | |||
9078ca557e | |||
2be1ef6ba0 | |||
47c02efccb | |||
d7ecfb432a | |||
59abf4a33f | |||
d6e715e726 | |||
fcfcd1037c | |||
f3ccd29e7b | |||
5c0bdae809 | |||
838902556b | |||
c6872c02d8 | |||
819982ea20 | |||
f9daa136c3 | |||
6a0d2ed6c8 | |||
2c1f35e794 | |||
5345e8da45 | |||
e35269dd87 | |||
60a03b7ef7 | |||
305b5a3887 | |||
bc549361d3 | |||
084b627f2e | |||
6755d00601 | |||
cba1da3e44 | |||
7be8bb1489 | |||
c7c0c1f626 | |||
3aa4629f92 | |||
2d86dbb090 | |||
91767ff0f9 | |||
078b004ecc | |||
930d204d83 | |||
8d82cdfc77 | |||
cb6996b5c3 | |||
a4f7740332 | |||
ba0faa2f77 | |||
3e68029522 | |||
b4e26b5828 | |||
15cf7fcac2 | |||
24ff0eb13b | |||
cf86f72eb7 | |||
61486f14f1 | |||
d16a7f3ecc | |||
82761ec50e | |||
235bfa77a9 | |||
299ae1bb1c | |||
80f7522dab | |||
028921e369 | |||
a4e11bb524 | |||
a4131752d2 | |||
060dcfbba1 | |||
4be7008f80 | |||
4a0d05515e | |||
83ab99c746 | |||
270da1f69f | |||
6b0e46e36c | |||
3642707145 | |||
0ea76edfd8 | |||
d493a83b2b | |||
f1721d5cef | |||
5b3fd6aa82 | |||
6f829180f7 | |||
27b95ba64a | |||
ef405b1e90 | |||
441073bad5 |
4
.bazelrc
4
.bazelrc
@ -74,8 +74,8 @@ test --test_output=errors
|
|||||||
# Trick bazel into treating BUILD files under integration/bazel as being regular files
|
# Trick bazel into treating BUILD files under integration/bazel as being regular files
|
||||||
# This lets us glob() up all the files inside this integration test to make them inputs to tests
|
# This lets us glob() up all the files inside this integration test to make them inputs to tests
|
||||||
# (Note, we cannot use common --deleted_packages because the bazel version command doesn't support it)
|
# (Note, we cannot use common --deleted_packages because the bazel version command doesn't support it)
|
||||||
build --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/tools,integration/bazel/test/e2e
|
build --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/test/e2e
|
||||||
query --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/tools,integration/bazel/test/e2e
|
query --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/test/e2e
|
||||||
|
|
||||||
################################
|
################################
|
||||||
# Temporary Settings for Ivy #
|
# Temporary Settings for Ivy #
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
3.5.1
|
3.2.0
|
||||||
# [NB: this comment has to be after the first line, see https://github.com/bazelbuild/bazelisk/issues/117]
|
# [NB: this comment has to be after the first line, see https://github.com/bazelbuild/bazelisk/issues/117]
|
||||||
# When updating the Bazel version you also need to update the RBE toolchains version in package.bzl
|
# When updating the Bazel version you also need to update the RBE toolchains version in package.bzl
|
||||||
|
@ -14,8 +14,8 @@ build --repository_cache=/home/circleci/bazel_repository_cache
|
|||||||
# Bazel doesn't calculate the memory ceiling correctly when running under Docker.
|
# Bazel doesn't calculate the memory ceiling correctly when running under Docker.
|
||||||
# Limit Bazel to consuming resources that fit in CircleCI "xlarge" class
|
# Limit Bazel to consuming resources that fit in CircleCI "xlarge" class
|
||||||
# https://circleci.com/docs/2.0/configuration-reference/#resource_class
|
# https://circleci.com/docs/2.0/configuration-reference/#resource_class
|
||||||
build --local_cpu_resources=20
|
build --local_cpu_resources=8
|
||||||
build --local_ram_resources=32768
|
build --local_ram_resources=14336
|
||||||
|
|
||||||
# All build executed remotely should be done using our RBE configuration.
|
# All build executed remotely should be done using our RBE configuration.
|
||||||
build:remote --google_default_credentials
|
build:remote --google_default_credentials
|
||||||
|
@ -11,8 +11,8 @@ try-import %workspace%/.circleci/bazel.common.rc
|
|||||||
build --repository_cache=C:/Users/circleci/bazel_repository_cache
|
build --repository_cache=C:/Users/circleci/bazel_repository_cache
|
||||||
|
|
||||||
# Manually set the local resources used in windows CI runs
|
# Manually set the local resources used in windows CI runs
|
||||||
build --local_ram_resources=120000
|
build --local_ram_resources=13500
|
||||||
build --local_cpu_resources=32
|
build --local_cpu_resources=4
|
||||||
|
|
||||||
# All windows jobs run on master and should use http caching
|
# All windows jobs run on master and should use http caching
|
||||||
build --remote_http_cache=https://storage.googleapis.com/angular-team-cache
|
build --remote_http_cache=https://storage.googleapis.com/angular-team-cache
|
||||||
|
@ -80,7 +80,7 @@ executors:
|
|||||||
|
|
||||||
windows-executor:
|
windows-executor:
|
||||||
working_directory: ~/ng
|
working_directory: ~/ng
|
||||||
resource_class: windows.2xlarge
|
resource_class: windows.medium
|
||||||
# CircleCI windows VMs do have the GitBash shell available:
|
# CircleCI windows VMs do have the GitBash shell available:
|
||||||
# https://github.com/CircleCI-Public/windows-preview-docs#shells
|
# https://github.com/CircleCI-Public/windows-preview-docs#shells
|
||||||
# But in this specific case we really should not use it because Bazel must not be ran from
|
# But in this specific case we really should not use it because Bazel must not be ran from
|
||||||
@ -273,7 +273,6 @@ jobs:
|
|||||||
- run: yarn -s ng-dev format changed $CI_GIT_BASE_REVISION --check
|
- run: yarn -s ng-dev format changed $CI_GIT_BASE_REVISION --check
|
||||||
- run: yarn -s ts-circular-deps:check
|
- run: yarn -s ts-circular-deps:check
|
||||||
- run: yarn -s ng-dev pullapprove verify
|
- run: yarn -s ng-dev pullapprove verify
|
||||||
- run: yarn -s ng-dev ngbot verify
|
|
||||||
- run: yarn -s ng-dev commit-message validate-range --range $CI_COMMIT_RANGE
|
- run: yarn -s ng-dev commit-message validate-range --range $CI_COMMIT_RANGE
|
||||||
|
|
||||||
test:
|
test:
|
||||||
@ -744,8 +743,8 @@ jobs:
|
|||||||
- run: yarn --cwd packages/zone.js promisetest
|
- run: yarn --cwd packages/zone.js promisetest
|
||||||
- run: yarn --cwd packages/zone.js promisefinallytest
|
- run: yarn --cwd packages/zone.js promisefinallytest
|
||||||
- run: yarn bazel build //packages/zone.js:npm_package &&
|
- run: yarn bazel build //packages/zone.js:npm_package &&
|
||||||
cp dist/bin/packages/zone.js/npm_package/bundles/zone-mix.umd.js ./packages/zone.js/test/extra/ &&
|
cp dist/bin/packages/zone.js/npm_package/dist/zone-mix.js ./packages/zone.js/test/extra/ &&
|
||||||
cp dist/bin/packages/zone.js/npm_package/bundles/zone-patch-electron.umd.js ./packages/zone.js/test/extra/ &&
|
cp dist/bin/packages/zone.js/npm_package/dist/zone-patch-electron.js ./packages/zone.js/test/extra/ &&
|
||||||
yarn --cwd packages/zone.js electrontest
|
yarn --cwd packages/zone.js electrontest
|
||||||
- run: yarn --cwd packages/zone.js jesttest
|
- run: yarn --cwd packages/zone.js jesttest
|
||||||
|
|
||||||
@ -858,16 +857,9 @@ workflows:
|
|||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
- build-ivy-npm-packages
|
- build-ivy-npm-packages
|
||||||
- legacy-unit-tests-saucelabs
|
- legacy-unit-tests-saucelabs
|
||||||
# Temporarily disabled components-repo-unit-tests to update rules_nodejs to 2.0.0. Breaking changes in
|
- components-repo-unit-tests:
|
||||||
# rules_nodejs create a dependency sandwich between angular/angular & angular/components that are very
|
requires:
|
||||||
# difficult and time consuming to resolve and involve patching @angular/bazel in components repo such
|
- build-npm-packages
|
||||||
# as https://github.com/angular/components/commit/9e7ba251207df77164d73d66620e619bcbc4d2ad. It is simpler to
|
|
||||||
# 1) land angular/angular upgrade to rule_nodejs 2.0.0 which has breaking changes
|
|
||||||
# 2) land angular/components upgrade to rules_nodejs 2.0.0 using the @angular/bazel builds snapshot
|
|
||||||
# 3) update angular/angular to the landed components commit and re-enable these tests
|
|
||||||
# - components-repo-unit-tests:
|
|
||||||
# requires:
|
|
||||||
# - build-npm-packages
|
|
||||||
- test_zonejs:
|
- test_zonejs:
|
||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
|
@ -41,8 +41,7 @@ copy .circleci\bazel.windows.rc ${Env:USERPROFILE}\.bazelrc
|
|||||||
####################################################################################################
|
####################################################################################################
|
||||||
# Install specific version of node.
|
# Install specific version of node.
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
nvm install 12.14.1
|
choco install nodejs --version 12.14.1 --no-progress
|
||||||
nvm use 12.14.1
|
|
||||||
|
|
||||||
# These Bazel prereqs aren't needed because the CircleCI image already includes them.
|
# These Bazel prereqs aren't needed because the CircleCI image already includes them.
|
||||||
# choco install yarn --version 1.16.0 --no-progress
|
# choco install yarn --version 1.16.0 --no-progress
|
||||||
|
55
.github/angular-robot.yml
vendored
55
.github/angular-robot.yml
vendored
@ -38,7 +38,6 @@ merge:
|
|||||||
- "modules/benchmarks/**"
|
- "modules/benchmarks/**"
|
||||||
- "modules/system.d.ts"
|
- "modules/system.d.ts"
|
||||||
- "packages/**"
|
- "packages/**"
|
||||||
- "dev-infra/benchmark/driver-utilities/**"
|
|
||||||
# list of patterns to ignore for the files changed by the PR
|
# list of patterns to ignore for the files changed by the PR
|
||||||
exclude:
|
exclude:
|
||||||
- "packages/*"
|
- "packages/*"
|
||||||
@ -48,10 +47,7 @@ merge:
|
|||||||
- "packages/bazel/src/ng_package/**"
|
- "packages/bazel/src/ng_package/**"
|
||||||
- "packages/bazel/src/protractor/**"
|
- "packages/bazel/src/protractor/**"
|
||||||
- "packages/bazel/src/schematics/**"
|
- "packages/bazel/src/schematics/**"
|
||||||
- "packages/compiler-cli/src/ngcc/**"
|
|
||||||
- "packages/compiler-cli/linker/**"
|
|
||||||
- "packages/compiler-cli/ngcc/**"
|
- "packages/compiler-cli/ngcc/**"
|
||||||
- "packages/compiler-cli/src/ngtsc/sourcemaps/**"
|
|
||||||
- "packages/docs/**"
|
- "packages/docs/**"
|
||||||
- "packages/elements/schematics/**"
|
- "packages/elements/schematics/**"
|
||||||
- "packages/examples/**"
|
- "packages/examples/**"
|
||||||
@ -59,8 +55,6 @@ merge:
|
|||||||
- "packages/localize/**"
|
- "packages/localize/**"
|
||||||
- "packages/private/**"
|
- "packages/private/**"
|
||||||
- "packages/service-worker/**"
|
- "packages/service-worker/**"
|
||||||
- "packages/common/locales/**"
|
|
||||||
- "packages/http/**"
|
|
||||||
- "**/.gitignore"
|
- "**/.gitignore"
|
||||||
- "**/.gitkeep"
|
- "**/.gitkeep"
|
||||||
- "**/yarn.lock"
|
- "**/yarn.lock"
|
||||||
@ -74,20 +68,20 @@ merge:
|
|||||||
- "packages/**/integrationtest/**"
|
- "packages/**/integrationtest/**"
|
||||||
- "packages/**/test/**"
|
- "packages/**/test/**"
|
||||||
- "packages/zone.js/*"
|
- "packages/zone.js/*"
|
||||||
- "packages/zone.js/dist/**"
|
|
||||||
- "packages/zone.js/doc/**"
|
- "packages/zone.js/doc/**"
|
||||||
- "packages/zone.js/example/**"
|
- "packages/zone.js/example/**"
|
||||||
- "packages/zone.js/scripts/**"
|
- "packages/zone.js/scripts/**"
|
||||||
|
|
||||||
# comment that will be added to a PR when there is a conflict, leave empty or set to false to disable
|
# comment that will be added to a PR when there is a conflict, leave empty or set to false to disable
|
||||||
mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.\nPlease help to unblock it by resolving these conflicts. Thanks!"
|
mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.
|
||||||
|
\nPlease help to unblock it by resolving these conflicts. Thanks!"
|
||||||
|
|
||||||
# label to monitor
|
# label to monitor
|
||||||
mergeLabel: "action: merge"
|
mergeLabel: "PR action: merge"
|
||||||
|
|
||||||
# adding any of these labels will also add the merge label
|
# adding any of these labels will also add the merge label
|
||||||
mergeLinkedLabels:
|
mergeLinkedLabels:
|
||||||
- "action: merge-assistance"
|
- "PR action: merge-assistance"
|
||||||
|
|
||||||
# list of checks that will determine if the merge label can be added
|
# list of checks that will determine if the merge label can be added
|
||||||
checks:
|
checks:
|
||||||
@ -100,17 +94,17 @@ merge:
|
|||||||
|
|
||||||
# whether the PR shouldn't have a conflict with the base branch
|
# whether the PR shouldn't have a conflict with the base branch
|
||||||
noConflict: true
|
noConflict: true
|
||||||
# list of labels that a PR needs to have, checked with a regexp (e.g. "target:" will work for the label "target: master")
|
# list of labels that a PR needs to have, checked with a regexp (e.g. "PR target:" will work for the label "PR target: master")
|
||||||
requiredLabels:
|
requiredLabels:
|
||||||
- "target: *"
|
- "PR target: *"
|
||||||
- "cla: yes"
|
- "cla: yes"
|
||||||
|
|
||||||
# list of labels that a PR shouldn't have, checked after the required labels with a regexp
|
# list of labels that a PR shouldn't have, checked after the required labels with a regexp
|
||||||
forbiddenLabels:
|
forbiddenLabels:
|
||||||
- "target: TBD"
|
- "PR target: TBD"
|
||||||
- "action: cleanup"
|
- "PR action: cleanup"
|
||||||
- "action: review"
|
- "PR action: review"
|
||||||
- "state: blocked"
|
- "PR state: blocked"
|
||||||
- "cla: no"
|
- "cla: no"
|
||||||
|
|
||||||
# list of PR statuses that need to be successful
|
# list of PR statuses that need to be successful
|
||||||
@ -127,7 +121,12 @@ merge:
|
|||||||
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
|
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
|
||||||
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
|
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
|
||||||
# {{PLACEHOLDER}} will be replaced by the list of failing checks
|
# {{PLACEHOLDER}} will be replaced by the list of failing checks
|
||||||
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:\n{{PLACEHOLDER}}\n\n**If you want your PR to be merged, it has to pass all the CI checks.**\n\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
|
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:
|
||||||
|
\n{{PLACEHOLDER}}
|
||||||
|
\n
|
||||||
|
\n**If you want your PR to be merged, it has to pass all the CI checks.**
|
||||||
|
\n
|
||||||
|
\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
|
||||||
|
|
||||||
# options for the triage plugin
|
# options for the triage plugin
|
||||||
triage:
|
triage:
|
||||||
@ -142,28 +141,24 @@ triage:
|
|||||||
# arrays of labels that determine if an issue has been fully triaged
|
# arrays of labels that determine if an issue has been fully triaged
|
||||||
l2TriageLabels:
|
l2TriageLabels:
|
||||||
-
|
-
|
||||||
- "P0"
|
- "type: bug/fix"
|
||||||
|
- "severity*"
|
||||||
|
- "freq*"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "P1"
|
- "type: feature"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "P2"
|
- "type: refactor"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "P3"
|
- "type: RFC / Discussion / question"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "P4"
|
- "type: confusing"
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
-
|
-
|
||||||
- "P5"
|
- "type: use-case"
|
||||||
- "comp: *"
|
|
||||||
-
|
|
||||||
- "feature"
|
|
||||||
- "comp: *"
|
|
||||||
-
|
|
||||||
- "discussion"
|
|
||||||
- "comp: *"
|
- "comp: *"
|
||||||
|
|
||||||
# options for the triage PR plugin
|
# options for the triage PR plugin
|
||||||
@ -191,4 +186,4 @@ rerunCircleCI:
|
|||||||
# set to true to disable
|
# set to true to disable
|
||||||
disabled: false
|
disabled: false
|
||||||
# the label which when added triggers a rerun of the default CircleCI workflow
|
# the label which when added triggers a rerun of the default CircleCI workflow
|
||||||
triggerRerunLabel: "action: rerun CI at HEAD"
|
triggerRerunLabel: "PR action: rerun CI at HEAD"
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -40,9 +40,6 @@ yarn-error.log
|
|||||||
# User specific bazel settings
|
# User specific bazel settings
|
||||||
.bazelrc.user
|
.bazelrc.user
|
||||||
|
|
||||||
# User specific ng-dev settings
|
|
||||||
.ng-dev.user*
|
|
||||||
|
|
||||||
.notes.md
|
.notes.md
|
||||||
baseline.json
|
baseline.json
|
||||||
|
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
import {CaretakerConfig} from '../dev-infra/caretaker/config';
|
|
||||||
|
|
||||||
/** The configuration for `ng-dev caretaker` commands. */
|
|
||||||
export const caretaker: CaretakerConfig = {
|
|
||||||
githubQueries: [
|
|
||||||
{
|
|
||||||
name: 'Merge Queue',
|
|
||||||
query: `is:pr is:open status:success label:"action: merge"`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Merge Assistance Queue',
|
|
||||||
query: `is:pr is:open label:"action: merge-assistance"`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Initial Triage Queue',
|
|
||||||
query: `is:open no:milestone`,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
@ -1,15 +1,11 @@
|
|||||||
import {caretaker} from './caretaker';
|
|
||||||
import {commitMessage} from './commit-message';
|
import {commitMessage} from './commit-message';
|
||||||
import {format} from './format';
|
import {format} from './format';
|
||||||
import {github} from './github';
|
import {github} from './github';
|
||||||
import {merge} from './merge';
|
import {merge} from './merge';
|
||||||
import {release} from './release';
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
commitMessage,
|
commitMessage,
|
||||||
format,
|
format,
|
||||||
github,
|
github,
|
||||||
merge,
|
merge,
|
||||||
caretaker,
|
|
||||||
release,
|
|
||||||
};
|
};
|
||||||
|
@ -1,28 +1,38 @@
|
|||||||
import {DevInfraMergeConfig} from '../dev-infra/pr/merge/config';
|
import {MergeConfig} from '../dev-infra/pr/merge/config';
|
||||||
import {getDefaultTargetLabelConfiguration} from '../dev-infra/pr/merge/defaults';
|
|
||||||
import {github} from './github';
|
|
||||||
import {release} from './release';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration for the merge tool in `ng-dev`. This sets up the labels which
|
* Configuration for the merge tool in `ng-dev`. This sets up the labels which
|
||||||
* are respected by the merge script (e.g. the target labels).
|
* are respected by the merge script (e.g. the target labels).
|
||||||
*/
|
*/
|
||||||
export const merge: DevInfraMergeConfig['merge'] = async api => {
|
export const merge = (): MergeConfig => {
|
||||||
|
// TODO: resume dynamically determining patch branch
|
||||||
|
const patch = '10.0.x';
|
||||||
return {
|
return {
|
||||||
githubApiMerge: false,
|
githubApiMerge: false,
|
||||||
claSignedLabel: 'cla: yes',
|
claSignedLabel: 'cla: yes',
|
||||||
mergeReadyLabel: /^action: merge(-assistance)?/,
|
mergeReadyLabel: /^PR action: merge(-assistance)?/,
|
||||||
caretakerNoteLabel: 'action: merge-assistance',
|
caretakerNoteLabel: 'PR action: merge-assistance',
|
||||||
commitMessageFixupLabel: 'commit message fixup',
|
commitMessageFixupLabel: 'commit message fixup',
|
||||||
// We can pick any of the NPM packages as we are in a monorepo where all packages are
|
labels: [
|
||||||
// published together with the same version and branching.
|
{
|
||||||
labels: await getDefaultTargetLabelConfiguration(api, github, release),
|
pattern: 'PR target: master-only',
|
||||||
|
branches: ['master'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: 'PR target: patch-only',
|
||||||
|
branches: [patch],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: 'PR target: master & patch',
|
||||||
|
branches: ['master', patch],
|
||||||
|
},
|
||||||
|
],
|
||||||
requiredBaseCommits: {
|
requiredBaseCommits: {
|
||||||
// PRs that target either `master` or the patch branch, need to be rebased
|
// PRs that target either `master` or the patch branch, need to be rebased
|
||||||
// on top of the latest commit message validation fix.
|
// on top of the latest commit message validation fix.
|
||||||
// These SHAs are the commits that update the required license text in the header.
|
// These SHAs are the commits that update the required license text in the header.
|
||||||
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
|
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
|
||||||
'10.0.x': '27b95ba64a5d99757f4042073fd1860e20e3ed24',
|
[patch]: '27b95ba64a5d99757f4042073fd1860e20e3ed24'
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
import {join} from 'path';
|
|
||||||
import {exec} from 'shelljs';
|
|
||||||
import {ReleaseConfig} from '../dev-infra/release/config';
|
|
||||||
|
|
||||||
/** Configuration for the `ng-dev release` command. */
|
|
||||||
export const release: ReleaseConfig = {
|
|
||||||
npmPackages: [
|
|
||||||
'@angular/animations',
|
|
||||||
'@angular/bazel',
|
|
||||||
'@angular/common',
|
|
||||||
'@angular/compiler',
|
|
||||||
'@angular/compiler-cli',
|
|
||||||
'@angular/core',
|
|
||||||
'@angular/elements',
|
|
||||||
'@angular/forms',
|
|
||||||
'@angular/language-service',
|
|
||||||
'@angular/localize',
|
|
||||||
'@angular/platform-browser',
|
|
||||||
'@angular/platform-browser-dynamic',
|
|
||||||
'@angular/platform-server',
|
|
||||||
'@angular/platform-webworker',
|
|
||||||
'@angular/platform-webworker-dynamic',
|
|
||||||
'@angular/router',
|
|
||||||
'@angular/service-worker',
|
|
||||||
'@angular/upgrade',
|
|
||||||
],
|
|
||||||
// TODO: Implement release package building here.
|
|
||||||
buildPackages: async () => [],
|
|
||||||
// TODO: This can be removed once there is an org-wide tool for changelog generation.
|
|
||||||
generateReleaseNotesForHead: async () => {
|
|
||||||
exec('yarn -s gulp changelog', {cwd: join(__dirname, '../')});
|
|
||||||
},
|
|
||||||
};
|
|
116
.pullapprove.yml
116
.pullapprove.yml
@ -115,42 +115,6 @@ pullapprove_conditions:
|
|||||||
|
|
||||||
|
|
||||||
groups:
|
groups:
|
||||||
# =========================================================
|
|
||||||
# Global Approvers
|
|
||||||
#
|
|
||||||
# All reviews performed for global approvals require using
|
|
||||||
# the `Reviewed-for:` specifier to set the approval
|
|
||||||
# specificity as documented at:
|
|
||||||
# https://docs.pullapprove.com/reviewed-for/
|
|
||||||
# =========================================================
|
|
||||||
global-approvers:
|
|
||||||
type: optional
|
|
||||||
reviewers:
|
|
||||||
teams:
|
|
||||||
- framework-global-approvers
|
|
||||||
reviews:
|
|
||||||
request: 0
|
|
||||||
required: 1
|
|
||||||
reviewed_for: required
|
|
||||||
|
|
||||||
# =========================================================
|
|
||||||
# Global Approvers For Docs
|
|
||||||
#
|
|
||||||
# All reviews performed for global docs approvals require
|
|
||||||
# using the `Reviewed-for:` specifier to set the approval
|
|
||||||
# specificity as documented at:
|
|
||||||
# https://docs.pullapprove.com/reviewed-for/
|
|
||||||
# =========================================================
|
|
||||||
global-docs-approvers:
|
|
||||||
type: optional
|
|
||||||
reviewers:
|
|
||||||
teams:
|
|
||||||
- framework-global-approvers-for-docs-only-changes
|
|
||||||
reviews:
|
|
||||||
request: 0
|
|
||||||
required: 1
|
|
||||||
reviewed_for: required
|
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
# Require review on all PRs
|
# Require review on all PRs
|
||||||
#
|
#
|
||||||
@ -159,9 +123,6 @@ groups:
|
|||||||
# one review is provided before the group is satisfied.
|
# one review is provided before the group is satisfied.
|
||||||
# =========================================================
|
# =========================================================
|
||||||
required-minimum-review:
|
required-minimum-review:
|
||||||
conditions:
|
|
||||||
- *can-be-global-approved
|
|
||||||
- *can-be-global-docs-approved
|
|
||||||
reviews:
|
reviews:
|
||||||
request: 0 # Do not request any reviews from the reviewer group
|
request: 0 # Do not request any reviews from the reviewer group
|
||||||
required: 1 # Require that all PRs have approval from at least one of the users in the group
|
required: 1 # Require that all PRs have approval from at least one of the users in the group
|
||||||
@ -196,12 +157,48 @@ groups:
|
|||||||
- manughub # Manu Murthy
|
- manughub # Manu Murthy
|
||||||
- mgechev # Minko Gechev
|
- mgechev # Minko Gechev
|
||||||
- mhevery # Miško Hevery
|
- mhevery # Miško Hevery
|
||||||
|
- michaelprentice # Michael Prentice
|
||||||
- mmalerba # Miles Malerba
|
- mmalerba # Miles Malerba
|
||||||
- petebacondarwin # Pete Bacon Darwin
|
- petebacondarwin # Pete Bacon Darwin
|
||||||
- pkozlowski-opensource # Pawel Kozlowski
|
- pkozlowski-opensource # Pawel Kozlowski
|
||||||
- Splaktar # Michael Prentice
|
|
||||||
- StephenFluin # Stephen Fluin
|
- StephenFluin # Stephen Fluin
|
||||||
|
|
||||||
|
# =========================================================
|
||||||
|
# Global Approvers
|
||||||
|
#
|
||||||
|
# All reviews performed for global approvals require using
|
||||||
|
# the `Reviewed-for:` specifier to set the approval
|
||||||
|
# specificity as documented at:
|
||||||
|
# https://docs.pullapprove.com/reviewed-for/
|
||||||
|
# =========================================================
|
||||||
|
global-approvers:
|
||||||
|
type: optional
|
||||||
|
reviewers:
|
||||||
|
teams:
|
||||||
|
- framework-global-approvers
|
||||||
|
reviews:
|
||||||
|
request: 0
|
||||||
|
required: 1
|
||||||
|
reviewed_for: required
|
||||||
|
|
||||||
|
# =========================================================
|
||||||
|
# Global Approvers For Docs
|
||||||
|
#
|
||||||
|
# All reviews performed for global docs approvals require
|
||||||
|
# using the `Reviewed-for:` specifier to set the approval
|
||||||
|
# specificity as documented at:
|
||||||
|
# https://docs.pullapprove.com/reviewed-for/
|
||||||
|
# =========================================================
|
||||||
|
global-docs-approvers:
|
||||||
|
type: optional
|
||||||
|
reviewers:
|
||||||
|
teams:
|
||||||
|
- framework-global-approvers-for-docs-only-changes
|
||||||
|
reviews:
|
||||||
|
request: 0
|
||||||
|
required: 1
|
||||||
|
reviewed_for: required
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
# Framework: Animations
|
# Framework: Animations
|
||||||
# =========================================================
|
# =========================================================
|
||||||
@ -284,7 +281,7 @@ groups:
|
|||||||
users:
|
users:
|
||||||
- alxhub
|
- alxhub
|
||||||
- crisbeto
|
- crisbeto
|
||||||
# OOO as of 2020-09-28 - devversion
|
- devversion
|
||||||
|
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
@ -326,7 +323,6 @@ groups:
|
|||||||
'aio/content/examples/component-interaction/**',
|
'aio/content/examples/component-interaction/**',
|
||||||
'aio/content/images/guide/component-interaction/**',
|
'aio/content/images/guide/component-interaction/**',
|
||||||
'aio/content/guide/component-styles.md',
|
'aio/content/guide/component-styles.md',
|
||||||
'aio/content/guide/view-encapsulation.md',
|
|
||||||
'aio/content/examples/component-styles/**',
|
'aio/content/examples/component-styles/**',
|
||||||
'aio/content/guide/dependency-injection.md',
|
'aio/content/guide/dependency-injection.md',
|
||||||
'aio/content/examples/dependency-injection/**',
|
'aio/content/examples/dependency-injection/**',
|
||||||
@ -336,7 +332,6 @@ groups:
|
|||||||
'aio/content/images/guide/dependency-injection-in-action/**',
|
'aio/content/images/guide/dependency-injection-in-action/**',
|
||||||
'aio/content/guide/dependency-injection-navtree.md',
|
'aio/content/guide/dependency-injection-navtree.md',
|
||||||
'aio/content/guide/dependency-injection-providers.md',
|
'aio/content/guide/dependency-injection-providers.md',
|
||||||
'aio/content/guide/lightweight-injection-tokens.md',
|
|
||||||
'aio/content/guide/displaying-data.md',
|
'aio/content/guide/displaying-data.md',
|
||||||
'aio/content/examples/displaying-data/**',
|
'aio/content/examples/displaying-data/**',
|
||||||
'aio/content/images/guide/displaying-data/**',
|
'aio/content/images/guide/displaying-data/**',
|
||||||
@ -420,7 +415,7 @@ groups:
|
|||||||
- atscott
|
- atscott
|
||||||
- ~kara # do not request reviews from Kara, but allow her to approve PRs
|
- ~kara # do not request reviews from Kara, but allow her to approve PRs
|
||||||
- mhevery
|
- mhevery
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
|
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
@ -663,7 +658,7 @@ groups:
|
|||||||
users:
|
users:
|
||||||
- AndrewKushnir
|
- AndrewKushnir
|
||||||
- IgorMinar
|
- IgorMinar
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
|
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
@ -680,7 +675,7 @@ groups:
|
|||||||
reviewers:
|
reviewers:
|
||||||
users:
|
users:
|
||||||
- IgorMinar
|
- IgorMinar
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
|
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
@ -698,7 +693,7 @@ groups:
|
|||||||
users:
|
users:
|
||||||
- IgorMinar
|
- IgorMinar
|
||||||
- jelbourn
|
- jelbourn
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
|
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
@ -724,7 +719,7 @@ groups:
|
|||||||
- IgorMinar
|
- IgorMinar
|
||||||
- mhevery
|
- mhevery
|
||||||
- jelbourn
|
- jelbourn
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
reviews:
|
reviews:
|
||||||
request: -1 # request reviews from everyone
|
request: -1 # request reviews from everyone
|
||||||
required: 2 # require at least 2 approvals
|
required: 2 # require at least 2 approvals
|
||||||
@ -788,21 +783,6 @@ groups:
|
|||||||
- JiaLiPassion
|
- JiaLiPassion
|
||||||
- mhevery
|
- mhevery
|
||||||
|
|
||||||
# =========================================================
|
|
||||||
# in-memory-web-api
|
|
||||||
# =========================================================
|
|
||||||
in-memory-web-api:
|
|
||||||
conditions:
|
|
||||||
- *can-be-global-approved
|
|
||||||
- *can-be-global-docs-approved
|
|
||||||
- >
|
|
||||||
contains_any_globs(files, [
|
|
||||||
'packages/misc/angular-in-memory-web-api/**',
|
|
||||||
])
|
|
||||||
reviewers:
|
|
||||||
users:
|
|
||||||
- IgorMinar
|
|
||||||
- crisbeto
|
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
# Benchpress
|
# Benchpress
|
||||||
@ -1111,12 +1091,10 @@ groups:
|
|||||||
'dev-infra/**',
|
'dev-infra/**',
|
||||||
'docs/BAZEL.md',
|
'docs/BAZEL.md',
|
||||||
'docs/CARETAKER.md',
|
'docs/CARETAKER.md',
|
||||||
'docs/CODING_STANDARDS.md',
|
|
||||||
'docs/COMMITTER.md',
|
'docs/COMMITTER.md',
|
||||||
'docs/DEBUG.md',
|
'docs/DEBUG.md',
|
||||||
'docs/DEBUG_COMPONENTS_REPO_IVY.md',
|
'docs/DEBUG_COMPONENTS_REPO_IVY.md',
|
||||||
'docs/DEVELOPER.md',
|
'docs/DEVELOPER.md',
|
||||||
'docs/FIXUP_COMMITS.md',
|
|
||||||
'docs/GITHUB_PROCESS.md',
|
'docs/GITHUB_PROCESS.md',
|
||||||
'docs/PR_REVIEW.md',
|
'docs/PR_REVIEW.md',
|
||||||
'docs/SAVED_REPLIES.md',
|
'docs/SAVED_REPLIES.md',
|
||||||
@ -1152,7 +1130,7 @@ groups:
|
|||||||
])
|
])
|
||||||
reviewers:
|
reviewers:
|
||||||
users:
|
users:
|
||||||
# OOO as of 2020-09-28 - devversion
|
- devversion
|
||||||
- filipesilva
|
- filipesilva
|
||||||
- gkalpak
|
- gkalpak
|
||||||
- IgorMinar
|
- IgorMinar
|
||||||
@ -1186,7 +1164,7 @@ groups:
|
|||||||
- atscott
|
- atscott
|
||||||
- jelbourn
|
- jelbourn
|
||||||
- petebacondarwin
|
- petebacondarwin
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
reviews:
|
reviews:
|
||||||
request: 4 # Request reviews from four people
|
request: 4 # Request reviews from four people
|
||||||
required: 3 # Require that three people approve
|
required: 3 # Require that three people approve
|
||||||
@ -1214,7 +1192,7 @@ groups:
|
|||||||
- atscott
|
- atscott
|
||||||
- jelbourn
|
- jelbourn
|
||||||
- petebacondarwin
|
- petebacondarwin
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
reviews:
|
reviews:
|
||||||
request: 4 # Request reviews from four people
|
request: 4 # Request reviews from four people
|
||||||
required: 2 # Require that two people approve
|
required: 2 # Require that two people approve
|
||||||
@ -1242,7 +1220,7 @@ groups:
|
|||||||
- atscott
|
- atscott
|
||||||
- jelbourn
|
- jelbourn
|
||||||
- petebacondarwin
|
- petebacondarwin
|
||||||
# OOO as of 2020-09-28 - pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
|
|
||||||
|
|
||||||
####################################################################################
|
####################################################################################
|
||||||
|
@ -44654,7 +44654,7 @@ const FOLDERS_IGNORE = [
|
|||||||
const DEFAULT_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([...FOLDERS_IGNORE,
|
const DEFAULT_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([...FOLDERS_IGNORE,
|
||||||
|
|
||||||
// ignore cruft
|
// ignore cruft
|
||||||
'yarn.lock', '.lock-wscript', '.wafpickle-{0..9}', '*.swp', '._*', 'npm-debug.log', 'yarn-error.log', '.npmrc', '.yarnrc', '.yarnrc.yml', '.npmignore', '.gitignore', '.DS_Store']);
|
'yarn.lock', '.lock-wscript', '.wafpickle-{0..9}', '*.swp', '._*', 'npm-debug.log', 'yarn-error.log', '.npmrc', '.yarnrc', '.npmignore', '.gitignore', '.DS_Store']);
|
||||||
|
|
||||||
const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([
|
const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([
|
||||||
// never ignore these files
|
// never ignore these files
|
||||||
@ -44663,7 +44663,6 @@ const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([
|
|||||||
function packWithIgnoreAndHeaders(cwd, ignoreFunction, { mapHeader } = {}) {
|
function packWithIgnoreAndHeaders(cwd, ignoreFunction, { mapHeader } = {}) {
|
||||||
return tar.pack(cwd, {
|
return tar.pack(cwd, {
|
||||||
ignore: ignoreFunction,
|
ignore: ignoreFunction,
|
||||||
sort: true,
|
|
||||||
map: header => {
|
map: header => {
|
||||||
const suffix = header.name === '.' ? '' : `/${header.name}`;
|
const suffix = header.name === '.' ? '' : `/${header.name}`;
|
||||||
header.name = `package${suffix}`;
|
header.name = `package${suffix}`;
|
||||||
@ -46679,7 +46678,7 @@ function mkdirfix (name, opts, cb) {
|
|||||||
/* 194 */
|
/* 194 */
|
||||||
/***/ (function(module, exports) {
|
/***/ (function(module, exports) {
|
||||||
|
|
||||||
module.exports = {"name":"yarn","installationMethod":"unknown","version":"1.22.5","license":"BSD-2-Clause","preferGlobal":true,"description":"📦🐈 Fast, reliable, and secure dependency management.","dependencies":{"@zkochan/cmd-shim":"^3.1.0","babel-runtime":"^6.26.0","bytes":"^3.0.0","camelcase":"^4.0.0","chalk":"^2.1.0","cli-table3":"^0.4.0","commander":"^2.9.0","death":"^1.0.0","debug":"^3.0.0","deep-equal":"^1.0.1","detect-indent":"^5.0.0","dnscache":"^1.0.1","glob":"^7.1.1","gunzip-maybe":"^1.4.0","hash-for-dep":"^1.2.3","imports-loader":"^0.8.0","ini":"^1.3.4","inquirer":"^6.2.0","invariant":"^2.2.0","is-builtin-module":"^2.0.0","is-ci":"^1.0.10","is-webpack-bundle":"^1.0.0","js-yaml":"^3.13.1","leven":"^2.0.0","loud-rejection":"^1.2.0","micromatch":"^2.3.11","mkdirp":"^0.5.1","node-emoji":"^1.6.1","normalize-url":"^2.0.0","npm-logical-tree":"^1.2.1","object-path":"^0.11.2","proper-lockfile":"^2.0.0","puka":"^1.0.0","read":"^1.0.7","request":"^2.87.0","request-capture-har":"^1.2.2","rimraf":"^2.5.0","semver":"^5.1.0","ssri":"^5.3.0","strip-ansi":"^4.0.0","strip-bom":"^3.0.0","tar-fs":"^1.16.0","tar-stream":"^1.6.1","uuid":"^3.0.1","v8-compile-cache":"^2.0.0","validate-npm-package-license":"^3.0.4","yn":"^2.0.0"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^7.2.3","babel-loader":"^6.2.5","babel-plugin-array-includes":"^2.0.3","babel-plugin-inline-import":"^3.0.0","babel-plugin-transform-builtin-extend":"^1.1.2","babel-plugin-transform-inline-imports-commonjs":"^1.0.0","babel-plugin-transform-runtime":"^6.4.3","babel-preset-env":"^1.6.0","babel-preset-flow":"^6.23.0","babel-preset-stage-0":"^6.0.0","babylon":"^6.5.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint":"^4.3.0","eslint-config-fb-strict":"^22.0.0","eslint-plugin-babel":"^5.0.0","eslint-plugin-flowtype":"^2.35.0","eslint-plugin-jasmine":"^2.6.2","eslint-plugin-jest":"^21.0.0","eslint-plugin-jsx-a11y":"^6.0.2","eslint-plugin-prefer-object-spread":"^1.2.1","eslint-plugin-prettier":"^2.1.2","eslint-plugin-react":"^7.1.0","eslint-plugin-relay":"^0.0.28","eslint-plugin-yarn-internal":"file:scripts/eslint-rules","execa":"^0.11.0","fancy-log":"^1.3.2","flow-bin":"^0.66.0","git-release-notes":"^3.0.0","gulp":"^4.0.0","gulp-babel":"^7.0.0","gulp-if":"^2.0.1","gulp-newer":"^1.0.0","gulp-plumber":"^1.0.1","gulp-sourcemaps":"^2.2.0","jest":"^22.4.4","jsinspect":"^0.12.6","minimatch":"^3.0.4","mock-stdin":"^0.3.0","prettier":"^1.5.2","string-replace-loader":"^2.1.1","temp":"^0.8.3","webpack":"^2.1.0-beta.25","yargs":"^6.3.0"},"resolutions":{"sshpk":"^1.14.2"},"engines":{"node":">=4.0.0"},"repository":"yarnpkg/yarn","bin":{"yarn":"./bin/yarn.js","yarnpkg":"./bin/yarn.js"},"scripts":{"build":"gulp build","build-bundle":"node ./scripts/build-webpack.js","build-chocolatey":"powershell ./scripts/build-chocolatey.ps1","build-deb":"./scripts/build-deb.sh","build-dist":"bash ./scripts/build-dist.sh","build-win-installer":"scripts\\build-windows-installer.bat","changelog":"git-release-notes $(git describe --tags --abbrev=0 $(git describe --tags --abbrev=0)^)..$(git describe --tags --abbrev=0) scripts/changelog.md","dupe-check":"yarn jsinspect ./src","lint":"eslint . && flow check","pkg-tests":"yarn --cwd packages/pkg-tests jest yarn.test.js","prettier":"eslint src __tests__ --fix","release-branch":"./scripts/release-branch.sh","test":"yarn lint && yarn test-only","test-only":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose","test-only-debug":"node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose","test-coverage":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --coverage --verbose","watch":"gulp watch","commit":"git-cz"},"jest":{"collectCoverageFrom":["src/**/*.js"],"testEnvironment":"node","modulePathIgnorePatterns":["__tests__/fixtures/","packages/pkg-tests/pkg-tests-fixtures","dist/"],"testPathIgnorePatterns":["__tests__/(fixtures|__mocks__)/","updates/","_(temp|mock|install|init|helpers).js$","packages/pkg-tests"]},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}}}
|
module.exports = {"name":"yarn","installationMethod":"unknown","version":"1.22.4","license":"BSD-2-Clause","preferGlobal":true,"description":"📦🐈 Fast, reliable, and secure dependency management.","dependencies":{"@zkochan/cmd-shim":"^3.1.0","babel-runtime":"^6.26.0","bytes":"^3.0.0","camelcase":"^4.0.0","chalk":"^2.1.0","cli-table3":"^0.4.0","commander":"^2.9.0","death":"^1.0.0","debug":"^3.0.0","deep-equal":"^1.0.1","detect-indent":"^5.0.0","dnscache":"^1.0.1","glob":"^7.1.1","gunzip-maybe":"^1.4.0","hash-for-dep":"^1.2.3","imports-loader":"^0.8.0","ini":"^1.3.4","inquirer":"^6.2.0","invariant":"^2.2.0","is-builtin-module":"^2.0.0","is-ci":"^1.0.10","is-webpack-bundle":"^1.0.0","js-yaml":"^3.13.1","leven":"^2.0.0","loud-rejection":"^1.2.0","micromatch":"^2.3.11","mkdirp":"^0.5.1","node-emoji":"^1.6.1","normalize-url":"^2.0.0","npm-logical-tree":"^1.2.1","object-path":"^0.11.2","proper-lockfile":"^2.0.0","puka":"^1.0.0","read":"^1.0.7","request":"^2.87.0","request-capture-har":"^1.2.2","rimraf":"^2.5.0","semver":"^5.1.0","ssri":"^5.3.0","strip-ansi":"^4.0.0","strip-bom":"^3.0.0","tar-fs":"^1.16.0","tar-stream":"^1.6.1","uuid":"^3.0.1","v8-compile-cache":"^2.0.0","validate-npm-package-license":"^3.0.4","yn":"^2.0.0"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^7.2.3","babel-loader":"^6.2.5","babel-plugin-array-includes":"^2.0.3","babel-plugin-inline-import":"^3.0.0","babel-plugin-transform-builtin-extend":"^1.1.2","babel-plugin-transform-inline-imports-commonjs":"^1.0.0","babel-plugin-transform-runtime":"^6.4.3","babel-preset-env":"^1.6.0","babel-preset-flow":"^6.23.0","babel-preset-stage-0":"^6.0.0","babylon":"^6.5.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint":"^4.3.0","eslint-config-fb-strict":"^22.0.0","eslint-plugin-babel":"^5.0.0","eslint-plugin-flowtype":"^2.35.0","eslint-plugin-jasmine":"^2.6.2","eslint-plugin-jest":"^21.0.0","eslint-plugin-jsx-a11y":"^6.0.2","eslint-plugin-prefer-object-spread":"^1.2.1","eslint-plugin-prettier":"^2.1.2","eslint-plugin-react":"^7.1.0","eslint-plugin-relay":"^0.0.28","eslint-plugin-yarn-internal":"file:scripts/eslint-rules","execa":"^0.11.0","fancy-log":"^1.3.2","flow-bin":"^0.66.0","git-release-notes":"^3.0.0","gulp":"^4.0.0","gulp-babel":"^7.0.0","gulp-if":"^2.0.1","gulp-newer":"^1.0.0","gulp-plumber":"^1.0.1","gulp-sourcemaps":"^2.2.0","jest":"^22.4.4","jsinspect":"^0.12.6","minimatch":"^3.0.4","mock-stdin":"^0.3.0","prettier":"^1.5.2","string-replace-loader":"^2.1.1","temp":"^0.8.3","webpack":"^2.1.0-beta.25","yargs":"^6.3.0"},"resolutions":{"sshpk":"^1.14.2"},"engines":{"node":">=4.0.0"},"repository":"yarnpkg/yarn","bin":{"yarn":"./bin/yarn.js","yarnpkg":"./bin/yarn.js"},"scripts":{"build":"gulp build","build-bundle":"node ./scripts/build-webpack.js","build-chocolatey":"powershell ./scripts/build-chocolatey.ps1","build-deb":"./scripts/build-deb.sh","build-dist":"bash ./scripts/build-dist.sh","build-win-installer":"scripts\\build-windows-installer.bat","changelog":"git-release-notes $(git describe --tags --abbrev=0 $(git describe --tags --abbrev=0)^)..$(git describe --tags --abbrev=0) scripts/changelog.md","dupe-check":"yarn jsinspect ./src","lint":"eslint . && flow check","pkg-tests":"yarn --cwd packages/pkg-tests jest yarn.test.js","prettier":"eslint src __tests__ --fix","release-branch":"./scripts/release-branch.sh","test":"yarn lint && yarn test-only","test-only":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose","test-only-debug":"node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose","test-coverage":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --coverage --verbose","watch":"gulp watch","commit":"git-cz"},"jest":{"collectCoverageFrom":["src/**/*.js"],"testEnvironment":"node","modulePathIgnorePatterns":["__tests__/fixtures/","packages/pkg-tests/pkg-tests-fixtures","dist/"],"testPathIgnorePatterns":["__tests__/(fixtures|__mocks__)/","updates/","_(temp|mock|install|init|helpers).js$","packages/pkg-tests"]},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}}}
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
/* 195 */
|
/* 195 */
|
||||||
@ -98339,7 +98338,7 @@ var _buildSubCommands = (0, (_buildSubCommands2 || _load_buildSubCommands()).def
|
|||||||
|
|
||||||
const bundle = yield fetchBundle(config, bundleUrl);
|
const bundle = yield fetchBundle(config, bundleUrl);
|
||||||
|
|
||||||
const yarnPath = path.resolve(config.lockfileFolder, `.yarn/releases/yarn-${bundleVersion}.cjs`);
|
const yarnPath = path.resolve(config.lockfileFolder, `.yarn/releases/yarn-${bundleVersion}.js`);
|
||||||
reporter.log(`Saving it into ${chalk.magenta(yarnPath)}...`);
|
reporter.log(`Saving it into ${chalk.magenta(yarnPath)}...`);
|
||||||
yield (_fs || _load_fs()).mkdirp(path.dirname(yarnPath));
|
yield (_fs || _load_fs()).mkdirp(path.dirname(yarnPath));
|
||||||
yield (_fs || _load_fs()).writeFile(yarnPath, bundle);
|
yield (_fs || _load_fs()).writeFile(yarnPath, bundle);
|
||||||
@ -100191,7 +100190,7 @@ let main = exports.main = (() => {
|
|||||||
|
|
||||||
const config = new (_config || _load_config()).default(reporter);
|
const config = new (_config || _load_config()).default(reporter);
|
||||||
const outputWrapperEnabled = (0, (_conversion || _load_conversion()).boolifyWithDefault)(process.env.YARN_WRAP_OUTPUT, true);
|
const outputWrapperEnabled = (0, (_conversion || _load_conversion()).boolifyWithDefault)(process.env.YARN_WRAP_OUTPUT, true);
|
||||||
const shouldWrapOutput = outputWrapperEnabled && !(_commander || _load_commander()).default.json && command.hasWrapper((_commander || _load_commander()).default, (_commander || _load_commander()).default.args) && !(commandName === 'init' && (_commander || _load_commander()).default[`2`]);
|
const shouldWrapOutput = outputWrapperEnabled && !(_commander || _load_commander()).default.json && command.hasWrapper((_commander || _load_commander()).default, (_commander || _load_commander()).default.args);
|
||||||
|
|
||||||
if (shouldWrapOutput) {
|
if (shouldWrapOutput) {
|
||||||
reporter.header(commandName, { name: 'yarn', version: (_yarnVersion || _load_yarnVersion()).version });
|
reporter.header(commandName, { name: 'yarn', version: (_yarnVersion || _load_yarnVersion()).version });
|
||||||
@ -100605,7 +100604,7 @@ let start = (() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (/\.[cm]?js$/.test(yarnPath)) {
|
if (yarnPath.endsWith(`.js`)) {
|
||||||
exitCode = yield (0, (_child || _load_child()).spawnp)(process.execPath, [yarnPath, ...argv], opts);
|
exitCode = yield (0, (_child || _load_child()).spawnp)(process.execPath, [yarnPath, ...argv], opts);
|
||||||
} else {
|
} else {
|
||||||
exitCode = yield (0, (_child || _load_child()).spawnp)(yarnPath, argv, opts);
|
exitCode = yield (0, (_child || _load_child()).spawnp)(yarnPath, argv, opts);
|
2
.yarnrc
2
.yarnrc
@ -2,4 +2,4 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
yarn-path ".yarn/releases/yarn-1.22.5.js"
|
yarn-path ".yarn/releases/yarn-1.22.4.js"
|
||||||
|
14
BUILD.bazel
14
BUILD.bazel
@ -20,9 +20,9 @@ filegroup(
|
|||||||
# do not sort
|
# do not sort
|
||||||
srcs = [
|
srcs = [
|
||||||
"@npm//:node_modules/core-js/client/core.js",
|
"@npm//:node_modules/core-js/client/core.js",
|
||||||
"//packages/zone.js/bundles:zone.umd.js",
|
"//packages/zone.js/dist:zone.js",
|
||||||
"//packages/zone.js/bundles:zone-testing.umd.js",
|
"//packages/zone.js/dist:zone-testing.js",
|
||||||
"//packages/zone.js/bundles:task-tracking.umd.js",
|
"//packages/zone.js/dist:task-tracking.js",
|
||||||
"//:test-events.js",
|
"//:test-events.js",
|
||||||
"//:third_party/shims_for_IE.js",
|
"//:third_party/shims_for_IE.js",
|
||||||
# Including systemjs because it defines `__eval`, which produces correct stack traces.
|
# Including systemjs because it defines `__eval`, which produces correct stack traces.
|
||||||
@ -34,7 +34,7 @@ filegroup(
|
|||||||
filegroup(
|
filegroup(
|
||||||
name = "angularjs_scripts",
|
name = "angularjs_scripts",
|
||||||
srcs = [
|
srcs = [
|
||||||
# We also declare the unminified AngularJS files since these can be used for
|
# We also declare the unminfied AngularJS files since these can be used for
|
||||||
# local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts)
|
# local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts)
|
||||||
"@npm//:node_modules/angular/angular.js",
|
"@npm//:node_modules/angular/angular.js",
|
||||||
"@npm//:node_modules/angular/angular.min.js",
|
"@npm//:node_modules/angular/angular.min.js",
|
||||||
@ -47,9 +47,3 @@ filegroup(
|
|||||||
"@npm//:node_modules/angular-mocks-1.6/angular-mocks.js",
|
"@npm//:node_modules/angular-mocks-1.6/angular-mocks.js",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Detect if the build is running under --stamp
|
|
||||||
config_setting(
|
|
||||||
name = "stamp",
|
|
||||||
values = {"stamp": "true"},
|
|
||||||
)
|
|
||||||
|
372
CHANGELOG.md
372
CHANGELOG.md
@ -1,206 +1,3 @@
|
|||||||
<a name="10.1.6"></a>
|
|
||||||
## 10.1.6 (2020-10-14)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **compiler:** incorrectly encapsulating [@import](https://github.com/import) containing colons and semicolons ([#38716](https://github.com/angular/angular/issues/38716)) ([52a0c6b](https://github.com/angular/angular/commit/52a0c6b)), closes [#38587](https://github.com/angular/angular/issues/38587)
|
|
||||||
* **compiler-cli:** support namespaced query types in directives ([#38959](https://github.com/angular/angular/issues/38959)) ([#39272](https://github.com/angular/angular/issues/39272)) ([f752ab9](https://github.com/angular/angular/commit/f752ab9))
|
|
||||||
* **elements:** detect matchesSelector prototype without IIFE ([#37799](https://github.com/angular/angular/issues/37799)) ([952fd86](https://github.com/angular/angular/commit/952fd86)), closes [#24551](https://github.com/angular/angular/issues/24551)
|
|
||||||
* **ngcc:** ensure that "inline exports" can be interpreted correctly ([#39272](https://github.com/angular/angular/issues/39272)) ([e08d021](https://github.com/angular/angular/commit/e08d021))
|
|
||||||
* **ngcc:** handle aliases in UMD export declarations ([#38959](https://github.com/angular/angular/issues/38959)) ([#39272](https://github.com/angular/angular/issues/39272)) ([9963c5d](https://github.com/angular/angular/commit/9963c5d)), closes [#38947](https://github.com/angular/angular/issues/38947)
|
|
||||||
* **ngcc:** map `exports` to the current module in UMD files ([#38959](https://github.com/angular/angular/issues/38959)) ([#39272](https://github.com/angular/angular/issues/39272)) ([13c4a7b](https://github.com/angular/angular/commit/13c4a7b))
|
|
||||||
* **ngcc:** support inline export declarations in UMD files ([#38959](https://github.com/angular/angular/issues/38959)) ([#39272](https://github.com/angular/angular/issues/39272)) ([9c875b3](https://github.com/angular/angular/commit/9c875b3)), closes [#38947](https://github.com/angular/angular/issues/38947)
|
|
||||||
|
|
||||||
|
|
||||||
### build
|
|
||||||
|
|
||||||
* upgrade angular build, integration/bazel and [@angular](https://github.com/angular)/bazel package to rule_nodejs 2.2.0 ([#39182](https://github.com/angular/angular/issues/39182)) ([7628c36](https://github.com/angular/angular/commit/7628c36))
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* **ngcc:** do not rescan program source files when referenced from multiple root files ([#39254](https://github.com/angular/angular/issues/39254)) ([5221df8](https://github.com/angular/angular/commit/5221df8)), closes [#39240](https://github.com/angular/angular/issues/39240)
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.5"></a>
|
|
||||||
## 10.1.5 (2020-10-07)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **router:** update getRouteGuards to check if the context outlet is activated ([#39049](https://github.com/angular/angular/issues/39049)) ([771f731](https://github.com/angular/angular/commit/771f731)), closes [#39030](https://github.com/angular/angular/issues/39030)
|
|
||||||
* **compiler:** Recover on malformed keyed reads and keyed writes ([#39004](https://github.com/angular/angular/issues/39004)) ([f50313f](https://github.com/angular/angular/commit/f50313f)), closes [#38596](https://github.com/angular/angular/issues/38596)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.4"></a>
|
|
||||||
## 10.1.4 (2020-09-30)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **compiler-cli:** enable [@types](https://github.com/types) discovery in incremental rebuilds ([#39011](https://github.com/angular/angular/issues/39011)) ([6e99427](https://github.com/angular/angular/commit/6e99427)), closes [#38979](https://github.com/angular/angular/issues/38979)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.3"></a>
|
|
||||||
## 10.1.3 (2020-09-23)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **http:** Fix error message when we call jsonp without importing HttpClientJsonpModule ([#38756](https://github.com/angular/angular/issues/38756)) ([3902ec0](https://github.com/angular/angular/commit/3902ec0))
|
|
||||||
* **ngcc:** fix compilation of `ChangeDetectorRef` in pipe constructors ([#38892](https://github.com/angular/angular/issues/38892)) ([093c3a1](https://github.com/angular/angular/commit/093c3a1)), closes [#38666](https://github.com/angular/angular/issues/38666) [#38883](https://github.com/angular/angular/issues/38883)
|
|
||||||
|
|
||||||
|
|
||||||
### Reverts
|
|
||||||
|
|
||||||
* feat(router): better warning message when a router outlet has not been instantiated ([#38920](https://github.com/angular/angular/issues/38920)) ([04d0aa6](https://github.com/angular/angular/commit/04d0aa6))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.2"></a>
|
|
||||||
## 10.1.2 (2020-09-16)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **compiler:** detect pipes in ICUs in template binder ([#38810](https://github.com/angular/angular/issues/38810)) ([ec2dbe7](https://github.com/angular/angular/commit/ec2dbe7)), closes [#38539](https://github.com/angular/angular/issues/38539) [#38539](https://github.com/angular/angular/issues/38539) [#38539](https://github.com/angular/angular/issues/38539)
|
|
||||||
* **core:** clear the `RefreshTransplantedView` when detached ([#38768](https://github.com/angular/angular/issues/38768)) ([edb7f90](https://github.com/angular/angular/commit/edb7f90)), closes [#38619](https://github.com/angular/angular/issues/38619)
|
|
||||||
* **localize:** ensure that `formatOptions` is optional ([#38787](https://github.com/angular/angular/issues/38787)) ([a47383d](https://github.com/angular/angular/commit/a47383d))
|
|
||||||
* **router:** Ensure routes are processed in priority order and only if needed ([#38780](https://github.com/angular/angular/issues/38780)) ([9c51ba3](https://github.com/angular/angular/commit/9c51ba3)), closes [#38691](https://github.com/angular/angular/issues/38691)
|
|
||||||
* **upgrade:** add try/catch when downgrading injectables ([#38671](https://github.com/angular/angular/issues/38671)) ([5de2ac3](https://github.com/angular/angular/commit/5de2ac3)), closes [#37579](https://github.com/angular/angular/issues/37579)
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* **compiler-cli:** only emit directive/pipe references that are used ([#38843](https://github.com/angular/angular/issues/38843)) ([5658405](https://github.com/angular/angular/commit/5658405))
|
|
||||||
* **compiler-cli:** optimize computation of type-check scope information ([#38843](https://github.com/angular/angular/issues/38843)) ([ebede67](https://github.com/angular/angular/commit/ebede67))
|
|
||||||
* **ngcc:** introduce cache for sharing data across entry-points ([#38840](https://github.com/angular/angular/issues/38840)) ([58411e7](https://github.com/angular/angular/commit/58411e7))
|
|
||||||
* **ngcc:** reduce maximum worker count ([#38840](https://github.com/angular/angular/issues/38840)) ([ea36466](https://github.com/angular/angular/commit/ea36466))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.1"></a>
|
|
||||||
## 10.1.1 (2020-09-09)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **compiler:** correct confusion between field and property names ([#38685](https://github.com/angular/angular/issues/38685)) ([a1c34c6](https://github.com/angular/angular/commit/a1c34c6))
|
|
||||||
* **compiler-cli:** compute source-mappings for localized strings ([#38747](https://github.com/angular/angular/issues/38747)) ([b4eb016](https://github.com/angular/angular/commit/b4eb016)), closes [#38588](https://github.com/angular/angular/issues/38588)
|
|
||||||
* **compiler-cli:** ensure that a declaration is available in type-to-value conversion ([#38684](https://github.com/angular/angular/issues/38684)) ([56d5ff2](https://github.com/angular/angular/commit/56d5ff2)), closes [#38670](https://github.com/angular/angular/issues/38670)
|
|
||||||
* **core:** reset `tView` between tests in Ivy TestBed ([#38659](https://github.com/angular/angular/issues/38659)) ([efc7606](https://github.com/angular/angular/commit/efc7606)), closes [#38600](https://github.com/angular/angular/issues/38600)
|
|
||||||
* **localize:** do not expose NodeJS typings in $localize runtime code ([#38700](https://github.com/angular/angular/issues/38700)) ([4de8dc3](https://github.com/angular/angular/commit/4de8dc3)), closes [#38692](https://github.com/angular/angular/issues/38692)
|
|
||||||
* **localize:** enable whitespace preservation marker in XLIFF files ([#38737](https://github.com/angular/angular/issues/38737)) ([190dca0](https://github.com/angular/angular/commit/190dca0)), closes [#38679](https://github.com/angular/angular/issues/38679)
|
|
||||||
* **localize:** install `[@angular](https://github.com/angular)/localize` in `devDependencies` by default ([#38680](https://github.com/angular/angular/issues/38680)) ([dbab744](https://github.com/angular/angular/commit/dbab744)), closes [#38329](https://github.com/angular/angular/issues/38329)
|
|
||||||
* **localize:** render context of translation file parse errors ([#38673](https://github.com/angular/angular/issues/38673)) ([32f33f0](https://github.com/angular/angular/commit/32f33f0)), closes [#38377](https://github.com/angular/angular/issues/38377)
|
|
||||||
* **localize:** render location in XLIFF 2 even if there is no metadata ([#38713](https://github.com/angular/angular/issues/38713)) ([ab4f953](https://github.com/angular/angular/commit/ab4f953)), closes [#38705](https://github.com/angular/angular/issues/38705)
|
|
||||||
* **ngcc:** use aliased exported types correctly ([#38666](https://github.com/angular/angular/issues/38666)) ([6a28675](https://github.com/angular/angular/commit/6a28675)), closes [#38238](https://github.com/angular/angular/issues/38238)
|
|
||||||
* **router:** If users are using the Alt key when clicking the router links, prioritize browser’s default behavior ([#38375](https://github.com/angular/angular/issues/38375)) ([309709d](https://github.com/angular/angular/commit/309709d))
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* **core:** use `ngDevMode` to tree-shake error messages ([#38612](https://github.com/angular/angular/issues/38612)) ([b084bff](https://github.com/angular/angular/commit/b084bff))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.0"></a>
|
|
||||||
# 10.1.0 (2020-09-02)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **bazel:** provide LinkablePackageInfo from ng_module ([#37623](https://github.com/angular/angular/issues/37623)) ([6898eab](https://github.com/angular/angular/commit/6898eab))
|
|
||||||
* **common:** add ReadonlyMap in place of Map in keyValuePipe ([#37311](https://github.com/angular/angular/issues/37311)) ([3373453](https://github.com/angular/angular/commit/3373453)), closes [#37308](https://github.com/angular/angular/issues/37308)
|
|
||||||
* **compiler-cli:** add `SourceFile.getOriginalLocation()` to sourcemaps package ([#32912](https://github.com/angular/angular/issues/32912)) ([6abb8d0](https://github.com/angular/angular/commit/6abb8d0))
|
|
||||||
* **compiler-cli:** Add compiler option to report errors when assigning to restricted input fields ([#38249](https://github.com/angular/angular/issues/38249)) ([71138f6](https://github.com/angular/angular/commit/71138f6))
|
|
||||||
* **compiler-cli:** add support for TypeScript 4.0 ([#38076](https://github.com/angular/angular/issues/38076)) ([0fc44e0](https://github.com/angular/angular/commit/0fc44e0))
|
|
||||||
* **compiler-cli:** explain why an expression cannot be used in AOT compilations ([#37587](https://github.com/angular/angular/issues/37587)) ([712f1bd](https://github.com/angular/angular/commit/712f1bd))
|
|
||||||
* **compiler:** support unary operators for more accurate type checking ([#37918](https://github.com/angular/angular/issues/37918)) ([874792d](https://github.com/angular/angular/commit/874792d)), closes [#20845](https://github.com/angular/angular/issues/20845) [#36178](https://github.com/angular/angular/issues/36178)
|
|
||||||
* **core:** rename async to waitForAsync to avoid confusing ([#37583](https://github.com/angular/angular/issues/37583)) ([8f07429](https://github.com/angular/angular/commit/8f07429))
|
|
||||||
* **core:** support injection token as predicate in queries ([#37506](https://github.com/angular/angular/issues/37506)) ([97dc85b](https://github.com/angular/angular/commit/97dc85b)), closes [#21152](https://github.com/angular/angular/issues/21152) [#36144](https://github.com/angular/angular/issues/36144)
|
|
||||||
* **core:** update reference and doc to change `async` to `waitAsync`. ([#37583](https://github.com/angular/angular/issues/37583)) ([8fbf40b](https://github.com/angular/angular/commit/8fbf40b))
|
|
||||||
* **forms:** AbstractControl to store raw validators in addition to combined validators function ([#37881](https://github.com/angular/angular/issues/37881)) ([ad7046b](https://github.com/angular/angular/commit/ad7046b))
|
|
||||||
* **localize:** allow duplicate messages to be handled during extraction ([#38082](https://github.com/angular/angular/issues/38082)) ([cf9a47b](https://github.com/angular/angular/commit/cf9a47b)), closes [#38077](https://github.com/angular/angular/issues/38077)
|
|
||||||
* **localize:** expose `canParse()` diagnostics ([#37909](https://github.com/angular/angular/issues/37909)) ([ec32eba](https://github.com/angular/angular/commit/ec32eba)), closes [#37901](https://github.com/angular/angular/issues/37901)
|
|
||||||
* **localize:** implement message extraction tool ([#32912](https://github.com/angular/angular/issues/32912)) ([190561d](https://github.com/angular/angular/commit/190561d))
|
|
||||||
* **platform-browser:** Allow `sms`-URLs ([#31463](https://github.com/angular/angular/issues/31463)) ([fc5c34d](https://github.com/angular/angular/commit/fc5c34d)), closes [#31462](https://github.com/angular/angular/issues/31462)
|
|
||||||
* **platform-server:** add option for absolute URL HTTP support ([#37539](https://github.com/angular/angular/issues/37539)) ([d37049a](https://github.com/angular/angular/commit/d37049a)), closes [#37071](https://github.com/angular/angular/issues/37071)
|
|
||||||
* **router:** better warning message when a router outlet has not been instantiated ([#30246](https://github.com/angular/angular/issues/30246)) ([1609815](https://github.com/angular/angular/commit/1609815))
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **bazel:** fix integration test for bazel building ([#38629](https://github.com/angular/angular/issues/38629)) ([dd82f2f](https://github.com/angular/angular/commit/dd82f2f))
|
|
||||||
* **common:** date pipe gives wrong week number ([#37632](https://github.com/angular/angular/issues/37632)) ([ef1fb6d](https://github.com/angular/angular/commit/ef1fb6d)), closes [#33961](https://github.com/angular/angular/issues/33961)
|
|
||||||
* **common:** narrow `NgIf` context variables in template type checker ([#36627](https://github.com/angular/angular/issues/36627)) ([9c8bc4a](https://github.com/angular/angular/commit/9c8bc4a))
|
|
||||||
* **compiler-cli:** avoid creating value expressions for symbols from type-only imports ([#37912](https://github.com/angular/angular/issues/37912)) ([18098d3](https://github.com/angular/angular/commit/18098d3)), closes [#37900](https://github.com/angular/angular/issues/37900)
|
|
||||||
* **compiler-cli:** ensure source-maps can handle webpack:// protocol ([#32912](https://github.com/angular/angular/issues/32912)) ([decd95e](https://github.com/angular/angular/commit/decd95e))
|
|
||||||
* **compiler-cli:** only read source-map comment from last line ([#32912](https://github.com/angular/angular/issues/32912)) ([07a07e3](https://github.com/angular/angular/commit/07a07e3))
|
|
||||||
* **compiler-cli:** type-check inputs that include undefined when there's coercion members ([#38273](https://github.com/angular/angular/issues/38273)) ([7525f3a](https://github.com/angular/angular/commit/7525f3a))
|
|
||||||
* **compiler:** incorrectly inferring namespace for HTML nodes inside SVG ([#38477](https://github.com/angular/angular/issues/38477)) ([0dda97e](https://github.com/angular/angular/commit/0dda97e)), closes [#37218](https://github.com/angular/angular/issues/37218)
|
|
||||||
* **compiler:** mark `NgModuleFactory` construction as not side effectful ([#38147](https://github.com/angular/angular/issues/38147)) ([7f8c222](https://github.com/angular/angular/commit/7f8c222))
|
|
||||||
* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#35464](https://github.com/angular/angular/issues/35464)) ([737506e](https://github.com/angular/angular/commit/737506e)), closes [#30497](https://github.com/angular/angular/issues/30497)
|
|
||||||
* **core:** detect DI parameters in JIT mode for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([ca07da4](https://github.com/angular/angular/commit/ca07da4)), closes [#38453](https://github.com/angular/angular/issues/38453)
|
|
||||||
* **core:** determine required DOMParser feature availability ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([c509243](https://github.com/angular/angular/commit/c509243))
|
|
||||||
* **core:** do not trigger CSP alert/report in Firefox and Chrome ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([b950d46](https://github.com/angular/angular/commit/b950d46)), closes [#25214](https://github.com/angular/angular/issues/25214)
|
|
||||||
* **core:** move generated i18n statements to the `consts` field of ComponentDef ([#38404](https://github.com/angular/angular/issues/38404)) ([cb05c01](https://github.com/angular/angular/commit/cb05c01))
|
|
||||||
* **elements:** run strategy methods in correct zone ([#37814](https://github.com/angular/angular/issues/37814)) ([8df888d](https://github.com/angular/angular/commit/8df888d)), closes [#24181](https://github.com/angular/angular/issues/24181)
|
|
||||||
* **forms:** handle form groups/arrays own pending async validation ([#22575](https://github.com/angular/angular/issues/22575)) ([77b62a5](https://github.com/angular/angular/commit/77b62a5)), closes [#10064](https://github.com/angular/angular/issues/10064)
|
|
||||||
* **language-service:** non-existent module format in package output ([#37623](https://github.com/angular/angular/issues/37623)) ([413a0fb](https://github.com/angular/angular/commit/413a0fb))
|
|
||||||
* **localize:** ensure required XLIFF parameters are serialized ([#38575](https://github.com/angular/angular/issues/38575)) ([f0af387](https://github.com/angular/angular/commit/f0af387)), closes [#38570](https://github.com/angular/angular/issues/38570)
|
|
||||||
* **localize:** extract the correct message ids ([#38498](https://github.com/angular/angular/issues/38498)) ([ac461e1](https://github.com/angular/angular/commit/ac461e1))
|
|
||||||
* **localize:** render ICU placeholders in extracted translation files ([#38484](https://github.com/angular/angular/issues/38484)) ([81c3e80](https://github.com/angular/angular/commit/81c3e80))
|
|
||||||
* **localize:** render text of extracted placeholders ([#38536](https://github.com/angular/angular/issues/38536)) ([14e90be](https://github.com/angular/angular/commit/14e90be))
|
|
||||||
* **ngcc:** detect synthesized delegate constructors for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([3b9c802](https://github.com/angular/angular/commit/3b9c802)), closes [#38453](https://github.com/angular/angular/issues/38453) [#38453](https://github.com/angular/angular/issues/38453)
|
|
||||||
* **router:** defer loading of wildcard module until needed ([#38348](https://github.com/angular/angular/issues/38348)) ([8f708b5](https://github.com/angular/angular/commit/8f708b5)), closes [#25494](https://github.com/angular/angular/issues/25494)
|
|
||||||
* **router:** fix navigation ignoring logic to compare to the browser url ([#37716](https://github.com/angular/angular/issues/37716)) ([a5ffca0](https://github.com/angular/angular/commit/a5ffca0)), closes [#16710](https://github.com/angular/angular/issues/16710) [#13586](https://github.com/angular/angular/issues/13586)
|
|
||||||
* **router:** properly compare array queryParams for equality ([#37709](https://github.com/angular/angular/issues/37709)) ([#37860](https://github.com/angular/angular/issues/37860)) ([1801d0c](https://github.com/angular/angular/commit/1801d0c))
|
|
||||||
* **router:** remove parenthesis for primary outlet segment after removing auxiliary outlet segment ([#24656](https://github.com/angular/angular/issues/24656)) ([#37163](https://github.com/angular/angular/issues/37163)) ([71f008f](https://github.com/angular/angular/commit/71f008f))
|
|
||||||
* **router:** restore 'history.state' object for navigations coming from Angular router ([#28108](https://github.com/angular/angular/issues/28108)) ([#28176](https://github.com/angular/angular/issues/28176)) ([df76a20](https://github.com/angular/angular/commit/df76a20))
|
|
||||||
|
|
||||||
### Code Refactoring
|
|
||||||
* **router:** export DefaultRouteReuseStrategy to Router public_api ([#31575](https://github.com/angular/angular/issues/31575)) ([ca79880](https://github.com/angular/angular/commit/ca79880))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
* **compiler-cli:** don't emit template guards when child scope is empty ([#38418](https://github.com/angular/angular/issues/38418)) ([1388c17](https://github.com/angular/angular/commit/1388c17))
|
|
||||||
* **compiler-cli:** fix regressions in incremental program reuse ([#37641](https://github.com/angular/angular/issues/37641)) ([5103d90](https://github.com/angular/angular/commit/5103d90))
|
|
||||||
* **compiler-cli:** only generate directive declarations when used ([#38418](https://github.com/angular/angular/issues/38418)) ([fb8f4b4](https://github.com/angular/angular/commit/fb8f4b4))
|
|
||||||
* **compiler-cli:** only generate type-check code for referenced DOM elements ([#38418](https://github.com/angular/angular/issues/38418)) ([f42e6ce](https://github.com/angular/angular/commit/f42e6ce))
|
|
||||||
* **forms:** use internal `ngDevMode` flag to tree-shake error messages in prod builds ([#37821](https://github.com/angular/angular/issues/37821)) ([201a546](https://github.com/angular/angular/commit/201a546)), closes [#37697](https://github.com/angular/angular/issues/37697)
|
|
||||||
* **ngcc:** shortcircuit tokenizing in ESM dependency host ([#37639](https://github.com/angular/angular/issues/37639)) ([bd7f440](https://github.com/angular/angular/commit/bd7f440))
|
|
||||||
* **ngcc:** use `EntryPointManifest` to speed up noop `ProgramBaseEntryPointFinder` ([#37665](https://github.com/angular/angular/issues/37665)) ([9318e23](https://github.com/angular/angular/commit/9318e23))
|
|
||||||
* **router:** apply prioritizedGuardValue operator to optimize CanLoad guards ([#37523](https://github.com/angular/angular/issues/37523)) ([d7dd295](https://github.com/angular/angular/commit/d7dd295))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.14"></a>
|
|
||||||
## 10.0.14 (2020-08-26)
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.12"></a>
|
|
||||||
## 10.0.12 (2020-08-24)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **compiler-cli:** adding references to const enums in runtime code ([#38542](https://github.com/angular/angular/issues/38542)) ([814b436](https://github.com/angular/angular/commit/814b436)), closes [#38513](https://github.com/angular/angular/issues/38513)
|
|
||||||
* **core:** remove closing body tag from inert DOM builder ([#38454](https://github.com/angular/angular/issues/38454)) ([5528536](https://github.com/angular/angular/commit/5528536))
|
|
||||||
* **localize:** include the last placeholder in parsed translation text ([#38452](https://github.com/angular/angular/issues/38452)) ([57d1a48](https://github.com/angular/angular/commit/57d1a48))
|
|
||||||
* **localize:** parse all parts of a translation with nested HTML ([#38452](https://github.com/angular/angular/issues/38452)) ([07b99f5](https://github.com/angular/angular/commit/07b99f5)), closes [#38422](https://github.com/angular/angular/issues/38422)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **language-service:** introduce hybrid visitor to locate AST node ([#38540](https://github.com/angular/angular/issues/38540)) ([66d8c22](https://github.com/angular/angular/commit/66d8c22))
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.11"></a>
|
<a name="10.0.11"></a>
|
||||||
## 10.0.11 (2020-08-19)
|
## 10.0.11 (2020-08-19)
|
||||||
|
|
||||||
@ -247,6 +44,7 @@
|
|||||||
* **service-worker:** fix the chrome debugger syntax highlighter ([#38332](https://github.com/angular/angular/issues/38332)) ([f5d5bac](https://github.com/angular/angular/commit/f5d5bac))
|
* **service-worker:** fix the chrome debugger syntax highlighter ([#38332](https://github.com/angular/angular/issues/38332)) ([f5d5bac](https://github.com/angular/angular/commit/f5d5bac))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.8"></a>
|
<a name="10.0.8"></a>
|
||||||
## 10.0.8 (2020-08-04)
|
## 10.0.8 (2020-08-04)
|
||||||
|
|
||||||
@ -315,6 +113,7 @@
|
|||||||
* **bazel:** provide LinkablePackageInfo from ng_module ([#37778](https://github.com/angular/angular/issues/37778)) ([6cd10a1](https://github.com/angular/angular/commit/6cd10a1)), closes [/github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl#L144-L146](https://github.com//github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl/issues/L144-L146)
|
* **bazel:** provide LinkablePackageInfo from ng_module ([#37778](https://github.com/angular/angular/issues/37778)) ([6cd10a1](https://github.com/angular/angular/commit/6cd10a1)), closes [/github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl#L144-L146](https://github.com//github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl/issues/L144-L146)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.3"></a>
|
<a name="10.0.3"></a>
|
||||||
## 10.0.3 (2020-07-08)
|
## 10.0.3 (2020-07-08)
|
||||||
|
|
||||||
@ -325,16 +124,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="9.1.12"></a>
|
|
||||||
## [9.1.12](https://github.com/angular/angular/compare/9.1.11...9.1.12) (2020-07-08)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **core:** infinite loop if injectable using inheritance has a custom decorator ([6c1ab47](https://github.com/angular/angular/commit/6c1ab47)), closes [#35733](https://github.com/angular/angular/issues/35733)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.2"></a>
|
<a name="10.0.2"></a>
|
||||||
## [10.0.2](https://github.com/angular/angular/compare/10.0.1...10.0.2) (2020-06-30)
|
## [10.0.2](https://github.com/angular/angular/compare/10.0.1...10.0.2) (2020-06-30)
|
||||||
|
|
||||||
@ -446,6 +235,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
* **compiler:** avoid undefined expressions in holey array ([#36343](https://github.com/angular/angular/issues/36343)) ([5516802](https://github.com/angular/angular/commit/5516802))
|
* **compiler:** avoid undefined expressions in holey array ([#36343](https://github.com/angular/angular/issues/36343)) ([5516802](https://github.com/angular/angular/commit/5516802))
|
||||||
* **compiler:** handle type references to namespaced symbols correctly ([#36106](https://github.com/angular/angular/issues/36106)) ([4aa4e6f](https://github.com/angular/angular/commit/4aa4e6f)), closes [#36006](https://github.com/angular/angular/issues/36006)
|
* **compiler:** handle type references to namespaced symbols correctly ([#36106](https://github.com/angular/angular/issues/36106)) ([4aa4e6f](https://github.com/angular/angular/commit/4aa4e6f)), closes [#36006](https://github.com/angular/angular/issues/36006)
|
||||||
* **compiler:** normalize line endings in ICU expansions ([#36741](https://github.com/angular/angular/issues/36741)) ([70dd27f](https://github.com/angular/angular/commit/70dd27f)), closes [#36725](https://github.com/angular/angular/issues/36725)
|
* **compiler:** normalize line endings in ICU expansions ([#36741](https://github.com/angular/angular/issues/36741)) ([70dd27f](https://github.com/angular/angular/commit/70dd27f)), closes [#36725](https://github.com/angular/angular/issues/36725)
|
||||||
|
* **compiler:** record correct end of expression ([#34690](https://github.com/angular/angular/issues/34690)) ([df890d7](https://github.com/angular/angular/commit/df890d7)), closes [#33477](https://github.com/angular/angular/issues/33477)
|
||||||
* **compiler:** remove outdated and invalid warning for unresolved DI parameters ([#36985](https://github.com/angular/angular/issues/36985)) ([d0280a0](https://github.com/angular/angular/commit/d0280a0))
|
* **compiler:** remove outdated and invalid warning for unresolved DI parameters ([#36985](https://github.com/angular/angular/issues/36985)) ([d0280a0](https://github.com/angular/angular/commit/d0280a0))
|
||||||
* **compiler:** resolve enum values in binary operations ([#36461](https://github.com/angular/angular/issues/36461)) ([64022f5](https://github.com/angular/angular/commit/64022f5)), closes [#35584](https://github.com/angular/angular/issues/35584)
|
* **compiler:** resolve enum values in binary operations ([#36461](https://github.com/angular/angular/issues/36461)) ([64022f5](https://github.com/angular/angular/commit/64022f5)), closes [#35584](https://github.com/angular/angular/issues/35584)
|
||||||
* **compiler:** switch to 'referencedFiles' for shim generation ([#36211](https://github.com/angular/angular/issues/36211)) ([4213e8d](https://github.com/angular/angular/commit/4213e8d))
|
* **compiler:** switch to 'referencedFiles' for shim generation ([#36211](https://github.com/angular/angular/issues/36211)) ([4213e8d](https://github.com/angular/angular/commit/4213e8d))
|
||||||
@ -702,30 +492,6 @@ subscribe to the observable and call markForCheck as needed.
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="9.1.11"></a>
|
|
||||||
## [9.1.11](https://github.com/angular/angular/compare/9.1.10...9.1.11) (2020-06-10)
|
|
||||||
|
|
||||||
### Reverts
|
|
||||||
|
|
||||||
* **elements:** fire custom element output events during component initialization ([dc9da17](https://github.com/angular/angular/commit/dc9da17))
|
|
||||||
|
|
||||||
|
|
||||||
<a name="9.1.10"></a>
|
|
||||||
## [9.1.10](https://github.com/angular/angular/compare/9.1.9...9.1.10) (2020-06-09)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **elements:** fire custom element output events during component initialization ([454e073](https://github.com/angular/angular/commit/454e073)), closes [/github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/create-custom-element.ts#L167-L170](https://github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/create-custom-element.ts/issues/L167-L170) [/github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/create-custom-element.ts#L164](https://github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/create-custom-element.ts/issues/L164) [/github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/component-factory-strategy.ts#L158](https://github.com/angular/angular/blob/c0143cb2abdd172de1b95fd1d2c4cfc738640e28/packages/elements/src/component-factory-strategy.ts/issues/L158) [#36141](https://github.com/angular/angular/issues/36141)
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* **ngcc:** cache parsed tsconfig between runs ([1aae94a](https://github.com/angular/angular/commit/1aae94a)), closes [#37417](https://github.com/angular/angular/issues/37417) [#36882](https://github.com/angular/angular/issues/36882)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="9.1.9"></a>
|
<a name="9.1.9"></a>
|
||||||
## [9.1.9](https://github.com/angular/angular/compare/9.1.8...9.1.9) (2020-05-20)
|
## [9.1.9](https://github.com/angular/angular/compare/9.1.8...9.1.9) (2020-05-20)
|
||||||
|
|
||||||
@ -767,7 +533,6 @@ This release contains various API docs improvements.
|
|||||||
* **compiler-cli**: Revert "fix(compiler-cli): fix case-sensitivity issues in NgtscCompilerHost (#36968)" (#37003)
|
* **compiler-cli**: Revert "fix(compiler-cli): fix case-sensitivity issues in NgtscCompilerHost (#36968)" (#37003)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="9.1.5"></a>
|
<a name="9.1.5"></a>
|
||||||
## [9.1.5](https://github.com/angular/angular/compare/9.1.4...9.1.5) (2020-05-07)
|
## [9.1.5](https://github.com/angular/angular/compare/9.1.4...9.1.5) (2020-05-07)
|
||||||
|
|
||||||
@ -813,7 +578,6 @@ This release contains various API docs improvements.
|
|||||||
* **ngcc:** recognize enum declarations emitted in JavaScript ([#36550](https://github.com/angular/angular/issues/36550)) ([c440165](https://github.com/angular/angular/commit/c440165)), closes [#35584](https://github.com/angular/angular/issues/35584)
|
* **ngcc:** recognize enum declarations emitted in JavaScript ([#36550](https://github.com/angular/angular/issues/36550)) ([c440165](https://github.com/angular/angular/commit/c440165)), closes [#35584](https://github.com/angular/angular/issues/35584)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="9.1.3"></a>
|
<a name="9.1.3"></a>
|
||||||
## [9.1.3](https://github.com/angular/angular/compare/9.1.2...9.1.3) (2020-04-22)
|
## [9.1.3](https://github.com/angular/angular/compare/9.1.2...9.1.3) (2020-04-22)
|
||||||
|
|
||||||
@ -828,8 +592,8 @@ This release contains various API docs improvements.
|
|||||||
* **core:** prevent unknown property check for AOT-compiled components ([#36072](https://github.com/angular/angular/issues/36072)) ([fe1d9ba](https://github.com/angular/angular/commit/fe1d9ba)), closes [#35945](https://github.com/angular/angular/issues/35945)
|
* **core:** prevent unknown property check for AOT-compiled components ([#36072](https://github.com/angular/angular/issues/36072)) ([fe1d9ba](https://github.com/angular/angular/commit/fe1d9ba)), closes [#35945](https://github.com/angular/angular/issues/35945)
|
||||||
* **core:** properly identify modules affected by overrides in TestBed ([#36649](https://github.com/angular/angular/issues/36649)) ([9724169](https://github.com/angular/angular/commit/9724169)), closes [#36619](https://github.com/angular/angular/issues/36619)
|
* **core:** properly identify modules affected by overrides in TestBed ([#36649](https://github.com/angular/angular/issues/36649)) ([9724169](https://github.com/angular/angular/commit/9724169)), closes [#36619](https://github.com/angular/angular/issues/36619)
|
||||||
* **language-service:** properly evaluate types in comparable expressions ([#36529](https://github.com/angular/angular/issues/36529)) ([5bab498](https://github.com/angular/angular/commit/5bab498))
|
* **language-service:** properly evaluate types in comparable expressions ([#36529](https://github.com/angular/angular/issues/36529)) ([5bab498](https://github.com/angular/angular/commit/5bab498))
|
||||||
* **ngcc:** display unlocker process output in sync mode ([#36637](https://github.com/angular/angular/issues/36637)) ([da159bd](https://github.com/angular/angular/commit/da159bd)), closes [/github.com/nodejs/node/issues/3596#issuecomment-250890218](https://github.com/nodejs/node/issues/3596/issues/issuecomment-250890218)
|
* **ngcc:** display unlocker process output in sync mode ([#36637](https://github.com/angular/angular/issues/36637)) ([da159bd](https://github.com/angular/angular/commit/da159bd)), closes [/github.com/nodejs/node/issues/3596#issuecomment-250890218](https://github.com/nodejs/node/issues/3596#issuecomment-250890218)
|
||||||
* **ngcc:** do not use cached file-system ([#36687](https://github.com/angular/angular/issues/36687)) ([18be33a](https://github.com/angular/angular/commit/18be33a)), closes [/github.com/angular/angular-cli/issues/16860#issuecomment-614694269](https://github.com/angular/angular-cli/issues/16860/issues/issuecomment-614694269)
|
* **ngcc:** do not use cached file-system ([#36687](https://github.com/angular/angular/issues/36687)) ([18be33a](https://github.com/angular/angular/commit/18be33a)), closes [/github.com/angular/angular-cli/issues/16860#issuecomment-614694269](https://github.com/angular/angular-cli/issues/16860#issuecomment-614694269)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -850,7 +614,7 @@ This release contains various API docs improvements.
|
|||||||
* **upgrade:** update $locationShim to handle Location changes before initialization ([#36498](https://github.com/angular/angular/issues/36498)) ([a67afcc](https://github.com/angular/angular/commit/a67afcc)), closes [#36492](https://github.com/angular/angular/issues/36492)
|
* **upgrade:** update $locationShim to handle Location changes before initialization ([#36498](https://github.com/angular/angular/issues/36498)) ([a67afcc](https://github.com/angular/angular/commit/a67afcc)), closes [#36492](https://github.com/angular/angular/issues/36492)
|
||||||
|
|
||||||
### Performance Improvements
|
### Performance Improvements
|
||||||
* **ngcc:** only load if it is needed ([#36486](https://github.com/angular/angular/issues/36486)) ([e06512b](https://github.com/angular/angular/commit/e06512b)) * **ngcc:** read dependencies from entry-point manifest ([#36486](https://github.com/angular/angular/issues/36486)) ([918e628](https://github.com/angular/angular/commit/918e628)), closes [#issuecomment-608401834](https://github.com/angular/angular/issues/issuecomment-608401834)
|
* **ngcc:** only load if it is needed ([#36486](https://github.com/angular/angular/issues/36486)) ([e06512b](https://github.com/angular/angular/commit/e06512b)) * **ngcc:** read dependencies from entry-point manifest ([#36486](https://github.com/angular/angular/issues/36486)) ([918e628](https://github.com/angular/angular/commit/918e628)), closes [#issuecomment-608401834](https://github.com/angular/angular#issuecomment-608401834)
|
||||||
* **ngcc:** reduce the size of the entry-point manifest file ([#36486](https://github.com/angular/angular/issues/36486)) ([603b094](https://github.com/angular/angular/commit/603b094))
|
* **ngcc:** reduce the size of the entry-point manifest file ([#36486](https://github.com/angular/angular/issues/36486)) ([603b094](https://github.com/angular/angular/commit/603b094))
|
||||||
|
|
||||||
|
|
||||||
@ -870,7 +634,7 @@ This release contains various API docs improvements.
|
|||||||
* **core:** undecorated-classes migration should handle derived abstract classes ([#35339](https://github.com/angular/angular/issues/35339)) ([a631b99](https://github.com/angular/angular/commit/a631b99))
|
* **core:** undecorated-classes migration should handle derived abstract classes ([#35339](https://github.com/angular/angular/issues/35339)) ([a631b99](https://github.com/angular/angular/commit/a631b99))
|
||||||
* **language-service:** infer type of elements of array-like objects ([#36312](https://github.com/angular/angular/issues/36312)) ([ff523c9](https://github.com/angular/angular/commit/ff523c9)), closes [#36191](https://github.com/angular/angular/issues/36191)
|
* **language-service:** infer type of elements of array-like objects ([#36312](https://github.com/angular/angular/issues/36312)) ([ff523c9](https://github.com/angular/angular/commit/ff523c9)), closes [#36191](https://github.com/angular/angular/issues/36191)
|
||||||
* **language-service:** use the `HtmlAst` to get the span of HTML tag ([#36371](https://github.com/angular/angular/issues/36371)) ([ffa4e11](https://github.com/angular/angular/commit/ffa4e11))
|
* **language-service:** use the `HtmlAst` to get the span of HTML tag ([#36371](https://github.com/angular/angular/issues/36371)) ([ffa4e11](https://github.com/angular/angular/commit/ffa4e11))
|
||||||
* **ngcc:** add process title ([#36448](https://github.com/angular/angular/issues/36448)) ([136596d](https://github.com/angular/angular/commit/136596d)), closes [/github.com/angular/angular/issues/36414#issuecomment-609644282](https://github.com/angular/angular/issues/36414/issues/issuecomment-609644282)
|
* **ngcc:** add process title ([#36448](https://github.com/angular/angular/issues/36448)) ([136596d](https://github.com/angular/angular/commit/136596d)), closes [36414#issuecomment-609644282](https://github.com/angular/angular/issues/36414#issuecomment-609644282)
|
||||||
* **ngcc:** allow ngcc configuration to match pre-release versions of packages ([#36370](https://github.com/angular/angular/issues/36370)) ([cb0a2a0](https://github.com/angular/angular/commit/cb0a2a0))
|
* **ngcc:** allow ngcc configuration to match pre-release versions of packages ([#36370](https://github.com/angular/angular/issues/36370)) ([cb0a2a0](https://github.com/angular/angular/commit/cb0a2a0))
|
||||||
* **ngcc:** correctly detect imported TypeScript helpers ([#36284](https://github.com/angular/angular/issues/36284)) ([879457c](https://github.com/angular/angular/commit/879457c)), closes [#36089](https://github.com/angular/angular/issues/36089)
|
* **ngcc:** correctly detect imported TypeScript helpers ([#36284](https://github.com/angular/angular/issues/36284)) ([879457c](https://github.com/angular/angular/commit/879457c)), closes [#36089](https://github.com/angular/angular/issues/36089)
|
||||||
* **ngcc:** correctly identify relative Windows-style import paths ([#36372](https://github.com/angular/angular/issues/36372)) ([0daa488](https://github.com/angular/angular/commit/0daa488))
|
* **ngcc:** correctly identify relative Windows-style import paths ([#36372](https://github.com/angular/angular/issues/36372)) ([0daa488](https://github.com/angular/angular/commit/0daa488))
|
||||||
@ -947,9 +711,12 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
* **animations:** allow computeStyle to work on elements created in Node ([#35810](https://github.com/angular/angular/issues/35810)) ([17cf04e](https://github.com/angular/angular/commit/17cf04e))
|
* **animations:** allow computeStyle to work on elements created in Node ([#35810](https://github.com/angular/angular/issues/35810)) ([17cf04e](https://github.com/angular/angular/commit/17cf04e))
|
||||||
* **animations:** false positive when detecting Node in Webpack builds ([#35134](https://github.com/angular/angular/issues/35134)) ([dc4ae4b](https://github.com/angular/angular/commit/dc4ae4b)), closes [#35117](https://github.com/angular/angular/issues/35117)
|
* **animations:** false positive when detecting Node in Webpack builds ([#35134](https://github.com/angular/angular/issues/35134)) ([dc4ae4b](https://github.com/angular/angular/commit/dc4ae4b)), closes [#35117](https://github.com/angular/angular/issues/35117)
|
||||||
* **animations:** process shorthand `margin` and `padding` styles correctly ([#35701](https://github.com/angular/angular/issues/35701)) ([35c9f0d](https://github.com/angular/angular/commit/35c9f0d)), closes [#35463](https://github.com/angular/angular/issues/35463)
|
* **animations:** process shorthand `margin` and `padding` styles correctly ([#35701](https://github.com/angular/angular/issues/35701)) ([35c9f0d](https://github.com/angular/angular/commit/35c9f0d)), closes [#35463](https://github.com/angular/angular/issues/35463)
|
||||||
|
* **bazel:** devserver shows blank page in Windows ([#35159](https://github.com/angular/angular/issues/35159)) ([727f92f](https://github.com/angular/angular/commit/727f92f))
|
||||||
* **bazel:** do not use manifest paths for generated imports within compilation unit ([#35841](https://github.com/angular/angular/issues/35841)) ([9581658](https://github.com/angular/angular/commit/9581658))
|
* **bazel:** do not use manifest paths for generated imports within compilation unit ([#35841](https://github.com/angular/angular/issues/35841)) ([9581658](https://github.com/angular/angular/commit/9581658))
|
||||||
* **bazel:** ng_package rule creates incorrect UMD module exports ([#35792](https://github.com/angular/angular/issues/35792)) ([5c2a908](https://github.com/angular/angular/commit/5c2a908)), closes [angular/components#18652](https://github.com/angular/components/issues/18652)
|
* **bazel:** ng_package rule creates incorrect UMD module exports ([#35792](https://github.com/angular/angular/issues/35792)) ([5c2a908](https://github.com/angular/angular/commit/5c2a908)), closes [angular/components#18652](https://github.com/angular/components/issues/18652)
|
||||||
* **bazel:** prod server doesn't serve files in windows ([#35991](https://github.com/angular/angular/issues/35991)) ([96e3449](https://github.com/angular/angular/commit/96e3449))
|
* **bazel:** prod server doesn't serve files in windows ([#35991](https://github.com/angular/angular/issues/35991)) ([96e3449](https://github.com/angular/angular/commit/96e3449))
|
||||||
|
* **bazel:** spawn prod server using port 4200 ([#35160](https://github.com/angular/angular/issues/35160)) ([829f506](https://github.com/angular/angular/commit/829f506))
|
||||||
|
* **bazel:** update ibazel to 0.11.1 ([#35158](https://github.com/angular/angular/issues/35158)) ([4e6d237](https://github.com/angular/angular/commit/4e6d237))
|
||||||
* **bazel:** update several packages for better windows support ([#35991](https://github.com/angular/angular/issues/35991)) ([32f099a](https://github.com/angular/angular/commit/32f099a))
|
* **bazel:** update several packages for better windows support ([#35991](https://github.com/angular/angular/issues/35991)) ([32f099a](https://github.com/angular/angular/commit/32f099a))
|
||||||
* **bazel:** update typescript peer dependency range ([#36013](https://github.com/angular/angular/issues/36013)) ([5e3a898](https://github.com/angular/angular/commit/5e3a898))
|
* **bazel:** update typescript peer dependency range ([#36013](https://github.com/angular/angular/issues/36013)) ([5e3a898](https://github.com/angular/angular/commit/5e3a898))
|
||||||
* **common:** let `KeyValuePipe` accept type unions with `null` ([#36093](https://github.com/angular/angular/issues/36093)) ([407fa42](https://github.com/angular/angular/commit/407fa42)), closes [#35743](https://github.com/angular/angular/issues/35743)
|
* **common:** let `KeyValuePipe` accept type unions with `null` ([#36093](https://github.com/angular/angular/issues/36093)) ([407fa42](https://github.com/angular/angular/commit/407fa42)), closes [#35743](https://github.com/angular/angular/issues/35743)
|
||||||
@ -958,6 +725,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
* **compiler:** Propagate value span of ExpressionBinding to ParsedProperty ([#36133](https://github.com/angular/angular/issues/36133)) ([2ce5fa3](https://github.com/angular/angular/commit/2ce5fa3))
|
* **compiler:** Propagate value span of ExpressionBinding to ParsedProperty ([#36133](https://github.com/angular/angular/issues/36133)) ([2ce5fa3](https://github.com/angular/angular/commit/2ce5fa3))
|
||||||
* **compiler:** do not recurse to find static symbols of same module ([#35262](https://github.com/angular/angular/issues/35262)) ([e179c58](https://github.com/angular/angular/commit/e179c58))
|
* **compiler:** do not recurse to find static symbols of same module ([#35262](https://github.com/angular/angular/issues/35262)) ([e179c58](https://github.com/angular/angular/commit/e179c58))
|
||||||
* **compiler:** record correct end of expression ([#34690](https://github.com/angular/angular/issues/34690)) ([df890d7](https://github.com/angular/angular/commit/df890d7)), closes [#33477](https://github.com/angular/angular/issues/33477)
|
* **compiler:** record correct end of expression ([#34690](https://github.com/angular/angular/issues/34690)) ([df890d7](https://github.com/angular/angular/commit/df890d7)), closes [#33477](https://github.com/angular/angular/issues/33477)
|
||||||
|
* **compiler:** report errors for missing binding names ([#34595](https://github.com/angular/angular/issues/34595)) ([d13cab7](https://github.com/angular/angular/commit/d13cab7))
|
||||||
* **compiler:** support directive inputs with interpolations on `<ng-template>`s ([#35984](https://github.com/angular/angular/issues/35984)) ([79659ee](https://github.com/angular/angular/commit/79659ee)), closes [#35752](https://github.com/angular/angular/issues/35752)
|
* **compiler:** support directive inputs with interpolations on `<ng-template>`s ([#35984](https://github.com/angular/angular/issues/35984)) ([79659ee](https://github.com/angular/angular/commit/79659ee)), closes [#35752](https://github.com/angular/angular/issues/35752)
|
||||||
* **compiler:** support i18n attributes on `<ng-template>` tags ([#35681](https://github.com/angular/angular/issues/35681)) ([40da51f](https://github.com/angular/angular/commit/40da51f))
|
* **compiler:** support i18n attributes on `<ng-template>` tags ([#35681](https://github.com/angular/angular/issues/35681)) ([40da51f](https://github.com/angular/angular/commit/40da51f))
|
||||||
* **compiler:** type-checking error for duplicate variables in templates ([#35674](https://github.com/angular/angular/issues/35674)) ([2c41bb8](https://github.com/angular/angular/commit/2c41bb8)), closes [#35186](https://github.com/angular/angular/issues/35186)
|
* **compiler:** type-checking error for duplicate variables in templates ([#35674](https://github.com/angular/angular/issues/35674)) ([2c41bb8](https://github.com/angular/angular/commit/2c41bb8)), closes [#35186](https://github.com/angular/angular/issues/35186)
|
||||||
@ -995,13 +763,19 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
* **core:** workaround Terser inlining bug ([#36200](https://github.com/angular/angular/issues/36200)) ([f71d132](https://github.com/angular/angular/commit/f71d132))
|
* **core:** workaround Terser inlining bug ([#36200](https://github.com/angular/angular/issues/36200)) ([f71d132](https://github.com/angular/angular/commit/f71d132))
|
||||||
* **elements:** correctly handle setting inputs to `undefined` ([#36140](https://github.com/angular/angular/issues/36140)) ([e066bdd](https://github.com/angular/angular/commit/e066bdd))
|
* **elements:** correctly handle setting inputs to `undefined` ([#36140](https://github.com/angular/angular/issues/36140)) ([e066bdd](https://github.com/angular/angular/commit/e066bdd))
|
||||||
* **elements:** correctly set `SimpleChange#firstChange` for pre-existing inputs ([#36140](https://github.com/angular/angular/issues/36140)) ([447a600](https://github.com/angular/angular/commit/447a600)), closes [#36130](https://github.com/angular/angular/issues/36130)
|
* **elements:** correctly set `SimpleChange#firstChange` for pre-existing inputs ([#36140](https://github.com/angular/angular/issues/36140)) ([447a600](https://github.com/angular/angular/commit/447a600)), closes [#36130](https://github.com/angular/angular/issues/36130)
|
||||||
|
* **elements:** schematics fail with schema.json not found error ([#35211](https://github.com/angular/angular/issues/35211)) ([94d002b](https://github.com/angular/angular/commit/94d002b)), closes [#35154](https://github.com/angular/angular/issues/35154)
|
||||||
|
* **forms:** change Array.reduce usage to Array.forEach ([#35349](https://github.com/angular/angular/issues/35349)) ([554c2cb](https://github.com/angular/angular/commit/554c2cb))
|
||||||
* **ivy:** `LFrame` needs to release memory on `leaveView()` ([#35156](https://github.com/angular/angular/issues/35156)) ([b9b512f](https://github.com/angular/angular/commit/b9b512f)), closes [#35148](https://github.com/angular/angular/issues/35148)
|
* **ivy:** `LFrame` needs to release memory on `leaveView()` ([#35156](https://github.com/angular/angular/issues/35156)) ([b9b512f](https://github.com/angular/angular/commit/b9b512f)), closes [#35148](https://github.com/angular/angular/issues/35148)
|
||||||
* **ivy:** add attributes and classes to host elements based on selector ([#34481](https://github.com/angular/angular/issues/34481)) ([f95b8ce](https://github.com/angular/angular/commit/f95b8ce))
|
* **ivy:** add attributes and classes to host elements based on selector ([#34481](https://github.com/angular/angular/issues/34481)) ([f95b8ce](https://github.com/angular/angular/commit/f95b8ce))
|
||||||
|
* **ivy:** ensure module imports are instantiated before the module being declared ([#35172](https://github.com/angular/angular/issues/35172)) ([b6a3a73](https://github.com/angular/angular/commit/b6a3a73))
|
||||||
* **ivy:** error if directive with synthetic property binding is on same node as directive that injects ViewContainerRef ([#35343](https://github.com/angular/angular/issues/35343)) ([d6bc63f](https://github.com/angular/angular/commit/d6bc63f)), closes [#35342](https://github.com/angular/angular/issues/35342)
|
* **ivy:** error if directive with synthetic property binding is on same node as directive that injects ViewContainerRef ([#35343](https://github.com/angular/angular/issues/35343)) ([d6bc63f](https://github.com/angular/angular/commit/d6bc63f)), closes [#35342](https://github.com/angular/angular/issues/35342)
|
||||||
* **ivy:** narrow `NgIf` context variables in template type checker ([#35125](https://github.com/angular/angular/issues/35125)) ([40039d8](https://github.com/angular/angular/commit/40039d8)), closes [#34572](https://github.com/angular/angular/issues/34572)
|
* **ivy:** narrow `NgIf` context variables in template type checker ([#35125](https://github.com/angular/angular/issues/35125)) ([40039d8](https://github.com/angular/angular/commit/40039d8)), closes [#34572](https://github.com/angular/angular/issues/34572)
|
||||||
* **ivy:** queries should match elements inside ng-container with the descendants: false option ([#35384](https://github.com/angular/angular/issues/35384)) ([3f4e02b](https://github.com/angular/angular/commit/3f4e02b)), closes [#34768](https://github.com/angular/angular/issues/34768)
|
* **ivy:** queries should match elements inside ng-container with the descendants: false option ([#35384](https://github.com/angular/angular/issues/35384)) ([3f4e02b](https://github.com/angular/angular/commit/3f4e02b)), closes [#34768](https://github.com/angular/angular/issues/34768)
|
||||||
|
* **ivy:** repeat template guards to narrow types in event handlers ([#35193](https://github.com/angular/angular/issues/35193)) ([dea1b96](https://github.com/angular/angular/commit/dea1b96)), closes [#35073](https://github.com/angular/angular/issues/35073)
|
||||||
|
* **ivy:** set namespace for host elements of dynamically created components ([#35136](https://github.com/angular/angular/issues/35136)) ([480a4c3](https://github.com/angular/angular/commit/480a4c3))
|
||||||
* **ivy:** support dynamic query tokens in AOT mode ([#35307](https://github.com/angular/angular/issues/35307)) ([3e3a1ef](https://github.com/angular/angular/commit/3e3a1ef)), closes [#34267](https://github.com/angular/angular/issues/34267)
|
* **ivy:** support dynamic query tokens in AOT mode ([#35307](https://github.com/angular/angular/issues/35307)) ([3e3a1ef](https://github.com/angular/angular/commit/3e3a1ef)), closes [#34267](https://github.com/angular/angular/issues/34267)
|
||||||
* **ivy:** wrong context passed to ngOnDestroy when resolved multiple times ([#35249](https://github.com/angular/angular/issues/35249)) ([5fbfe69](https://github.com/angular/angular/commit/5fbfe69)), closes [#35167](https://github.com/angular/angular/issues/35167)
|
* **ivy:** wrong context passed to ngOnDestroy when resolved multiple times ([#35249](https://github.com/angular/angular/issues/35249)) ([5fbfe69](https://github.com/angular/angular/commit/5fbfe69)), closes [#35167](https://github.com/angular/angular/issues/35167)
|
||||||
|
* **language-service:** Suggest ? and ! operator on nullable receiver ([#35200](https://github.com/angular/angular/issues/35200)) ([3cc24a9](https://github.com/angular/angular/commit/3cc24a9))
|
||||||
* **language-service:** fix calculation of pipe spans ([#35986](https://github.com/angular/angular/issues/35986)) ([406419b](https://github.com/angular/angular/commit/406419b))
|
* **language-service:** fix calculation of pipe spans ([#35986](https://github.com/angular/angular/issues/35986)) ([406419b](https://github.com/angular/angular/commit/406419b))
|
||||||
* **language-service:** get the right 'ElementAst' in the nested HTML tag ([#35317](https://github.com/angular/angular/issues/35317)) ([8e354da](https://github.com/angular/angular/commit/8e354da))
|
* **language-service:** get the right 'ElementAst' in the nested HTML tag ([#35317](https://github.com/angular/angular/issues/35317)) ([8e354da](https://github.com/angular/angular/commit/8e354da))
|
||||||
* **language-service:** infer $implicit value for ngIf template contexts ([#35941](https://github.com/angular/angular/issues/35941)) ([18b1bd4](https://github.com/angular/angular/commit/18b1bd4))
|
* **language-service:** infer $implicit value for ngIf template contexts ([#35941](https://github.com/angular/angular/issues/35941)) ([18b1bd4](https://github.com/angular/angular/commit/18b1bd4))
|
||||||
@ -1026,6 +800,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
* **ngcc:** correctly detect outer aliased class identifiers in ES5 ([#35527](https://github.com/angular/angular/issues/35527)) ([fde8915](https://github.com/angular/angular/commit/fde8915)), closes [#35399](https://github.com/angular/angular/issues/35399)
|
* **ngcc:** correctly detect outer aliased class identifiers in ES5 ([#35527](https://github.com/angular/angular/issues/35527)) ([fde8915](https://github.com/angular/angular/commit/fde8915)), closes [#35399](https://github.com/angular/angular/issues/35399)
|
||||||
* **ngcc:** do not crash on entry-point that fails to compile ([#36083](https://github.com/angular/angular/issues/36083)) ([ff665b9](https://github.com/angular/angular/commit/ff665b9))
|
* **ngcc:** do not crash on entry-point that fails to compile ([#36083](https://github.com/angular/angular/issues/36083)) ([ff665b9](https://github.com/angular/angular/commit/ff665b9))
|
||||||
* **ngcc:** do not crash on overlapping entry-points ([#36083](https://github.com/angular/angular/issues/36083)) ([c9f554c](https://github.com/angular/angular/commit/c9f554c))
|
* **ngcc:** do not crash on overlapping entry-points ([#36083](https://github.com/angular/angular/issues/36083)) ([c9f554c](https://github.com/angular/angular/commit/c9f554c))
|
||||||
|
* **ngcc:** ensure that path-mapped secondary entry-points are processed correctly ([#35227](https://github.com/angular/angular/issues/35227)) ([c3c1140](https://github.com/angular/angular/commit/c3c1140)), closes [#35188](https://github.com/angular/angular/issues/35188)
|
||||||
* **ngcc:** handle imports in dts files when processing CommonJS ([#35191](https://github.com/angular/angular/issues/35191)) ([b6e8847](https://github.com/angular/angular/commit/b6e8847)), closes [#34356](https://github.com/angular/angular/issues/34356)
|
* **ngcc:** handle imports in dts files when processing CommonJS ([#35191](https://github.com/angular/angular/issues/35191)) ([b6e8847](https://github.com/angular/angular/commit/b6e8847)), closes [#34356](https://github.com/angular/angular/issues/34356)
|
||||||
* **ngcc:** handle mappings outside the content when flattening source-maps ([#35718](https://github.com/angular/angular/issues/35718)) ([73cf7d5](https://github.com/angular/angular/commit/73cf7d5)), closes [#35709](https://github.com/angular/angular/issues/35709)
|
* **ngcc:** handle mappings outside the content when flattening source-maps ([#35718](https://github.com/angular/angular/issues/35718)) ([73cf7d5](https://github.com/angular/angular/commit/73cf7d5)), closes [#35709](https://github.com/angular/angular/issues/35709)
|
||||||
* **ngcc:** handle missing sources when flattening source-maps ([#35718](https://github.com/angular/angular/issues/35718)) ([72c4fda](https://github.com/angular/angular/commit/72c4fda)), closes [#35709](https://github.com/angular/angular/issues/35709)
|
* **ngcc:** handle missing sources when flattening source-maps ([#35718](https://github.com/angular/angular/issues/35718)) ([72c4fda](https://github.com/angular/angular/commit/72c4fda)), closes [#35709](https://github.com/angular/angular/issues/35709)
|
||||||
@ -1283,7 +1058,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
* **compiler-cli:** require node 10 as runtime engine ([#34722](https://github.com/angular/angular/issues/34722)) ([7b77b3d](https://github.com/angular/angular/commit/7b77b3d))
|
* **compiler-cli:** require node 10 as runtime engine ([#34722](https://github.com/angular/angular/issues/34722)) ([7b77b3d](https://github.com/angular/angular/commit/7b77b3d))
|
||||||
* **language-service:** specific suggestions for template context diags ([#34751](https://github.com/angular/angular/issues/34751)) ([cc7fca4](https://github.com/angular/angular/commit/cc7fca4))
|
* **language-service:** specific suggestions for template context diags ([#34751](https://github.com/angular/angular/issues/34751)) ([cc7fca4](https://github.com/angular/angular/commit/cc7fca4))
|
||||||
* **language-service:** support multiple symbol definitions ([#34782](https://github.com/angular/angular/issues/34782)) ([2f2396c](https://github.com/angular/angular/commit/2f2396c))
|
* **language-service:** support multiple symbol definitions ([#34782](https://github.com/angular/angular/issues/34782)) ([2f2396c](https://github.com/angular/angular/commit/2f2396c))
|
||||||
* **ngcc:** lock ngcc when processing ([#34722](https://github.com/angular/angular/issues/34722)) ([6dd51f1](https://github.com/angular/angular/commit/6dd51f1)), closes [/github.com/angular/angular/issues/32431#issuecomment-571825781](https://github.com/angular/angular/issues/32431/issues/issuecomment-571825781)
|
* **ngcc:** lock ngcc when processing ([#34722](https://github.com/angular/angular/issues/34722)) ([6dd51f1](https://github.com/angular/angular/commit/6dd51f1)), closes [32431#issuecomment-571825781](https://github.com/angular/angular/issues/32431#issuecomment-571825781)
|
||||||
* work around 'noImplicityAny' incompatibility due to ts3.7 update ([#34798](https://github.com/angular/angular/issues/34798)) ([251d548](https://github.com/angular/angular/commit/251d548))
|
* work around 'noImplicityAny' incompatibility due to ts3.7 update ([#34798](https://github.com/angular/angular/issues/34798)) ([251d548](https://github.com/angular/angular/commit/251d548))
|
||||||
* **animations:** not waiting for child animations to finish when removing parent in Ivy ([#34702](https://github.com/angular/angular/issues/34702)) ([92c17fe](https://github.com/angular/angular/commit/92c17fe)), closes [#33597](https://github.com/angular/angular/issues/33597)
|
* **animations:** not waiting for child animations to finish when removing parent in Ivy ([#34702](https://github.com/angular/angular/issues/34702)) ([92c17fe](https://github.com/angular/angular/commit/92c17fe)), closes [#33597](https://github.com/angular/angular/issues/33597)
|
||||||
* **common:** ensure diffing in ngStyle/ngClass correctly emits value changes ([#34307](https://github.com/angular/angular/issues/34307)) ([93a035f](https://github.com/angular/angular/commit/93a035f)), closes [#34336](https://github.com/angular/angular/issues/34336) [#34444](https://github.com/angular/angular/issues/34444)
|
* **common:** ensure diffing in ngStyle/ngClass correctly emits value changes ([#34307](https://github.com/angular/angular/issues/34307)) ([93a035f](https://github.com/angular/angular/commit/93a035f)), closes [#34336](https://github.com/angular/angular/issues/34336) [#34444](https://github.com/angular/angular/issues/34444)
|
||||||
@ -1414,7 +1189,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
* **ngcc:** do not output duplicate ɵprov properties ([#34085](https://github.com/angular/angular/issues/34085)) ([5a8d25d](https://github.com/angular/angular/commit/5a8d25d))
|
* **ngcc:** do not output duplicate ɵprov properties ([#34085](https://github.com/angular/angular/issues/34085)) ([5a8d25d](https://github.com/angular/angular/commit/5a8d25d))
|
||||||
* **ngcc:** render localized strings when in ES5 format ([#33857](https://github.com/angular/angular/issues/33857)) ([c6695fa](https://github.com/angular/angular/commit/c6695fa))
|
* **ngcc:** render localized strings when in ES5 format ([#33857](https://github.com/angular/angular/issues/33857)) ([c6695fa](https://github.com/angular/angular/commit/c6695fa))
|
||||||
* **ngcc:** render UMD global imports correctly ([#34012](https://github.com/angular/angular/issues/34012)) ([83989b8](https://github.com/angular/angular/commit/83989b8))
|
* **ngcc:** render UMD global imports correctly ([#34012](https://github.com/angular/angular/issues/34012)) ([83989b8](https://github.com/angular/angular/commit/83989b8))
|
||||||
* **ngcc:** report errors from `analyze` and `resolve` processing ([#33964](https://github.com/angular/angular/issues/33964)) ([ca5d772](https://github.com/angular/angular/commit/ca5d772)), closes [/github.com/angular/angular/issues/33685#issuecomment-557091719](https://github.com/angular/angular/issues/33685/issues/issuecomment-557091719)
|
* **ngcc:** report errors from `analyze` and `resolve` processing ([#33964](https://github.com/angular/angular/issues/33964)) ([ca5d772](https://github.com/angular/angular/commit/ca5d772)), closes [33685#issuecomment-557091719](https://github.com/angular/angular/issues/33685#issuecomment-557091719)
|
||||||
* **router:** make routerLinkActive work with query params which contain arrays ([#22666](https://github.com/angular/angular/issues/22666)) ([f1bf5b2](https://github.com/angular/angular/commit/f1bf5b2)), closes [#22223](https://github.com/angular/angular/issues/22223)
|
* **router:** make routerLinkActive work with query params which contain arrays ([#22666](https://github.com/angular/angular/issues/22666)) ([f1bf5b2](https://github.com/angular/angular/commit/f1bf5b2)), closes [#22223](https://github.com/angular/angular/issues/22223)
|
||||||
* **service-worker:** allow creating post api requests after cache failure ([#33930](https://github.com/angular/angular/issues/33930)) ([63c9123](https://github.com/angular/angular/commit/63c9123)), closes [#33793](https://github.com/angular/angular/issues/33793)
|
* **service-worker:** allow creating post api requests after cache failure ([#33930](https://github.com/angular/angular/issues/33930)) ([63c9123](https://github.com/angular/angular/commit/63c9123)), closes [#33793](https://github.com/angular/angular/issues/33793)
|
||||||
* **service-worker:** throw when using the unsupported `versionedFiles` option in config ([#33903](https://github.com/angular/angular/issues/33903)) ([250e6fd](https://github.com/angular/angular/commit/250e6fd))
|
* **service-worker:** throw when using the unsupported `versionedFiles` option in config ([#33903](https://github.com/angular/angular/issues/33903)) ([250e6fd](https://github.com/angular/angular/commit/250e6fd))
|
||||||
@ -1493,7 +1268,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
* **language-service:** Should not crash if expr ends unexpectedly ([#33524](https://github.com/angular/angular/issues/33524)) ([9ebac71](https://github.com/angular/angular/commit/9ebac71))
|
* **language-service:** Should not crash if expr ends unexpectedly ([#33524](https://github.com/angular/angular/issues/33524)) ([9ebac71](https://github.com/angular/angular/commit/9ebac71))
|
||||||
* **ngcc:** handle new `__spreadArrays` tslib helper ([#33617](https://github.com/angular/angular/issues/33617)) ([d749dd3](https://github.com/angular/angular/commit/d749dd3)), closes [#33614](https://github.com/angular/angular/issues/33614)
|
* **ngcc:** handle new `__spreadArrays` tslib helper ([#33617](https://github.com/angular/angular/issues/33617)) ([d749dd3](https://github.com/angular/angular/commit/d749dd3)), closes [#33614](https://github.com/angular/angular/issues/33614)
|
||||||
* **ngcc:** override `getInternalNameOfClass()` and `getAdjacentNameOfClass()` for ES5 ([#33533](https://github.com/angular/angular/issues/33533)) ([93a23b9](https://github.com/angular/angular/commit/93a23b9))
|
* **ngcc:** override `getInternalNameOfClass()` and `getAdjacentNameOfClass()` for ES5 ([#33533](https://github.com/angular/angular/issues/33533)) ([93a23b9](https://github.com/angular/angular/commit/93a23b9))
|
||||||
* **ngcc:** render adjacent statements after static properties ([#33630](https://github.com/angular/angular/issues/33630)) ([fe12d0d](https://github.com/angular/angular/commit/fe12d0d)), closes [/github.com/angular/angular/pull/33337#issuecomment-545487737](https://github.com/angular/angular/pull/33337/issues/issuecomment-545487737)
|
* **ngcc:** render adjacent statements after static properties ([#33630](https://github.com/angular/angular/issues/33630)) ([fe12d0d](https://github.com/angular/angular/commit/fe12d0d)), closes [/github.com/angular/angular/pull/33337#issuecomment-545487737](https://github.com/angular/angular/pull/33337#issuecomment-545487737)
|
||||||
* **ngcc:** render new definitions using the inner name of the class ([#33533](https://github.com/angular/angular/issues/33533)) ([85298e3](https://github.com/angular/angular/commit/85298e3))
|
* **ngcc:** render new definitions using the inner name of the class ([#33533](https://github.com/angular/angular/issues/33533)) ([85298e3](https://github.com/angular/angular/commit/85298e3))
|
||||||
* **service-worker:** ensure initialization before handling messages ([#32525](https://github.com/angular/angular/issues/32525)) ([72eba77](https://github.com/angular/angular/commit/72eba77)), closes [#25611](https://github.com/angular/angular/issues/25611)
|
* **service-worker:** ensure initialization before handling messages ([#32525](https://github.com/angular/angular/issues/32525)) ([72eba77](https://github.com/angular/angular/commit/72eba77)), closes [#25611](https://github.com/angular/angular/issues/25611)
|
||||||
* **compiler:** i18n - ignore `alt-trans` tags in XLIFF 1.2 ([#33450](https://github.com/angular/angular/issues/33450)) ([936700a](https://github.com/angular/angular/commit/936700a)), closes [#33161](https://github.com/angular/angular/issues/33161)
|
* **compiler:** i18n - ignore `alt-trans` tags in XLIFF 1.2 ([#33450](https://github.com/angular/angular/issues/33450)) ([936700a](https://github.com/angular/angular/commit/936700a)), closes [#33161](https://github.com/angular/angular/issues/33161)
|
||||||
@ -1523,7 +1298,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
* **language-service:** Add directive selectors & banana-in-a-box to completions ([#33311](https://github.com/angular/angular/issues/33311)) ([49eec5d](https://github.com/angular/angular/commit/49eec5d))
|
* **language-service:** Add directive selectors & banana-in-a-box to completions ([#33311](https://github.com/angular/angular/issues/33311)) ([49eec5d](https://github.com/angular/angular/commit/49eec5d))
|
||||||
* **language-service:** Add global symbol for $any() ([#33245](https://github.com/angular/angular/issues/33245)) ([3f257e9](https://github.com/angular/angular/commit/3f257e9))
|
* **language-service:** Add global symbol for $any() ([#33245](https://github.com/angular/angular/issues/33245)) ([3f257e9](https://github.com/angular/angular/commit/3f257e9))
|
||||||
* **language-service:** Preserve CRLF in templates for language-service ([#33241](https://github.com/angular/angular/issues/33241)) ([65a0d2b](https://github.com/angular/angular/commit/65a0d2b))
|
* **language-service:** Preserve CRLF in templates for language-service ([#33241](https://github.com/angular/angular/issues/33241)) ([65a0d2b](https://github.com/angular/angular/commit/65a0d2b))
|
||||||
* **ngcc:** do not fail when multiple workers try to create the same directory ([#33237](https://github.com/angular/angular/issues/33237)) ([8017229](https://github.com/angular/angular/commit/8017229)), closes [/github.com/angular/angular/pull/33049#issuecomment-540485703](https://github.com/angular/angular/pull/33049/issues/issuecomment-540485703)
|
* **ngcc:** do not fail when multiple workers try to create the same directory ([#33237](https://github.com/angular/angular/issues/33237)) ([8017229](https://github.com/angular/angular/commit/8017229)), closes [/github.com/angular/angular/pull/33049#issuecomment-540485703](https://github.com/angular/angular/pull/33049#issuecomment-540485703)
|
||||||
* **bazel:** Remove angular devkit and restore ngc postinstall ([#32946](https://github.com/angular/angular/issues/32946)) ([f036684](https://github.com/angular/angular/commit/f036684))
|
* **bazel:** Remove angular devkit and restore ngc postinstall ([#32946](https://github.com/angular/angular/issues/32946)) ([f036684](https://github.com/angular/angular/commit/f036684))
|
||||||
* **common:** remove deprecated support for intl API ([#29250](https://github.com/angular/angular/issues/29250)) ([9e7668f](https://github.com/angular/angular/commit/9e7668f)), closes [#18284](https://github.com/angular/angular/issues/18284)
|
* **common:** remove deprecated support for intl API ([#29250](https://github.com/angular/angular/issues/29250)) ([9e7668f](https://github.com/angular/angular/commit/9e7668f)), closes [#18284](https://github.com/angular/angular/issues/18284)
|
||||||
* **compiler:** absolute source span for template attribute expressions ([#33189](https://github.com/angular/angular/issues/33189)) ([fd4fed1](https://github.com/angular/angular/commit/fd4fed1))
|
* **compiler:** absolute source span for template attribute expressions ([#33189](https://github.com/angular/angular/issues/33189)) ([fd4fed1](https://github.com/angular/angular/commit/fd4fed1))
|
||||||
@ -1580,7 +1355,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
* **language-service:** Turn on strict mode for test project ([#32783](https://github.com/angular/angular/issues/32783)) ([28358b6](https://github.com/angular/angular/commit/28358b6))
|
* **language-service:** Turn on strict mode for test project ([#32783](https://github.com/angular/angular/issues/32783)) ([28358b6](https://github.com/angular/angular/commit/28358b6))
|
||||||
* **ngcc:** ensure private exports are added for `ModuleWithProviders` ([#32902](https://github.com/angular/angular/issues/32902)) ([002a97d](https://github.com/angular/angular/commit/002a97d))
|
* **ngcc:** ensure private exports are added for `ModuleWithProviders` ([#32902](https://github.com/angular/angular/issues/32902)) ([002a97d](https://github.com/angular/angular/commit/002a97d))
|
||||||
* **ngcc:** handle presence of both `ctorParameters` and `__decorate` ([#32901](https://github.com/angular/angular/issues/32901)) ([747f0cf](https://github.com/angular/angular/commit/747f0cf))
|
* **ngcc:** handle presence of both `ctorParameters` and `__decorate` ([#32901](https://github.com/angular/angular/issues/32901)) ([747f0cf](https://github.com/angular/angular/commit/747f0cf))
|
||||||
* **ngcc:** make the build-marker error more clear ([#32712](https://github.com/angular/angular/issues/32712)) ([0ea4875](https://github.com/angular/angular/commit/0ea4875)), closes [/github.com/angular/angular/issues/31354#issuecomment-532080537](https://github.com/angular/angular/issues/31354/issues/issuecomment-532080537)
|
* **ngcc:** make the build-marker error more clear ([#32712](https://github.com/angular/angular/issues/32712)) ([0ea4875](https://github.com/angular/angular/commit/0ea4875)), closes [31354#issuecomment-532080537](https://github.com/angular/angular/issues/31354#issuecomment-532080537)
|
||||||
* **upgrade:** fix AngularJsUrlCodec to support Safari ([#32959](https://github.com/angular/angular/issues/32959)) ([39e8ceb](https://github.com/angular/angular/commit/39e8ceb))
|
* **upgrade:** fix AngularJsUrlCodec to support Safari ([#32959](https://github.com/angular/angular/issues/32959)) ([39e8ceb](https://github.com/angular/angular/commit/39e8ceb))
|
||||||
* **ivy:** ensure `window.ng.getDebugNode` returns debug info for component elements ([#32780](https://github.com/angular/angular/issues/32780)) ([5651fa3](https://github.com/angular/angular/commit/5651fa3))
|
* **ivy:** ensure `window.ng.getDebugNode` returns debug info for component elements ([#32780](https://github.com/angular/angular/issues/32780)) ([5651fa3](https://github.com/angular/angular/commit/5651fa3))
|
||||||
* **ivy:** ensure multiple map-based bindings do not skip intermediate values ([#32774](https://github.com/angular/angular/issues/32774)) ([86fd571](https://github.com/angular/angular/commit/86fd571))
|
* **ivy:** ensure multiple map-based bindings do not skip intermediate values ([#32774](https://github.com/angular/angular/issues/32774)) ([86fd571](https://github.com/angular/angular/commit/86fd571))
|
||||||
@ -1689,7 +1464,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
* **ivy:** graceful evaluation of unknown or invalid expressions ([#33453](https://github.com/angular/angular/issues/33453)) ([ce30888](https://github.com/angular/angular/commit/ce30888))
|
* **ivy:** graceful evaluation of unknown or invalid expressions ([#33453](https://github.com/angular/angular/issues/33453)) ([ce30888](https://github.com/angular/angular/commit/ce30888))
|
||||||
* **ivy:** implement unknown element detection in jit mode ([#33419](https://github.com/angular/angular/issues/33419)) ([c83f501](https://github.com/angular/angular/commit/c83f501))
|
* **ivy:** implement unknown element detection in jit mode ([#33419](https://github.com/angular/angular/issues/33419)) ([c83f501](https://github.com/angular/angular/commit/c83f501))
|
||||||
* add a flag in bootstrap to enable coalesce event change detection to improve performance ([#30533](https://github.com/angular/angular/issues/30533)) ([44623a1](https://github.com/angular/angular/commit/44623a1))
|
* add a flag in bootstrap to enable coalesce event change detection to improve performance ([#30533](https://github.com/angular/angular/issues/30533)) ([44623a1](https://github.com/angular/angular/commit/44623a1))
|
||||||
* **bazel:** update [@bazel](https://github.com/bazel)/schematics to Bazel 1.0.0 ([#33476](https://github.com/angular/angular/issues/33476)) ([540d104](https://github.com/angular/angular/commit/540d104)), closes [/github.com/angular/angular/pull/33367#issuecomment-547643246](https://github.com/angular/angular/pull/33367/issues/issuecomment-547643246)
|
* **bazel:** update [@bazel](https://github.com/bazel)/schematics to Bazel 1.0.0 ([#33476](https://github.com/angular/angular/issues/33476)) ([540d104](https://github.com/angular/angular/commit/540d104)), closes [/github.com/angular/angular/pull/33367#issuecomment-547643246](https://github.com/angular/angular/pull/33367#issuecomment-547643246)
|
||||||
* **bazel:** update bazel-schematics to use Ivy and new rollup_bundle ([#33435](https://github.com/angular/angular/issues/33435)) ([bf913cc](https://github.com/angular/angular/commit/bf913cc))
|
* **bazel:** update bazel-schematics to use Ivy and new rollup_bundle ([#33435](https://github.com/angular/angular/issues/33435)) ([bf913cc](https://github.com/angular/angular/commit/bf913cc))
|
||||||
* **ivy:** i18n - support inlining of XTB formatted translation files ([#33444](https://github.com/angular/angular/issues/33444)) ([2c623fd](https://github.com/angular/angular/commit/2c623fd))
|
* **ivy:** i18n - support inlining of XTB formatted translation files ([#33444](https://github.com/angular/angular/issues/33444)) ([2c623fd](https://github.com/angular/angular/commit/2c623fd))
|
||||||
* **language-service:** add support for text replacement ([#33091](https://github.com/angular/angular/issues/33091)) ([da4eb91](https://github.com/angular/angular/commit/da4eb91))
|
* **language-service:** add support for text replacement ([#33091](https://github.com/angular/angular/issues/33091)) ([da4eb91](https://github.com/angular/angular/commit/da4eb91))
|
||||||
@ -1731,7 +1506,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
* **ivy:** i18n - implement compile-time inlining ([#32881](https://github.com/angular/angular/issues/32881)) ([2cdb3a0](https://github.com/angular/angular/commit/2cdb3a0))
|
* **ivy:** i18n - implement compile-time inlining ([#32881](https://github.com/angular/angular/issues/32881)) ([2cdb3a0](https://github.com/angular/angular/commit/2cdb3a0))
|
||||||
* **ivy:** i18n - render legacy message ids in `$localize` if requested ([#32937](https://github.com/angular/angular/issues/32937)) ([bcbf3e4](https://github.com/angular/angular/commit/bcbf3e4))
|
* **ivy:** i18n - render legacy message ids in `$localize` if requested ([#32937](https://github.com/angular/angular/issues/32937)) ([bcbf3e4](https://github.com/angular/angular/commit/bcbf3e4))
|
||||||
* **language-service:** module definitions on directive hover ([#32763](https://github.com/angular/angular/issues/32763)) ([0d186dd](https://github.com/angular/angular/commit/0d186dd)), closes [#32565](https://github.com/angular/angular/issues/32565)
|
* **language-service:** module definitions on directive hover ([#32763](https://github.com/angular/angular/issues/32763)) ([0d186dd](https://github.com/angular/angular/commit/0d186dd)), closes [#32565](https://github.com/angular/angular/issues/32565)
|
||||||
* **ngcc:** expose `--create-ivy-entry-points` option on ivy-ngcc ([#33049](https://github.com/angular/angular/issues/33049)) ([b2b917d](https://github.com/angular/angular/commit/b2b917d)), closes [/github.com/angular/angular/pull/32999#issuecomment-539937368](https://github.com/angular/angular/pull/32999/issues/issuecomment-539937368)
|
* **ngcc:** expose `--create-ivy-entry-points` option on ivy-ngcc ([#33049](https://github.com/angular/angular/issues/33049)) ([b2b917d](https://github.com/angular/angular/commit/b2b917d)), closes [/github.com/angular/angular/pull/32999#issuecomment-539937368](https://github.com/angular/angular/pull/32999#issuecomment-539937368)
|
||||||
* update rxjs peerDependencies minimum requirment to 6.5.3 ([#32812](https://github.com/angular/angular/issues/32812)) ([66658c4](https://github.com/angular/angular/commit/66658c4))
|
* update rxjs peerDependencies minimum requirment to 6.5.3 ([#32812](https://github.com/angular/angular/issues/32812)) ([66658c4](https://github.com/angular/angular/commit/66658c4))
|
||||||
* **ivy:** support ng-add in localize package ([#32791](https://github.com/angular/angular/issues/32791)) ([e41cbfb](https://github.com/angular/angular/commit/e41cbfb))
|
* **ivy:** support ng-add in localize package ([#32791](https://github.com/angular/angular/issues/32791)) ([e41cbfb](https://github.com/angular/angular/commit/e41cbfb))
|
||||||
* **language-service:** allow retreiving synchronized analyzed NgModules ([#32779](https://github.com/angular/angular/issues/32779)) ([98feee7](https://github.com/angular/angular/commit/98feee7))
|
* **language-service:** allow retreiving synchronized analyzed NgModules ([#32779](https://github.com/angular/angular/issues/32779)) ([98feee7](https://github.com/angular/angular/commit/98feee7))
|
||||||
@ -2110,6 +1885,7 @@ This release contains various API docs improvements.
|
|||||||
* **language-service:** Eagarly initialize data members ([#31577](https://github.com/angular/angular/issues/31577)) ([0110de2](https://github.com/angular/angular/commit/0110de2))
|
* **language-service:** Eagarly initialize data members ([#31577](https://github.com/angular/angular/issues/31577)) ([0110de2](https://github.com/angular/angular/commit/0110de2))
|
||||||
* **bazel:** revert location of xi18n outputs to bazel-genfiles ([#31410](https://github.com/angular/angular/issues/31410)) ([1d3e227](https://github.com/angular/angular/commit/1d3e227))
|
* **bazel:** revert location of xi18n outputs to bazel-genfiles ([#31410](https://github.com/angular/angular/issues/31410)) ([1d3e227](https://github.com/angular/angular/commit/1d3e227))
|
||||||
* **compiler:** give ASTWithSource its own visit method ([#31347](https://github.com/angular/angular/issues/31347)) ([6aaca21](https://github.com/angular/angular/commit/6aaca21))
|
* **compiler:** give ASTWithSource its own visit method ([#31347](https://github.com/angular/angular/issues/31347)) ([6aaca21](https://github.com/angular/angular/commit/6aaca21))
|
||||||
|
* **core:** handle `undefined` meta in `injectArgs` ([#31333](https://github.com/angular/angular/issues/31333)) ([80ccd6c](https://github.com/angular/angular/commit/80ccd6c)), closes [CLI #14888](https://github.com/angular/angular-cli/issues/14888)
|
||||||
* **service-worker:** cache opaque responses in data groups with `freshness` strategy ([#30977](https://github.com/angular/angular/issues/30977)) ([d7be38f](https://github.com/angular/angular/commit/d7be38f)), closes [#30968](https://github.com/angular/angular/issues/30968)
|
* **service-worker:** cache opaque responses in data groups with `freshness` strategy ([#30977](https://github.com/angular/angular/issues/30977)) ([d7be38f](https://github.com/angular/angular/commit/d7be38f)), closes [#30968](https://github.com/angular/angular/issues/30968)
|
||||||
* **service-worker:** cache opaque responses when requests exceeds timeout threshold ([#30977](https://github.com/angular/angular/issues/30977)) ([93abc35](https://github.com/angular/angular/commit/93abc35))
|
* **service-worker:** cache opaque responses when requests exceeds timeout threshold ([#30977](https://github.com/angular/angular/issues/30977)) ([93abc35](https://github.com/angular/angular/commit/93abc35))
|
||||||
|
|
||||||
@ -2139,6 +1915,7 @@ This release contains various API docs improvements.
|
|||||||
|
|
||||||
* use the correct WTF array to iterate over ([#31208](https://github.com/angular/angular/issues/31208)) ([4aed480](https://github.com/angular/angular/commit/4aed480))
|
* use the correct WTF array to iterate over ([#31208](https://github.com/angular/angular/issues/31208)) ([4aed480](https://github.com/angular/angular/commit/4aed480))
|
||||||
* **compiler-cli:** Return original sourceFile instead of redirected sourceFile from getSourceFile ([#26036](https://github.com/angular/angular/issues/26036)) ([13dbb98](https://github.com/angular/angular/commit/13dbb98)), closes [#22524](https://github.com/angular/angular/issues/22524)
|
* **compiler-cli:** Return original sourceFile instead of redirected sourceFile from getSourceFile ([#26036](https://github.com/angular/angular/issues/26036)) ([13dbb98](https://github.com/angular/angular/commit/13dbb98)), closes [#22524](https://github.com/angular/angular/issues/22524)
|
||||||
|
* **core:** export provider interfaces that are part of the public API types ([#31377](https://github.com/angular/angular/issues/31377)) ([bebf089](https://github.com/angular/angular/commit/bebf089)), closes [/github.com/angular/angular/pull/31377#discussion_r299254408](https://github.com/angular/angular/pull/31377/issues/discussion_r299254408) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L365-L366](https://github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L365-L366) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts#L283-L284](https://github.com/angular/angular/blob/9e34670b2/packages/core/src/di/interface/provider.ts/issues/L283-L284) [/github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts#L23](https://github.com/angular/angular/blob/9e34670b2/packages/core/src/di/index.ts/issues/L23)
|
||||||
|
|
||||||
|
|
||||||
<a name="8.1.1"></a>
|
<a name="8.1.1"></a>
|
||||||
@ -2316,6 +2093,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
### Features
|
### Features
|
||||||
|
|
||||||
* add support for TypeScript 3.4 (and drop older versions) ([#29372](https://github.com/angular/angular/issues/29372)) ([ef85336](https://github.com/angular/angular/commit/ef85336))
|
* add support for TypeScript 3.4 (and drop older versions) ([#29372](https://github.com/angular/angular/issues/29372)) ([ef85336](https://github.com/angular/angular/commit/ef85336))
|
||||||
|
* **common:** add ability to watch for AngularJS URL updates through `onUrlChange` hook ([#30466](https://github.com/angular/angular/issues/30466)) ([8022d36](https://github.com/angular/angular/commit/8022d36))
|
||||||
* **common:** stricter types for `SlicePipe` ([#30156](https://github.com/angular/angular/issues/30156)) ([722b2fa](https://github.com/angular/angular/commit/722b2fa))
|
* **common:** stricter types for `SlicePipe` ([#30156](https://github.com/angular/angular/issues/30156)) ([722b2fa](https://github.com/angular/angular/commit/722b2fa))
|
||||||
* **bazel:** use `rbe_autoconfig()` and new container ([#29336](https://github.com/angular/angular/issues/29336)) ([e562acc](https://github.com/angular/angular/commit/e562acc))
|
* **bazel:** use `rbe_autoconfig()` and new container ([#29336](https://github.com/angular/angular/issues/29336)) ([e562acc](https://github.com/angular/angular/commit/e562acc))
|
||||||
* **common:** add @angular/common/upgrade package for `$location`-related APIs ([#30055](https://github.com/angular/angular/issues/30055)) ([152d99e](https://github.com/angular/angular/commit/152d99e))
|
* **common:** add @angular/common/upgrade package for `$location`-related APIs ([#30055](https://github.com/angular/angular/issues/30055)) ([152d99e](https://github.com/angular/angular/commit/152d99e))
|
||||||
@ -2432,6 +2210,8 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
* **bazel:** use `//:tsconfig.json` as the default for `ng_module` ([#29670](https://github.com/angular/angular/issues/29670)) ([b14537a](https://github.com/angular/angular/commit/b14537a))
|
* **bazel:** use `//:tsconfig.json` as the default for `ng_module` ([#29670](https://github.com/angular/angular/issues/29670)) ([b14537a](https://github.com/angular/angular/commit/b14537a))
|
||||||
* **compiler-cli:** ngcc - cope with processing entry-points multiple times ([#29657](https://github.com/angular/angular/issues/29657)) ([6b39c9c](https://github.com/angular/angular/commit/6b39c9c))
|
* **compiler-cli:** ngcc - cope with processing entry-points multiple times ([#29657](https://github.com/angular/angular/issues/29657)) ([6b39c9c](https://github.com/angular/angular/commit/6b39c9c))
|
||||||
* **core:** static-query schematic should detect static queries in getters. ([#29609](https://github.com/angular/angular/issues/29609)) ([33016b8](https://github.com/angular/angular/commit/33016b8))
|
* **core:** static-query schematic should detect static queries in getters. ([#29609](https://github.com/angular/angular/issues/29609)) ([33016b8](https://github.com/angular/angular/commit/33016b8))
|
||||||
|
* **common:** escape query selector used when anchor scrolling ([#29577](https://github.com/angular/angular/issues/29577)) ([7671c73](https://github.com/angular/angular/commit/7671c73)), closes [#28193](https://github.com/angular/angular/issues/28193)
|
||||||
|
* **router:** adjust setting navigationTransition when a new navigation cancels an existing one ([#29636](https://github.com/angular/angular/issues/29636)) ([e884c0c](https://github.com/angular/angular/commit/e884c0c)), closes [#29389](https://github.com/angular/angular/issues/29389) [#29590](https://github.com/angular/angular/issues/29590)
|
||||||
* **bazel:** allow `ng_module` users to set `createExternalSymbolFactoryReexports` ([#29459](https://github.com/angular/angular/issues/29459)) ([21be0fb](https://github.com/angular/angular/commit/21be0fb))
|
* **bazel:** allow `ng_module` users to set `createExternalSymbolFactoryReexports` ([#29459](https://github.com/angular/angular/issues/29459)) ([21be0fb](https://github.com/angular/angular/commit/21be0fb))
|
||||||
* **bazel:** workaround problem reading summary files from node_modules ([#29459](https://github.com/angular/angular/issues/29459)) ([769d960](https://github.com/angular/angular/commit/769d960))
|
* **bazel:** workaround problem reading summary files from node_modules ([#29459](https://github.com/angular/angular/issues/29459)) ([769d960](https://github.com/angular/angular/commit/769d960))
|
||||||
* **compiler:** inherit param types when class has a constructor which takes no declared parameters and delegates up ([#29232](https://github.com/angular/angular/issues/29232)) ([0007564](https://github.com/angular/angular/commit/0007564))
|
* **compiler:** inherit param types when class has a constructor which takes no declared parameters and delegates up ([#29232](https://github.com/angular/angular/issues/29232)) ([0007564](https://github.com/angular/angular/commit/0007564))
|
||||||
@ -2458,7 +2238,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
* **platform-server:** update minimum domino version to latest released ([#28893](https://github.com/angular/angular/issues/28893)) ([79e2ca0](https://github.com/angular/angular/commit/79e2ca0))
|
* **platform-server:** update minimum domino version to latest released ([#28893](https://github.com/angular/angular/issues/28893)) ([79e2ca0](https://github.com/angular/angular/commit/79e2ca0))
|
||||||
* **router:** removed obsolete TODO comment ([#29085](https://github.com/angular/angular/issues/29085)) ([72ecc45](https://github.com/angular/angular/commit/72ecc45))
|
* **router:** removed obsolete TODO comment ([#29085](https://github.com/angular/angular/issues/29085)) ([72ecc45](https://github.com/angular/angular/commit/72ecc45))
|
||||||
* **service-worker:** detect new version even if files are identical to an old one ([#26006](https://github.com/angular/angular/issues/26006)) ([586234b](https://github.com/angular/angular/commit/586234b)), closes [#24338](https://github.com/angular/angular/issues/24338)
|
* **service-worker:** detect new version even if files are identical to an old one ([#26006](https://github.com/angular/angular/issues/26006)) ([586234b](https://github.com/angular/angular/commit/586234b)), closes [#24338](https://github.com/angular/angular/issues/24338)
|
||||||
* **service-worker:** ignore passive mixed content requests ([#25994](https://github.com/angular/angular/issues/25994)) ([48214e2](https://github.com/angular/angular/commit/48214e2)), closes [/github.com/angular/angular/issues/23012#issuecomment-376430187](https://github.com/angular/angular/issues/23012/issues/issuecomment-376430187) [#23012](https://github.com/angular/angular/issues/23012)
|
* **service-worker:** ignore passive mixed content requests ([#25994](https://github.com/angular/angular/issues/25994)) ([48214e2](https://github.com/angular/angular/commit/48214e2)), closes [23012#issuecomment-376430187](https://github.com/angular/angular/issues/23012#issuecomment-376430187) [#23012](https://github.com/angular/angular/issues/23012)
|
||||||
* **bazel:** Pin browsers for schematics ([#28913](https://github.com/angular/angular/issues/28913)) ([1145bdb](https://github.com/angular/angular/commit/1145bdb))
|
* **bazel:** Pin browsers for schematics ([#28913](https://github.com/angular/angular/issues/28913)) ([1145bdb](https://github.com/angular/angular/commit/1145bdb))
|
||||||
* **bazel:** rxjs_umd_modules should always be present ([#28881](https://github.com/angular/angular/issues/28881)) ([9ae14db](https://github.com/angular/angular/commit/9ae14db))
|
* **bazel:** rxjs_umd_modules should always be present ([#28881](https://github.com/angular/angular/issues/28881)) ([9ae14db](https://github.com/angular/angular/commit/9ae14db))
|
||||||
* **compiler:** use correct variable in invalid function ([#28656](https://github.com/angular/angular/issues/28656)) ([f75acbd](https://github.com/angular/angular/commit/f75acbd))
|
* **compiler:** use correct variable in invalid function ([#28656](https://github.com/angular/angular/issues/28656)) ([f75acbd](https://github.com/angular/angular/commit/f75acbd))
|
||||||
@ -2520,6 +2300,7 @@ To learn about the release highlights and our CLI-powered automated update workf
|
|||||||
|
|
||||||
* **core:** deprecate integration with the Web Tracing Framework (WTF) ([#30642](https://github.com/angular/angular/issues/30642)) ([b408445](https://github.com/angular/angular/commit/b408445))
|
* **core:** deprecate integration with the Web Tracing Framework (WTF) ([#30642](https://github.com/angular/angular/issues/30642)) ([b408445](https://github.com/angular/angular/commit/b408445))
|
||||||
* **platform-webworker:** deprecate platform-webworker ([#30642](https://github.com/angular/angular/issues/30642)) ([361f181](https://github.com/angular/angular/commit/361f181))
|
* **platform-webworker:** deprecate platform-webworker ([#30642](https://github.com/angular/angular/issues/30642)) ([361f181](https://github.com/angular/angular/commit/361f181))
|
||||||
|
* `TestBed.get()` has two signatures, one which is typed and another which accepts and returns `any`. The signature for `any` is deprecated; all usage of `TestBed.get()` should go through the typed API. This mainly affects string tokens
|
||||||
(which aren't supported) and abstract class tokens.
|
(which aren't supported) and abstract class tokens.
|
||||||
|
|
||||||
Before:
|
Before:
|
||||||
@ -2672,7 +2453,7 @@ This release contains various API docs improvements.
|
|||||||
* **animations:** ensure `position` and `display` styles are handled outside of keyframes/web-animations ([#28911](https://github.com/angular/angular/issues/28911)) ([86981b3](https://github.com/angular/angular/commit/86981b3)), closes [#24923](https://github.com/angular/angular/issues/24923) [#25635](https://github.com/angular/angular/issues/25635)
|
* **animations:** ensure `position` and `display` styles are handled outside of keyframes/web-animations ([#28911](https://github.com/angular/angular/issues/28911)) ([86981b3](https://github.com/angular/angular/commit/86981b3)), closes [#24923](https://github.com/angular/angular/issues/24923) [#25635](https://github.com/angular/angular/issues/25635)
|
||||||
* **router:** removed obsolete TODO comment ([#29085](https://github.com/angular/angular/issues/29085)) ([2a25ac2](https://github.com/angular/angular/commit/2a25ac2))
|
* **router:** removed obsolete TODO comment ([#29085](https://github.com/angular/angular/issues/29085)) ([2a25ac2](https://github.com/angular/angular/commit/2a25ac2))
|
||||||
* **service-worker:** detect new version even if files are identical to an old one ([#26006](https://github.com/angular/angular/issues/26006)) ([5669333](https://github.com/angular/angular/commit/5669333)), closes [#24338](https://github.com/angular/angular/issues/24338)
|
* **service-worker:** detect new version even if files are identical to an old one ([#26006](https://github.com/angular/angular/issues/26006)) ([5669333](https://github.com/angular/angular/commit/5669333)), closes [#24338](https://github.com/angular/angular/issues/24338)
|
||||||
* **service-worker:** ignore passive mixed content requests ([#25994](https://github.com/angular/angular/issues/25994)) ([b598e88](https://github.com/angular/angular/commit/b598e88)), closes [/github.com/angular/angular/issues/23012#issuecomment-376430187](https://github.com/angular/angular/issues/23012/issues/issuecomment-376430187) [#23012](https://github.com/angular/angular/issues/23012)
|
* **service-worker:** ignore passive mixed content requests ([#25994](https://github.com/angular/angular/issues/25994)) ([b598e88](https://github.com/angular/angular/commit/b598e88)), closes [23012#issuecomment-376430187](https://github.com/angular/angular/issues/23012#issuecomment-376430187) [#23012](https://github.com/angular/angular/issues/23012)
|
||||||
|
|
||||||
|
|
||||||
<a name="7.2.7"></a>
|
<a name="7.2.7"></a>
|
||||||
@ -2768,6 +2549,14 @@ This release contains various API docs improvements.
|
|||||||
# [8.0.0-beta.0](https://github.com/angular/angular/compare/7.2.0...8.0.0-beta.0) (2019-01-16)
|
# [8.0.0-beta.0](https://github.com/angular/angular/compare/7.2.0...8.0.0-beta.0) (2019-01-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
### Performance Improvements
|
||||||
|
|
||||||
|
|
||||||
@ -2915,9 +2704,42 @@ This release contains various API docs improvements.
|
|||||||
# [7.1.0](https://github.com/angular/angular/compare/7.1.0-rc.0...7.1.0) (2018-11-21)
|
# [7.1.0](https://github.com/angular/angular/compare/7.1.0-rc.0...7.1.0) (2018-11-21)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **core:** allow null value for renderer setElement(…) ([#17065](https://github.com/angular/angular/issues/17065)) ([ff15043](https://github.com/angular/angular/commit/ff15043)), closes [#13686](https://github.com/angular/angular/issues/13686)
|
||||||
|
* **router:** fix regression where navigateByUrl promise didn't resolve on CanLoad failure ([#26455](https://github.com/angular/angular/issues/26455)) ([1c9b065](https://github.com/angular/angular/commit/1c9b065)), closes [#26284](https://github.com/angular/angular/issues/26284)
|
||||||
|
* **service-worker:** clean up caches from old SW versions ([#26319](https://github.com/angular/angular/issues/26319)) ([2326b9c](https://github.com/angular/angular/commit/2326b9c))
|
||||||
|
* **upgrade:** properly destroy upgraded component elements and descendants ([#26209](https://github.com/angular/angular/issues/26209)) ([071934e](https://github.com/angular/angular/commit/071934e)), closes [#26208](https://github.com/angular/angular/issues/26208)
|
||||||
|
* **compiler:** generate inputs with aliases properly ([#26774](https://github.com/angular/angular/issues/26774)) ([19fcfc3](https://github.com/angular/angular/commit/19fcfc3))
|
||||||
|
* **compiler:** generate relative paths only in summary file errors ([#26759](https://github.com/angular/angular/issues/26759)) ([56f44be](https://github.com/angular/angular/commit/56f44be))
|
||||||
|
* **core:** ignore comment nodes under unsafe elements ([#25879](https://github.com/angular/angular/issues/25879)) ([d5cbcef](https://github.com/angular/angular/commit/d5cbcef))
|
||||||
|
* **core:** Remove static dependency from @angular/core to @angular/compiler ([#26734](https://github.com/angular/angular/issues/26734)) ([d042c4a](https://github.com/angular/angular/commit/d042c4a))
|
||||||
|
* **core:** support computed base class in metadata inheritance ([#24014](https://github.com/angular/angular/issues/24014)) ([95743e3](https://github.com/angular/angular/commit/95743e3))
|
||||||
|
* **bazel:** unknown replay compiler error in windows ([#26711](https://github.com/angular/angular/issues/26711)) ([aed95fd](https://github.com/angular/angular/commit/aed95fd))
|
||||||
|
* **core:** ensure that `ɵdefineNgModule` is available in flat-file formats ([#26403](https://github.com/angular/angular/issues/26403)) ([a64859b](https://github.com/angular/angular/commit/a64859b))
|
||||||
|
* **router:** remove type bludgeoning of context and outlet when running CanDeactivate ([#26496](https://github.com/angular/angular/issues/26496)) ([496372d](https://github.com/angular/angular/commit/496372d)), closes [#18253](https://github.com/angular/angular/issues/18253)
|
||||||
|
* **service-worker:** add typing to public api guard and fix lint errors ([#25860](https://github.com/angular/angular/issues/25860)) ([1061875](https://github.com/angular/angular/commit/1061875))
|
||||||
|
* **upgrade:** improve downgrading-related error messages ([#26217](https://github.com/angular/angular/issues/26217)) ([7dbc103](https://github.com/angular/angular/commit/7dbc103))
|
||||||
|
* **upgrade:** make typings compatible with older AngularJS typings ([#26880](https://github.com/angular/angular/issues/26880)) ([64647af](https://github.com/angular/angular/commit/64647af)), closes [#26420](https://github.com/angular/angular/issues/26420)
|
||||||
|
* **compiler-cli:** add missing tslib dependency ([#27063](https://github.com/angular/angular/issues/27063)) ([c31e78f](https://github.com/angular/angular/commit/c31e78f))
|
||||||
|
* **compiler-cli:** only pass canonical genfile paths to compiler host ([#27062](https://github.com/angular/angular/issues/27062)) ([0ada23a](https://github.com/angular/angular/commit/0ada23a))
|
||||||
|
* **router:** add `relativeLinkResolution` to `recognize` operator ([#26990](https://github.com/angular/angular/issues/26990)) ([a752971](https://github.com/angular/angular/commit/a752971)), closes [#26983](https://github.com/angular/angular/issues/26983)
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* **bazel:** Bazel workspace schematics ([#26971](https://github.com/angular/angular/issues/26971)) ([b07bd30](https://github.com/angular/angular/commit/b07bd30))
|
* **bazel:** Bazel workspace schematics ([#26971](https://github.com/angular/angular/issues/26971)) ([b07bd30](https://github.com/angular/angular/commit/b07bd30))
|
||||||
|
* **router:** add prioritizedGuardValue operator optimization and allowing UrlTree return from guard ([#26478](https://github.com/angular/angular/issues/26478)) ([fdfedce](https://github.com/angular/angular/commit/fdfedce))
|
||||||
|
* **compiler:** ability to mark an InvokeFunctionExpr as pure ([#26860](https://github.com/angular/angular/issues/26860)) ([4dfa71f](https://github.com/angular/angular/commit/4dfa71f))
|
||||||
|
* **forms:** add updateOn option to FormBuilder ([#24599](https://github.com/angular/angular/issues/24599)) ([e9e804f](https://github.com/angular/angular/commit/e9e804f))
|
||||||
|
* **router:** allow guards to return UrlTree as well as boolean ([#26521](https://github.com/angular/angular/issues/26521)) ([081f95c](https://github.com/angular/angular/commit/081f95c))
|
||||||
|
* **router:** allow redirect from guards by returning UrlTree ([#26521](https://github.com/angular/angular/issues/26521)) ([152ca66](https://github.com/angular/angular/commit/152ca66))
|
||||||
|
* **router:** guard returning UrlTree cancels current navigation and redirects ([#26521](https://github.com/angular/angular/issues/26521)) ([4e9f2e5](https://github.com/angular/angular/commit/4e9f2e5)), closes [#24618](https://github.com/angular/angular/issues/24618)
|
||||||
|
* **service-worker:** add typing for messagesClicked in SwPush service ([#25860](https://github.com/angular/angular/issues/25860)) ([c78c221](https://github.com/angular/angular/commit/c78c221))
|
||||||
|
* **service-worker:** close notifications and focus window on click ([#25860](https://github.com/angular/angular/issues/25860)) ([f5d5a3d](https://github.com/angular/angular/commit/f5d5a3d))
|
||||||
|
* **service-worker:** handle 'notificationclick' events ([#25860](https://github.com/angular/angular/issues/25860)) ([cf6ea28](https://github.com/angular/angular/commit/cf6ea28)), closes [#20956](https://github.com/angular/angular/issues/20956) [#22311](https://github.com/angular/angular/issues/22311)
|
||||||
|
* **upgrade:** support downgrading multiple modules ([#26217](https://github.com/angular/angular/issues/26217)) ([93837e9](https://github.com/angular/angular/commit/93837e9)), closes [#26062](https://github.com/angular/angular/issues/26062)
|
||||||
|
* **router:** add pathParamsChange mode for runGuardsAndResolvers ([#26861](https://github.com/angular/angular/issues/26861)) ([bf6ac6c](https://github.com/angular/angular/commit/bf6ac6c)), closes [#18253](https://github.com/angular/angular/issues/18253)
|
||||||
|
|
||||||
|
|
||||||
<a name="7.1.0-rc.0"></a>
|
<a name="7.1.0-rc.0"></a>
|
||||||
@ -3020,7 +2842,10 @@ This release contains various API docs improvements.
|
|||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
* **core:** allow null value for renderer setElement(…) ([#17065](https://github.com/angular/angular/issues/17065)) ([ff15043](https://github.com/angular/angular/commit/ff15043)), closes [#13686](https://github.com/angular/angular/issues/13686)
|
||||||
|
* **router:** fix regression where navigateByUrl promise didn't resolve on CanLoad failure ([#26455](https://github.com/angular/angular/issues/26455)) ([1c9b065](https://github.com/angular/angular/commit/1c9b065)), closes [#26284](https://github.com/angular/angular/issues/26284)
|
||||||
* **service-worker:** clean up caches from old SW versions ([#26319](https://github.com/angular/angular/issues/26319)) ([2326b9c](https://github.com/angular/angular/commit/2326b9c))
|
* **service-worker:** clean up caches from old SW versions ([#26319](https://github.com/angular/angular/issues/26319)) ([2326b9c](https://github.com/angular/angular/commit/2326b9c))
|
||||||
|
* **upgrade:** properly destroy upgraded component elements and descendants ([#26209](https://github.com/angular/angular/issues/26209)) ([071934e](https://github.com/angular/angular/commit/071934e)), closes [#26208](https://github.com/angular/angular/issues/26208)
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
@ -3192,6 +3017,7 @@ Note: the 6.1.5 release on npm accidentally glitched-out midway, so we cut 6.1.6
|
|||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **animations:** always render end-state styles for orphaned DOM nodes ([#24236](https://github.com/angular/angular/issues/24236)) ([dc4a3d0](https://github.com/angular/angular/commit/dc4a3d0))
|
* **animations:** always render end-state styles for orphaned DOM nodes ([#24236](https://github.com/angular/angular/issues/24236)) ([dc4a3d0](https://github.com/angular/angular/commit/dc4a3d0))
|
||||||
|
* **animations:** set animations styles properly on platform-server ([#24624](https://github.com/angular/angular/issues/24624)) ([0b356d4](https://github.com/angular/angular/commit/0b356d4))
|
||||||
* **animations:** do not throw errors when a destroyed component is animated ([#23836](https://github.com/angular/angular/issues/23836)) ([d2a8687](https://github.com/angular/angular/commit/d2a8687))
|
* **animations:** do not throw errors when a destroyed component is animated ([#23836](https://github.com/angular/angular/issues/23836)) ([d2a8687](https://github.com/angular/angular/commit/d2a8687))
|
||||||
* **animations:** Fix browser detection logic ([#24188](https://github.com/angular/angular/issues/24188)) ([b492b9e](https://github.com/angular/angular/commit/b492b9e))
|
* **animations:** Fix browser detection logic ([#24188](https://github.com/angular/angular/issues/24188)) ([b492b9e](https://github.com/angular/angular/commit/b492b9e))
|
||||||
* **animations:** properly clean up queried element styles in safari/edge ([#23633](https://github.com/angular/angular/issues/23633)) ([da9ff25](https://github.com/angular/angular/commit/da9ff25))
|
* **animations:** properly clean up queried element styles in safari/edge ([#23633](https://github.com/angular/angular/issues/23633)) ([da9ff25](https://github.com/angular/angular/commit/da9ff25))
|
||||||
@ -3203,6 +3029,7 @@ Note: the 6.1.5 release on npm accidentally glitched-out midway, so we cut 6.1.6
|
|||||||
* **common:** format fractional seconds ([#24844](https://github.com/angular/angular/issues/24844)) ([0b4d85e](https://github.com/angular/angular/commit/0b4d85e)), closes [#24831](https://github.com/angular/angular/issues/24831)
|
* **common:** format fractional seconds ([#24844](https://github.com/angular/angular/issues/24844)) ([0b4d85e](https://github.com/angular/angular/commit/0b4d85e)), closes [#24831](https://github.com/angular/angular/issues/24831)
|
||||||
* **common:** properly update collection reference in NgForOf ([#24684](https://github.com/angular/angular/issues/24684)) ([ff84c5c](https://github.com/angular/angular/commit/ff84c5c)), closes [#24155](https://github.com/angular/angular/issues/24155)
|
* **common:** properly update collection reference in NgForOf ([#24684](https://github.com/angular/angular/issues/24684)) ([ff84c5c](https://github.com/angular/angular/commit/ff84c5c)), closes [#24155](https://github.com/angular/angular/issues/24155)
|
||||||
* **common:** use correct currency format for locale de-AT ([#24658](https://github.com/angular/angular/issues/24658)) ([dcabb05](https://github.com/angular/angular/commit/dcabb05)), closes [#24609](https://github.com/angular/angular/issues/24609)
|
* **common:** use correct currency format for locale de-AT ([#24658](https://github.com/angular/angular/issues/24658)) ([dcabb05](https://github.com/angular/angular/commit/dcabb05)), closes [#24609](https://github.com/angular/angular/issues/24609)
|
||||||
|
* **common:** use correct ICU plural for locale mk ([#24659](https://github.com/angular/angular/issues/24659)) ([64a8584](https://github.com/angular/angular/commit/64a8584))
|
||||||
* **compiler:** fix a few non-tree-shakeable code patterns ([#24677](https://github.com/angular/angular/issues/24677)) ([50d4a4f](https://github.com/angular/angular/commit/50d4a4f))
|
* **compiler:** fix a few non-tree-shakeable code patterns ([#24677](https://github.com/angular/angular/issues/24677)) ([50d4a4f](https://github.com/angular/angular/commit/50d4a4f))
|
||||||
* **compiler:** i18n_extractor now outputs the correct source file name ([#24885](https://github.com/angular/angular/issues/24885)) ([c8ad965](https://github.com/angular/angular/commit/c8ad965)), closes [#24884](https://github.com/angular/angular/issues/24884)
|
* **compiler:** i18n_extractor now outputs the correct source file name ([#24885](https://github.com/angular/angular/issues/24885)) ([c8ad965](https://github.com/angular/angular/commit/c8ad965)), closes [#24884](https://github.com/angular/angular/issues/24884)
|
||||||
* **compiler:** support `.` in import statements. ([#20634](https://github.com/angular/angular/issues/20634)) ([d8f7b29](https://github.com/angular/angular/commit/d8f7b29)), closes [#20363](https://github.com/angular/angular/issues/20363)
|
* **compiler:** support `.` in import statements. ([#20634](https://github.com/angular/angular/issues/20634)) ([d8f7b29](https://github.com/angular/angular/commit/d8f7b29)), closes [#20363](https://github.com/angular/angular/issues/20363)
|
||||||
@ -3238,6 +3065,7 @@ Note: the 6.1.5 release on npm accidentally glitched-out midway, so we cut 6.1.6
|
|||||||
* **service-worker:** don't include sourceMappingURL in ngsw-worker ([#24877](https://github.com/angular/angular/issues/24877)) ([8620373](https://github.com/angular/angular/commit/8620373)), closes [#23596](https://github.com/angular/angular/issues/23596)
|
* **service-worker:** don't include sourceMappingURL in ngsw-worker ([#24877](https://github.com/angular/angular/issues/24877)) ([8620373](https://github.com/angular/angular/commit/8620373)), closes [#23596](https://github.com/angular/angular/issues/23596)
|
||||||
* **service-worker:** avoid network requests when looking up hashed resources in cache ([#24127](https://github.com/angular/angular/issues/24127)) ([52d43a9](https://github.com/angular/angular/commit/52d43a9))
|
* **service-worker:** avoid network requests when looking up hashed resources in cache ([#24127](https://github.com/angular/angular/issues/24127)) ([52d43a9](https://github.com/angular/angular/commit/52d43a9))
|
||||||
* **service-worker:** fix `SwPush.unsubscribe()` ([#24162](https://github.com/angular/angular/issues/24162)) ([3ed2d75](https://github.com/angular/angular/commit/3ed2d75)), closes [#24095](https://github.com/angular/angular/issues/24095)
|
* **service-worker:** fix `SwPush.unsubscribe()` ([#24162](https://github.com/angular/angular/issues/24162)) ([3ed2d75](https://github.com/angular/angular/commit/3ed2d75)), closes [#24095](https://github.com/angular/angular/issues/24095)
|
||||||
|
* **service-worker:** add badge to NOTIFICATION_OPTION_NAMES ([#23241](https://github.com/angular/angular/issues/23241)) ([fb59b2d](https://github.com/angular/angular/commit/fb59b2d)), closes [#23196](https://github.com/angular/angular/issues/23196)
|
||||||
* **service-worker:** check platformBrowser before accessing navigator.serviceWorker ([#21231](https://github.com/angular/angular/issues/21231)) ([0bdd30e](https://github.com/angular/angular/commit/0bdd30e))
|
* **service-worker:** check platformBrowser before accessing navigator.serviceWorker ([#21231](https://github.com/angular/angular/issues/21231)) ([0bdd30e](https://github.com/angular/angular/commit/0bdd30e))
|
||||||
* **service-worker:** correctly handle requests with empty `clientId` ([#23625](https://github.com/angular/angular/issues/23625)) ([e0ed59e](https://github.com/angular/angular/commit/e0ed59e)), closes [#23526](https://github.com/angular/angular/issues/23526)
|
* **service-worker:** correctly handle requests with empty `clientId` ([#23625](https://github.com/angular/angular/issues/23625)) ([e0ed59e](https://github.com/angular/angular/commit/e0ed59e)), closes [#23526](https://github.com/angular/angular/issues/23526)
|
||||||
* **service-worker:** deprecate `versionedFiles` in asset-group resources ([#23584](https://github.com/angular/angular/issues/23584)) ([1d378e2](https://github.com/angular/angular/commit/1d378e2))
|
* **service-worker:** deprecate `versionedFiles` in asset-group resources ([#23584](https://github.com/angular/angular/issues/23584)) ([1d378e2](https://github.com/angular/angular/commit/1d378e2))
|
||||||
@ -3438,6 +3266,8 @@ To learn about the release highlights and our new CLI-powered update workflow fo
|
|||||||
* **forms:** multiple validators for array method ([#20766](https://github.com/angular/angular/issues/20766)) ([941e88f](https://github.com/angular/angular/commit/941e88f)), closes [#20665](https://github.com/angular/angular/issues/20665)
|
* **forms:** multiple validators for array method ([#20766](https://github.com/angular/angular/issues/20766)) ([941e88f](https://github.com/angular/angular/commit/941e88f)), closes [#20665](https://github.com/angular/angular/issues/20665)
|
||||||
* **forms:** allow markAsPending to emit events ([#20212](https://github.com/angular/angular/issues/20212)) ([e86b64b](https://github.com/angular/angular/commit/e86b64b)), closes [#17958](https://github.com/angular/angular/issues/17958)
|
* **forms:** allow markAsPending to emit events ([#20212](https://github.com/angular/angular/issues/20212)) ([e86b64b](https://github.com/angular/angular/commit/e86b64b)), closes [#17958](https://github.com/angular/angular/issues/17958)
|
||||||
* **platform-browser:** add token marking which the type of animation module nearest in the injector tree ([#23075](https://github.com/angular/angular/issues/23075)) ([b551f84](https://github.com/angular/angular/commit/b551f84))
|
* **platform-browser:** add token marking which the type of animation module nearest in the injector tree ([#23075](https://github.com/angular/angular/issues/23075)) ([b551f84](https://github.com/angular/angular/commit/b551f84))
|
||||||
|
* **platform-browser:** do not throw error when Hammer.js not loaded ([#22257](https://github.com/angular/angular/issues/22257)) ([991300b](https://github.com/angular/angular/commit/991300b)), closes [#16992](https://github.com/angular/angular/issues/16992)
|
||||||
|
* **platform-browser:** fix [#19604](https://github.com/angular/angular/issues/19604), can config hammerOptions ([#21979](https://github.com/angular/angular/issues/21979)) ([1d571b2](https://github.com/angular/angular/commit/1d571b2))
|
||||||
* **platform-server:** bump Domino to v2.0 ([#22411](https://github.com/angular/angular/issues/22411)) ([d3827a0](https://github.com/angular/angular/commit/d3827a0))
|
* **platform-server:** bump Domino to v2.0 ([#22411](https://github.com/angular/angular/issues/22411)) ([d3827a0](https://github.com/angular/angular/commit/d3827a0))
|
||||||
* **router:** add navigationSource and restoredState to NavigationStart event ([#21728](https://github.com/angular/angular/issues/21728)) ([c40ae7f](https://github.com/angular/angular/commit/c40ae7f))
|
* **router:** add navigationSource and restoredState to NavigationStart event ([#21728](https://github.com/angular/angular/issues/21728)) ([c40ae7f](https://github.com/angular/angular/commit/c40ae7f))
|
||||||
* **service-worker:** add support for configuring navigations URLs ([#23339](https://github.com/angular/angular/issues/23339)) ([08325aa](https://github.com/angular/angular/commit/08325aa)), closes [#20404](https://github.com/angular/angular/issues/20404)
|
* **service-worker:** add support for configuring navigations URLs ([#23339](https://github.com/angular/angular/issues/23339)) ([08325aa](https://github.com/angular/angular/commit/08325aa)), closes [#20404](https://github.com/angular/angular/issues/20404)
|
||||||
@ -3656,7 +3486,12 @@ To learn about the release highlights and our new CLI-powered update workflow fo
|
|||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **platform-server:** generate correct stylings for camel case names ([#22263](https://github.com/angular/angular/issues/22263)) ([de02a7a](https://github.com/angular/angular/commit/de02a7a)), closes [#19235](https://github.com/angular/angular/issues/19235)
|
||||||
|
* **router:** don't mutate route configs ([#22358](https://github.com/angular/angular/issues/22358)) ([8f0a064](https://github.com/angular/angular/commit/8f0a064)), closes [#22203](https://github.com/angular/angular/issues/22203)
|
||||||
* **router:** fix URL serialization so special characters are only encoded where needed ([#22337](https://github.com/angular/angular/issues/22337)) ([789a47e](https://github.com/angular/angular/commit/789a47e)), closes [#10280](https://github.com/angular/angular/issues/10280)
|
* **router:** fix URL serialization so special characters are only encoded where needed ([#22337](https://github.com/angular/angular/issues/22337)) ([789a47e](https://github.com/angular/angular/commit/789a47e)), closes [#10280](https://github.com/angular/angular/issues/10280)
|
||||||
|
* **upgrade:** correctly destroy nested downgraded component ([#22400](https://github.com/angular/angular/issues/22400)) ([4aef9de](https://github.com/angular/angular/commit/4aef9de)), closes [#22392](https://github.com/angular/angular/issues/22392)
|
||||||
|
* **upgrade:** correctly handle `=` bindings in `@angular/upgrade` ([#22167](https://github.com/angular/angular/issues/22167)) ([6638390](https://github.com/angular/angular/commit/6638390))
|
||||||
|
* **upgrade:** fix empty transclusion content with AngularJS@>=1.5.8 ([#22167](https://github.com/angular/angular/issues/22167)) ([a9a0e27](https://github.com/angular/angular/commit/a9a0e27)), closes [#22175](https://github.com/angular/angular/issues/22175)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -4051,6 +3886,15 @@ Note: Due to an animation fix back in 5.1.1 ([c2b3792](https://github.com/angula
|
|||||||
<a name="5.1.0-beta.0"></a>
|
<a name="5.1.0-beta.0"></a>
|
||||||
# [5.1.0-beta.0](https://github.com/angular/angular/compare/5.0.0-rc.4...5.1.0-beta.0) (2017-11-08)
|
# [5.1.0-beta.0](https://github.com/angular/angular/compare/5.0.0-rc.4...5.1.0-beta.0) (2017-11-08)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **compiler:** don't overwrite missingTranslation's value in JIT ([#19952](https://github.com/angular/angular/issues/19952)) ([799cbb9](https://github.com/angular/angular/commit/799cbb9))
|
||||||
|
* **compiler:** report a reasonable error with invalid metadata ([#20062](https://github.com/angular/angular/issues/20062)) ([da22c48](https://github.com/angular/angular/commit/da22c48))
|
||||||
|
* **compiler-cli:** don't report emit diagnostics when `--noEmitOnError` is off ([#20063](https://github.com/angular/angular/issues/20063)) ([8639995](https://github.com/angular/angular/commit/8639995))
|
||||||
|
* **core:** `__symbol__` should return `__zone_symbol__` without zone.js loaded ([#19541](https://github.com/angular/angular/issues/19541)) ([678d1cf](https://github.com/angular/angular/commit/678d1cf))
|
||||||
|
* **core:** should support event.stopImmediatePropagation ([#19222](https://github.com/angular/angular/issues/19222)) ([7083791](https://github.com/angular/angular/commit/7083791))
|
||||||
|
* **platform-browser:** support Symbols in custom `jasmineToString()` method ([#19794](https://github.com/angular/angular/issues/19794)) ([5a6efa7](https://github.com/angular/angular/commit/5a6efa7))
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* **compiler:** introduce `TestBed.overrideTemplateUsingTestingModule` ([a460066](https://github.com/angular/angular/commit/a460066)), closes [#19815](https://github.com/angular/angular/issues/19815)
|
* **compiler:** introduce `TestBed.overrideTemplateUsingTestingModule` ([a460066](https://github.com/angular/angular/commit/a460066)), closes [#19815](https://github.com/angular/angular/issues/19815)
|
||||||
@ -4086,12 +3930,14 @@ Note: Due to an animation fix back in 5.1.1 ([c2b3792](https://github.com/angula
|
|||||||
* **compiler-cli:** add watch mode to `ngc` ([#18818](https://github.com/angular/angular/issues/18818)) ([06d01b2](https://github.com/angular/angular/commit/06d01b2))
|
* **compiler-cli:** add watch mode to `ngc` ([#18818](https://github.com/angular/angular/issues/18818)) ([06d01b2](https://github.com/angular/angular/commit/06d01b2))
|
||||||
* **compiler-cli:** lower metadata `useValue` and `data` literal fields ([#18905](https://github.com/angular/angular/issues/18905)) ([0e64261](https://github.com/angular/angular/commit/0e64261))
|
* **compiler-cli:** lower metadata `useValue` and `data` literal fields ([#18905](https://github.com/angular/angular/issues/18905)) ([0e64261](https://github.com/angular/angular/commit/0e64261))
|
||||||
* **compiler:** add representation of placeholders to xliff & xmb ([b3085e9](https://github.com/angular/angular/commit/b3085e9)), closes [#17345](https://github.com/angular/angular/issues/17345)
|
* **compiler:** add representation of placeholders to xliff & xmb ([b3085e9](https://github.com/angular/angular/commit/b3085e9)), closes [#17345](https://github.com/angular/angular/issues/17345)
|
||||||
|
* **compiler:** allow multiple exportAs names ([#18723](https://github.com/angular/angular/issues/18723)) ([7ec28fe](https://github.com/angular/angular/commit/7ec28fe))
|
||||||
* **compiler:** enabled strict checking of parameters to an `@Injectable` ([#19412](https://github.com/angular/angular/issues/19412)) ([dfb8d21](https://github.com/angular/angular/commit/dfb8d21))
|
* **compiler:** enabled strict checking of parameters to an `@Injectable` ([#19412](https://github.com/angular/angular/issues/19412)) ([dfb8d21](https://github.com/angular/angular/commit/dfb8d21))
|
||||||
* **compiler:** make `.ngsummary.json` files portable ([2572bf5](https://github.com/angular/angular/commit/2572bf5))
|
* **compiler:** make `.ngsummary.json` files portable ([2572bf5](https://github.com/angular/angular/commit/2572bf5))
|
||||||
* **compiler:** reuse the TypeScript typecheck for template typechecking. ([#19152](https://github.com/angular/angular/issues/19152)) ([996c7c2](https://github.com/angular/angular/commit/996c7c2))
|
* **compiler:** reuse the TypeScript typecheck for template typechecking. ([#19152](https://github.com/angular/angular/issues/19152)) ([996c7c2](https://github.com/angular/angular/commit/996c7c2))
|
||||||
* **compiler:** set `enableLegacyTemplate` to false by default ([#18756](https://github.com/angular/angular/issues/18756)) ([56238fe](https://github.com/angular/angular/commit/56238fe))
|
* **compiler:** set `enableLegacyTemplate` to false by default ([#18756](https://github.com/angular/angular/issues/18756)) ([56238fe](https://github.com/angular/angular/commit/56238fe))
|
||||||
* **compiler:** use typescript for resolving resource paths ([43226cb](https://github.com/angular/angular/commit/43226cb))
|
* **compiler:** use typescript for resolving resource paths ([43226cb](https://github.com/angular/angular/commit/43226cb))
|
||||||
* **core:** Create StaticInjector which does not depend on Reflect polyfill. ([d9d00bd](https://github.com/angular/angular/commit/d9d00bd))
|
* **core:** Create StaticInjector which does not depend on Reflect polyfill. ([d9d00bd](https://github.com/angular/angular/commit/d9d00bd))
|
||||||
|
* **core:** add option to remove blank text nodes from compiled templates ([#18823](https://github.com/angular/angular/issues/18823)) ([b8b551c](https://github.com/angular/angular/commit/b8b551c))
|
||||||
* **core:** support for bootstrap with custom zone ([#17672](https://github.com/angular/angular/issues/17672)) ([344a5ca](https://github.com/angular/angular/commit/344a5ca))
|
* **core:** support for bootstrap with custom zone ([#17672](https://github.com/angular/angular/issues/17672)) ([344a5ca](https://github.com/angular/angular/commit/344a5ca))
|
||||||
* **forms:** add default updateOn values for groups and arrays ([#18536](https://github.com/angular/angular/issues/18536)) ([ff5c58b](https://github.com/angular/angular/commit/ff5c58b))
|
* **forms:** add default updateOn values for groups and arrays ([#18536](https://github.com/angular/angular/issues/18536)) ([ff5c58b](https://github.com/angular/angular/commit/ff5c58b))
|
||||||
* **forms:** add options arg to abstract controls ([ebef5e6](https://github.com/angular/angular/commit/ebef5e6))
|
* **forms:** add options arg to abstract controls ([ebef5e6](https://github.com/angular/angular/commit/ebef5e6))
|
||||||
@ -4450,6 +4296,7 @@ Note: the 4.4.0 release on npm accidentally glitched-out midway, so we cut 4.4.1
|
|||||||
* **animations:** properly collect :enter nodes that exist within multi-level DOM trees ([40f77cb](https://github.com/angular/angular/commit/40f77cb)), closes [#17632](https://github.com/angular/angular/issues/17632)
|
* **animations:** properly collect :enter nodes that exist within multi-level DOM trees ([40f77cb](https://github.com/angular/angular/commit/40f77cb)), closes [#17632](https://github.com/angular/angular/issues/17632)
|
||||||
* **animations:** compute removal node height correctly ([185075d](https://github.com/angular/angular/commit/185075d))
|
* **animations:** compute removal node height correctly ([185075d](https://github.com/angular/angular/commit/185075d))
|
||||||
* **animations:** do not treat a `0` animation state as `void` ([451257a](https://github.com/angular/angular/commit/451257a))
|
* **animations:** do not treat a `0` animation state as `void` ([451257a](https://github.com/angular/angular/commit/451257a))
|
||||||
|
* **animations:** properly collect :enter nodes in a partially updated collection ([6ca4692](https://github.com/angular/angular/commit/6ca4692)), closes [#17440](https://github.com/angular/angular/issues/17440)
|
||||||
* **animations:** remove duplicate license header ([e096a85](https://github.com/angular/angular/commit/e096a85))
|
* **animations:** remove duplicate license header ([e096a85](https://github.com/angular/angular/commit/e096a85))
|
||||||
* **common/http:** document HttpClient, fixing a few other issues ([1855989](https://github.com/angular/angular/commit/1855989))
|
* **common/http:** document HttpClient, fixing a few other issues ([1855989](https://github.com/angular/angular/commit/1855989))
|
||||||
* **common/http:** don't guess Content-Type for FormData bodies ([#18104](https://github.com/angular/angular/issues/18104)) ([4f1e4ff](https://github.com/angular/angular/commit/4f1e4ff)), closes [#18096](https://github.com/angular/angular/issues/18096)
|
* **common/http:** don't guess Content-Type for FormData bodies ([#18104](https://github.com/angular/angular/issues/18104)) ([4f1e4ff](https://github.com/angular/angular/commit/4f1e4ff)), closes [#18096](https://github.com/angular/angular/issues/18096)
|
||||||
@ -4558,6 +4405,7 @@ Note: the 4.4.0 release on npm accidentally glitched-out midway, so we cut 4.4.1
|
|||||||
|
|
||||||
* **animations:** compute removal node height correctly ([185075d](https://github.com/angular/angular/commit/185075d))
|
* **animations:** compute removal node height correctly ([185075d](https://github.com/angular/angular/commit/185075d))
|
||||||
* **animations:** do not treat a `0` animation state as `void` ([451257a](https://github.com/angular/angular/commit/451257a))
|
* **animations:** do not treat a `0` animation state as `void` ([451257a](https://github.com/angular/angular/commit/451257a))
|
||||||
|
* **animations:** properly collect :enter nodes in a partially updated collection ([6ca4692](https://github.com/angular/angular/commit/6ca4692)), closes [#17440](https://github.com/angular/angular/issues/17440)
|
||||||
* **animations:** remove duplicate license header ([b192dd5](https://github.com/angular/angular/commit/b192dd5))
|
* **animations:** remove duplicate license header ([b192dd5](https://github.com/angular/angular/commit/b192dd5))
|
||||||
* **forms:** temp roll back breaking change with min/max directives ([b8c39cd](https://github.com/angular/angular/commit/b8c39cd)), closes [#17491](https://github.com/angular/angular/issues/17491)
|
* **forms:** temp roll back breaking change with min/max directives ([b8c39cd](https://github.com/angular/angular/commit/b8c39cd)), closes [#17491](https://github.com/angular/angular/issues/17491)
|
||||||
|
|
||||||
@ -4793,6 +4641,7 @@ Note: the 4.4.0 release on npm accidentally glitched-out midway, so we cut 4.4.1
|
|||||||
* **benchpress:** Update types for TypeScript nullability support ([14669f2](https://github.com/angular/angular/commit/14669f2))
|
* **benchpress:** Update types for TypeScript nullability support ([14669f2](https://github.com/angular/angular/commit/14669f2))
|
||||||
* **common:** Update types for TypeScript nullability support ([d8b73e4](https://github.com/angular/angular/commit/d8b73e4))
|
* **common:** Update types for TypeScript nullability support ([d8b73e4](https://github.com/angular/angular/commit/d8b73e4))
|
||||||
* **compiler:** fix build error in xliff2 ([bd704c9](https://github.com/angular/angular/commit/bd704c9))
|
* **compiler:** fix build error in xliff2 ([bd704c9](https://github.com/angular/angular/commit/bd704c9))
|
||||||
|
* **compiler:** fix inheritance for AOT with summaries ([#15583](https://github.com/angular/angular/issues/15583)) ([8ef621a](https://github.com/angular/angular/commit/8ef621a))
|
||||||
* **compiler:** ignore calls to unresolved symbols in metadata ([38a7e0d](https://github.com/angular/angular/commit/38a7e0d)), closes [#15969](https://github.com/angular/angular/issues/15969)
|
* **compiler:** ignore calls to unresolved symbols in metadata ([38a7e0d](https://github.com/angular/angular/commit/38a7e0d)), closes [#15969](https://github.com/angular/angular/issues/15969)
|
||||||
* **compiler:** ignore calls to unresolved symbols in metadata ([#15970](https://github.com/angular/angular/issues/15970)) ([ce47d33](https://github.com/angular/angular/commit/ce47d33)), closes [#15969](https://github.com/angular/angular/issues/15969)
|
* **compiler:** ignore calls to unresolved symbols in metadata ([#15970](https://github.com/angular/angular/issues/15970)) ([ce47d33](https://github.com/angular/angular/commit/ce47d33)), closes [#15969](https://github.com/angular/angular/issues/15969)
|
||||||
* **compiler:** Inform user where Quoted error was thrown ([a77b126](https://github.com/angular/angular/commit/a77b126))
|
* **compiler:** Inform user where Quoted error was thrown ([a77b126](https://github.com/angular/angular/commit/a77b126))
|
||||||
@ -4809,8 +4658,10 @@ Note: the 4.4.0 release on npm accidentally glitched-out midway, so we cut 4.4.1
|
|||||||
* **http:** Update types for TypeScript nullability support ([c36ec9b](https://github.com/angular/angular/commit/c36ec9b))
|
* **http:** Update types for TypeScript nullability support ([c36ec9b](https://github.com/angular/angular/commit/c36ec9b))
|
||||||
* **http:** Update types for TypeScript nullability support ([ec028b8](https://github.com/angular/angular/commit/ec028b8))
|
* **http:** Update types for TypeScript nullability support ([ec028b8](https://github.com/angular/angular/commit/ec028b8))
|
||||||
* **language-service:** avoid throwing exceptions when reporting metadata errors ([7764c5c](https://github.com/angular/angular/commit/7764c5c))
|
* **language-service:** avoid throwing exceptions when reporting metadata errors ([7764c5c](https://github.com/angular/angular/commit/7764c5c))
|
||||||
|
* **language-service:** detect when there isn't a tsconfig.json ([258d539](https://github.com/angular/angular/commit/258d539)), closes [#15874](https://github.com/angular/angular/issues/15874)
|
||||||
* **language-service:** improve resilience to incomplete information ([71a8627](https://github.com/angular/angular/commit/71a8627))
|
* **language-service:** improve resilience to incomplete information ([71a8627](https://github.com/angular/angular/commit/71a8627))
|
||||||
* **language-service:** infer correct type of `?.` expressions ([0a3a9af](https://github.com/angular/angular/commit/0a3a9af)), closes [#15885](https://github.com/angular/angular/issues/15885)
|
* **language-service:** infer correct type of `?.` expressions ([0a3a9af](https://github.com/angular/angular/commit/0a3a9af)), closes [#15885](https://github.com/angular/angular/issues/15885)
|
||||||
|
* **language-service:** initialize static reflector correctly ([fe0d02f](https://github.com/angular/angular/commit/fe0d02f)), closes [#15768](https://github.com/angular/angular/issues/15768)
|
||||||
* **language-service:** look for type constructors on canonical symbol ([2ddf3bc](https://github.com/angular/angular/commit/2ddf3bc))
|
* **language-service:** look for type constructors on canonical symbol ([2ddf3bc](https://github.com/angular/angular/commit/2ddf3bc))
|
||||||
* **language-service:** only use canonical symbols ([5a88d2f](https://github.com/angular/angular/commit/5a88d2f))
|
* **language-service:** only use canonical symbols ([5a88d2f](https://github.com/angular/angular/commit/5a88d2f))
|
||||||
* **language-service:** parse extended i18n forms ([bde9771](https://github.com/angular/angular/commit/bde9771))
|
* **language-service:** parse extended i18n forms ([bde9771](https://github.com/angular/angular/commit/bde9771))
|
||||||
@ -4835,6 +4686,7 @@ Note: the 4.4.0 release on npm accidentally glitched-out midway, so we cut 4.4.1
|
|||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
|
* **animations:** Update types for TypeScript nullability support ([38d75d4](https://github.com/angular/angular/commit/38d75d4)), closes [#15870](https://github.com/angular/angular/issues/15870)
|
||||||
* **compiler:** add source files to xmb/xliff translations ([#14705](https://github.com/angular/angular/issues/14705)) ([4054055](https://github.com/angular/angular/commit/4054055)), closes [#14190](https://github.com/angular/angular/issues/14190)
|
* **compiler:** add source files to xmb/xliff translations ([#14705](https://github.com/angular/angular/issues/14705)) ([4054055](https://github.com/angular/angular/commit/4054055)), closes [#14190](https://github.com/angular/angular/issues/14190)
|
||||||
* **compiler:** Implement i18n XLIFF 2.0 serializer ([#14185](https://github.com/angular/angular/issues/14185)) ([09c4cb2](https://github.com/angular/angular/commit/09c4cb2)), closes [#11735](https://github.com/angular/angular/issues/11735)
|
* **compiler:** Implement i18n XLIFF 2.0 serializer ([#14185](https://github.com/angular/angular/issues/14185)) ([09c4cb2](https://github.com/angular/angular/commit/09c4cb2)), closes [#11735](https://github.com/angular/angular/issues/11735)
|
||||||
* **upgrade:** allow setting the angularjs lib at runtime ([#15168](https://github.com/angular/angular/issues/15168)) ([e927aea](https://github.com/angular/angular/commit/e927aea))
|
* **upgrade:** allow setting the angularjs lib at runtime ([#15168](https://github.com/angular/angular/issues/15168)) ([e927aea](https://github.com/angular/angular/commit/e927aea))
|
||||||
@ -5572,18 +5424,27 @@ returned value being an array.
|
|||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **animations:** fix internal jscompiler issue and AOT quoting ([#13798](https://github.com/angular/angular/issues/13798)) ([c2aa981](https://github.com/angular/angular/commit/c2aa981))
|
||||||
|
* **common:** support numeric value as discrete cases for NgPlural ([#13876](https://github.com/angular/angular/issues/13876)) ([f364557](https://github.com/angular/angular/commit/f364557))
|
||||||
* **compiler:** [i18n] XMB/XTB placeholder names can contain only A-Z, 0-9, _n ([d02eab4](https://github.com/angular/angular/commit/d02eab4))
|
* **compiler:** [i18n] XMB/XTB placeholder names can contain only A-Z, 0-9, _n ([d02eab4](https://github.com/angular/angular/commit/d02eab4))
|
||||||
* **compiler:** fix regexp to support firefox 31 ([#14082](https://github.com/angular/angular/issues/14082)) ([b2f9d56](https://github.com/angular/angular/commit/b2f9d56)), closes [#14029](https://github.com/angular/angular/issues/14029) [#13900](https://github.com/angular/angular/issues/13900)
|
* **compiler:** fix regexp to support firefox 31 ([#14082](https://github.com/angular/angular/issues/14082)) ([b2f9d56](https://github.com/angular/angular/commit/b2f9d56)), closes [#14029](https://github.com/angular/angular/issues/14029) [#13900](https://github.com/angular/angular/issues/13900)
|
||||||
* **core:** export animation classes required for Renderer impl ([#14002](https://github.com/angular/angular/issues/14002)) ([83361d8](https://github.com/angular/angular/commit/83361d8)), closes [#14001](https://github.com/angular/angular/issues/14001)
|
* **core:** export animation classes required for Renderer impl ([#14002](https://github.com/angular/angular/issues/14002)) ([83361d8](https://github.com/angular/angular/commit/83361d8)), closes [#14001](https://github.com/angular/angular/issues/14001)
|
||||||
* **core:** fix not declared variable in view engine ([#14045](https://github.com/angular/angular/issues/14045)) ([d3a3a8e](https://github.com/angular/angular/commit/d3a3a8e))
|
* **core:** fix not declared variable in view engine ([#14045](https://github.com/angular/angular/issues/14045)) ([d3a3a8e](https://github.com/angular/angular/commit/d3a3a8e))
|
||||||
|
* **http:** don't create a blob out of ArrayBuffer when type is application/octet-stream ([#13992](https://github.com/angular/angular/issues/13992)) ([1200cf2](https://github.com/angular/angular/commit/1200cf2)), closes [#13973](https://github.com/angular/angular/issues/13973)
|
||||||
|
* **router:** enable loadChildren with function in aot ([#13909](https://github.com/angular/angular/issues/13909)) ([635bf02](https://github.com/angular/angular/commit/635bf02)), closes [#11075](https://github.com/angular/angular/issues/11075)
|
||||||
|
* **router:** routerLinkActive should not throw when not initialized ([#13273](https://github.com/angular/angular/issues/13273)) ([e8ea741](https://github.com/angular/angular/commit/e8ea741)), closes [#13270](https://github.com/angular/angular/issues/13270)
|
||||||
|
* **upgrade:** detect async downgrade component changes ([#13812](https://github.com/angular/angular/issues/13812)) ([d6382bf](https://github.com/angular/angular/commit/d6382bf)), closes [#6385](https://github.com/angular/angular/issues/6385) [#6385](https://github.com/angular/angular/issues/6385) [#10660](https://github.com/angular/angular/issues/10660) [#12318](https://github.com/angular/angular/issues/12318) [#12034](https://github.com/angular/angular/issues/12034)
|
||||||
* **upgrade/static:** ensure upgraded injector is initialized early enough ([#14065](https://github.com/angular/angular/issues/14065)) ([6152eb2](https://github.com/angular/angular/commit/6152eb2)), closes [#13811](https://github.com/angular/angular/issues/13811)
|
* **upgrade/static:** ensure upgraded injector is initialized early enough ([#14065](https://github.com/angular/angular/issues/14065)) ([6152eb2](https://github.com/angular/angular/commit/6152eb2)), closes [#13811](https://github.com/angular/angular/issues/13811)
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
|
* **build:** optionally build an ES2015 distro ([#13471](https://github.com/angular/angular/issues/13471)) ([be6c95a](https://github.com/angular/angular/commit/be6c95a))
|
||||||
* **core:** add event support to view engine ([0adb97b](https://github.com/angular/angular/commit/0adb97b))
|
* **core:** add event support to view engine ([0adb97b](https://github.com/angular/angular/commit/0adb97b))
|
||||||
* **core:** add initial view engine ([#14014](https://github.com/angular/angular/issues/14014)) ([2f87eb5](https://github.com/angular/angular/commit/2f87eb5))
|
* **core:** add initial view engine ([#14014](https://github.com/angular/angular/issues/14014)) ([2f87eb5](https://github.com/angular/angular/commit/2f87eb5))
|
||||||
* **core:** add pure expression support to view engine ([6541737](https://github.com/angular/angular/commit/6541737))
|
* **core:** add pure expression support to view engine ([6541737](https://github.com/angular/angular/commit/6541737))
|
||||||
|
* **core:** Add type information to injector.get() ([#13785](https://github.com/angular/angular/issues/13785)) ([d169c24](https://github.com/angular/angular/commit/d169c24))
|
||||||
|
* **security:** allow calc and gradient functions. ([#13943](https://github.com/angular/angular/issues/13943)) ([e19bf70](https://github.com/angular/angular/commit/e19bf70))
|
||||||
* **tsc-wrapped:** Support of vinyl like config file was added ([#13987](https://github.com/angular/angular/issues/13987)) ([0c7726d](https://github.com/angular/angular/commit/0c7726d))
|
* **tsc-wrapped:** Support of vinyl like config file was added ([#13987](https://github.com/angular/angular/issues/13987)) ([0c7726d](https://github.com/angular/angular/commit/0c7726d))
|
||||||
* **upgrade:** Support ng-model in downgraded components ([#10578](https://github.com/angular/angular/issues/10578)) ([e21e9c5](https://github.com/angular/angular/commit/e21e9c5))
|
* **upgrade:** Support ng-model in downgraded components ([#10578](https://github.com/angular/angular/issues/10578)) ([e21e9c5](https://github.com/angular/angular/commit/e21e9c5))
|
||||||
|
|
||||||
@ -6111,12 +5972,19 @@ Note: The 2.3.0-beta.0 release also contains all the changes present in the 2.2.
|
|||||||
|
|
||||||
### Features (summary of all features from 2.2.0-beta.0 - 2.2.0-rc.0 releases)
|
### Features (summary of all features from 2.2.0-beta.0 - 2.2.0-rc.0 releases)
|
||||||
|
|
||||||
|
* **common:** support narrow forms for month and weekdays in DatePipe ([#12297](https://github.com/angular/angular/issues/12297)) ([f77ab6a](https://github.com/angular/angular/commit/f77ab6a)), closes [#12294](https://github.com/angular/angular/issues/12294)
|
||||||
* **core:** map 'for' attribute to 'htmlFor' property ([#10546](https://github.com/angular/angular/issues/10546)) ([634b3bb](https://github.com/angular/angular/commit/634b3bb)), closes [#7516](https://github.com/angular/angular/issues/7516)
|
* **core:** map 'for' attribute to 'htmlFor' property ([#10546](https://github.com/angular/angular/issues/10546)) ([634b3bb](https://github.com/angular/angular/commit/634b3bb)), closes [#7516](https://github.com/angular/angular/issues/7516)
|
||||||
* **core:** add the find method to QueryList ([7c16ef9](https://github.com/angular/angular/commit/7c16ef9))
|
* **core:** add the find method to QueryList ([7c16ef9](https://github.com/angular/angular/commit/7c16ef9))
|
||||||
|
* **forms:** add hasError and getError to AbstractControlDirective ([#11985](https://github.com/angular/angular/issues/11985)) ([592f40a](https://github.com/angular/angular/commit/592f40a)), closes [#7255](https://github.com/angular/angular/issues/7255)
|
||||||
|
* **forms:** add ng-pending CSS class during async validation ([#11243](https://github.com/angular/angular/issues/11243)) ([97bc971](https://github.com/angular/angular/commit/97bc971)), closes [#10336](https://github.com/angular/angular/issues/10336)
|
||||||
* **forms:** add emitEvent to AbstractControl methods ([#11949](https://github.com/angular/angular/issues/11949)) ([b9fc090](https://github.com/angular/angular/commit/b9fc090))
|
* **forms:** add emitEvent to AbstractControl methods ([#11949](https://github.com/angular/angular/issues/11949)) ([b9fc090](https://github.com/angular/angular/commit/b9fc090))
|
||||||
|
* **forms:** make 'parent' a public property of 'AbstractControl' ([#11855](https://github.com/angular/angular/issues/11855)) ([445e592](https://github.com/angular/angular/commit/445e592))
|
||||||
|
* **forms:** Validator.pattern accepts a RegExp ([#12323](https://github.com/angular/angular/issues/12323)) ([bf60418](https://github.com/angular/angular/commit/bf60418))
|
||||||
* **router:** add a provider making angular1/angular2 integration easier ([#12769](https://github.com/angular/angular/issues/12769)) ([6e35d13](https://github.com/angular/angular/commit/6e35d13))
|
* **router:** add a provider making angular1/angular2 integration easier ([#12769](https://github.com/angular/angular/issues/12769)) ([6e35d13](https://github.com/angular/angular/commit/6e35d13))
|
||||||
* **router:** add support for custom url matchers ([7340735](https://github.com/angular/angular/commit/7340735)), closes [#12442](https://github.com/angular/angular/issues/12442) [#12772](https://github.com/angular/angular/issues/12772)
|
* **router:** add support for custom url matchers ([7340735](https://github.com/angular/angular/commit/7340735)), closes [#12442](https://github.com/angular/angular/issues/12442) [#12772](https://github.com/angular/angular/issues/12772)
|
||||||
* **router:** export routerLinkActive w/ isActive property ([c9f58cf](https://github.com/angular/angular/commit/c9f58cf))
|
* **router:** export routerLinkActive w/ isActive property ([c9f58cf](https://github.com/angular/angular/commit/c9f58cf))
|
||||||
|
* **router:** add support for ng1/ng2 migration ([#12160](https://github.com/angular/angular/issues/12160)) ([8b9ab44](https://github.com/angular/angular/commit/8b9ab44))
|
||||||
|
* **upgrade:** add support for AoT compiled upgrade applications ([d6791ff](https://github.com/angular/angular/commit/d6791ff)), closes [#12239](https://github.com/angular/angular/issues/12239)
|
||||||
* **upgrade:** add support for `require` in UpgradeComponent ([fe1d0e2](https://github.com/angular/angular/commit/fe1d0e2))
|
* **upgrade:** add support for `require` in UpgradeComponent ([fe1d0e2](https://github.com/angular/angular/commit/fe1d0e2))
|
||||||
* **upgrade:** add/improve support for lifecycle hooks in UpgradeComponent ([469010e](https://github.com/angular/angular/commit/469010e))
|
* **upgrade:** add/improve support for lifecycle hooks in UpgradeComponent ([469010e](https://github.com/angular/angular/commit/469010e))
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
As contributors and maintainers of the Angular project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities.
|
As contributors and maintainers of the Angular project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities.
|
||||||
|
|
||||||
Communication through any of Angular's channels (GitHub, Discord, Gitter, IRC, mailing lists, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
Communication through any of Angular's channels (GitHub, Gitter, IRC, mailing lists, Google+, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
||||||
|
|
||||||
We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the Angular project to do the same.
|
We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the Angular project to do the same.
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ Stack Overflow is a much better place to ask questions since:
|
|||||||
|
|
||||||
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
|
To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow.
|
||||||
|
|
||||||
If you would like to chat about the question in real-time, you can reach out via [our Discord server][discord].
|
If you would like to chat about the question in real-time, you can reach out via [our gitter channel][gitter].
|
||||||
|
|
||||||
|
|
||||||
## <a name="issue"></a> Found a Bug?
|
## <a name="issue"></a> Found a Bug?
|
||||||
@ -107,7 +107,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
|
|||||||
Adherence to these conventions is necessary because release notes are automatically generated from these messages.
|
Adherence to these conventions is necessary because release notes are automatically generated from these messages.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git commit --all
|
git commit -a
|
||||||
```
|
```
|
||||||
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
||||||
|
|
||||||
@ -119,55 +119,20 @@ Before you submit your Pull Request (PR) consider the following guidelines:
|
|||||||
|
|
||||||
11. In GitHub, send a pull request to `angular:master`.
|
11. In GitHub, send a pull request to `angular:master`.
|
||||||
|
|
||||||
|
If we ask for changes via code reviews then:
|
||||||
|
|
||||||
#### Addressing review feedback
|
* Make the required updates.
|
||||||
|
* Re-run the Angular test suites to ensure tests are still passing.
|
||||||
|
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
|
||||||
|
|
||||||
If we ask for changes via code reviews then:
|
```shell
|
||||||
|
git rebase master -i
|
||||||
1. Make the required updates to the code.
|
git push -f
|
||||||
|
```
|
||||||
2. Re-run the Angular test suites to ensure tests are still passing.
|
|
||||||
|
|
||||||
3. Create a fixup commit and push to your GitHub repository (this will update your Pull Request):
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git commit --all --fixup HEAD
|
|
||||||
git push
|
|
||||||
```
|
|
||||||
|
|
||||||
For more info on working with fixup commits see [here](docs/FIXUP_COMMITS.md).
|
|
||||||
|
|
||||||
That's it! Thank you for your contribution!
|
That's it! Thank you for your contribution!
|
||||||
|
|
||||||
|
|
||||||
##### Updating the commit message
|
|
||||||
|
|
||||||
A reviewer might often suggest changes to a commit message (for example, to add more context for a change or adhere to our [commit message guidelines](#commit)).
|
|
||||||
In order to update the commit message of the last commit on your branch:
|
|
||||||
|
|
||||||
1. Check out your branch:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git checkout my-fix-branch
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Amend the last commit and modify the commit message:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git commit --amend
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Push to your GitHub repository:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git push --force-with-lease
|
|
||||||
```
|
|
||||||
|
|
||||||
> NOTE:<br />
|
|
||||||
> If you need to update the commit message of an earlier commit, you can use `git rebase` in interactive mode.
|
|
||||||
> See the [git docs](https://git-scm.com/docs/git-rebase#_interactive_mode) for more details.
|
|
||||||
|
|
||||||
|
|
||||||
#### After your pull request is merged
|
#### After your pull request is merged
|
||||||
|
|
||||||
After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository:
|
After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository:
|
||||||
@ -265,6 +230,7 @@ Must be one of the following:
|
|||||||
* **fix**: A bug fix
|
* **fix**: A bug fix
|
||||||
* **perf**: A code change that improves performance
|
* **perf**: A code change that improves performance
|
||||||
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||||
|
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
|
||||||
* **test**: Adding missing tests or correcting existing tests
|
* **test**: Adding missing tests or correcting existing tests
|
||||||
|
|
||||||
|
|
||||||
@ -384,7 +350,7 @@ The following documents can help you sort out issues with GitHub accounts and mu
|
|||||||
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
|
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
|
||||||
[dev-doc]: https://github.com/angular/angular/blob/master/docs/DEVELOPER.md
|
[dev-doc]: https://github.com/angular/angular/blob/master/docs/DEVELOPER.md
|
||||||
[github]: https://github.com/angular/angular
|
[github]: https://github.com/angular/angular
|
||||||
[discord]: https://discord.gg/angular
|
[gitter]: https://gitter.im/angular/angular
|
||||||
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
||||||
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
|
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
|
||||||
[jsfiddle]: http://jsfiddle.net
|
[jsfiddle]: http://jsfiddle.net
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
[](https://circleci.com/gh/angular/workflows/angular/tree/master)
|
[](https://circleci.com/gh/angular/workflows/angular/tree/master)
|
||||||
[](https://discord.gg/angular)
|
|
||||||
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
[](https://www.npmjs.com/@angular/core)
|
[](https://www.npmjs.com/@angular/core)
|
||||||
|
|
||||||
|
24
WORKSPACE
24
WORKSPACE
@ -8,8 +8,8 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
|||||||
# Fetch rules_nodejs so we can install our npm dependencies
|
# Fetch rules_nodejs so we can install our npm dependencies
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "build_bazel_rules_nodejs",
|
name = "build_bazel_rules_nodejs",
|
||||||
sha256 = "4952ef879704ab4ad6729a29007e7094aef213ea79e9f2e94cbe1c9a753e63ef",
|
sha256 = "84abf7ac4234a70924628baa9a73a5a5cbad944c4358cf9abdb4aab29c9a5b77",
|
||||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/2.2.0/rules_nodejs-2.2.0.tar.gz"],
|
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.7.0/rules_nodejs-1.7.0.tar.gz"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check the rules_nodejs version and download npm dependencies
|
# Check the rules_nodejs version and download npm dependencies
|
||||||
@ -17,7 +17,7 @@ http_archive(
|
|||||||
# assert on that.
|
# assert on that.
|
||||||
load("@build_bazel_rules_nodejs//:index.bzl", "check_rules_nodejs_version", "node_repositories", "yarn_install")
|
load("@build_bazel_rules_nodejs//:index.bzl", "check_rules_nodejs_version", "node_repositories", "yarn_install")
|
||||||
|
|
||||||
check_rules_nodejs_version(minimum_version_string = "2.2.0")
|
check_rules_nodejs_version(minimum_version_string = "1.7.0")
|
||||||
|
|
||||||
# Setup the Node.js toolchain
|
# Setup the Node.js toolchain
|
||||||
node_repositories(
|
node_repositories(
|
||||||
@ -39,18 +39,23 @@ yarn_install(
|
|||||||
yarn_lock = "//:yarn.lock",
|
yarn_lock = "//:yarn.lock",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Install all bazel dependencies of the @npm npm packages
|
||||||
|
load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
|
||||||
|
|
||||||
|
install_bazel_dependencies()
|
||||||
|
|
||||||
# Load angular dependencies
|
# Load angular dependencies
|
||||||
load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies")
|
load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies")
|
||||||
|
|
||||||
rules_angular_dev_dependencies()
|
rules_angular_dev_dependencies()
|
||||||
|
|
||||||
# Load protractor dependencies
|
# Load protractor dependencies
|
||||||
load("@npm//@bazel/protractor:package.bzl", "npm_bazel_protractor_dependencies")
|
load("@npm_bazel_protractor//:package.bzl", "npm_bazel_protractor_dependencies")
|
||||||
|
|
||||||
npm_bazel_protractor_dependencies()
|
npm_bazel_protractor_dependencies()
|
||||||
|
|
||||||
# Load karma dependencies
|
# Load karma dependencies
|
||||||
load("@npm//@bazel/karma:package.bzl", "npm_bazel_karma_dependencies")
|
load("@npm_bazel_karma//:package.bzl", "npm_bazel_karma_dependencies")
|
||||||
|
|
||||||
npm_bazel_karma_dependencies()
|
npm_bazel_karma_dependencies()
|
||||||
|
|
||||||
@ -63,6 +68,11 @@ load("//dev-infra/browsers:browser_repositories.bzl", "browser_repositories")
|
|||||||
|
|
||||||
browser_repositories()
|
browser_repositories()
|
||||||
|
|
||||||
|
# Setup the rules_typescript tooolchain
|
||||||
|
load("@npm_bazel_typescript//:index.bzl", "ts_setup_workspace")
|
||||||
|
|
||||||
|
ts_setup_workspace()
|
||||||
|
|
||||||
# Setup the rules_sass toolchain
|
# Setup the rules_sass toolchain
|
||||||
load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")
|
load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")
|
||||||
|
|
||||||
@ -81,8 +91,8 @@ rbe_autoconfig(
|
|||||||
# Need to specify a base container digest in order to ensure that we can use the checked-in
|
# Need to specify a base container digest in order to ensure that we can use the checked-in
|
||||||
# platform configurations for the "ubuntu16_04" image. Otherwise the autoconfig rule would
|
# platform configurations for the "ubuntu16_04" image. Otherwise the autoconfig rule would
|
||||||
# need to pull the image and run it in order determine the toolchain configuration. See:
|
# need to pull the image and run it in order determine the toolchain configuration. See:
|
||||||
# https://github.com/bazelbuild/bazel-toolchains/blob/3.5.1/configs/ubuntu16_04_clang/versions.bzl
|
# https://github.com/bazelbuild/bazel-toolchains/blob/3.2.0/configs/ubuntu16_04_clang/versions.bzl
|
||||||
base_container_digest = "sha256:f6568d8168b14aafd1b707019927a63c2d37113a03bcee188218f99bd0327ea1",
|
base_container_digest = "sha256:5e750dd878df9fcf4e185c6f52b9826090f6e532b097f286913a428290622332",
|
||||||
# Note that if you change the `digest`, you might also need to update the
|
# Note that if you change the `digest`, you might also need to update the
|
||||||
# `base_container_digest` to make sure marketplace.gcr.io/google/rbe-ubuntu16-04-webtest:<digest>
|
# `base_container_digest` to make sure marketplace.gcr.io/google/rbe-ubuntu16-04-webtest:<digest>
|
||||||
# and marketplace.gcr.io/google/rbe-ubuntu16-04:<base_container_digest> have
|
# and marketplace.gcr.io/google/rbe-ubuntu16-04:<base_container_digest> have
|
||||||
|
@ -6,7 +6,6 @@ Everything in this folder is part of the documentation project. This includes
|
|||||||
* the dgeni configuration for converting source files to rendered files that can be viewed in the web site.
|
* the dgeni configuration for converting source files to rendered files that can be viewed in the web site.
|
||||||
* the tooling for setting up examples for development; and generating live-example and zip files from the examples.
|
* the tooling for setting up examples for development; and generating live-example and zip files from the examples.
|
||||||
|
|
||||||
<a name="developer-tasks"></a>
|
|
||||||
## Developer tasks
|
## Developer tasks
|
||||||
|
|
||||||
We use [Yarn](https://yarnpkg.com) to manage the dependencies and to run build tasks.
|
We use [Yarn](https://yarnpkg.com) to manage the dependencies and to run build tasks.
|
||||||
|
@ -16,6 +16,13 @@ import {BuildNums, PrNums, SHA} from './constants';
|
|||||||
|
|
||||||
const logger = new Logger('mock-external-apis');
|
const logger = new Logger('mock-external-apis');
|
||||||
|
|
||||||
|
const log = (...args: any[]) => {
|
||||||
|
// Filter out non-matching URL checks
|
||||||
|
if (!/^matching.+: false$/.test(args[0])) {
|
||||||
|
logger.log(...args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const AIO_CIRCLE_CI_TOKEN = getEnvVar('AIO_CIRCLE_CI_TOKEN');
|
const AIO_CIRCLE_CI_TOKEN = getEnvVar('AIO_CIRCLE_CI_TOKEN');
|
||||||
const AIO_GITHUB_TOKEN = getEnvVar('AIO_GITHUB_TOKEN');
|
const AIO_GITHUB_TOKEN = getEnvVar('AIO_GITHUB_TOKEN');
|
||||||
|
|
||||||
@ -84,8 +91,8 @@ const createArchive = (buildNum: number, prNum: number, sha: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create request scopes
|
// Create request scopes
|
||||||
const circleCiApi = nock(CIRCLE_CI_API_HOST).persist();
|
const circleCiApi = nock(CIRCLE_CI_API_HOST).log(log).persist();
|
||||||
const githubApi = nock(GITHUB_API_HOST).persist().matchHeader('Authorization', `token ${AIO_GITHUB_TOKEN}`);
|
const githubApi = nock(GITHUB_API_HOST).log(log).persist().matchHeader('Authorization', `token ${AIO_GITHUB_TOKEN}`);
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
|
|
||||||
|
@ -27,28 +27,28 @@
|
|||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
"delete-empty": "^3.0.0",
|
"delete-empty": "^3.0.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"jasmine": "^3.6.1",
|
"jasmine": "^3.5.0",
|
||||||
"nock": "^13.0.4",
|
"nock": "^12.0.3",
|
||||||
"node-fetch": "^2.6.1",
|
"node-fetch": "^2.6.0",
|
||||||
"shelljs": "^0.8.4",
|
"shelljs": "^0.8.4",
|
||||||
"source-map-support": "^0.5.19",
|
"source-map-support": "^0.5.19",
|
||||||
"tar-stream": "^2.1.3",
|
"tar-stream": "^2.1.2",
|
||||||
"tslib": "^2.0.1"
|
"tslib": "^1.11.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/body-parser": "^1.19.0",
|
"@types/body-parser": "^1.19.0",
|
||||||
"@types/express": "^4.17.8",
|
"@types/express": "^4.17.6",
|
||||||
"@types/jasmine": "^3.5.14",
|
"@types/jasmine": "^3.5.10",
|
||||||
"@types/nock": "^11.1.0",
|
"@types/nock": "^11.1.0",
|
||||||
"@types/node": "^14.6.4",
|
"@types/node": "^13.13.2",
|
||||||
"@types/node-fetch": "^2.5.7",
|
"@types/node-fetch": "^2.5.7",
|
||||||
"@types/shelljs": "^0.8.8",
|
"@types/shelljs": "^0.8.7",
|
||||||
"@types/supertest": "^2.0.10",
|
"@types/supertest": "^2.0.8",
|
||||||
"nodemon": "^2.0.4",
|
"nodemon": "^2.0.3",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"supertest": "^4.0.2",
|
"supertest": "^4.0.2",
|
||||||
"tslint": "^6.1.3",
|
"tslint": "^6.1.1",
|
||||||
"tslint-jasmine-noSkipOrFocus": "^1.0.9",
|
"tslint-jasmine-noSkipOrFocus": "^1.0.9",
|
||||||
"typescript": "^4.0.2"
|
"typescript": "^3.8.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,24 +214,23 @@ describe('GithubApi', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should call \'https.request()\' with the correct options', async () => {
|
it('should call \'https.request()\' with the correct options', () => {
|
||||||
const requestHandler = nock('https://api.github.com')
|
const requestHandler = nock('https://api.github.com')
|
||||||
.intercept('/path', 'method')
|
.intercept('/path', 'method')
|
||||||
.reply(200);
|
.reply(200);
|
||||||
|
|
||||||
await (api as any).request('method', '/path');
|
(api as any).request('method', '/path');
|
||||||
requestHandler.done();
|
requestHandler.done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should add the \'Authorization\' header containing the \'githubToken\'', async () => {
|
it('should add the \'Authorization\' header containing the \'githubToken\'', () => {
|
||||||
const requestHandler = nock('https://api.github.com')
|
const requestHandler = nock('https://api.github.com')
|
||||||
.intercept('/path', 'method', undefined, {
|
.intercept('/path', 'method', undefined, {
|
||||||
reqheaders: {Authorization: 'token 12345'},
|
reqheaders: {Authorization: 'token 12345'},
|
||||||
})
|
})
|
||||||
.reply(200);
|
.reply(200);
|
||||||
|
(api as any).request('method', '/path');
|
||||||
await (api as any).request('method', '/path');
|
|
||||||
requestHandler.done();
|
requestHandler.done();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -245,13 +244,12 @@ describe('GithubApi', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should \'JSON.stringify\' and send the data along with the request', async () => {
|
it('should \'JSON.stringify\' and send the data along with the request', () => {
|
||||||
const data = {key: 'value'};
|
const data = {key: 'value'};
|
||||||
const requestHandler = nock('https://api.github.com')
|
const requestHandler = nock('https://api.github.com')
|
||||||
.intercept('/path', 'method', JSON.stringify(data))
|
.intercept('/path', 'method', JSON.stringify(data))
|
||||||
.reply(200);
|
.reply(200);
|
||||||
|
(api as any).request('method', '/path', data);
|
||||||
await (api as any).request('method', '/path', data);
|
|
||||||
requestHandler.done();
|
requestHandler.done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@ you don't need to specify values for those.
|
|||||||
The domain name of the server.
|
The domain name of the server.
|
||||||
|
|
||||||
- `AIO_GITHUB_ORGANIZATION`:
|
- `AIO_GITHUB_ORGANIZATION`:
|
||||||
The GitHub organization whose teams are trusted for accepting build artifacts.
|
The GitHub organization whose teams are whitelisted for accepting build artifacts.
|
||||||
See also `AIO_GITHUB_TEAM_SLUGS`.
|
See also `AIO_GITHUB_TEAM_SLUGS`.
|
||||||
|
|
||||||
- `AIO_GITHUB_REPO`:
|
- `AIO_GITHUB_REPO`:
|
||||||
|
@ -98,7 +98,7 @@ This section describes how each of the aforementioned sub-tasks is accomplished:
|
|||||||
Such a label can only have been added by a maintainer (with the necessary rights) and
|
Such a label can only have been added by a maintainer (with the necessary rights) and
|
||||||
designates that they have manually verified the PR contents.
|
designates that they have manually verified the PR contents.
|
||||||
2. We can verify (again using the GitHub API) the author's membership in one of the
|
2. We can verify (again using the GitHub API) the author's membership in one of the
|
||||||
trusted GitHub teams. For this operation, we need a Personal Access Token with the
|
whitelisted/trusted GitHub teams. For this operation, we need a Personal Access Token with the
|
||||||
`read:org` scope issued by a user that can "see" the specified GitHub organization.
|
`read:org` scope issued by a user that can "see" the specified GitHub organization.
|
||||||
Here too, we use the token by @mary-poppins.
|
Here too, we use the token by @mary-poppins.
|
||||||
|
|
||||||
|
2
aio/content/examples/.gitignore
vendored
2
aio/content/examples/.gitignore
vendored
@ -17,7 +17,6 @@
|
|||||||
**/e2e/tsconfig.e2e.json
|
**/e2e/tsconfig.e2e.json
|
||||||
**/src/karma.conf.js
|
**/src/karma.conf.js
|
||||||
**/.angular-cli.json
|
**/.angular-cli.json
|
||||||
**/.browserslistrc
|
|
||||||
**/.editorconfig
|
**/.editorconfig
|
||||||
**/.gitignore
|
**/.gitignore
|
||||||
**/angular.json
|
**/angular.json
|
||||||
@ -31,6 +30,7 @@
|
|||||||
**/tslint.json
|
**/tslint.json
|
||||||
**/karma-test-shim.js
|
**/karma-test-shim.js
|
||||||
**/browser-test-shim.js
|
**/browser-test-shim.js
|
||||||
|
**/browserslist
|
||||||
**/node_modules
|
**/node_modules
|
||||||
|
|
||||||
# built files
|
# built files
|
||||||
|
@ -21,13 +21,11 @@ import { ItemDirective } from './item.directive';
|
|||||||
ItemDirective
|
ItemDirective
|
||||||
],
|
],
|
||||||
// #enddocregion declarations
|
// #enddocregion declarations
|
||||||
// #docregion imports
|
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
HttpClientModule
|
HttpClientModule
|
||||||
],
|
],
|
||||||
// #enddocregion imports
|
|
||||||
providers: [],
|
providers: [],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
import { browser, by, element } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Component Communication Cookbook Tests', () => {
|
describe('Component Communication Cookbook Tests', () => {
|
||||||
|
|
||||||
beforeEach(() => browser.get(browser.baseUrl));
|
// Note: '?e2e' which app can read to know it is running in protractor
|
||||||
|
// e.g. `if (!/e2e/.test(location.search)) { ...`
|
||||||
|
beforeAll(() => {
|
||||||
|
browser.get('?e2e');
|
||||||
|
});
|
||||||
|
|
||||||
describe('Parent-to-child communication', () => {
|
describe('Parent-to-child communication', () => {
|
||||||
// #docregion parent-to-child
|
// #docregion parent-to-child
|
||||||
@ -11,7 +15,7 @@ describe('Component Communication Cookbook Tests', () => {
|
|||||||
const masterName = 'Master';
|
const masterName = 'Master';
|
||||||
|
|
||||||
it('should pass properties to children properly', () => {
|
it('should pass properties to children properly', () => {
|
||||||
const parent = element(by.tagName('app-hero-parent'));
|
const parent = element.all(by.tagName('app-hero-parent')).get(0);
|
||||||
const heroes = parent.all(by.tagName('app-hero-child'));
|
const heroes = parent.all(by.tagName('app-hero-child'));
|
||||||
|
|
||||||
for (let i = 0; i < heroNames.length; i++) {
|
for (let i = 0; i < heroNames.length; i++) {
|
||||||
@ -31,7 +35,7 @@ describe('Component Communication Cookbook Tests', () => {
|
|||||||
it('should display trimmed, non-empty names', () => {
|
it('should display trimmed, non-empty names', () => {
|
||||||
const nonEmptyNameIndex = 0;
|
const nonEmptyNameIndex = 0;
|
||||||
const nonEmptyName = '"Dr IQ"';
|
const nonEmptyName = '"Dr IQ"';
|
||||||
const parent = element(by.tagName('app-name-parent'));
|
const parent = element.all(by.tagName('app-name-parent')).get(0);
|
||||||
const hero = parent.all(by.tagName('app-name-child')).get(nonEmptyNameIndex);
|
const hero = parent.all(by.tagName('app-name-child')).get(nonEmptyNameIndex);
|
||||||
|
|
||||||
const displayName = hero.element(by.tagName('h3')).getText();
|
const displayName = hero.element(by.tagName('h3')).getText();
|
||||||
@ -41,7 +45,7 @@ describe('Component Communication Cookbook Tests', () => {
|
|||||||
it('should replace empty name with default name', () => {
|
it('should replace empty name with default name', () => {
|
||||||
const emptyNameIndex = 1;
|
const emptyNameIndex = 1;
|
||||||
const defaultName = '"<no name set>"';
|
const defaultName = '"<no name set>"';
|
||||||
const parent = element(by.tagName('app-name-parent'));
|
const parent = element.all(by.tagName('app-name-parent')).get(0);
|
||||||
const hero = parent.all(by.tagName('app-name-child')).get(emptyNameIndex);
|
const hero = parent.all(by.tagName('app-name-child')).get(emptyNameIndex);
|
||||||
|
|
||||||
const displayName = hero.element(by.tagName('h3')).getText();
|
const displayName = hero.element(by.tagName('h3')).getText();
|
||||||
@ -66,36 +70,38 @@ describe('Component Communication Cookbook Tests', () => {
|
|||||||
expect(actual.logs.get(0).getText()).toBe(initialLog);
|
expect(actual.logs.get(0).getText()).toBe(initialLog);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set expected values after clicking \'Minor\' twice', async () => {
|
it('should set expected values after clicking \'Minor\' twice', () => {
|
||||||
const repoTag = element(by.tagName('app-version-parent'));
|
const repoTag = element(by.tagName('app-version-parent'));
|
||||||
const newMinorButton = repoTag.all(by.tagName('button')).get(0);
|
const newMinorButton = repoTag.all(by.tagName('button')).get(0);
|
||||||
|
|
||||||
await newMinorButton.click();
|
newMinorButton.click().then(() => {
|
||||||
await newMinorButton.click();
|
newMinorButton.click().then(() => {
|
||||||
|
const actual = getActual();
|
||||||
|
|
||||||
const actual = getActual();
|
const labelAfter2Minor = 'Version 1.25';
|
||||||
|
const logAfter2Minor = 'minor changed from 24 to 25';
|
||||||
|
|
||||||
const labelAfter2Minor = 'Version 1.25';
|
expect(actual.label).toBe(labelAfter2Minor);
|
||||||
const logAfter2Minor = 'minor changed from 24 to 25';
|
expect(actual.count).toBe(3);
|
||||||
|
expect(actual.logs.get(2).getText()).toBe(logAfter2Minor);
|
||||||
expect(actual.label).toBe(labelAfter2Minor);
|
});
|
||||||
expect(actual.count).toBe(3);
|
});
|
||||||
expect(actual.logs.get(2).getText()).toBe(logAfter2Minor);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set expected values after clicking \'Major\' once', async () => {
|
it('should set expected values after clicking \'Major\' once', () => {
|
||||||
const repoTag = element(by.tagName('app-version-parent'));
|
const repoTag = element(by.tagName('app-version-parent'));
|
||||||
const newMajorButton = repoTag.all(by.tagName('button')).get(1);
|
const newMajorButton = repoTag.all(by.tagName('button')).get(1);
|
||||||
|
|
||||||
await newMajorButton.click();
|
newMajorButton.click().then(() => {
|
||||||
const actual = getActual();
|
const actual = getActual();
|
||||||
|
|
||||||
const labelAfterMajor = 'Version 2.0';
|
const labelAfterMajor = 'Version 2.0';
|
||||||
const logAfterMajor = 'major changed from 1 to 2, minor changed from 23 to 0';
|
const logAfterMajor = 'major changed from 1 to 2, minor changed from 25 to 0';
|
||||||
|
|
||||||
expect(actual.label).toBe(labelAfterMajor);
|
expect(actual.label).toBe(labelAfterMajor);
|
||||||
expect(actual.count).toBe(2);
|
expect(actual.count).toBe(4);
|
||||||
expect(actual.logs.get(1).getText()).toBe(logAfterMajor);
|
expect(actual.logs.get(3).getText()).toBe(logAfterMajor);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function getActual() {
|
function getActual() {
|
||||||
@ -112,125 +118,110 @@ describe('Component Communication Cookbook Tests', () => {
|
|||||||
}
|
}
|
||||||
// ...
|
// ...
|
||||||
// #enddocregion parent-to-child-onchanges
|
// #enddocregion parent-to-child-onchanges
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Child-to-parent communication', () => {
|
describe('Child-to-parent communication', () => {
|
||||||
// #docregion child-to-parent
|
// #docregion child-to-parent
|
||||||
// ...
|
// ...
|
||||||
it('should not emit the event initially', () => {
|
it('should not emit the event initially', () => {
|
||||||
const voteLabel = element(by.tagName('app-vote-taker')).element(by.tagName('h3'));
|
const voteLabel = element(by.tagName('app-vote-taker'))
|
||||||
expect(voteLabel.getText()).toBe('Agree: 0, Disagree: 0');
|
.element(by.tagName('h3')).getText();
|
||||||
|
expect(voteLabel).toBe('Agree: 0, Disagree: 0');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should process Agree vote', async () => {
|
it('should process Agree vote', () => {
|
||||||
const voteLabel = element(by.tagName('app-vote-taker')).element(by.tagName('h3'));
|
|
||||||
const agreeButton1 = element.all(by.tagName('app-voter')).get(0)
|
const agreeButton1 = element.all(by.tagName('app-voter')).get(0)
|
||||||
.all(by.tagName('button')).get(0);
|
.all(by.tagName('button')).get(0);
|
||||||
|
agreeButton1.click().then(() => {
|
||||||
await agreeButton1.click();
|
const voteLabel = element(by.tagName('app-vote-taker'))
|
||||||
|
.element(by.tagName('h3')).getText();
|
||||||
expect(voteLabel.getText()).toBe('Agree: 1, Disagree: 0');
|
expect(voteLabel).toBe('Agree: 1, Disagree: 0');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should process Disagree vote', async () => {
|
it('should process Disagree vote', () => {
|
||||||
const voteLabel = element(by.tagName('app-vote-taker')).element(by.tagName('h3'));
|
|
||||||
const agreeButton1 = element.all(by.tagName('app-voter')).get(1)
|
const agreeButton1 = element.all(by.tagName('app-voter')).get(1)
|
||||||
.all(by.tagName('button')).get(1);
|
.all(by.tagName('button')).get(1);
|
||||||
|
agreeButton1.click().then(() => {
|
||||||
await agreeButton1.click();
|
const voteLabel = element(by.tagName('app-vote-taker'))
|
||||||
|
.element(by.tagName('h3')).getText();
|
||||||
expect(voteLabel.getText()).toBe('Agree: 0, Disagree: 1');
|
expect(voteLabel).toBe('Agree: 1, Disagree: 1');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
// ...
|
// ...
|
||||||
// #enddocregion child-to-parent
|
// #enddocregion child-to-parent
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Parent calls child via local var', () => {
|
// Can't run timer tests in protractor because
|
||||||
countDownTimerTests('app-countdown-parent-lv');
|
// interaction w/ zones causes all tests to freeze & timeout.
|
||||||
|
xdescribe('Parent calls child via local var', () => {
|
||||||
|
countDownTimerTests('countdown-parent-lv');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Parent calls ViewChild', () => {
|
xdescribe('Parent calls ViewChild', () => {
|
||||||
countDownTimerTests('app-countdown-parent-vc');
|
countDownTimerTests('countdown-parent-vc');
|
||||||
});
|
});
|
||||||
|
|
||||||
function countDownTimerTests(parentTag: string) {
|
function countDownTimerTests(parentTag: string) {
|
||||||
// #docregion countdown-timer-tests
|
// #docregion countdown-timer-tests
|
||||||
// ...
|
// ...
|
||||||
// The tests trigger periodic asynchronous operations (via `setInterval()`), which will prevent
|
it('timer and parent seconds should match', () => {
|
||||||
// the app from stabilizing. See https://angular.io/api/core/ApplicationRef#is-stable-examples
|
|
||||||
// for more details.
|
|
||||||
// To allow the tests to complete, we will disable automatically waiting for the Angular app to
|
|
||||||
// stabilize.
|
|
||||||
beforeEach(() => browser.waitForAngularEnabled(false));
|
|
||||||
afterEach(() => browser.waitForAngularEnabled(true));
|
|
||||||
|
|
||||||
it('timer and parent seconds should match', async () => {
|
|
||||||
const parent = element(by.tagName(parentTag));
|
const parent = element(by.tagName(parentTag));
|
||||||
const startButton = parent.element(by.buttonText('Start'));
|
const message = parent.element(by.tagName('app-countdown-timer')).getText();
|
||||||
const seconds = parent.element(by.className('seconds'));
|
browser.sleep(10); // give `seconds` a chance to catchup with `message`
|
||||||
const timer = parent.element(by.tagName('app-countdown-timer'));
|
const seconds = parent.element(by.className('seconds')).getText();
|
||||||
|
expect(message).toContain(seconds);
|
||||||
await startButton.click();
|
|
||||||
|
|
||||||
// Wait for `<app-countdown-timer>` to be populated with any text.
|
|
||||||
await browser.wait(() => timer.getText(), 2000);
|
|
||||||
|
|
||||||
expect(await timer.getText()).toContain(await seconds.getText());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should stop the countdown', async () => {
|
it('should stop the countdown', () => {
|
||||||
const parent = element(by.tagName(parentTag));
|
const parent = element(by.tagName(parentTag));
|
||||||
const startButton = parent.element(by.buttonText('Start'));
|
const stopButton = parent.all(by.tagName('button')).get(1);
|
||||||
const stopButton = parent.element(by.buttonText('Stop'));
|
|
||||||
const timer = parent.element(by.tagName('app-countdown-timer'));
|
|
||||||
|
|
||||||
await startButton.click();
|
stopButton.click().then(() => {
|
||||||
expect(await timer.getText()).not.toContain('Holding');
|
const message = parent.element(by.tagName('app-countdown-timer')).getText();
|
||||||
|
expect(message).toContain('Holding');
|
||||||
await stopButton.click();
|
});
|
||||||
expect(await timer.getText()).toContain('Holding');
|
|
||||||
});
|
});
|
||||||
// ...
|
// ...
|
||||||
// #enddocregion countdown-timer-tests
|
// #enddocregion countdown-timer-tests
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
describe('Parent and children communicate via a service', () => {
|
describe('Parent and children communicate via a service', () => {
|
||||||
// #docregion bidirectional-service
|
// #docregion bidirectional-service
|
||||||
// ...
|
// ...
|
||||||
it('should announce a mission', async () => {
|
it('should announce a mission', () => {
|
||||||
const missionControl = element(by.tagName('app-mission-control'));
|
const missionControl = element(by.tagName('app-mission-control'));
|
||||||
const announceButton = missionControl.all(by.tagName('button')).get(0);
|
const announceButton = missionControl.all(by.tagName('button')).get(0);
|
||||||
const history = missionControl.all(by.tagName('li'));
|
announceButton.click().then(() => {
|
||||||
|
const history = missionControl.all(by.tagName('li'));
|
||||||
await announceButton.click();
|
expect(history.count()).toBe(1);
|
||||||
|
expect(history.get(0).getText()).toMatch(/Mission.* announced/);
|
||||||
expect(history.count()).toBe(1);
|
});
|
||||||
expect(history.get(0).getText()).toMatch(/Mission.* announced/);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should confirm the mission by Lovell', async () => {
|
it('should confirm the mission by Lovell', () => {
|
||||||
await testConfirmMission(1, 'Lovell');
|
testConfirmMission(1, 2, 'Lovell');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should confirm the mission by Haise', async () => {
|
it('should confirm the mission by Haise', () => {
|
||||||
await testConfirmMission(3, 'Haise');
|
testConfirmMission(3, 3, 'Haise');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should confirm the mission by Swigert', async () => {
|
it('should confirm the mission by Swigert', () => {
|
||||||
await testConfirmMission(2, 'Swigert');
|
testConfirmMission(2, 4, 'Swigert');
|
||||||
});
|
});
|
||||||
|
|
||||||
async function testConfirmMission(buttonIndex: number, astronaut: string) {
|
function testConfirmMission(buttonIndex: number, expectedLogCount: number, astronaut: string) {
|
||||||
|
const confirmedLog = ' confirmed the mission';
|
||||||
const missionControl = element(by.tagName('app-mission-control'));
|
const missionControl = element(by.tagName('app-mission-control'));
|
||||||
const announceButton = missionControl.all(by.tagName('button')).get(0);
|
|
||||||
const confirmButton = missionControl.all(by.tagName('button')).get(buttonIndex);
|
const confirmButton = missionControl.all(by.tagName('button')).get(buttonIndex);
|
||||||
const history = missionControl.all(by.tagName('li'));
|
confirmButton.click().then(() => {
|
||||||
|
const history = missionControl.all(by.tagName('li'));
|
||||||
await announceButton.click();
|
expect(history.count()).toBe(expectedLogCount);
|
||||||
await confirmButton.click();
|
expect(history.get(expectedLogCount - 1).getText()).toBe(astronaut + confirmedLog);
|
||||||
|
});
|
||||||
expect(history.count()).toBe(2);
|
|
||||||
expect(history.get(1).getText()).toBe(`${astronaut} confirmed the mission`);
|
|
||||||
}
|
}
|
||||||
// ...
|
// ...
|
||||||
// #enddocregion bidirectional-service
|
// #enddocregion bidirectional-service
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"tests": [
|
||||||
|
{
|
||||||
|
"cmd": "yarn",
|
||||||
|
"args": [
|
||||||
|
"e2e",
|
||||||
|
"--protractor-config=e2e/protractor-puppeteer.conf.js",
|
||||||
|
"--no-webdriver-update",
|
||||||
|
"--port={PORT}"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
@ -30,21 +30,22 @@
|
|||||||
<app-vote-taker></app-vote-taker>
|
<app-vote-taker></app-vote-taker>
|
||||||
</div>
|
</div>
|
||||||
<a href="#top" class="to-top">Back to Top</a>
|
<a href="#top" class="to-top">Back to Top</a>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div id="parent-to-child-local-var">
|
<div id="parent-to-child-local-var">
|
||||||
<app-countdown-parent-lv></app-countdown-parent-lv>
|
<app-countdown-parent-lv></app-countdown-parent-lv>
|
||||||
</div>
|
</div>
|
||||||
<a href="#top" class="to-top">Back to Top</a>
|
<a href="#top" class="to-top">Back to Top</a>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div id="parent-to-view-child">
|
<div id="parent-to-view-child">
|
||||||
<app-countdown-parent-vc></app-countdown-parent-vc>
|
<app-countdown-parent-vc></app-countdown-parent-vc>
|
||||||
</div>
|
</div>
|
||||||
<a href="#top" class="to-top">Back to Top</a>
|
<a href="#top" class="to-top">Back to Top</a>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div id="bidirectional-service">
|
<div id="bidirectional-service">
|
||||||
<app-mission-control></app-mission-control>
|
<app-mission-control></app-mission-control>
|
||||||
</div>
|
</div>
|
||||||
<a href="#top" class="to-top">Back to Top</a>
|
<a href="#top" class="to-top">Back to Top</a>
|
||||||
|
<hr>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
@ -15,17 +15,10 @@ import { VersionParentComponent } from './version-parent.component';
|
|||||||
import { VoterComponent } from './voter.component';
|
import { VoterComponent } from './voter.component';
|
||||||
import { VoteTakerComponent } from './votetaker.component';
|
import { VoteTakerComponent } from './votetaker.component';
|
||||||
|
|
||||||
|
const directives: any[] = [
|
||||||
@NgModule({
|
|
||||||
imports: [
|
|
||||||
BrowserModule,
|
|
||||||
],
|
|
||||||
declarations: [
|
|
||||||
AppComponent,
|
AppComponent,
|
||||||
AstronautComponent,
|
AstronautComponent,
|
||||||
CountdownLocalVarParentComponent,
|
|
||||||
CountdownTimerComponent,
|
CountdownTimerComponent,
|
||||||
CountdownViewChildParentComponent,
|
|
||||||
HeroChildComponent,
|
HeroChildComponent,
|
||||||
HeroParentComponent,
|
HeroParentComponent,
|
||||||
MissionControlComponent,
|
MissionControlComponent,
|
||||||
@ -34,8 +27,28 @@ import { VoteTakerComponent } from './votetaker.component';
|
|||||||
VersionChildComponent,
|
VersionChildComponent,
|
||||||
VersionParentComponent,
|
VersionParentComponent,
|
||||||
VoterComponent,
|
VoterComponent,
|
||||||
VoteTakerComponent,
|
VoteTakerComponent
|
||||||
|
];
|
||||||
|
|
||||||
|
const schemas: any[] = [];
|
||||||
|
|
||||||
|
// Include Countdown examples
|
||||||
|
// unless in e2e tests which they break.
|
||||||
|
if (!/e2e/.test(location.search)) {
|
||||||
|
console.log('adding countdown timer examples');
|
||||||
|
directives.push(CountdownLocalVarParentComponent);
|
||||||
|
directives.push(CountdownViewChildParentComponent);
|
||||||
|
} else {
|
||||||
|
// In e2e test use CUSTOM_ELEMENTS_SCHEMA to suppress unknown element errors
|
||||||
|
schemas.push(CUSTOM_ELEMENTS_SCHEMA);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
BrowserModule
|
||||||
],
|
],
|
||||||
|
declarations: directives,
|
||||||
bootstrap: [ AppComponent ],
|
bootstrap: [ AppComponent ],
|
||||||
|
schemas
|
||||||
})
|
})
|
||||||
export class AppModule { }
|
export class AppModule { }
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Component, OnDestroy } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-countdown-timer',
|
selector: 'app-countdown-timer',
|
||||||
template: '<p>{{message}}</p>'
|
template: '<p>{{message}}</p>'
|
||||||
})
|
})
|
||||||
export class CountdownTimerComponent implements OnDestroy {
|
export class CountdownTimerComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
intervalId = 0;
|
intervalId = 0;
|
||||||
message = '';
|
message = '';
|
||||||
seconds = 11;
|
seconds = 11;
|
||||||
|
|
||||||
|
clearTimer() { clearInterval(this.intervalId); }
|
||||||
|
|
||||||
|
ngOnInit() { this.start(); }
|
||||||
ngOnDestroy() { this.clearTimer(); }
|
ngOnDestroy() { this.clearTimer(); }
|
||||||
|
|
||||||
start() { this.countDown(); }
|
start() { this.countDown(); }
|
||||||
@ -19,8 +22,6 @@ export class CountdownTimerComponent implements OnDestroy {
|
|||||||
this.message = `Holding at T-${this.seconds} seconds`;
|
this.message = `Holding at T-${this.seconds} seconds`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private clearTimer() { clearInterval(this.intervalId); }
|
|
||||||
|
|
||||||
private countDown() {
|
private countDown() {
|
||||||
this.clearTimer();
|
this.clearTimer();
|
||||||
this.intervalId = window.setInterval(() => {
|
this.intervalId = window.setInterval(() => {
|
||||||
|
@ -1,31 +1,31 @@
|
|||||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
import { TestBed, async } from '@angular/core/testing';
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { ReactiveModule } from './reactive/reactive.module';
|
|
||||||
import { TemplateModule } from './template/template.module';
|
import { TemplateModule } from './template/template.module';
|
||||||
|
import { ReactiveModule } from './reactive/reactive.module';
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
describe('AppComponent', () => {
|
||||||
beforeEach(waitForAsync(() => {
|
|
||||||
TestBed
|
beforeEach(async(() => {
|
||||||
.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [ReactiveModule, TemplateModule],
|
imports: [ReactiveModule, TemplateModule],
|
||||||
declarations: [AppComponent],
|
declarations: [
|
||||||
})
|
AppComponent
|
||||||
.compileComponents();
|
],
|
||||||
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should create the app', waitForAsync(() => {
|
it('should create the app', async(() => {
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
const app = fixture.componentInstance;
|
const app = fixture.componentInstance;
|
||||||
|
|
||||||
expect(app).toBeTruthy();
|
expect(app).toBeTruthy();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should render title', waitForAsync(() => {
|
it('should render title', async(() => {
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const compiled = fixture.debugElement.nativeElement;
|
const compiled = fixture.debugElement.nativeElement;
|
||||||
expect(compiled.querySelector('h1').textContent).toContain('Forms Overview');
|
expect(compiled.querySelector('h1').textContent).toContain('Forms Overview');
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
|
|
||||||
import { createNewEvent } from '../../shared/utils';
|
|
||||||
import { FavoriteColorComponent } from './favorite-color.component';
|
import { FavoriteColorComponent } from './favorite-color.component';
|
||||||
|
import { createNewEvent } from '../../shared/utils';
|
||||||
|
|
||||||
describe('Favorite Color Component', () => {
|
describe('Favorite Color Component', () => {
|
||||||
let component: FavoriteColorComponent;
|
let component: FavoriteColorComponent;
|
||||||
let fixture: ComponentFixture<FavoriteColorComponent>;
|
let fixture: ComponentFixture<FavoriteColorComponent>;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule(
|
imports: [ ReactiveFormsModule ],
|
||||||
{imports: [ReactiveFormsModule], declarations: [FavoriteColorComponent]})
|
declarations: [ FavoriteColorComponent ]
|
||||||
.compileComponents();
|
})
|
||||||
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testing';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
import { createNewEvent } from '../../shared/utils';
|
|
||||||
import { FavoriteColorComponent } from './favorite-color.component';
|
import { FavoriteColorComponent } from './favorite-color.component';
|
||||||
|
import { createNewEvent } from '../../shared/utils';
|
||||||
|
|
||||||
describe('FavoriteColorComponent', () => {
|
describe('FavoriteColorComponent', () => {
|
||||||
let component: FavoriteColorComponent;
|
let component: FavoriteColorComponent;
|
||||||
let fixture: ComponentFixture<FavoriteColorComponent>;
|
let fixture: ComponentFixture<FavoriteColorComponent>;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({imports: [FormsModule], declarations: [FavoriteColorComponent]})
|
TestBed.configureTestingModule({
|
||||||
.compileComponents();
|
imports: [ FormsModule ],
|
||||||
|
declarations: [ FavoriteColorComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -25,29 +28,29 @@ describe('FavoriteColorComponent', () => {
|
|||||||
|
|
||||||
// #docregion model-to-view
|
// #docregion model-to-view
|
||||||
it('should update the favorite color on the input field', fakeAsync(() => {
|
it('should update the favorite color on the input field', fakeAsync(() => {
|
||||||
component.favoriteColor = 'Blue';
|
component.favoriteColor = 'Blue';
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
tick();
|
tick();
|
||||||
|
|
||||||
const input = fixture.nativeElement.querySelector('input');
|
const input = fixture.nativeElement.querySelector('input');
|
||||||
|
|
||||||
expect(input.value).toBe('Blue');
|
expect(input.value).toBe('Blue');
|
||||||
}));
|
}));
|
||||||
// #enddocregion model-to-view
|
// #enddocregion model-to-view
|
||||||
|
|
||||||
// #docregion view-to-model
|
// #docregion view-to-model
|
||||||
it('should update the favorite color in the component', fakeAsync(() => {
|
it('should update the favorite color in the component', fakeAsync(() => {
|
||||||
const input = fixture.nativeElement.querySelector('input');
|
const input = fixture.nativeElement.querySelector('input');
|
||||||
const event = createNewEvent('input');
|
const event = createNewEvent('input');
|
||||||
|
|
||||||
input.value = 'Red';
|
input.value = 'Red';
|
||||||
input.dispatchEvent(event);
|
input.dispatchEvent(event);
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(component.favoriteColor).toEqual('Red');
|
expect(component.favoriteColor).toEqual('Red');
|
||||||
}));
|
}));
|
||||||
// #enddocregion view-to-model
|
// #enddocregion view-to-model
|
||||||
});
|
});
|
||||||
|
@ -24,7 +24,7 @@ export class UploaderService {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
upload(file: File) {
|
upload(file: File) {
|
||||||
if (!file) { return of<string>(); }
|
if (!file) { return; }
|
||||||
|
|
||||||
// COULD HAVE WRITTEN:
|
// COULD HAVE WRITTEN:
|
||||||
// return this.http.post('/upload/file', file, {
|
// return this.http.post('/upload/file', file, {
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
<!-- #enddocregion translated-plural -->
|
<!-- #enddocregion translated-plural -->
|
||||||
<!-- #docregion translated-select -->
|
<!-- #docregion translated-select -->
|
||||||
<!-- #docregion translate-select-1 -->
|
<!-- #docregion translate-select-1 -->
|
||||||
|
</trans-unit>
|
||||||
<trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">
|
<trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">
|
||||||
<source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>
|
<source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>
|
||||||
<target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>
|
<target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// TODO: Add unit tests for this file.
|
|
||||||
// tslint:disable: no-output-native
|
// tslint:disable: no-output-native
|
||||||
// #docregion
|
// #docregion
|
||||||
import { Component, Output, OnInit, EventEmitter, NgModule } from '@angular/core';
|
import { Component, Output, OnInit, EventEmitter, NgModule } from '@angular/core';
|
||||||
|
@ -2,11 +2,7 @@
|
|||||||
"tests": [
|
"tests": [
|
||||||
{
|
{
|
||||||
"cmd": "yarn",
|
"cmd": "yarn",
|
||||||
"args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"]
|
"args": [ "tsc", "--project", "./tsconfig.app.json" ]
|
||||||
},
|
|
||||||
{
|
|
||||||
"cmd": "yarn",
|
|
||||||
"args": ["jasmine", "out-tsc/**/*.spec.js"]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
import { docRegionFromEvent, docRegionSubscriber } from './creating';
|
|
||||||
|
|
||||||
describe('observables', () => {
|
|
||||||
it('should create an observable using the constructor', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
docRegionSubscriber(console);
|
|
||||||
expect(console.log).toHaveBeenCalledTimes(4);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
[1],
|
|
||||||
[2],
|
|
||||||
[3],
|
|
||||||
['Finished sequence'],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should listen to input changes', () => {
|
|
||||||
let triggerInputChange;
|
|
||||||
const input = {
|
|
||||||
value: 'Test',
|
|
||||||
addEventListener: jasmine
|
|
||||||
.createSpy('addEvent')
|
|
||||||
.and.callFake((eventName: string, cb: (e) => void) => {
|
|
||||||
if (eventName === 'keydown') {
|
|
||||||
triggerInputChange = cb;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
removeEventListener: jasmine.createSpy('removeEventListener'),
|
|
||||||
};
|
|
||||||
|
|
||||||
const document = { getElementById: () => input };
|
|
||||||
docRegionFromEvent(document);
|
|
||||||
triggerInputChange({keyCode: 65});
|
|
||||||
expect(input.value).toBe('Test');
|
|
||||||
|
|
||||||
triggerInputChange({keyCode: 27});
|
|
||||||
expect(input.value).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call removeEventListener when unsubscribing', (doneFn: DoneFn) => {
|
|
||||||
const input = {
|
|
||||||
addEventListener: jasmine.createSpy('addEvent'),
|
|
||||||
removeEventListener: jasmine
|
|
||||||
.createSpy('removeEvent')
|
|
||||||
.and.callFake((eventName: string, cb: (e) => void) => {
|
|
||||||
if (eventName === 'keydown') {
|
|
||||||
doneFn();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
const document = { getElementById: () => input };
|
|
||||||
const subscription = docRegionFromEvent(document);
|
|
||||||
subscription.unsubscribe();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,39 +1,38 @@
|
|||||||
// #docplaster
|
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
export function docRegionSubscriber(console) {
|
// #docregion subscriber
|
||||||
// #docregion subscriber
|
|
||||||
// This function runs when subscribe() is called
|
|
||||||
function sequenceSubscriber(observer) {
|
|
||||||
// synchronously deliver 1, 2, and 3, then complete
|
|
||||||
observer.next(1);
|
|
||||||
observer.next(2);
|
|
||||||
observer.next(3);
|
|
||||||
observer.complete();
|
|
||||||
|
|
||||||
// unsubscribe function doesn't need to do anything in this
|
// This function runs when subscribe() is called
|
||||||
// because values are delivered synchronously
|
function sequenceSubscriber(observer) {
|
||||||
return {unsubscribe() {}};
|
// synchronously deliver 1, 2, and 3, then complete
|
||||||
}
|
observer.next(1);
|
||||||
|
observer.next(2);
|
||||||
|
observer.next(3);
|
||||||
|
observer.complete();
|
||||||
|
|
||||||
// Create a new Observable that will deliver the above sequence
|
// unsubscribe function doesn't need to do anything in this
|
||||||
const sequence = new Observable(sequenceSubscriber);
|
// because values are delivered synchronously
|
||||||
|
return {unsubscribe() {}};
|
||||||
// execute the Observable and print the result of each notification
|
|
||||||
sequence.subscribe({
|
|
||||||
next(num) { console.log(num); },
|
|
||||||
complete() { console.log('Finished sequence'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// Logs:
|
|
||||||
// 1
|
|
||||||
// 2
|
|
||||||
// 3
|
|
||||||
// Finished sequence
|
|
||||||
// #enddocregion subscriber
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a new Observable that will deliver the above sequence
|
||||||
|
const sequence = new Observable(sequenceSubscriber);
|
||||||
|
|
||||||
|
// execute the Observable and print the result of each notification
|
||||||
|
sequence.subscribe({
|
||||||
|
next(num) { console.log(num); },
|
||||||
|
complete() { console.log('Finished sequence'); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Logs:
|
||||||
|
// 1
|
||||||
|
// 2
|
||||||
|
// 3
|
||||||
|
// Finished sequence
|
||||||
|
|
||||||
|
// #enddocregion subscriber
|
||||||
|
|
||||||
// #docregion fromevent
|
// #docregion fromevent
|
||||||
|
|
||||||
function fromEvent(target, eventName) {
|
function fromEvent(target, eventName) {
|
||||||
@ -52,18 +51,16 @@ function fromEvent(target, eventName) {
|
|||||||
|
|
||||||
// #enddocregion fromevent
|
// #enddocregion fromevent
|
||||||
|
|
||||||
export function docRegionFromEvent(document) {
|
// #docregion fromevent_use
|
||||||
// #docregion fromevent_use
|
|
||||||
|
|
||||||
const ESC_KEY = 27;
|
const ESC_KEY = 27;
|
||||||
const nameInput = document.getElementById('name') as HTMLInputElement;
|
const nameInput = document.getElementById('name') as HTMLInputElement;
|
||||||
|
|
||||||
const subscription = fromEvent(nameInput, 'keydown').subscribe((e: KeyboardEvent) => {
|
const subscription = fromEvent(nameInput, 'keydown')
|
||||||
|
.subscribe((e: KeyboardEvent) => {
|
||||||
if (e.keyCode === ESC_KEY) {
|
if (e.keyCode === ESC_KEY) {
|
||||||
nameInput.value = '';
|
nameInput.value = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// #enddocregion fromevent_use
|
|
||||||
return subscription;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// #enddocregion fromevent_use
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// TODO: Add unit tests for this file.
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
// #docregion
|
// #docregion
|
||||||
|
|
||||||
// Create an Observable that will start listening to geolocation updates
|
// Create an Observable that will start listening to geolocation updates
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
import { docRegionDelaySequence, docRegionMulticastSequence } from './multicasting';
|
|
||||||
|
|
||||||
describe('multicasting', () => {
|
|
||||||
let console;
|
|
||||||
beforeEach(() => {
|
|
||||||
jasmine.clock().install();
|
|
||||||
console = {log: jasmine.createSpy('log')};
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
jasmine.clock().uninstall();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create an observable and emit in sequence', () => {
|
|
||||||
docRegionDelaySequence(console);
|
|
||||||
jasmine.clock().tick(10000);
|
|
||||||
expect(console.log).toHaveBeenCalledTimes(12);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
[1],
|
|
||||||
['1st subscribe: 1'],
|
|
||||||
['2nd subscribe: 1'],
|
|
||||||
[2],
|
|
||||||
['1st subscribe: 2'],
|
|
||||||
['2nd subscribe: 2'],
|
|
||||||
[3],
|
|
||||||
['Finished sequence'],
|
|
||||||
['1st subscribe: 3'],
|
|
||||||
['1st sequence finished.'],
|
|
||||||
['2nd subscribe: 3'],
|
|
||||||
['2nd sequence finished.']
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create an observable and multicast the emissions', () => {
|
|
||||||
docRegionMulticastSequence(console);
|
|
||||||
jasmine.clock().tick(10000);
|
|
||||||
expect(console.log).toHaveBeenCalledTimes(7);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
['1st subscribe: 1'],
|
|
||||||
['1st subscribe: 2'],
|
|
||||||
['2nd subscribe: 2'],
|
|
||||||
['1st subscribe: 3'],
|
|
||||||
['2nd subscribe: 3'],
|
|
||||||
['1st sequence finished.'],
|
|
||||||
['2nd sequence finished.']
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,160 +1,155 @@
|
|||||||
// #docplaster
|
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
export function docRegionDelaySequence(console) {
|
// #docregion delay_sequence
|
||||||
// #docregion delay_sequence
|
|
||||||
function sequenceSubscriber(observer) {
|
|
||||||
const seq = [1, 2, 3];
|
|
||||||
let timeoutId;
|
|
||||||
|
|
||||||
// Will run through an array of numbers, emitting one value
|
function sequenceSubscriber(observer) {
|
||||||
// per second until it gets to the end of the array.
|
const seq = [1, 2, 3];
|
||||||
function doInSequence(arr, idx) {
|
let timeoutId;
|
||||||
timeoutId = setTimeout(() => {
|
|
||||||
observer.next(arr[idx]);
|
|
||||||
if (idx === arr.length - 1) {
|
|
||||||
observer.complete();
|
|
||||||
} else {
|
|
||||||
doInSequence(arr, ++idx);
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
doInSequence(seq, 0);
|
// Will run through an array of numbers, emitting one value
|
||||||
|
|
||||||
// Unsubscribe should clear the timeout to stop execution
|
|
||||||
return {
|
|
||||||
unsubscribe() {
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new Observable that will deliver the above sequence
|
|
||||||
const sequence = new Observable(sequenceSubscriber);
|
|
||||||
|
|
||||||
sequence.subscribe({
|
|
||||||
next(num) { console.log(num); },
|
|
||||||
complete() { console.log('Finished sequence'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// Logs:
|
|
||||||
// (at 1 second): 1
|
|
||||||
// (at 2 seconds): 2
|
|
||||||
// (at 3 seconds): 3
|
|
||||||
// (at 3 seconds): Finished sequence
|
|
||||||
|
|
||||||
// #enddocregion delay_sequence
|
|
||||||
|
|
||||||
// #docregion subscribe_twice
|
|
||||||
|
|
||||||
// Subscribe starts the clock, and will emit after 1 second
|
|
||||||
sequence.subscribe({
|
|
||||||
next(num) { console.log('1st subscribe: ' + num); },
|
|
||||||
complete() { console.log('1st sequence finished.'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// After 1/2 second, subscribe again.
|
|
||||||
setTimeout(() => {
|
|
||||||
sequence.subscribe({
|
|
||||||
next(num) { console.log('2nd subscribe: ' + num); },
|
|
||||||
complete() { console.log('2nd sequence finished.'); }
|
|
||||||
});
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
// Logs:
|
|
||||||
// (at 1 second): 1st subscribe: 1
|
|
||||||
// (at 1.5 seconds): 2nd subscribe: 1
|
|
||||||
// (at 2 seconds): 1st subscribe: 2
|
|
||||||
// (at 2.5 seconds): 2nd subscribe: 2
|
|
||||||
// (at 3 seconds): 1st subscribe: 3
|
|
||||||
// (at 3 seconds): 1st sequence finished
|
|
||||||
// (at 3.5 seconds): 2nd subscribe: 3
|
|
||||||
// (at 3.5 seconds): 2nd sequence finished
|
|
||||||
|
|
||||||
// #enddocregion subscribe_twice
|
|
||||||
}
|
|
||||||
|
|
||||||
export function docRegionMulticastSequence(console) {
|
|
||||||
// #docregion multicast_sequence
|
|
||||||
function multicastSequenceSubscriber() {
|
|
||||||
const seq = [1, 2, 3];
|
|
||||||
// Keep track of each observer (one for every active subscription)
|
|
||||||
const observers = [];
|
|
||||||
// Still a single timeoutId because there will only ever be one
|
|
||||||
// set of values being generated, multicasted to each subscriber
|
|
||||||
let timeoutId;
|
|
||||||
|
|
||||||
// Return the subscriber function (runs when subscribe()
|
|
||||||
// function is invoked)
|
|
||||||
return observer => {
|
|
||||||
observers.push(observer);
|
|
||||||
// When this is the first subscription, start the sequence
|
|
||||||
if (observers.length === 1) {
|
|
||||||
timeoutId = doSequence({
|
|
||||||
next(val) {
|
|
||||||
// Iterate through observers and notify all subscriptions
|
|
||||||
observers.forEach(obs => obs.next(val));
|
|
||||||
},
|
|
||||||
complete() {
|
|
||||||
// Notify all complete callbacks
|
|
||||||
observers.slice(0).forEach(obs => obs.complete());
|
|
||||||
}
|
|
||||||
}, seq, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
unsubscribe() {
|
|
||||||
// Remove from the observers array so it's no longer notified
|
|
||||||
observers.splice(observers.indexOf(observer), 1);
|
|
||||||
// If there's no more listeners, do cleanup
|
|
||||||
if (observers.length === 0) {
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run through an array of numbers, emitting one value
|
|
||||||
// per second until it gets to the end of the array.
|
// per second until it gets to the end of the array.
|
||||||
function doSequence(observer, arr, idx) {
|
function doInSequence(arr, idx) {
|
||||||
return setTimeout(() => {
|
timeoutId = setTimeout(() => {
|
||||||
observer.next(arr[idx]);
|
observer.next(arr[idx]);
|
||||||
if (idx === arr.length - 1) {
|
if (idx === arr.length - 1) {
|
||||||
observer.complete();
|
observer.complete();
|
||||||
} else {
|
} else {
|
||||||
doSequence(observer, arr, ++idx);
|
doInSequence(arr, ++idx);
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new Observable that will deliver the above sequence
|
doInSequence(seq, 0);
|
||||||
const multicastSequence = new Observable(multicastSequenceSubscriber());
|
|
||||||
|
|
||||||
// Subscribe starts the clock, and begins to emit after 1 second
|
// Unsubscribe should clear the timeout to stop execution
|
||||||
multicastSequence.subscribe({
|
return {unsubscribe() {
|
||||||
next(num) { console.log('1st subscribe: ' + num); },
|
clearTimeout(timeoutId);
|
||||||
complete() { console.log('1st sequence finished.'); }
|
}};
|
||||||
});
|
|
||||||
|
|
||||||
// After 1 1/2 seconds, subscribe again (should "miss" the first value).
|
|
||||||
setTimeout(() => {
|
|
||||||
multicastSequence.subscribe({
|
|
||||||
next(num) { console.log('2nd subscribe: ' + num); },
|
|
||||||
complete() { console.log('2nd sequence finished.'); }
|
|
||||||
});
|
|
||||||
}, 1500);
|
|
||||||
|
|
||||||
// Logs:
|
|
||||||
// (at 1 second): 1st subscribe: 1
|
|
||||||
// (at 2 seconds): 1st subscribe: 2
|
|
||||||
// (at 2 seconds): 2nd subscribe: 2
|
|
||||||
// (at 3 seconds): 1st subscribe: 3
|
|
||||||
// (at 3 seconds): 1st sequence finished
|
|
||||||
// (at 3 seconds): 2nd subscribe: 3
|
|
||||||
// (at 3 seconds): 2nd sequence finished
|
|
||||||
|
|
||||||
// #enddocregion multicast_sequence
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a new Observable that will deliver the above sequence
|
||||||
|
const sequence = new Observable(sequenceSubscriber);
|
||||||
|
|
||||||
|
sequence.subscribe({
|
||||||
|
next(num) { console.log(num); },
|
||||||
|
complete() { console.log('Finished sequence'); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Logs:
|
||||||
|
// (at 1 second): 1
|
||||||
|
// (at 2 seconds): 2
|
||||||
|
// (at 3 seconds): 3
|
||||||
|
// (at 3 seconds): Finished sequence
|
||||||
|
|
||||||
|
// #enddocregion delay_sequence
|
||||||
|
|
||||||
|
// #docregion subscribe_twice
|
||||||
|
|
||||||
|
// Subscribe starts the clock, and will emit after 1 second
|
||||||
|
sequence.subscribe({
|
||||||
|
next(num) { console.log('1st subscribe: ' + num); },
|
||||||
|
complete() { console.log('1st sequence finished.'); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// After 1/2 second, subscribe again.
|
||||||
|
setTimeout(() => {
|
||||||
|
sequence.subscribe({
|
||||||
|
next(num) { console.log('2nd subscribe: ' + num); },
|
||||||
|
complete() { console.log('2nd sequence finished.'); }
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
// Logs:
|
||||||
|
// (at 1 second): 1st subscribe: 1
|
||||||
|
// (at 1.5 seconds): 2nd subscribe: 1
|
||||||
|
// (at 2 seconds): 1st subscribe: 2
|
||||||
|
// (at 2.5 seconds): 2nd subscribe: 2
|
||||||
|
// (at 3 seconds): 1st subscribe: 3
|
||||||
|
// (at 3 seconds): 1st sequence finished
|
||||||
|
// (at 3.5 seconds): 2nd subscribe: 3
|
||||||
|
// (at 3.5 seconds): 2nd sequence finished
|
||||||
|
|
||||||
|
// #enddocregion subscribe_twice
|
||||||
|
|
||||||
|
// #docregion multicast_sequence
|
||||||
|
|
||||||
|
function multicastSequenceSubscriber() {
|
||||||
|
const seq = [1, 2, 3];
|
||||||
|
// Keep track of each observer (one for every active subscription)
|
||||||
|
const observers = [];
|
||||||
|
// Still a single timeoutId because there will only ever be one
|
||||||
|
// set of values being generated, multicasted to each subscriber
|
||||||
|
let timeoutId;
|
||||||
|
|
||||||
|
// Return the subscriber function (runs when subscribe()
|
||||||
|
// function is invoked)
|
||||||
|
return (observer) => {
|
||||||
|
observers.push(observer);
|
||||||
|
// When this is the first subscription, start the sequence
|
||||||
|
if (observers.length === 1) {
|
||||||
|
timeoutId = doSequence({
|
||||||
|
next(val) {
|
||||||
|
// Iterate through observers and notify all subscriptions
|
||||||
|
observers.forEach(obs => obs.next(val));
|
||||||
|
},
|
||||||
|
complete() {
|
||||||
|
// Notify all complete callbacks
|
||||||
|
observers.slice(0).forEach(obs => obs.complete());
|
||||||
|
}
|
||||||
|
}, seq, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
unsubscribe() {
|
||||||
|
// Remove from the observers array so it's no longer notified
|
||||||
|
observers.splice(observers.indexOf(observer), 1);
|
||||||
|
// If there's no more listeners, do cleanup
|
||||||
|
if (observers.length === 0) {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run through an array of numbers, emitting one value
|
||||||
|
// per second until it gets to the end of the array.
|
||||||
|
function doSequence(observer, arr, idx) {
|
||||||
|
return setTimeout(() => {
|
||||||
|
observer.next(arr[idx]);
|
||||||
|
if (idx === arr.length - 1) {
|
||||||
|
observer.complete();
|
||||||
|
} else {
|
||||||
|
doSequence(observer, arr, ++idx);
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new Observable that will deliver the above sequence
|
||||||
|
const multicastSequence = new Observable(multicastSequenceSubscriber());
|
||||||
|
|
||||||
|
// Subscribe starts the clock, and begins to emit after 1 second
|
||||||
|
multicastSequence.subscribe({
|
||||||
|
next(num) { console.log('1st subscribe: ' + num); },
|
||||||
|
complete() { console.log('1st sequence finished.'); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// After 1 1/2 seconds, subscribe again (should "miss" the first value).
|
||||||
|
setTimeout(() => {
|
||||||
|
multicastSequence.subscribe({
|
||||||
|
next(num) { console.log('2nd subscribe: ' + num); },
|
||||||
|
complete() { console.log('2nd sequence finished.'); }
|
||||||
|
});
|
||||||
|
}, 1500);
|
||||||
|
|
||||||
|
// Logs:
|
||||||
|
// (at 1 second): 1st subscribe: 1
|
||||||
|
// (at 2 seconds): 1st subscribe: 2
|
||||||
|
// (at 2 seconds): 2nd subscribe: 2
|
||||||
|
// (at 3 seconds): 1st subscribe: 3
|
||||||
|
// (at 3 seconds): 1st sequence finished
|
||||||
|
// (at 3 seconds): 2nd subscribe: 3
|
||||||
|
// (at 3 seconds): 2nd sequence finished
|
||||||
|
|
||||||
|
// #enddocregion multicast_sequence
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
import { docRegionObserver } from './subscribing';
|
|
||||||
|
|
||||||
describe('subscribing', () => {
|
|
||||||
it('should subscribe and emit', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
docRegionObserver(console);
|
|
||||||
expect(console.log).toHaveBeenCalledTimes(8);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
['Observer got a next value: 1'],
|
|
||||||
['Observer got a next value: 2'],
|
|
||||||
['Observer got a next value: 3'],
|
|
||||||
['Observer got a complete notification'],
|
|
||||||
['Observer got a next value: 1'],
|
|
||||||
['Observer got a next value: 2'],
|
|
||||||
['Observer got a next value: 3'],
|
|
||||||
['Observer got a complete notification'],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,35 +1,32 @@
|
|||||||
// #docplaster
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
|
|
||||||
export function docRegionObserver(console) {
|
import { Observable, of } from 'rxjs';
|
||||||
// #docregion observer
|
|
||||||
|
|
||||||
// Create simple observable that emits three values
|
// #docregion observer
|
||||||
const myObservable = of(1, 2, 3);
|
|
||||||
|
|
||||||
// Create observer object
|
// Create simple observable that emits three values
|
||||||
const myObserver = {
|
const myObservable = of(1, 2, 3);
|
||||||
next: x => console.log('Observer got a next value: ' + x),
|
|
||||||
error: err => console.error('Observer got an error: ' + err),
|
|
||||||
complete: () => console.log('Observer got a complete notification'),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Execute with the observer object
|
// Create observer object
|
||||||
myObservable.subscribe(myObserver);
|
const myObserver = {
|
||||||
|
next: x => console.log('Observer got a next value: ' + x),
|
||||||
|
error: err => console.error('Observer got an error: ' + err),
|
||||||
|
complete: () => console.log('Observer got a complete notification'),
|
||||||
|
};
|
||||||
|
|
||||||
// Logs:
|
// Execute with the observer object
|
||||||
// Observer got a next value: 1
|
myObservable.subscribe(myObserver);
|
||||||
// Observer got a next value: 2
|
// Logs:
|
||||||
// Observer got a next value: 3
|
// Observer got a next value: 1
|
||||||
// Observer got a complete notification
|
// Observer got a next value: 2
|
||||||
|
// Observer got a next value: 3
|
||||||
|
// Observer got a complete notification
|
||||||
|
|
||||||
// #enddocregion observer
|
// #enddocregion observer
|
||||||
|
|
||||||
// #docregion sub_fn
|
// #docregion sub_fn
|
||||||
myObservable.subscribe(
|
myObservable.subscribe(
|
||||||
x => console.log('Observer got a next value: ' + x),
|
x => console.log('Observer got a next value: ' + x),
|
||||||
err => console.error('Observer got an error: ' + err),
|
err => console.error('Observer got an error: ' + err),
|
||||||
() => console.log('Observer got a complete notification')
|
() => console.log('Observer got a complete notification')
|
||||||
);
|
);
|
||||||
// #enddocregion sub_fn
|
// #enddocregion sub_fn
|
||||||
}
|
|
||||||
|
@ -2,11 +2,7 @@
|
|||||||
"tests": [
|
"tests": [
|
||||||
{
|
{
|
||||||
"cmd": "yarn",
|
"cmd": "yarn",
|
||||||
"args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"]
|
"args": [ "tsc", "--project", "./tsconfig.app.json" ]
|
||||||
},
|
|
||||||
{
|
|
||||||
"cmd": "yarn",
|
|
||||||
"args": ["jasmine", "out-tsc/**/*.spec.js"]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
import { interval } from 'rxjs';
|
|
||||||
import { tap } from 'rxjs/operators';
|
|
||||||
import { backoff } from './backoff';
|
|
||||||
|
|
||||||
describe('backoff()', () => {
|
|
||||||
beforeEach(() => jasmine.clock().install());
|
|
||||||
afterEach(() => jasmine.clock().uninstall());
|
|
||||||
|
|
||||||
it('should retry in case of error', () => {
|
|
||||||
const mockConsole = {log: jasmine.createSpy('log')};
|
|
||||||
const source = interval(10).pipe(
|
|
||||||
tap(i => {
|
|
||||||
if (i > 0) {
|
|
||||||
throw new Error('Test error');
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
backoff(3, 100),
|
|
||||||
);
|
|
||||||
source.subscribe({
|
|
||||||
next: v => mockConsole.log(`Emitted: ${v}`),
|
|
||||||
error: e => mockConsole.log(`Errored: ${e.message || e}`),
|
|
||||||
complete: () => mockConsole.log('Completed'),
|
|
||||||
});
|
|
||||||
|
|
||||||
// Initial try:
|
|
||||||
// Errors on second emission and schedules retrying (with delay).
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]);
|
|
||||||
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]);
|
|
||||||
mockConsole.log.calls.reset();
|
|
||||||
|
|
||||||
// First re-attempt after 100ms:
|
|
||||||
// Errors again on second emission and schedules retrying (with larger delay).
|
|
||||||
jasmine.clock().tick(100);
|
|
||||||
expect(mockConsole.log).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]);
|
|
||||||
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]);
|
|
||||||
mockConsole.log.calls.reset();
|
|
||||||
|
|
||||||
// Second re-attempt after 400ms:
|
|
||||||
// Errors again on second emission and schedules retrying (with even larger delay).
|
|
||||||
jasmine.clock().tick(400);
|
|
||||||
expect(mockConsole.log).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]);
|
|
||||||
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]);
|
|
||||||
mockConsole.log.calls.reset();
|
|
||||||
|
|
||||||
// Third re-attempt after 900ms:
|
|
||||||
// Errors again on second emission and gives up (no retrying).
|
|
||||||
jasmine.clock().tick(900);
|
|
||||||
expect(mockConsole.log).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]);
|
|
||||||
mockConsole.log.calls.reset();
|
|
||||||
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([['Errored: Test error']]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,32 +1,23 @@
|
|||||||
// #docplaster
|
|
||||||
// #docregion
|
|
||||||
import { of, pipe, range, throwError, timer, zip } from 'rxjs';
|
|
||||||
import { ajax } from 'rxjs/ajax';
|
|
||||||
import { map, mergeMap, retryWhen } from 'rxjs/operators';
|
|
||||||
|
|
||||||
export function backoff(maxTries, delay) {
|
import { pipe, range, timer, zip } from 'rxjs';
|
||||||
return pipe(
|
import { ajax } from 'rxjs/ajax';
|
||||||
retryWhen(attempts =>
|
import { retryWhen, map, mergeMap } from 'rxjs/operators';
|
||||||
zip(range(1, maxTries + 1), attempts).pipe(
|
|
||||||
mergeMap(([i, err]) => (i > maxTries) ? throwError(err) : of(i)),
|
function backoff(maxTries, ms) {
|
||||||
map(i => i * i),
|
return pipe(
|
||||||
mergeMap(v => timer(v * delay)),
|
retryWhen(attempts => zip(range(1, maxTries), attempts)
|
||||||
),
|
.pipe(
|
||||||
),
|
map(([i]) => i * i),
|
||||||
);
|
mergeMap(i => timer(i * ms))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #enddocregion
|
|
||||||
/*
|
|
||||||
This function declaration is necessary to ensure that it does not get called
|
|
||||||
when running the unit tests. It will not get rendered into the docs.
|
|
||||||
The indentation needs to start in the leftmost level position as well because of how
|
|
||||||
the docplaster combines the different regions together.
|
|
||||||
*/
|
|
||||||
function docRegionAjaxCall() {
|
|
||||||
// #docregion
|
|
||||||
ajax('/api/endpoint')
|
ajax('/api/endpoint')
|
||||||
.pipe(backoff(3, 250))
|
.pipe(backoff(3, 250))
|
||||||
.subscribe(function handleData(data) { /* ... */ });
|
.subscribe(data => handleData(data));
|
||||||
// #enddocregion
|
|
||||||
|
function handleData(data) {
|
||||||
|
// ...
|
||||||
}
|
}
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
import { of } from 'rxjs';
|
|
||||||
import { docRegionTypeahead } from './typeahead';
|
|
||||||
|
|
||||||
describe('typeahead', () => {
|
|
||||||
let document;
|
|
||||||
let ajax;
|
|
||||||
let triggertInputChange;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
jasmine.clock().install();
|
|
||||||
const input = {
|
|
||||||
addEventListener: jasmine
|
|
||||||
.createSpy('addEvent')
|
|
||||||
.and.callFake((eventName: string, cb: (e) => void) => {
|
|
||||||
if (eventName === 'input') {
|
|
||||||
triggertInputChange = cb;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
removeEventListener: jasmine.createSpy('removeEvent'),
|
|
||||||
};
|
|
||||||
|
|
||||||
document = { getElementById: (id: string) => input };
|
|
||||||
ajax = jasmine.createSpy('ajax').and.callFake((url: string) => of('foo bar'));
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
jasmine.clock().uninstall();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should make an ajax call to the corrent endpoint', () => {
|
|
||||||
docRegionTypeahead(document, ajax);
|
|
||||||
triggertInputChange({ target: { value: 'foo' } });
|
|
||||||
jasmine.clock().tick(11);
|
|
||||||
expect(ajax).toHaveBeenCalledWith('/api/endpoint?search=foo');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not make an ajax call, when the input length < 3', () => {
|
|
||||||
docRegionTypeahead(document, ajax);
|
|
||||||
triggertInputChange({ target: { value: '' } });
|
|
||||||
jasmine.clock().tick(11);
|
|
||||||
expect(ajax).not.toHaveBeenCalled();
|
|
||||||
triggertInputChange({ target: { value: 'fo' } });
|
|
||||||
jasmine.clock().tick(11);
|
|
||||||
expect(ajax).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not make an ajax call for intermediate values when debouncing', () => {
|
|
||||||
docRegionTypeahead(document, ajax);
|
|
||||||
triggertInputChange({ target: { value: 'foo' } });
|
|
||||||
jasmine.clock().tick(9);
|
|
||||||
triggertInputChange({ target: { value: 'bar' } });
|
|
||||||
jasmine.clock().tick(9);
|
|
||||||
triggertInputChange({ target: { value: 'baz' } });
|
|
||||||
jasmine.clock().tick(9);
|
|
||||||
triggertInputChange({ target: { value: 'qux' } });
|
|
||||||
expect(ajax).not.toHaveBeenCalled();
|
|
||||||
jasmine.clock().tick(10);
|
|
||||||
expect(ajax).toHaveBeenCalledTimes(1);
|
|
||||||
expect(ajax).toHaveBeenCalledWith('/api/endpoint?search=qux');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not make an ajax call, when the input value has not changed', () => {
|
|
||||||
docRegionTypeahead(document, ajax);
|
|
||||||
triggertInputChange({ target: { value: 'foo' } });
|
|
||||||
jasmine.clock().tick(11);
|
|
||||||
expect(ajax).toHaveBeenCalled();
|
|
||||||
ajax.calls.reset();
|
|
||||||
triggertInputChange({ target: { value: 'foo' } });
|
|
||||||
jasmine.clock().tick(11);
|
|
||||||
expect(ajax).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,32 +1,18 @@
|
|||||||
/*
|
import { fromEvent } from 'rxjs';
|
||||||
Because of how the code is merged together using the doc regions,
|
import { ajax } from 'rxjs/ajax';
|
||||||
we need to indent the imports with the function below.
|
import { debounceTime, distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators';
|
||||||
*/
|
|
||||||
// #docplaster
|
|
||||||
// #docregion
|
|
||||||
import { fromEvent } from 'rxjs';
|
|
||||||
import { ajax } from 'rxjs/ajax';
|
|
||||||
import { debounceTime, distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators';
|
|
||||||
|
|
||||||
// #enddocregion
|
|
||||||
/* tslint:disable:no-shadowed-variable */
|
|
||||||
/* tslint:disable:align */
|
|
||||||
export function docRegionTypeahead(document, ajax) {
|
|
||||||
// #docregion
|
|
||||||
const searchBox = document.getElementById('search-box');
|
|
||||||
|
|
||||||
const typeahead = fromEvent(searchBox, 'input').pipe(
|
const searchBox = document.getElementById('search-box');
|
||||||
map((e: KeyboardEvent) => (e.target as HTMLInputElement).value),
|
|
||||||
filter(text => text.length > 2),
|
|
||||||
debounceTime(10),
|
|
||||||
distinctUntilChanged(),
|
|
||||||
switchMap(searchTerm => ajax(`/api/endpoint?search=${searchTerm}`))
|
|
||||||
);
|
|
||||||
|
|
||||||
typeahead.subscribe(data => {
|
const typeahead = fromEvent(searchBox, 'input').pipe(
|
||||||
// Handle the data from the API
|
map((e: KeyboardEvent) => (e.target as HTMLInputElement).value),
|
||||||
});
|
filter(text => text.length > 2),
|
||||||
|
debounceTime(10),
|
||||||
|
distinctUntilChanged(),
|
||||||
|
switchMap(() => ajax('/api/endpoint'))
|
||||||
|
);
|
||||||
|
|
||||||
// #enddocregion
|
typeahead.subscribe(data => {
|
||||||
return typeahead;
|
// Handle the data from the API
|
||||||
}
|
});
|
||||||
|
@ -2,11 +2,7 @@
|
|||||||
"tests": [
|
"tests": [
|
||||||
{
|
{
|
||||||
"cmd": "yarn",
|
"cmd": "yarn",
|
||||||
"args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"]
|
"args": [ "tsc", "--project", "./tsconfig.app.json" ]
|
||||||
},
|
|
||||||
{
|
|
||||||
"cmd": "yarn",
|
|
||||||
"args": ["jasmine", "out-tsc/**/*.spec.js"]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
import { Subject, throwError } from 'rxjs';
|
|
||||||
import { docRegionDefault } from './error-handling';
|
|
||||||
|
|
||||||
describe('error-handling', () => {
|
|
||||||
let mockConsole;
|
|
||||||
let ajaxSubject;
|
|
||||||
let ajax;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
mockConsole = {log: jasmine.createSpy('log')};
|
|
||||||
ajaxSubject = new Subject();
|
|
||||||
ajax = jasmine
|
|
||||||
.createSpy('ajax')
|
|
||||||
.and.callFake((url: string) => ajaxSubject);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => ajaxSubject.unsubscribe());
|
|
||||||
|
|
||||||
it('should return the response object', () => {
|
|
||||||
docRegionDefault(mockConsole, ajax);
|
|
||||||
|
|
||||||
ajaxSubject.next({response: {foo: 'bar'}});
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['data: ', {foo: 'bar'}]
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an empty array when using an object without a `response` property', () => {
|
|
||||||
docRegionDefault(mockConsole, ajax);
|
|
||||||
|
|
||||||
ajaxSubject.next({foo: 'bar'});
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['data: ', []]
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an empty array when the ajax observable errors', () => {
|
|
||||||
ajax.and.returnValue(throwError('Test Error'));
|
|
||||||
|
|
||||||
docRegionDefault(mockConsole, ajax);
|
|
||||||
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['data: ', []]
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,36 +1,25 @@
|
|||||||
// #docplaster
|
|
||||||
/*
|
import { of } from 'rxjs';
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:no-shadowed-variable */
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { ajax } from 'rxjs/ajax';
|
import { ajax } from 'rxjs/ajax';
|
||||||
import { map, catchError } from 'rxjs/operators';
|
import { map, catchError } from 'rxjs/operators';
|
||||||
|
// Return "response" from the API. If an error happens,
|
||||||
|
// return an empty array.
|
||||||
|
const apiData = ajax('/api/data').pipe(
|
||||||
|
map(res => {
|
||||||
|
if (!res.response) {
|
||||||
|
throw new Error('Value expected!');
|
||||||
|
}
|
||||||
|
return res.response;
|
||||||
|
}),
|
||||||
|
catchError(err => of([]))
|
||||||
|
);
|
||||||
|
|
||||||
|
apiData.subscribe({
|
||||||
|
next(x) { console.log('data: ', x); },
|
||||||
|
error(err) { console.log('errors already caught... will not run'); }
|
||||||
|
});
|
||||||
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
export function docRegionDefault(console, ajax) {
|
|
||||||
// #docregion
|
|
||||||
// Return "response" from the API. If an error happens,
|
|
||||||
// return an empty array.
|
|
||||||
const apiData = ajax('/api/data').pipe(
|
|
||||||
map((res: any) => {
|
|
||||||
if (!res.response) {
|
|
||||||
throw new Error('Value expected!');
|
|
||||||
}
|
|
||||||
return res.response;
|
|
||||||
}),
|
|
||||||
catchError(err => of([]))
|
|
||||||
);
|
|
||||||
|
|
||||||
apiData.subscribe({
|
|
||||||
next(x) { console.log('data: ', x); },
|
|
||||||
error(err) { console.log('errors already caught... will not run'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// #enddocregion
|
|
||||||
return apiData;
|
|
||||||
}
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import { docRegionDefault } from './operators.1';
|
|
||||||
|
|
||||||
describe('squareOdd - operators.1.ts', () => {
|
|
||||||
it('should return square odds', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
docRegionDefault(console);
|
|
||||||
expect(console.log).toHaveBeenCalledTimes(3);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
[1],
|
|
||||||
[9],
|
|
||||||
[25],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,30 +1,23 @@
|
|||||||
// #docplaster
|
import { of, pipe } from 'rxjs';
|
||||||
/*
|
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { of, pipe } from 'rxjs';
|
|
||||||
import { filter, map } from 'rxjs/operators';
|
import { filter, map } from 'rxjs/operators';
|
||||||
|
|
||||||
|
const nums = of(1, 2, 3, 4, 5);
|
||||||
|
|
||||||
|
// Create a function that accepts an Observable.
|
||||||
|
const squareOddVals = pipe(
|
||||||
|
filter((n: number) => n % 2 !== 0),
|
||||||
|
map(n => n * n)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create an Observable that will run the filter and map functions
|
||||||
|
const squareOdd = squareOddVals(nums);
|
||||||
|
|
||||||
|
// Subscribe to run the combined functions
|
||||||
|
squareOdd.subscribe(x => console.log(x));
|
||||||
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
export function docRegionDefault(console) {
|
|
||||||
// #docregion
|
|
||||||
const nums = of(1, 2, 3, 4, 5);
|
|
||||||
|
|
||||||
// Create a function that accepts an Observable.
|
|
||||||
const squareOddVals = pipe(
|
|
||||||
filter((n: number) => n % 2 !== 0),
|
|
||||||
map(n => n * n)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create an Observable that will run the filter and map functions
|
|
||||||
const squareOdd = squareOddVals(nums);
|
|
||||||
|
|
||||||
// Subscribe to run the combined functions
|
|
||||||
squareOdd.subscribe(x => console.log(x));
|
|
||||||
|
|
||||||
// #enddocregion
|
|
||||||
}
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import { docRegionDefault } from './operators.2';
|
|
||||||
|
|
||||||
describe('squareOdd - operators.2.ts', () => {
|
|
||||||
it('should return square odds', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
docRegionDefault(console);
|
|
||||||
expect(console.log).toHaveBeenCalledTimes(3);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
[1],
|
|
||||||
[9],
|
|
||||||
[25],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,25 +1,16 @@
|
|||||||
// #docplaster
|
import { Observable, of } from 'rxjs';
|
||||||
/*
|
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { filter, map } from 'rxjs/operators';
|
import { filter, map } from 'rxjs/operators';
|
||||||
|
|
||||||
|
const squareOdd = of(1, 2, 3, 4, 5)
|
||||||
|
.pipe(
|
||||||
|
filter(n => n % 2 !== 0),
|
||||||
|
map(n => n * n)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Subscribe to get values
|
||||||
|
squareOdd.subscribe(x => console.log(x));
|
||||||
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
export function docRegionDefault(console) {
|
|
||||||
// #docregion
|
|
||||||
const squareOdd = of(1, 2, 3, 4, 5)
|
|
||||||
.pipe(
|
|
||||||
filter(n => n % 2 !== 0),
|
|
||||||
map(n => n * n)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Subscribe to get values
|
|
||||||
squareOdd.subscribe(x => console.log(x));
|
|
||||||
|
|
||||||
// #enddocregion
|
|
||||||
}
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import { docRegionDefault } from './operators';
|
|
||||||
|
|
||||||
describe('squaredNums - operators.ts', () => {
|
|
||||||
it('should return square odds', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
docRegionDefault(console);
|
|
||||||
expect(console.log).toHaveBeenCalledTimes(3);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
[1],
|
|
||||||
[4],
|
|
||||||
[9],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,28 +1,20 @@
|
|||||||
// #docplaster
|
|
||||||
/*
|
import { Observable, of } from 'rxjs';
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
|
|
||||||
|
const nums = of(1, 2, 3);
|
||||||
|
|
||||||
|
const squareValues = map((val: number) => val * val);
|
||||||
|
const squaredNums = squareValues(nums);
|
||||||
|
|
||||||
|
squaredNums.subscribe(x => console.log(x));
|
||||||
|
|
||||||
|
// Logs
|
||||||
|
// 1
|
||||||
|
// 4
|
||||||
|
// 9
|
||||||
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
export function docRegionDefault(console) {
|
|
||||||
// #docregion
|
|
||||||
const nums = of(1, 2, 3);
|
|
||||||
|
|
||||||
const squareValues = map((val: number) => val * val);
|
|
||||||
const squaredNums = squareValues(nums);
|
|
||||||
|
|
||||||
squaredNums.subscribe(x => console.log(x));
|
|
||||||
|
|
||||||
// Logs
|
|
||||||
// 1
|
|
||||||
// 4
|
|
||||||
// 9
|
|
||||||
|
|
||||||
// #enddocregion
|
|
||||||
}
|
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
import { of, throwError } from 'rxjs';
|
|
||||||
import { mergeMap, tap } from 'rxjs/operators';
|
|
||||||
import { docRegionDefault } from './retry-on-error';
|
|
||||||
|
|
||||||
describe('retry-on-error', () => {
|
|
||||||
let mockConsole;
|
|
||||||
beforeEach(() => mockConsole = { log: jasmine.createSpy('log') });
|
|
||||||
|
|
||||||
it('should return the response object', () => {
|
|
||||||
const ajax = () => of({ response: { foo: 'bar' } });
|
|
||||||
|
|
||||||
docRegionDefault(mockConsole, ajax);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['data: ', { foo: 'bar' }],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an empty array after 3 retries + 1 initial request', () => {
|
|
||||||
const ajax = () => {
|
|
||||||
return of({ noresponse: true }).pipe(tap(() => mockConsole.log('Subscribed to AJAX')));
|
|
||||||
};
|
|
||||||
|
|
||||||
docRegionDefault(mockConsole, ajax);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['Subscribed to AJAX'],
|
|
||||||
['Error occured.'],
|
|
||||||
['Subscribed to AJAX'],
|
|
||||||
['Error occured.'],
|
|
||||||
['Subscribed to AJAX'],
|
|
||||||
['Error occured.'],
|
|
||||||
['Subscribed to AJAX'],
|
|
||||||
['Error occured.'],
|
|
||||||
['data: ', []],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the response if the request succeeds upon retrying', () => {
|
|
||||||
// Fail on the first two requests, but succeed from the 3rd onwards.
|
|
||||||
let failCount = 2;
|
|
||||||
const ajax = () => of(null).pipe(
|
|
||||||
tap(() => mockConsole.log('Subscribed to AJAX')),
|
|
||||||
// Fail on the first 2 requests, but succeed from the 3rd onwards.
|
|
||||||
mergeMap(() => {
|
|
||||||
if (failCount > 0) {
|
|
||||||
failCount--;
|
|
||||||
return throwError('Test error');
|
|
||||||
}
|
|
||||||
return of({ response: { foo: 'bar' } });
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
docRegionDefault(mockConsole, ajax);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['Subscribed to AJAX'], // Initial request | 1st attempt overall
|
|
||||||
['Subscribed to AJAX'], // 1st retry attempt | 2nd attempt overall
|
|
||||||
['Subscribed to AJAX'], // 2nd retry attempt | 3rd attempt overall
|
|
||||||
['data: ', { foo: 'bar' }],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an empty array when the ajax observable throws an error', () => {
|
|
||||||
const ajax = () => throwError('Test Error');
|
|
||||||
|
|
||||||
docRegionDefault(mockConsole, ajax);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['data: ', []],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,35 +1,26 @@
|
|||||||
// #docplaster
|
|
||||||
/*
|
import { Observable, of } from 'rxjs';
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:no-shadowed-variable */
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { of } from 'rxjs';
|
|
||||||
import { ajax } from 'rxjs/ajax';
|
import { ajax } from 'rxjs/ajax';
|
||||||
import { map, retry, catchError } from 'rxjs/operators';
|
import { map, retry, catchError } from 'rxjs/operators';
|
||||||
|
|
||||||
|
const apiData = ajax('/api/data').pipe(
|
||||||
|
retry(3), // Retry up to 3 times before failing
|
||||||
|
map(res => {
|
||||||
|
if (!res.response) {
|
||||||
|
throw new Error('Value expected!');
|
||||||
|
}
|
||||||
|
return res.response;
|
||||||
|
}),
|
||||||
|
catchError(err => of([]))
|
||||||
|
);
|
||||||
|
|
||||||
|
apiData.subscribe({
|
||||||
|
next(x) { console.log('data: ', x); },
|
||||||
|
error(err) { console.log('errors already caught... will not run'); }
|
||||||
|
});
|
||||||
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
export function docRegionDefault(console, ajax) {
|
|
||||||
// #docregion
|
|
||||||
const apiData = ajax('/api/data').pipe(
|
|
||||||
map((res: any) => {
|
|
||||||
if (!res.response) {
|
|
||||||
console.log('Error occured.');
|
|
||||||
throw new Error('Value expected!');
|
|
||||||
}
|
|
||||||
return res.response;
|
|
||||||
}),
|
|
||||||
retry(3), // Retry up to 3 times before failing
|
|
||||||
catchError(err => of([]))
|
|
||||||
);
|
|
||||||
|
|
||||||
apiData.subscribe({
|
|
||||||
next(x) { console.log('data: ', x); },
|
|
||||||
error(err) { console.log('errors already caught... will not run'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// #enddocregion
|
|
||||||
}
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import { of } from 'rxjs';
|
|
||||||
import { docRegionPromise } from './simple-creation.1';
|
|
||||||
|
|
||||||
describe('simple-creation.1', () => {
|
|
||||||
it('should create a promise from an observable and return an empty object', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
const fetch = () => of({foo: 42});
|
|
||||||
docRegionPromise(console, fetch);
|
|
||||||
expect(console.log.calls.allArgs()).toEqual([
|
|
||||||
[{foo: 42}],
|
|
||||||
['Completed'],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,24 +0,0 @@
|
|||||||
// #docplaster
|
|
||||||
/*
|
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion promise
|
|
||||||
import { from } from 'rxjs';
|
|
||||||
|
|
||||||
// #enddocregion promise
|
|
||||||
|
|
||||||
export function docRegionPromise(console, fetch) {
|
|
||||||
// #docregion promise
|
|
||||||
// Create an Observable out of a promise
|
|
||||||
const data = from(fetch('/api/endpoint'));
|
|
||||||
// Subscribe to begin listening for async result
|
|
||||||
data.subscribe({
|
|
||||||
next(response) { console.log(response); },
|
|
||||||
error(err) { console.error('Error: ' + err); },
|
|
||||||
complete() { console.log('Completed'); }
|
|
||||||
});
|
|
||||||
|
|
||||||
// #enddocregion promise
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
import { docRegionInterval } from './simple-creation.2';
|
|
||||||
|
|
||||||
describe('simple-creation.2', () => {
|
|
||||||
beforeEach(() => jasmine.clock().install());
|
|
||||||
afterEach(() => jasmine.clock().uninstall());
|
|
||||||
|
|
||||||
it('should create an Observable that will publish a value on an interval', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
const subscription = docRegionInterval(console);
|
|
||||||
jasmine.clock().tick(1000);
|
|
||||||
expect(console.log).toHaveBeenCalledWith('It\'s been 1 seconds since subscribing!');
|
|
||||||
console.log.calls.reset();
|
|
||||||
|
|
||||||
jasmine.clock().tick(999);
|
|
||||||
expect(console.log).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
jasmine.clock().tick(1);
|
|
||||||
expect(console.log).toHaveBeenCalledWith('It\'s been 2 seconds since subscribing!');
|
|
||||||
subscription.unsubscribe();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,22 +0,0 @@
|
|||||||
// #docplaster
|
|
||||||
/*
|
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion interval
|
|
||||||
import { interval } from 'rxjs';
|
|
||||||
|
|
||||||
// #enddocregion interval
|
|
||||||
|
|
||||||
export function docRegionInterval(console) {
|
|
||||||
// #docregion interval
|
|
||||||
// Create an Observable that will publish a value on an interval
|
|
||||||
const secondsCounter = interval(1000);
|
|
||||||
// Subscribe to begin publishing values
|
|
||||||
const subscription = secondsCounter.subscribe(n =>
|
|
||||||
console.log(`It's been ${n + 1} seconds since subscribing!`));
|
|
||||||
|
|
||||||
// #enddocregion interval
|
|
||||||
return subscription;
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
import { docRegionEvent } from './simple-creation.3';
|
|
||||||
|
|
||||||
describe('simple-creation.3', () => {
|
|
||||||
let triggerMousemove;
|
|
||||||
let mockConsole;
|
|
||||||
let input;
|
|
||||||
let mockDocument;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
mockConsole = {log: jasmine.createSpy('log')};
|
|
||||||
input = {
|
|
||||||
addEventListener: jasmine
|
|
||||||
.createSpy('addEventListener')
|
|
||||||
.and.callFake((eventName, cb) => {
|
|
||||||
if (eventName === 'mousemove') {
|
|
||||||
triggerMousemove = cb;
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
removeEventListener: jasmine.createSpy('removeEventListener'),
|
|
||||||
};
|
|
||||||
mockDocument = { getElementById: () => input };
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should log coords when subscribing', () => {
|
|
||||||
docRegionEvent(mockConsole, mockDocument);
|
|
||||||
|
|
||||||
expect(mockConsole.log).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
triggerMousemove({ clientX: 50, clientY: 50 });
|
|
||||||
triggerMousemove({ clientX: 30, clientY: 50 });
|
|
||||||
triggerMousemove({ clientX: 50, clientY: 30 });
|
|
||||||
expect(mockConsole.log).toHaveBeenCalledTimes(3);
|
|
||||||
expect(mockConsole.log.calls.allArgs()).toEqual([
|
|
||||||
['Coords: 50 X 50'],
|
|
||||||
['Coords: 30 X 50'],
|
|
||||||
['Coords: 50 X 30']
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call unsubscribe when clientX and clientY are below < 40 ', () => {
|
|
||||||
docRegionEvent(mockConsole, mockDocument);
|
|
||||||
|
|
||||||
expect(mockConsole.log).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
// Ensure that we have unsubscribed.
|
|
||||||
triggerMousemove({ clientX: 30, clientY: 30 });
|
|
||||||
expect(input.removeEventListener).toHaveBeenCalledWith('mousemove', triggerMousemove, undefined);
|
|
||||||
mockConsole.log.calls.reset();
|
|
||||||
|
|
||||||
triggerMousemove({ clientX: 50, clientY: 50 });
|
|
||||||
expect(mockConsole.log).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,32 +0,0 @@
|
|||||||
// #docplaster
|
|
||||||
/*
|
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
|
||||||
*/
|
|
||||||
/* tslint:disable:align */
|
|
||||||
// #docregion event
|
|
||||||
import { fromEvent } from 'rxjs';
|
|
||||||
|
|
||||||
// #enddocregion event
|
|
||||||
|
|
||||||
export function docRegionEvent(console, document) {
|
|
||||||
// #docregion event
|
|
||||||
const el = document.getElementById('my-element');
|
|
||||||
|
|
||||||
// Create an Observable that will publish mouse movements
|
|
||||||
const mouseMoves = fromEvent(el, 'mousemove');
|
|
||||||
|
|
||||||
// Subscribe to start listening for mouse-move events
|
|
||||||
const subscription = mouseMoves.subscribe((evt: MouseEvent) => {
|
|
||||||
// Log coords of mouse movements
|
|
||||||
console.log(`Coords: ${evt.clientX} X ${evt.clientY}`);
|
|
||||||
|
|
||||||
// When the mouse is over the upper-left of the screen,
|
|
||||||
// unsubscribe to stop listening for mouse movements
|
|
||||||
if (evt.clientX < 40 && evt.clientY < 40) {
|
|
||||||
subscription.unsubscribe();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// #enddocregion event
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
import { of } from 'rxjs';
|
|
||||||
import { docRegionAjax } from './simple-creation';
|
|
||||||
|
|
||||||
describe('ajax', () => {
|
|
||||||
it('should make a request and console log the status and response', () => {
|
|
||||||
const console = {log: jasmine.createSpy('log')};
|
|
||||||
const ajax = jasmine.createSpy('ajax').and.callFake((url: string) => {
|
|
||||||
return of({status: 200, response: 'foo bar'});
|
|
||||||
});
|
|
||||||
|
|
||||||
docRegionAjax(console, ajax);
|
|
||||||
expect(console.log).toHaveBeenCalledWith(200, 'foo bar');
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,19 +1,65 @@
|
|||||||
// #docplaster
|
|
||||||
/*
|
// #docregion promise
|
||||||
Because of how the code is merged together using the doc regions,
|
|
||||||
we need to indent the imports with the function below.
|
import { from } from 'rxjs';
|
||||||
*/
|
|
||||||
/* tslint:disable:no-shadowed-variable */
|
// Create an Observable out of a promise
|
||||||
/* tslint:disable:align */
|
const data = from(fetch('/api/endpoint'));
|
||||||
|
// Subscribe to begin listening for async result
|
||||||
|
data.subscribe({
|
||||||
|
next(response) { console.log(response); },
|
||||||
|
error(err) { console.error('Error: ' + err); },
|
||||||
|
complete() { console.log('Completed'); }
|
||||||
|
});
|
||||||
|
|
||||||
|
// #enddocregion promise
|
||||||
|
|
||||||
|
// #docregion interval
|
||||||
|
|
||||||
|
import { interval } from 'rxjs';
|
||||||
|
|
||||||
|
// Create an Observable that will publish a value on an interval
|
||||||
|
const secondsCounter = interval(1000);
|
||||||
|
// Subscribe to begin publishing values
|
||||||
|
secondsCounter.subscribe(n =>
|
||||||
|
console.log(`It's been ${n} seconds since subscribing!`));
|
||||||
|
|
||||||
|
// #enddocregion interval
|
||||||
|
|
||||||
|
|
||||||
|
// #docregion event
|
||||||
|
|
||||||
|
import { fromEvent } from 'rxjs';
|
||||||
|
|
||||||
|
const el = document.getElementById('my-element');
|
||||||
|
|
||||||
|
// Create an Observable that will publish mouse movements
|
||||||
|
const mouseMoves = fromEvent(el, 'mousemove');
|
||||||
|
|
||||||
|
// Subscribe to start listening for mouse-move events
|
||||||
|
const subscription = mouseMoves.subscribe((evt: MouseEvent) => {
|
||||||
|
// Log coords of mouse movements
|
||||||
|
console.log(`Coords: ${evt.clientX} X ${evt.clientY}`);
|
||||||
|
|
||||||
|
// When the mouse is over the upper-left of the screen,
|
||||||
|
// unsubscribe to stop listening for mouse movements
|
||||||
|
if (evt.clientX < 40 && evt.clientY < 40) {
|
||||||
|
subscription.unsubscribe();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// #enddocregion event
|
||||||
|
|
||||||
|
|
||||||
// #docregion ajax
|
// #docregion ajax
|
||||||
import { ajax } from 'rxjs/ajax';
|
|
||||||
|
import { ajax } from 'rxjs/ajax';
|
||||||
|
|
||||||
// Create an Observable that will create an AJAX request
|
// Create an Observable that will create an AJAX request
|
||||||
|
const apiData = ajax('/api/data');
|
||||||
|
// Subscribe to create the request
|
||||||
|
apiData.subscribe(res => console.log(res.status, res.response));
|
||||||
|
|
||||||
// #enddocregion ajax
|
// #enddocregion ajax
|
||||||
export function docRegionAjax(console, ajax) {
|
|
||||||
// #docregion ajax
|
|
||||||
const apiData = ajax('/api/data');
|
|
||||||
// Subscribe to create the request
|
|
||||||
apiData.subscribe(res => console.log(res.status, res.response));
|
|
||||||
// #enddocregion ajax
|
|
||||||
}
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { MyLibComponent } from './my-lib.component';
|
import { MyLibComponent } from './my-lib.component';
|
||||||
|
|
||||||
@ -6,8 +6,11 @@ describe('MyLibComponent', () => {
|
|||||||
let component: MyLibComponent;
|
let component: MyLibComponent;
|
||||||
let fixture: ComponentFixture<MyLibComponent>;
|
let fixture: ComponentFixture<MyLibComponent>;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({declarations: [MyLibComponent]}).compileComponents();
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ MyLibComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
import { DebugElement } from '@angular/core';
|
|
||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
|
||||||
import { By } from '@angular/platform-browser';
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { DebugElement } from '@angular/core';
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
describe('AppComponent', () => {
|
||||||
let de: DebugElement;
|
let de: DebugElement;
|
||||||
let comp: AppComponent;
|
let comp: AppComponent;
|
||||||
let fixture: ComponentFixture<AppComponent>;
|
let fixture: ComponentFixture<AppComponent>;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({declarations: [AppComponent]}).compileComponents();
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ AppComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -19,11 +22,12 @@ describe('AppComponent', () => {
|
|||||||
de = fixture.debugElement.query(By.css('h1'));
|
de = fixture.debugElement.query(By.css('h1'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create component', () => expect(comp).toBeDefined());
|
it('should create component', () => expect(comp).toBeDefined() );
|
||||||
|
|
||||||
it('should have expected <h1> text', () => {
|
it('should have expected <h1> text', () => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const h1 = de.nativeElement;
|
const h1 = de.nativeElement;
|
||||||
expect(h1.textContent).toMatch(/angular/i, '<h1> should say something about "Angular"');
|
expect(h1.textContent).toMatch(/angular/i,
|
||||||
|
'<h1> should say something about "Angular"');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||||
|
|
||||||
<script src="node_modules/zone.js/bundles/zone.umd.js"></script>
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
<script src="systemjs.config.js"></script>
|
<script src="systemjs.config.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
@ -10,8 +10,8 @@ import { Hero } from '../shared/hero.model';
|
|||||||
template: `
|
template: `
|
||||||
<section>
|
<section>
|
||||||
Our list of heroes:
|
Our list of heroes:
|
||||||
<toh-hero *ngFor="let hero of heroes" [hero]="hero">
|
<hero-profile *ngFor="let hero of heroes" [hero]="hero">
|
||||||
</toh-hero>
|
</hero-profile>
|
||||||
Total powers: {{totalPowers}}<br>
|
Total powers: {{totalPowers}}<br>
|
||||||
Average power: {{totalPowers / heroes.length}}
|
Average power: {{totalPowers / heroes.length}}
|
||||||
</section>
|
</section>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
import { TestBed, async } from '@angular/core/testing';
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
import { AppComponent } from './app-initial.component';
|
import { AppComponent } from './app-initial.component';
|
||||||
/*
|
/*
|
||||||
@ -12,29 +12,29 @@ describe('AppComponent', () => {
|
|||||||
*/
|
*/
|
||||||
describe('AppComponent (initial CLI version)', () => {
|
describe('AppComponent (initial CLI version)', () => {
|
||||||
// #docregion
|
// #docregion
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule({
|
declarations: [
|
||||||
declarations: [AppComponent],
|
AppComponent
|
||||||
})
|
],
|
||||||
.compileComponents();
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
it('should create the app', async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
expect(app).toBeTruthy();
|
||||||
|
}));
|
||||||
|
it(`should have as title 'app'`, async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
expect(app.title).toEqual('app');
|
||||||
|
}));
|
||||||
|
it('should render title', async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const compiled = fixture.nativeElement;
|
||||||
|
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
|
||||||
}));
|
}));
|
||||||
it('should create the app', waitForAsync(() => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
const app = fixture.componentInstance;
|
|
||||||
expect(app).toBeTruthy();
|
|
||||||
}));
|
|
||||||
it(`should have as title 'app'`, waitForAsync(() => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
const app = fixture.componentInstance;
|
|
||||||
expect(app.title).toEqual('app');
|
|
||||||
}));
|
|
||||||
it('should render title', waitForAsync(() => {
|
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
|
||||||
fixture.detectChanges();
|
|
||||||
const compiled = fixture.nativeElement;
|
|
||||||
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
@ -43,13 +43,16 @@ import { DebugElement } from '@angular/core';
|
|||||||
import { ComponentFixture } from '@angular/core/testing';
|
import { ComponentFixture } from '@angular/core/testing';
|
||||||
|
|
||||||
describe('AppComponent (initial CLI version - as it should be)', () => {
|
describe('AppComponent (initial CLI version - as it should be)', () => {
|
||||||
|
|
||||||
let app: AppComponent;
|
let app: AppComponent;
|
||||||
let de: DebugElement;
|
let de: DebugElement;
|
||||||
let fixture: ComponentFixture<AppComponent>;
|
let fixture: ComponentFixture<AppComponent>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [AppComponent],
|
declarations: [
|
||||||
|
AppComponent
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
fixture = TestBed.createComponent(AppComponent);
|
fixture = TestBed.createComponent(AppComponent);
|
||||||
@ -67,6 +70,7 @@ describe('AppComponent (initial CLI version - as it should be)', () => {
|
|||||||
|
|
||||||
it('should render title in an h1 tag', () => {
|
it('should render title in an h1 tag', () => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(de.nativeElement.querySelector('h1').textContent).toContain('Welcome to app!');
|
expect(de.nativeElement.querySelector('h1').textContent)
|
||||||
|
.toContain('Welcome to app!');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// For more examples:
|
// For more examples:
|
||||||
// https://github.com/angular/angular/blob/master/modules/@angular/router/test/integration.spec.ts
|
// https://github.com/angular/angular/blob/master/modules/@angular/router/test/integration.spec.ts
|
||||||
|
|
||||||
import { waitForAsync, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||||
|
|
||||||
import { asyncData } from '../testing';
|
import { asyncData } from '../testing';
|
||||||
|
|
||||||
@ -21,9 +21,9 @@ import { AppModule } from './app.module';
|
|||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { AboutComponent } from './about/about.component';
|
import { AboutComponent } from './about/about.component';
|
||||||
import { DashboardComponent } from './dashboard/dashboard.component';
|
import { DashboardComponent } from './dashboard/dashboard.component';
|
||||||
|
import { TwainService } from './twain/twain.service';
|
||||||
|
|
||||||
import { HeroService, TestHeroService } from './model/testing/test-hero.service';
|
import { HeroService, TestHeroService } from './model/testing/test-hero.service';
|
||||||
import { TwainService } from './twain/twain.service';
|
|
||||||
|
|
||||||
let comp: AppComponent;
|
let comp: AppComponent;
|
||||||
let fixture: ComponentFixture<AppComponent>;
|
let fixture: ComponentFixture<AppComponent>;
|
||||||
@ -32,51 +32,54 @@ let router: Router;
|
|||||||
let location: SpyLocation;
|
let location: SpyLocation;
|
||||||
|
|
||||||
describe('AppComponent & RouterTestingModule', () => {
|
describe('AppComponent & RouterTestingModule', () => {
|
||||||
beforeEach(waitForAsync(() => {
|
|
||||||
TestBed
|
beforeEach(async(() => {
|
||||||
.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
AppModule,
|
AppModule,
|
||||||
RouterTestingModule.withRoutes(routes),
|
RouterTestingModule.withRoutes(routes),
|
||||||
],
|
],
|
||||||
providers: [{provide: HeroService, useClass: TestHeroService}]
|
providers: [
|
||||||
})
|
{ provide: HeroService, useClass: TestHeroService }
|
||||||
.compileComponents();
|
]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should navigate to "Dashboard" immediately', fakeAsync(() => {
|
it('should navigate to "Dashboard" immediately', fakeAsync(() => {
|
||||||
createComponent();
|
createComponent();
|
||||||
tick(); // wait for async data to arrive
|
tick(); // wait for async data to arrive
|
||||||
expectPathToBe('/dashboard', 'after initialNavigation()');
|
expectPathToBe('/dashboard', 'after initialNavigation()');
|
||||||
expectElementOf(DashboardComponent);
|
expectElementOf(DashboardComponent);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should navigate to "About" on click', fakeAsync(() => {
|
it('should navigate to "About" on click', fakeAsync(() => {
|
||||||
createComponent();
|
createComponent();
|
||||||
click(page.aboutLinkDe);
|
click(page.aboutLinkDe);
|
||||||
// page.aboutLinkDe.nativeElement.click(); // ok but fails in phantom
|
// page.aboutLinkDe.nativeElement.click(); // ok but fails in phantom
|
||||||
|
|
||||||
advance();
|
advance();
|
||||||
expectPathToBe('/about');
|
expectPathToBe('/about');
|
||||||
expectElementOf(AboutComponent);
|
expectElementOf(AboutComponent);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should navigate to "About" w/ browser location URL change', fakeAsync(() => {
|
it('should navigate to "About" w/ browser location URL change', fakeAsync(() => {
|
||||||
createComponent();
|
createComponent();
|
||||||
location.simulateHashChange('/about');
|
location.simulateHashChange('/about');
|
||||||
// location.go('/about'); // also works ... except, perhaps, in Stackblitz
|
// location.go('/about'); // also works ... except, perhaps, in Stackblitz
|
||||||
advance();
|
advance();
|
||||||
expectPathToBe('/about');
|
expectPathToBe('/about');
|
||||||
expectElementOf(AboutComponent);
|
expectElementOf(AboutComponent);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Can't navigate to lazy loaded modules with this technique
|
// Can't navigate to lazy loaded modules with this technique
|
||||||
xit('should navigate to "Heroes" on click (not working yet)', fakeAsync(() => {
|
xit('should navigate to "Heroes" on click (not working yet)', fakeAsync(() => {
|
||||||
createComponent();
|
createComponent();
|
||||||
page.heroesLinkDe.nativeElement.click();
|
page.heroesLinkDe.nativeElement.click();
|
||||||
advance();
|
advance();
|
||||||
expectPathToBe('/heroes');
|
expectPathToBe('/heroes');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -91,37 +94,37 @@ let loader: SpyNgModuleFactoryLoader;
|
|||||||
|
|
||||||
///////// Can't get lazy loaded Heroes to work yet
|
///////// Can't get lazy loaded Heroes to work yet
|
||||||
xdescribe('AppComponent & Lazy Loading (not working yet)', () => {
|
xdescribe('AppComponent & Lazy Loading (not working yet)', () => {
|
||||||
beforeEach(waitForAsync(() => {
|
|
||||||
TestBed
|
beforeEach(async(() => {
|
||||||
.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
AppModule,
|
AppModule,
|
||||||
RouterTestingModule.withRoutes(routes),
|
RouterTestingModule.withRoutes(routes),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(fakeAsync(() => {
|
beforeEach(fakeAsync(() => {
|
||||||
createComponent();
|
createComponent();
|
||||||
loader = TestBed.inject(NgModuleFactoryLoader) as SpyNgModuleFactoryLoader;
|
loader = TestBed.inject(NgModuleFactoryLoader) as SpyNgModuleFactoryLoader;
|
||||||
loader.stubbedModules = {expected: HeroModule};
|
loader.stubbedModules = { expected: HeroModule };
|
||||||
router.resetConfig([{path: 'heroes', loadChildren: 'expected'}]);
|
router.resetConfig([{path: 'heroes', loadChildren: 'expected'}]);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should navigate to "Heroes" on click', waitForAsync(() => {
|
it('should navigate to "Heroes" on click', async(() => {
|
||||||
page.heroesLinkDe.nativeElement.click();
|
page.heroesLinkDe.nativeElement.click();
|
||||||
advance();
|
advance();
|
||||||
expectPathToBe('/heroes');
|
expectPathToBe('/heroes');
|
||||||
expectElementOf(HeroListComponent);
|
expectElementOf(HeroListComponent);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('can navigate to "Heroes" w/ browser location URL change', fakeAsync(() => {
|
it('can navigate to "Heroes" w/ browser location URL change', fakeAsync(() => {
|
||||||
location.go('/heroes');
|
location.go('/heroes');
|
||||||
advance();
|
advance();
|
||||||
expectPathToBe('/heroes');
|
expectPathToBe('/heroes');
|
||||||
expectElementOf(HeroListComponent);
|
expectElementOf(HeroListComponent);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
////// Helpers /////////
|
////// Helpers /////////
|
||||||
@ -131,9 +134,9 @@ xdescribe('AppComponent & Lazy Loading (not working yet)', () => {
|
|||||||
* Wait a tick, then detect changes, and tick again
|
* Wait a tick, then detect changes, and tick again
|
||||||
*/
|
*/
|
||||||
function advance(): void {
|
function advance(): void {
|
||||||
tick(); // wait while navigating
|
tick(); // wait while navigating
|
||||||
fixture.detectChanges(); // update view
|
fixture.detectChanges(); // update view
|
||||||
tick(); // wait for async data to arrive
|
tick(); // wait for async data to arrive
|
||||||
}
|
}
|
||||||
|
|
||||||
function createComponent() {
|
function createComponent() {
|
||||||
@ -145,8 +148,8 @@ function createComponent() {
|
|||||||
router = injector.get(Router);
|
router = injector.get(Router);
|
||||||
router.initialNavigation();
|
router.initialNavigation();
|
||||||
spyOn(injector.get(TwainService), 'getQuote')
|
spyOn(injector.get(TwainService), 'getQuote')
|
||||||
// fake fast async observable
|
// fake fast async observable
|
||||||
.and.returnValue(asyncData('Test Quote'));
|
.and.returnValue(asyncData('Test Quote'));
|
||||||
advance();
|
advance();
|
||||||
|
|
||||||
page = new Page();
|
page = new Page();
|
||||||
@ -165,14 +168,14 @@ class Page {
|
|||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
const links = fixture.debugElement.queryAll(By.directive(RouterLinkWithHref));
|
const links = fixture.debugElement.queryAll(By.directive(RouterLinkWithHref));
|
||||||
this.aboutLinkDe = links[2];
|
this.aboutLinkDe = links[2];
|
||||||
this.dashboardLinkDe = links[0];
|
this.dashboardLinkDe = links[0];
|
||||||
this.heroesLinkDe = links[1];
|
this.heroesLinkDe = links[1];
|
||||||
|
|
||||||
// for debugging
|
// for debugging
|
||||||
this.comp = comp;
|
this.comp = comp;
|
||||||
this.fixture = fixture;
|
this.fixture = fixture;
|
||||||
this.router = router;
|
this.router = router;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,70 +1,66 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { Component, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
|
import { Component, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
|
|
||||||
import { RouterLinkDirectiveStub } from '../testing';
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
import { RouterLinkDirectiveStub } from '../testing';
|
||||||
|
|
||||||
// #docregion component-stubs
|
// #docregion component-stubs
|
||||||
@Component({selector: 'app-banner', template: ''})
|
@Component({selector: 'app-banner', template: ''})
|
||||||
class BannerStubComponent {
|
class BannerStubComponent {}
|
||||||
}
|
|
||||||
|
|
||||||
@Component({selector: 'router-outlet', template: ''})
|
@Component({selector: 'router-outlet', template: ''})
|
||||||
class RouterOutletStubComponent {
|
class RouterOutletStubComponent { }
|
||||||
}
|
|
||||||
|
|
||||||
@Component({selector: 'app-welcome', template: ''})
|
@Component({selector: 'app-welcome', template: ''})
|
||||||
class WelcomeStubComponent {
|
class WelcomeStubComponent {}
|
||||||
}
|
|
||||||
// #enddocregion component-stubs
|
// #enddocregion component-stubs
|
||||||
|
|
||||||
let comp: AppComponent;
|
let comp: AppComponent;
|
||||||
let fixture: ComponentFixture<AppComponent>;
|
let fixture: ComponentFixture<AppComponent>;
|
||||||
|
|
||||||
describe('AppComponent & TestModule', () => {
|
describe('AppComponent & TestModule', () => {
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
// #docregion testbed-stubs
|
// #docregion testbed-stubs
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule({
|
declarations: [
|
||||||
declarations: [
|
AppComponent,
|
||||||
AppComponent, RouterLinkDirectiveStub, BannerStubComponent, RouterOutletStubComponent,
|
RouterLinkDirectiveStub,
|
||||||
WelcomeStubComponent
|
BannerStubComponent,
|
||||||
]
|
RouterOutletStubComponent,
|
||||||
})
|
WelcomeStubComponent
|
||||||
// #enddocregion testbed-stubs
|
]
|
||||||
.compileComponents()
|
})
|
||||||
.then(() => {
|
// #enddocregion testbed-stubs
|
||||||
fixture = TestBed.createComponent(AppComponent);
|
.compileComponents().then(() => {
|
||||||
comp = fixture.componentInstance;
|
fixture = TestBed.createComponent(AppComponent);
|
||||||
});
|
comp = fixture.componentInstance;
|
||||||
|
});
|
||||||
}));
|
}));
|
||||||
tests();
|
tests();
|
||||||
});
|
});
|
||||||
|
|
||||||
//////// Testing w/ NO_ERRORS_SCHEMA //////
|
//////// Testing w/ NO_ERRORS_SCHEMA //////
|
||||||
describe('AppComponent & NO_ERRORS_SCHEMA', () => {
|
describe('AppComponent & NO_ERRORS_SCHEMA', () => {
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
// #docregion no-errors-schema, mixed-setup
|
// #docregion no-errors-schema, mixed-setup
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule({
|
declarations: [
|
||||||
declarations: [
|
AppComponent,
|
||||||
AppComponent,
|
// #enddocregion no-errors-schema
|
||||||
// #enddocregion no-errors-schema
|
BannerStubComponent,
|
||||||
BannerStubComponent,
|
// #docregion no-errors-schema
|
||||||
// #docregion no-errors-schema
|
RouterLinkDirectiveStub
|
||||||
RouterLinkDirectiveStub
|
],
|
||||||
],
|
schemas: [ NO_ERRORS_SCHEMA ]
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
})
|
||||||
})
|
// #enddocregion no-errors-schema, mixed-setup
|
||||||
// #enddocregion no-errors-schema, mixed-setup
|
.compileComponents().then(() => {
|
||||||
.compileComponents()
|
fixture = TestBed.createComponent(AppComponent);
|
||||||
.then(() => {
|
comp = fixture.componentInstance;
|
||||||
fixture = TestBed.createComponent(AppComponent);
|
});
|
||||||
comp = fixture.componentInstance;
|
|
||||||
});
|
|
||||||
}));
|
}));
|
||||||
tests();
|
tests();
|
||||||
});
|
});
|
||||||
@ -76,23 +72,30 @@ import { AppModule } from './app.module';
|
|||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
|
|
||||||
describe('AppComponent & AppModule', () => {
|
describe('AppComponent & AppModule', () => {
|
||||||
beforeEach(waitForAsync(() => {
|
|
||||||
TestBed
|
|
||||||
.configureTestingModule({imports: [AppModule]})
|
|
||||||
|
|
||||||
// Get rid of app's Router configuration otherwise many failures.
|
beforeEach(async(() => {
|
||||||
// Doing so removes Router declarations; add the Router stubs
|
|
||||||
.overrideModule(AppModule, {
|
|
||||||
remove: {imports: [AppRoutingModule]},
|
|
||||||
add: {declarations: [RouterLinkDirectiveStub, RouterOutletStubComponent]}
|
|
||||||
})
|
|
||||||
|
|
||||||
.compileComponents()
|
TestBed.configureTestingModule({
|
||||||
|
imports: [ AppModule ]
|
||||||
|
})
|
||||||
|
|
||||||
.then(() => {
|
// Get rid of app's Router configuration otherwise many failures.
|
||||||
fixture = TestBed.createComponent(AppComponent);
|
// Doing so removes Router declarations; add the Router stubs
|
||||||
comp = fixture.componentInstance;
|
.overrideModule(AppModule, {
|
||||||
});
|
remove: {
|
||||||
|
imports: [ AppRoutingModule ]
|
||||||
|
},
|
||||||
|
add: {
|
||||||
|
declarations: [ RouterLinkDirectiveStub, RouterOutletStubComponent ]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
.compileComponents()
|
||||||
|
|
||||||
|
.then(() => {
|
||||||
|
fixture = TestBed.createComponent(AppComponent);
|
||||||
|
comp = fixture.componentInstance;
|
||||||
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
tests();
|
tests();
|
||||||
@ -104,10 +107,11 @@ function tests() {
|
|||||||
|
|
||||||
// #docregion test-setup
|
// #docregion test-setup
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture.detectChanges(); // trigger initial data binding
|
fixture.detectChanges(); // trigger initial data binding
|
||||||
|
|
||||||
// find DebugElements with an attached RouterLinkStubDirective
|
// find DebugElements with an attached RouterLinkStubDirective
|
||||||
linkDes = fixture.debugElement.queryAll(By.directive(RouterLinkDirectiveStub));
|
linkDes = fixture.debugElement
|
||||||
|
.queryAll(By.directive(RouterLinkDirectiveStub));
|
||||||
|
|
||||||
// get attached link directive instances
|
// get attached link directive instances
|
||||||
// using each DebugElement's injector
|
// using each DebugElement's injector
|
||||||
@ -128,8 +132,8 @@ function tests() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('can click Heroes link in template', () => {
|
it('can click Heroes link in template', () => {
|
||||||
const heroesLinkDe = linkDes[1]; // heroes link DebugElement
|
const heroesLinkDe = linkDes[1]; // heroes link DebugElement
|
||||||
const heroesLink = routerLinks[1]; // heroes link directive
|
const heroesLink = routerLinks[1]; // heroes link directive
|
||||||
|
|
||||||
expect(heroesLink.navigatedTo).toBeNull('should not have navigated yet');
|
expect(heroesLink.navigatedTo).toBeNull('should not have navigated yet');
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion import-async
|
// #docregion import-async
|
||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
// #enddocregion import-async
|
// #enddocregion import-async
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { DebugElement } from '@angular/core';
|
import { DebugElement } from '@angular/core';
|
||||||
@ -14,12 +14,11 @@ describe('BannerComponent (external files)', () => {
|
|||||||
|
|
||||||
describe('Two beforeEach', () => {
|
describe('Two beforeEach', () => {
|
||||||
// #docregion async-before-each
|
// #docregion async-before-each
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule({
|
declarations: [ BannerComponent ],
|
||||||
declarations: [BannerComponent],
|
})
|
||||||
})
|
.compileComponents(); // compile template and css
|
||||||
.compileComponents(); // compile template and css
|
|
||||||
}));
|
}));
|
||||||
// #enddocregion async-before-each
|
// #enddocregion async-before-each
|
||||||
|
|
||||||
@ -27,7 +26,7 @@ describe('BannerComponent (external files)', () => {
|
|||||||
// #docregion sync-before-each
|
// #docregion sync-before-each
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(BannerComponent);
|
fixture = TestBed.createComponent(BannerComponent);
|
||||||
component = fixture.componentInstance; // BannerComponent test instance
|
component = fixture.componentInstance; // BannerComponent test instance
|
||||||
h1 = fixture.nativeElement.querySelector('h1');
|
h1 = fixture.nativeElement.querySelector('h1');
|
||||||
});
|
});
|
||||||
// #enddocregion sync-before-each
|
// #enddocregion sync-before-each
|
||||||
@ -37,17 +36,16 @@ describe('BannerComponent (external files)', () => {
|
|||||||
|
|
||||||
describe('One beforeEach', () => {
|
describe('One beforeEach', () => {
|
||||||
// #docregion one-before-each
|
// #docregion one-before-each
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule({
|
declarations: [ BannerComponent ],
|
||||||
declarations: [BannerComponent],
|
})
|
||||||
})
|
.compileComponents()
|
||||||
.compileComponents()
|
.then(() => {
|
||||||
.then(() => {
|
fixture = TestBed.createComponent(BannerComponent);
|
||||||
fixture = TestBed.createComponent(BannerComponent);
|
component = fixture.componentInstance;
|
||||||
component = fixture.componentInstance;
|
h1 = fixture.nativeElement.querySelector('h1');
|
||||||
h1 = fixture.nativeElement.querySelector('h1');
|
});
|
||||||
});
|
|
||||||
}));
|
}));
|
||||||
// #enddocregion one-before-each
|
// #enddocregion one-before-each
|
||||||
|
|
||||||
@ -71,3 +69,4 @@ describe('BannerComponent (external files)', () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion import-by
|
// #docregion import-by
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
// #enddocregion import-by
|
// #enddocregion import-by
|
||||||
// #docregion import-debug-element
|
// #docregion import-debug-element
|
||||||
import { DebugElement } from '@angular/core';
|
import { DebugElement } from '@angular/core';
|
||||||
// #enddocregion import-debug-element
|
// #enddocregion import-debug-element
|
||||||
// #docregion v1
|
// #docregion v1
|
||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { By } from '@angular/platform-browser';
|
|
||||||
|
|
||||||
// #enddocregion v1
|
// #enddocregion v1
|
||||||
import { BannerComponent } from './banner-initial.component';
|
import { BannerComponent } from './banner-initial.component';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// #docregion v1
|
// #docregion v1
|
||||||
import { BannerComponent } from './banner.component';
|
import { BannerComponent } from './banner.component';
|
||||||
@ -19,12 +17,15 @@ describe('BannerComponent', () => {
|
|||||||
// #enddocregion v1
|
// #enddocregion v1
|
||||||
*/
|
*/
|
||||||
describe('BannerComponent (initial CLI generated)', () => {
|
describe('BannerComponent (initial CLI generated)', () => {
|
||||||
// #docregion v1
|
// #docregion v1
|
||||||
let component: BannerComponent;
|
let component: BannerComponent;
|
||||||
let fixture: ComponentFixture<BannerComponent>;
|
let fixture: ComponentFixture<BannerComponent>;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({declarations: [BannerComponent]}).compileComponents();
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ BannerComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -43,7 +44,9 @@ describe('BannerComponent (initial CLI generated)', () => {
|
|||||||
describe('BannerComponent (minimal)', () => {
|
describe('BannerComponent (minimal)', () => {
|
||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
// #docregion configureTestingModule
|
// #docregion configureTestingModule
|
||||||
TestBed.configureTestingModule({declarations: [BannerComponent]});
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ BannerComponent ]
|
||||||
|
});
|
||||||
// #enddocregion configureTestingModule
|
// #enddocregion configureTestingModule
|
||||||
// #docregion createComponent
|
// #docregion createComponent
|
||||||
const fixture = TestBed.createComponent(BannerComponent);
|
const fixture = TestBed.createComponent(BannerComponent);
|
||||||
@ -62,7 +65,9 @@ describe('BannerComponent (with beforeEach)', () => {
|
|||||||
let fixture: ComponentFixture<BannerComponent>;
|
let fixture: ComponentFixture<BannerComponent>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({declarations: [BannerComponent]});
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ BannerComponent ]
|
||||||
|
});
|
||||||
fixture = TestBed.createComponent(BannerComponent);
|
fixture = TestBed.createComponent(BannerComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
});
|
});
|
||||||
|
@ -1,21 +1,22 @@
|
|||||||
|
|
||||||
// #docplaster
|
// #docplaster
|
||||||
import { DebugElement } from '@angular/core';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { DebugElement } from '@angular/core';
|
||||||
|
|
||||||
import { addMatchers, click } from '../../testing';
|
import { addMatchers, click } from '../../testing';
|
||||||
import { Hero } from '../model/hero';
|
|
||||||
|
|
||||||
|
import { Hero } from '../model/hero';
|
||||||
import { DashboardHeroComponent } from './dashboard-hero.component';
|
import { DashboardHeroComponent } from './dashboard-hero.component';
|
||||||
|
|
||||||
beforeEach(addMatchers);
|
beforeEach( addMatchers );
|
||||||
|
|
||||||
describe('DashboardHeroComponent class only', () => {
|
describe('DashboardHeroComponent class only', () => {
|
||||||
// #docregion class-only
|
// #docregion class-only
|
||||||
it('raises the selected event when clicked', () => {
|
it('raises the selected event when clicked', () => {
|
||||||
const comp = new DashboardHeroComponent();
|
const comp = new DashboardHeroComponent();
|
||||||
const hero: Hero = {id: 42, name: 'Test'};
|
const hero: Hero = { id: 42, name: 'Test' };
|
||||||
comp.hero = hero;
|
comp.hero = hero;
|
||||||
|
|
||||||
comp.selected.subscribe((selectedHero: Hero) => expect(selectedHero).toBe(hero));
|
comp.selected.subscribe((selectedHero: Hero) => expect(selectedHero).toBe(hero));
|
||||||
@ -25,31 +26,33 @@ describe('DashboardHeroComponent class only', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('DashboardHeroComponent when tested directly', () => {
|
describe('DashboardHeroComponent when tested directly', () => {
|
||||||
|
|
||||||
let comp: DashboardHeroComponent;
|
let comp: DashboardHeroComponent;
|
||||||
let expectedHero: Hero;
|
let expectedHero: Hero;
|
||||||
let fixture: ComponentFixture<DashboardHeroComponent>;
|
let fixture: ComponentFixture<DashboardHeroComponent>;
|
||||||
let heroDe: DebugElement;
|
let heroDe: DebugElement;
|
||||||
let heroEl: HTMLElement;
|
let heroEl: HTMLElement;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
// #docregion setup, config-testbed
|
// #docregion setup, config-testbed
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule({declarations: [DashboardHeroComponent]})
|
declarations: [ DashboardHeroComponent ]
|
||||||
// #enddocregion setup, config-testbed
|
})
|
||||||
.compileComponents();
|
// #enddocregion setup, config-testbed
|
||||||
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
// #docregion setup
|
// #docregion setup
|
||||||
fixture = TestBed.createComponent(DashboardHeroComponent);
|
fixture = TestBed.createComponent(DashboardHeroComponent);
|
||||||
comp = fixture.componentInstance;
|
comp = fixture.componentInstance;
|
||||||
|
|
||||||
// find the hero's DebugElement and element
|
// find the hero's DebugElement and element
|
||||||
heroDe = fixture.debugElement.query(By.css('.hero'));
|
heroDe = fixture.debugElement.query(By.css('.hero'));
|
||||||
heroEl = heroDe.nativeElement;
|
heroEl = heroDe.nativeElement;
|
||||||
|
|
||||||
// mock the hero supplied by the parent component
|
// mock the hero supplied by the parent component
|
||||||
expectedHero = {id: 42, name: 'Test Name'};
|
expectedHero = { id: 42, name: 'Test Name' };
|
||||||
|
|
||||||
// simulate the parent setting the input property with that hero
|
// simulate the parent setting the input property with that hero
|
||||||
comp.hero = expectedHero;
|
comp.hero = expectedHero;
|
||||||
@ -93,8 +96,8 @@ describe('DashboardHeroComponent when tested directly', () => {
|
|||||||
let selectedHero: Hero;
|
let selectedHero: Hero;
|
||||||
comp.selected.subscribe((hero: Hero) => selectedHero = hero);
|
comp.selected.subscribe((hero: Hero) => selectedHero = hero);
|
||||||
|
|
||||||
click(heroDe); // click helper with DebugElement
|
click(heroDe); // click helper with DebugElement
|
||||||
click(heroEl); // click helper with native element
|
click(heroEl); // click helper with native element
|
||||||
|
|
||||||
expect(selectedHero).toBe(expectedHero);
|
expect(selectedHero).toBe(expectedHero);
|
||||||
});
|
});
|
||||||
@ -108,21 +111,22 @@ describe('DashboardHeroComponent when inside a test host', () => {
|
|||||||
let fixture: ComponentFixture<TestHostComponent>;
|
let fixture: ComponentFixture<TestHostComponent>;
|
||||||
let heroEl: HTMLElement;
|
let heroEl: HTMLElement;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
// #docregion test-host-setup
|
// #docregion test-host-setup
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule({declarations: [DashboardHeroComponent, TestHostComponent]})
|
declarations: [ DashboardHeroComponent, TestHostComponent ]
|
||||||
// #enddocregion test-host-setup
|
})
|
||||||
.compileComponents();
|
// #enddocregion test-host-setup
|
||||||
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
// #docregion test-host-setup
|
// #docregion test-host-setup
|
||||||
// create TestHostComponent instead of DashboardHeroComponent
|
// create TestHostComponent instead of DashboardHeroComponent
|
||||||
fixture = TestBed.createComponent(TestHostComponent);
|
fixture = TestBed.createComponent(TestHostComponent);
|
||||||
testHost = fixture.componentInstance;
|
testHost = fixture.componentInstance;
|
||||||
heroEl = fixture.nativeElement.querySelector('.hero');
|
heroEl = fixture.nativeElement.querySelector('.hero');
|
||||||
fixture.detectChanges(); // trigger initial data binding
|
fixture.detectChanges(); // trigger initial data binding
|
||||||
// #enddocregion test-host-setup
|
// #enddocregion test-host-setup
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -151,10 +155,8 @@ import { Component } from '@angular/core';
|
|||||||
</dashboard-hero>`
|
</dashboard-hero>`
|
||||||
})
|
})
|
||||||
class TestHostComponent {
|
class TestHostComponent {
|
||||||
hero: Hero = {id: 42, name: 'Test Name'};
|
hero: Hero = {id: 42, name: 'Test Name' };
|
||||||
selectedHero: Hero;
|
selectedHero: Hero;
|
||||||
onSelected(hero: Hero) {
|
onSelected(hero: Hero) { this.selectedHero = hero; }
|
||||||
this.selectedHero = hero;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// #enddocregion test-host
|
// #enddocregion test-host
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
|
import { async, inject, ComponentFixture, TestBed
|
||||||
|
} from '@angular/core/testing';
|
||||||
|
|
||||||
import { addMatchers, asyncData, click } from '../../testing';
|
import { addMatchers, asyncData, click } from '../../testing';
|
||||||
import { HeroService } from '../model/hero.service';
|
import { HeroService } from '../model/hero.service';
|
||||||
@ -11,7 +12,7 @@ import { Router } from '@angular/router';
|
|||||||
import { DashboardComponent } from './dashboard.component';
|
import { DashboardComponent } from './dashboard.component';
|
||||||
import { DashboardModule } from './dashboard.module';
|
import { DashboardModule } from './dashboard.module';
|
||||||
|
|
||||||
beforeEach(addMatchers);
|
beforeEach ( addMatchers );
|
||||||
|
|
||||||
let comp: DashboardComponent;
|
let comp: DashboardComponent;
|
||||||
let fixture: ComponentFixture<DashboardComponent>;
|
let fixture: ComponentFixture<DashboardComponent>;
|
||||||
@ -20,7 +21,9 @@ let fixture: ComponentFixture<DashboardComponent>;
|
|||||||
|
|
||||||
describe('DashboardComponent (deep)', () => {
|
describe('DashboardComponent (deep)', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({imports: [DashboardModule]});
|
TestBed.configureTestingModule({
|
||||||
|
imports: [ DashboardModule ]
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
compileAndCreate();
|
compileAndCreate();
|
||||||
@ -40,8 +43,10 @@ import { NO_ERRORS_SCHEMA } from '@angular/core';
|
|||||||
|
|
||||||
describe('DashboardComponent (shallow)', () => {
|
describe('DashboardComponent (shallow)', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule(
|
TestBed.configureTestingModule({
|
||||||
{declarations: [DashboardComponent], schemas: [NO_ERRORS_SCHEMA]});
|
declarations: [ DashboardComponent ],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
compileAndCreate();
|
compileAndCreate();
|
||||||
@ -58,26 +63,25 @@ describe('DashboardComponent (shallow)', () => {
|
|||||||
/** Add TestBed providers, compile, and create DashboardComponent */
|
/** Add TestBed providers, compile, and create DashboardComponent */
|
||||||
function compileAndCreate() {
|
function compileAndCreate() {
|
||||||
// #docregion compile-and-create-body
|
// #docregion compile-and-create-body
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
// #docregion router-spy
|
// #docregion router-spy
|
||||||
const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']);
|
const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']);
|
||||||
const heroServiceSpy = jasmine.createSpyObj('HeroService', ['getHeroes']);
|
const heroServiceSpy = jasmine.createSpyObj('HeroService', ['getHeroes']);
|
||||||
|
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule({
|
providers: [
|
||||||
providers: [
|
{ provide: HeroService, useValue: heroServiceSpy },
|
||||||
{provide: HeroService, useValue: heroServiceSpy}, {provide: Router, useValue: routerSpy}
|
{ provide: Router, useValue: routerSpy }
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
// #enddocregion router-spy
|
// #enddocregion router-spy
|
||||||
.compileComponents()
|
.compileComponents().then(() => {
|
||||||
.then(() => {
|
fixture = TestBed.createComponent(DashboardComponent);
|
||||||
fixture = TestBed.createComponent(DashboardComponent);
|
comp = fixture.componentInstance;
|
||||||
comp = fixture.componentInstance;
|
|
||||||
|
|
||||||
// getHeroes spy returns observable of test heroes
|
// getHeroes spy returns observable of test heroes
|
||||||
heroServiceSpy.getHeroes.and.returnValue(asyncData(getTestHeroes()));
|
heroServiceSpy.getHeroes.and.returnValue(asyncData(getTestHeroes()));
|
||||||
});
|
});
|
||||||
// #enddocregion compile-and-create-body
|
// #enddocregion compile-and-create-body
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -89,20 +93,23 @@ function compileAndCreate() {
|
|||||||
function tests(heroClick: () => void) {
|
function tests(heroClick: () => void) {
|
||||||
|
|
||||||
it('should NOT have heroes before ngOnInit', () => {
|
it('should NOT have heroes before ngOnInit', () => {
|
||||||
expect(comp.heroes.length).toBe(0, 'should not have heroes before ngOnInit');
|
expect(comp.heroes.length).toBe(0,
|
||||||
|
'should not have heroes before ngOnInit');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should NOT have heroes immediately after ngOnInit', () => {
|
it('should NOT have heroes immediately after ngOnInit', () => {
|
||||||
fixture.detectChanges(); // runs initial lifecycle hooks
|
fixture.detectChanges(); // runs initial lifecycle hooks
|
||||||
|
|
||||||
expect(comp.heroes.length).toBe(0, 'should not have heroes until service promise resolves');
|
expect(comp.heroes.length).toBe(0,
|
||||||
|
'should not have heroes until service promise resolves');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('after get dashboard heroes', () => {
|
describe('after get dashboard heroes', () => {
|
||||||
|
|
||||||
let router: Router;
|
let router: Router;
|
||||||
|
|
||||||
// Trigger component so it gets heroes and binds to them
|
// Trigger component so it gets heroes and binds to them
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
router = fixture.debugElement.injector.get(Router);
|
router = fixture.debugElement.injector.get(Router);
|
||||||
fixture.detectChanges(); // runs ngOnInit -> getHeroes
|
fixture.detectChanges(); // runs ngOnInit -> getHeroes
|
||||||
fixture.whenStable() // No need for the `lastPromise` hack!
|
fixture.whenStable() // No need for the `lastPromise` hack!
|
||||||
@ -110,8 +117,8 @@ function tests(heroClick: () => void) {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
it('should HAVE heroes', () => {
|
it('should HAVE heroes', () => {
|
||||||
expect(comp.heroes.length)
|
expect(comp.heroes.length).toBeGreaterThan(0,
|
||||||
.toBeGreaterThan(0, 'should have heroes after service promise resolves');
|
'should have heroes after service promise resolves');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should DISPLAY heroes', () => {
|
it('should DISPLAY heroes', () => {
|
||||||
@ -123,7 +130,8 @@ function tests(heroClick: () => void) {
|
|||||||
|
|
||||||
// #docregion navigate-test
|
// #docregion navigate-test
|
||||||
it('should tell ROUTER to navigate when hero clicked', () => {
|
it('should tell ROUTER to navigate when hero clicked', () => {
|
||||||
heroClick(); // trigger click on first inner <div class="hero">
|
|
||||||
|
heroClick(); // trigger click on first inner <div class="hero">
|
||||||
|
|
||||||
// args passed to router.navigateByUrl() spy
|
// args passed to router.navigateByUrl() spy
|
||||||
const spy = router.navigateByUrl as jasmine.Spy;
|
const spy = router.navigateByUrl as jasmine.Spy;
|
||||||
@ -131,8 +139,10 @@ function tests(heroClick: () => void) {
|
|||||||
|
|
||||||
// expecting to navigate to id of the component's first hero
|
// expecting to navigate to id of the component's first hero
|
||||||
const id = comp.heroes[0].id;
|
const id = comp.heroes[0].id;
|
||||||
expect(navArgs).toBe('/heroes/' + id, 'should nav to HeroDetail for first hero');
|
expect(navArgs).toBe('/heroes/' + id,
|
||||||
|
'should nav to HeroDetail for first hero');
|
||||||
});
|
});
|
||||||
// #enddocregion navigate-test
|
// #enddocregion navigate-test
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,23 +1,18 @@
|
|||||||
// tslint:disable-next-line:no-unused-variable
|
// tslint:disable-next-line:no-unused-variable
|
||||||
import { fakeAsync, tick, waitForAsync } from '@angular/core/testing';
|
import { async, fakeAsync, tick } from '@angular/core/testing';
|
||||||
import { interval, of } from 'rxjs';
|
import { interval, of } from 'rxjs';
|
||||||
import { delay, take } from 'rxjs/operators';
|
import { delay, take } from 'rxjs/operators';
|
||||||
|
|
||||||
describe('Angular async helper', () => {
|
describe('Angular async helper', () => {
|
||||||
|
|
||||||
describe('async', () => {
|
describe('async', () => {
|
||||||
let actuallyDone = false;
|
let actuallyDone = false;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => { actuallyDone = false; });
|
||||||
actuallyDone = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => { expect(actuallyDone).toBe(true, 'actuallyDone should be true'); });
|
||||||
expect(actuallyDone).toBe(true, 'actuallyDone should be true');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should run normal test', () => {
|
it('should run normal test', () => { actuallyDone = true; });
|
||||||
actuallyDone = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should run normal async test', (done: DoneFn) => {
|
it('should run normal async test', (done: DoneFn) => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -26,50 +21,39 @@ describe('Angular async helper', () => {
|
|||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should run async test with task', waitForAsync(() => {
|
it('should run async test with task',
|
||||||
setTimeout(() => {
|
async(() => { setTimeout(() => { actuallyDone = true; }, 0); }));
|
||||||
actuallyDone = true;
|
|
||||||
}, 0);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should run async test with task', waitForAsync(() => {
|
it('should run async test with task', async(() => {
|
||||||
const id = setInterval(() => {
|
const id = setInterval(() => {
|
||||||
actuallyDone = true;
|
actuallyDone = true;
|
||||||
clearInterval(id);
|
clearInterval(id);
|
||||||
}, 100);
|
}, 100);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should run async test with successful promise', waitForAsync(() => {
|
it('should run async test with successful promise', async(() => {
|
||||||
const p = new Promise(resolve => {
|
const p = new Promise(resolve => { setTimeout(resolve, 10); });
|
||||||
setTimeout(resolve, 10);
|
p.then(() => { actuallyDone = true; });
|
||||||
});
|
|
||||||
p.then(() => {
|
|
||||||
actuallyDone = true;
|
|
||||||
});
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should run async test with failed promise', waitForAsync(() => {
|
it('should run async test with failed promise', async(() => {
|
||||||
const p = new Promise((resolve, reject) => {
|
const p = new Promise((resolve, reject) => { setTimeout(reject, 10); });
|
||||||
setTimeout(reject, 10);
|
p.catch(() => { actuallyDone = true; });
|
||||||
});
|
|
||||||
p.catch(() => {
|
|
||||||
actuallyDone = true;
|
|
||||||
});
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Use done. Can also use async or fakeAsync.
|
// Use done. Can also use async or fakeAsync.
|
||||||
it('should run async test with successful delayed Observable', (done: DoneFn) => {
|
it('should run async test with successful delayed Observable', (done: DoneFn) => {
|
||||||
const source = of(true).pipe(delay(10));
|
const source = of (true).pipe(delay(10));
|
||||||
source.subscribe(val => actuallyDone = true, err => fail(err), done);
|
source.subscribe(val => actuallyDone = true, err => fail(err), done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should run async test with successful delayed Observable', waitForAsync(() => {
|
it('should run async test with successful delayed Observable', async(() => {
|
||||||
const source = of(true).pipe(delay(10));
|
const source = of (true).pipe(delay(10));
|
||||||
source.subscribe(val => actuallyDone = true, err => fail(err));
|
source.subscribe(val => actuallyDone = true, err => fail(err));
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should run async test with successful delayed Observable', fakeAsync(() => {
|
it('should run async test with successful delayed Observable', fakeAsync(() => {
|
||||||
const source = of(true).pipe(delay(10));
|
const source = of (true).pipe(delay(10));
|
||||||
source.subscribe(val => actuallyDone = true, err => fail(err));
|
source.subscribe(val => actuallyDone = true, err => fail(err));
|
||||||
|
|
||||||
tick(10);
|
tick(10);
|
||||||
@ -80,9 +64,7 @@ describe('Angular async helper', () => {
|
|||||||
// #docregion fake-async-test-tick
|
// #docregion fake-async-test-tick
|
||||||
it('should run timeout callback with delay after call tick with millis', fakeAsync(() => {
|
it('should run timeout callback with delay after call tick with millis', fakeAsync(() => {
|
||||||
let called = false;
|
let called = false;
|
||||||
setTimeout(() => {
|
setTimeout(() => { called = true; }, 100);
|
||||||
called = true;
|
|
||||||
}, 100);
|
|
||||||
tick(100);
|
tick(100);
|
||||||
expect(called).toBe(true);
|
expect(called).toBe(true);
|
||||||
}));
|
}));
|
||||||
@ -91,9 +73,7 @@ describe('Angular async helper', () => {
|
|||||||
// #docregion fake-async-test-tick-new-macro-task-sync
|
// #docregion fake-async-test-tick-new-macro-task-sync
|
||||||
it('should run new macro task callback with delay after call tick with millis',
|
it('should run new macro task callback with delay after call tick with millis',
|
||||||
fakeAsync(() => {
|
fakeAsync(() => {
|
||||||
function nestedTimer(cb: () => any): void {
|
function nestedTimer(cb: () => any): void { setTimeout(() => setTimeout(() => cb())); }
|
||||||
setTimeout(() => setTimeout(() => cb()));
|
|
||||||
}
|
|
||||||
const callback = jasmine.createSpy('callback');
|
const callback = jasmine.createSpy('callback');
|
||||||
nestedTimer(callback);
|
nestedTimer(callback);
|
||||||
expect(callback).not.toHaveBeenCalled();
|
expect(callback).not.toHaveBeenCalled();
|
||||||
@ -106,9 +86,7 @@ describe('Angular async helper', () => {
|
|||||||
// #docregion fake-async-test-tick-new-macro-task-async
|
// #docregion fake-async-test-tick-new-macro-task-async
|
||||||
it('should not run new macro task callback with delay after call tick with millis',
|
it('should not run new macro task callback with delay after call tick with millis',
|
||||||
fakeAsync(() => {
|
fakeAsync(() => {
|
||||||
function nestedTimer(cb: () => any): void {
|
function nestedTimer(cb: () => any): void { setTimeout(() => setTimeout(() => cb())); }
|
||||||
setTimeout(() => setTimeout(() => cb()));
|
|
||||||
}
|
|
||||||
const callback = jasmine.createSpy('callback');
|
const callback = jasmine.createSpy('callback');
|
||||||
nestedTimer(callback);
|
nestedTimer(callback);
|
||||||
expect(callback).not.toHaveBeenCalled();
|
expect(callback).not.toHaveBeenCalled();
|
||||||
@ -134,9 +112,7 @@ describe('Angular async helper', () => {
|
|||||||
// need to add `import 'zone.js/dist/zone-patch-rxjs-fake-async'
|
// need to add `import 'zone.js/dist/zone-patch-rxjs-fake-async'
|
||||||
// to patch rxjs scheduler
|
// to patch rxjs scheduler
|
||||||
let result = null;
|
let result = null;
|
||||||
of('hello').pipe(delay(1000)).subscribe(v => {
|
of ('hello').pipe(delay(1000)).subscribe(v => { result = v; });
|
||||||
result = v;
|
|
||||||
});
|
|
||||||
expect(result).toBeNull();
|
expect(result).toBeNull();
|
||||||
tick(1000);
|
tick(1000);
|
||||||
expect(result).toBe('hello');
|
expect(result).toBe('hello');
|
||||||
@ -157,18 +133,12 @@ describe('Angular async helper', () => {
|
|||||||
describe('use jasmine.clock()', () => {
|
describe('use jasmine.clock()', () => {
|
||||||
// need to config __zone_symbol__fakeAsyncPatchLock flag
|
// need to config __zone_symbol__fakeAsyncPatchLock flag
|
||||||
// before loading zone.js/dist/zone-testing
|
// before loading zone.js/dist/zone-testing
|
||||||
beforeEach(() => {
|
beforeEach(() => { jasmine.clock().install(); });
|
||||||
jasmine.clock().install();
|
afterEach(() => { jasmine.clock().uninstall(); });
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
jasmine.clock().uninstall();
|
|
||||||
});
|
|
||||||
it('should auto enter fakeAsync', () => {
|
it('should auto enter fakeAsync', () => {
|
||||||
// is in fakeAsync now, don't need to call fakeAsync(testFn)
|
// is in fakeAsync now, don't need to call fakeAsync(testFn)
|
||||||
let called = false;
|
let called = false;
|
||||||
setTimeout(() => {
|
setTimeout(() => { called = true; }, 100);
|
||||||
called = true;
|
|
||||||
}, 100);
|
|
||||||
jasmine.clock().tick(100);
|
jasmine.clock().tick(100);
|
||||||
expect(called).toBe(true);
|
expect(called).toBe(true);
|
||||||
});
|
});
|
||||||
@ -182,7 +152,7 @@ describe('Angular async helper', () => {
|
|||||||
}
|
}
|
||||||
// need to config __zone_symbol__supportWaitUnResolvedChainedPromise flag
|
// need to config __zone_symbol__supportWaitUnResolvedChainedPromise flag
|
||||||
// before loading zone.js/dist/zone-testing
|
// before loading zone.js/dist/zone-testing
|
||||||
it('should wait until promise.then is called', waitForAsync(() => {
|
it('should wait until promise.then is called', async(() => {
|
||||||
let finished = false;
|
let finished = false;
|
||||||
new Promise((res, rej) => {
|
new Promise((res, rej) => {
|
||||||
jsonp('localhost:8080/jsonp', () => {
|
jsonp('localhost:8080/jsonp', () => {
|
||||||
@ -198,4 +168,5 @@ describe('Angular async helper', () => {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
// #enddocregion async-test-promise-then
|
// #enddocregion async-test-promise-then
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -24,18 +24,17 @@ import { FormsModule } from '@angular/forms';
|
|||||||
// Forms symbols imported only for a specific test below
|
// Forms symbols imported only for a specific test below
|
||||||
import { NgModel, NgControl } from '@angular/forms';
|
import { NgModel, NgControl } from '@angular/forms';
|
||||||
|
|
||||||
import {
|
import { async, ComponentFixture, fakeAsync, inject, TestBed, tick
|
||||||
ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync
|
|
||||||
} from '@angular/core/testing';
|
} from '@angular/core/testing';
|
||||||
|
|
||||||
import { addMatchers, click } from '../../testing';
|
import { addMatchers, newEvent, click } from '../../testing';
|
||||||
|
|
||||||
export class NotProvided extends ValueService { /* example below */ }
|
export class NotProvided extends ValueService { /* example below */}
|
||||||
beforeEach(addMatchers);
|
beforeEach( addMatchers );
|
||||||
|
|
||||||
describe('demo (with TestBed):', () => {
|
describe('demo (with TestBed):', () => {
|
||||||
|
|
||||||
//////// Service Tests /////////////
|
//////// Service Tests /////////////
|
||||||
|
|
||||||
// #docregion ValueService
|
// #docregion ValueService
|
||||||
describe('ValueService', () => {
|
describe('ValueService', () => {
|
||||||
@ -65,13 +64,13 @@ describe('demo (with TestBed):', () => {
|
|||||||
// #enddocregion testbed-get-w-null
|
// #enddocregion testbed-get-w-null
|
||||||
});
|
});
|
||||||
|
|
||||||
it('test should wait for ValueService.getPromiseValue', waitForAsync(() => {
|
it('test should wait for ValueService.getPromiseValue', async(() => {
|
||||||
service.getPromiseValue().then(
|
service.getPromiseValue().then(
|
||||||
value => expect(value).toBe('promise value')
|
value => expect(value).toBe('promise value')
|
||||||
);
|
);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('test should wait for ValueService.getObservableValue', waitForAsync(() => {
|
it('test should wait for ValueService.getObservableValue', async(() => {
|
||||||
service.getObservableValue().subscribe(
|
service.getObservableValue().subscribe(
|
||||||
value => expect(value).toBe('observable value')
|
value => expect(value).toBe('observable value')
|
||||||
);
|
);
|
||||||
@ -151,7 +150,7 @@ describe('demo (with TestBed):', () => {
|
|||||||
TestBed.configureTestingModule({ providers: [ValueService] });
|
TestBed.configureTestingModule({ providers: [ValueService] });
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(waitForAsync(inject([ValueService], (service: ValueService) => {
|
beforeEach(async(inject([ValueService], (service: ValueService) => {
|
||||||
service.getPromiseValue().then(value => serviceValue = value);
|
service.getPromiseValue().then(value => serviceValue = value);
|
||||||
})));
|
})));
|
||||||
|
|
||||||
@ -160,11 +159,11 @@ describe('demo (with TestBed):', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
/////////// Component Tests //////////////////
|
/////////// Component Tests //////////////////
|
||||||
|
|
||||||
describe('TestBed component tests', () => {
|
describe('TestBed component tests', () => {
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
TestBed
|
TestBed
|
||||||
.configureTestingModule({
|
.configureTestingModule({
|
||||||
imports: [DemoModule],
|
imports: [DemoModule],
|
||||||
@ -236,7 +235,7 @@ describe('demo (with TestBed):', () => {
|
|||||||
// #docregion ButtonComp
|
// #docregion ButtonComp
|
||||||
it('should support clicking a button', () => {
|
it('should support clicking a button', () => {
|
||||||
const fixture = TestBed.createComponent(LightswitchComponent);
|
const fixture = TestBed.createComponent(LightswitchComponent);
|
||||||
const btn = fixture.debugElement.query(By.css('button'));
|
const btn = fixture.debugElement.query(By.css('button'));
|
||||||
const span = fixture.debugElement.query(By.css('span')).nativeElement;
|
const span = fixture.debugElement.query(By.css('span')).nativeElement;
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@ -249,7 +248,7 @@ describe('demo (with TestBed):', () => {
|
|||||||
// #enddocregion ButtonComp
|
// #enddocregion ButtonComp
|
||||||
|
|
||||||
// ngModel is async so we must wait for it with promise-based `whenStable`
|
// ngModel is async so we must wait for it with promise-based `whenStable`
|
||||||
it('should support entering text in input box (ngModel)', waitForAsync(() => {
|
it('should support entering text in input box (ngModel)', async(() => {
|
||||||
const expectedOrigName = 'John';
|
const expectedOrigName = 'John';
|
||||||
const expectedNewName = 'Sally';
|
const expectedNewName = 'Sally';
|
||||||
|
|
||||||
@ -274,17 +273,15 @@ describe('demo (with TestBed):', () => {
|
|||||||
expect(comp.name).toBe(expectedOrigName,
|
expect(comp.name).toBe(expectedOrigName,
|
||||||
`comp.name should still be ${expectedOrigName} after value change, before binding happens`);
|
`comp.name should still be ${expectedOrigName} after value change, before binding happens`);
|
||||||
|
|
||||||
// Dispatch a DOM event so that Angular learns of input value change.
|
// dispatch a DOM event so that Angular learns of input value change.
|
||||||
// then wait while ngModel pushes input.box value to comp.name
|
// then wait while ngModel pushes input.box value to comp.name
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
input.dispatchEvent(newEvent('input'));
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
|
||||||
input.dispatchEvent(new Event('input'));
|
|
||||||
return fixture.whenStable();
|
return fixture.whenStable();
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
expect(comp.name).toBe(expectedNewName,
|
expect(comp.name).toBe(expectedNewName,
|
||||||
`After ngModel updates the model, comp.name should be ${expectedNewName} `);
|
`After ngModel updates the model, comp.name should be ${expectedNewName} `);
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// fakeAsync version of ngModel input test enables sync test style
|
// fakeAsync version of ngModel input test enables sync test style
|
||||||
@ -314,11 +311,9 @@ describe('demo (with TestBed):', () => {
|
|||||||
expect(comp.name).toBe(expectedOrigName,
|
expect(comp.name).toBe(expectedOrigName,
|
||||||
`comp.name should still be ${expectedOrigName} after value change, before binding happens`);
|
`comp.name should still be ${expectedOrigName} after value change, before binding happens`);
|
||||||
|
|
||||||
// Dispatch a DOM event so that Angular learns of input value change.
|
// dispatch a DOM event so that Angular learns of input value change.
|
||||||
// then wait a tick while ngModel pushes input.box value to comp.name
|
// then wait a tick while ngModel pushes input.box value to comp.name
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
input.dispatchEvent(newEvent('input'));
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
|
||||||
input.dispatchEvent(new Event('input'));
|
|
||||||
tick();
|
tick();
|
||||||
expect(comp.name).toBe(expectedNewName,
|
expect(comp.name).toBe(expectedNewName,
|
||||||
`After ngModel updates the model, comp.name should be ${expectedNewName} `);
|
`After ngModel updates the model, comp.name should be ${expectedNewName} `);
|
||||||
@ -332,19 +327,17 @@ describe('demo (with TestBed):', () => {
|
|||||||
const fixture = TestBed.createComponent(ReversePipeComponent);
|
const fixture = TestBed.createComponent(ReversePipeComponent);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const comp = fixture.componentInstance;
|
const comp = fixture.componentInstance;
|
||||||
const input = fixture.debugElement.query(By.css('input')).nativeElement as HTMLInputElement;
|
const input = fixture.debugElement.query(By.css('input')).nativeElement as HTMLInputElement;
|
||||||
const span = fixture.debugElement.query(By.css('span')).nativeElement as HTMLElement;
|
const span = fixture.debugElement.query(By.css('span')).nativeElement as HTMLElement;
|
||||||
|
|
||||||
// simulate user entering new name in input
|
// simulate user entering new name in input
|
||||||
input.value = inputText;
|
input.value = inputText;
|
||||||
|
|
||||||
// Dispatch a DOM event so that Angular learns of input value change.
|
// dispatch a DOM event so that Angular learns of input value change.
|
||||||
// then wait a tick while ngModel pushes input.box value to comp.text
|
// then wait a tick while ngModel pushes input.box value to comp.text
|
||||||
// and Angular updates the output span
|
// and Angular updates the output span
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
input.dispatchEvent(newEvent('input'));
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
|
||||||
input.dispatchEvent(new Event('input'));
|
|
||||||
tick();
|
tick();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(span.textContent).toBe(expectedText, 'output span');
|
expect(span.textContent).toBe(expectedText, 'output span');
|
||||||
@ -388,12 +381,12 @@ describe('demo (with TestBed):', () => {
|
|||||||
|
|
||||||
expect(el.styles.color).toBe(comp.color, 'color style');
|
expect(el.styles.color).toBe(comp.color, 'color style');
|
||||||
expect(el.styles.width).toBe(comp.width + 'px', 'width style');
|
expect(el.styles.width).toBe(comp.width + 'px', 'width style');
|
||||||
// #enddocregion dom-attributes
|
// #enddocregion dom-attributes
|
||||||
|
|
||||||
// Removed on 12/02/2016 when ceased public discussion of the `Renderer`. Revive in future?
|
// Removed on 12/02/2016 when ceased public discussion of the `Renderer`. Revive in future?
|
||||||
// expect(el.properties['customProperty']).toBe(true, 'customProperty');
|
// expect(el.properties['customProperty']).toBe(true, 'customProperty');
|
||||||
|
|
||||||
// #docregion dom-attributes
|
// #docregion dom-attributes
|
||||||
});
|
});
|
||||||
// #enddocregion dom-attributes
|
// #enddocregion dom-attributes
|
||||||
|
|
||||||
@ -407,10 +400,10 @@ describe('demo (with TestBed):', () => {
|
|||||||
const fixture = TestBed.configureTestingModule({
|
const fixture = TestBed.configureTestingModule({
|
||||||
declarations: [Child1Component],
|
declarations: [Child1Component],
|
||||||
})
|
})
|
||||||
.overrideComponent(Child1Component, {
|
.overrideComponent(Child1Component, {
|
||||||
set: { template: '<span>Fake</span>' }
|
set: { template: '<span>Fake</span>' }
|
||||||
})
|
})
|
||||||
.createComponent(Child1Component);
|
.createComponent(Child1Component);
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(fixture).toHaveText('Fake');
|
expect(fixture).toHaveText('Fake');
|
||||||
@ -420,14 +413,14 @@ describe('demo (with TestBed):', () => {
|
|||||||
const fixture = TestBed.configureTestingModule({
|
const fixture = TestBed.configureTestingModule({
|
||||||
declarations: [TestProvidersComponent],
|
declarations: [TestProvidersComponent],
|
||||||
})
|
})
|
||||||
.overrideComponent(TestProvidersComponent, {
|
.overrideComponent(TestProvidersComponent, {
|
||||||
remove: { providers: [ValueService] },
|
remove: { providers: [ValueService]},
|
||||||
add: { providers: [{ provide: ValueService, useClass: FakeValueService }] },
|
add: { providers: [{ provide: ValueService, useClass: FakeValueService }] },
|
||||||
|
|
||||||
// Or replace them all (this component has only one provider)
|
// Or replace them all (this component has only one provider)
|
||||||
// set: { providers: [{ provide: ValueService, useClass: FakeValueService }] },
|
// set: { providers: [{ provide: ValueService, useClass: FakeValueService }] },
|
||||||
})
|
})
|
||||||
.createComponent(TestProvidersComponent);
|
.createComponent(TestProvidersComponent);
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(fixture).toHaveText('injected value: faked value', 'text');
|
expect(fixture).toHaveText('injected value: faked value', 'text');
|
||||||
@ -443,14 +436,14 @@ describe('demo (with TestBed):', () => {
|
|||||||
const fixture = TestBed.configureTestingModule({
|
const fixture = TestBed.configureTestingModule({
|
||||||
declarations: [TestViewProvidersComponent],
|
declarations: [TestViewProvidersComponent],
|
||||||
})
|
})
|
||||||
.overrideComponent(TestViewProvidersComponent, {
|
.overrideComponent(TestViewProvidersComponent, {
|
||||||
// remove: { viewProviders: [ValueService]},
|
// remove: { viewProviders: [ValueService]},
|
||||||
// add: { viewProviders: [{ provide: ValueService, useClass: FakeValueService }] },
|
// add: { viewProviders: [{ provide: ValueService, useClass: FakeValueService }] },
|
||||||
|
|
||||||
// Or replace them all (this component has only one viewProvider)
|
// Or replace them all (this component has only one viewProvider)
|
||||||
set: { viewProviders: [{ provide: ValueService, useClass: FakeValueService }] },
|
set: { viewProviders: [{ provide: ValueService, useClass: FakeValueService }] },
|
||||||
})
|
})
|
||||||
.createComponent(TestViewProvidersComponent);
|
.createComponent(TestViewProvidersComponent);
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(fixture).toHaveText('injected value: faked value');
|
expect(fixture).toHaveText('injected value: faked value');
|
||||||
@ -460,20 +453,20 @@ describe('demo (with TestBed):', () => {
|
|||||||
|
|
||||||
// TestComponent is parent of TestProvidersComponent
|
// TestComponent is parent of TestProvidersComponent
|
||||||
@Component({ template: '<my-service-comp></my-service-comp>' })
|
@Component({ template: '<my-service-comp></my-service-comp>' })
|
||||||
class TestComponent { }
|
class TestComponent {}
|
||||||
|
|
||||||
// 3 levels of ValueService provider: module, TestCompomponent, TestProvidersComponent
|
// 3 levels of ValueService provider: module, TestCompomponent, TestProvidersComponent
|
||||||
const fixture = TestBed.configureTestingModule({
|
const fixture = TestBed.configureTestingModule({
|
||||||
declarations: [TestComponent, TestProvidersComponent],
|
declarations: [TestComponent, TestProvidersComponent],
|
||||||
providers: [ValueService]
|
providers: [ValueService]
|
||||||
})
|
})
|
||||||
.overrideComponent(TestComponent, {
|
.overrideComponent(TestComponent, {
|
||||||
set: { providers: [{ provide: ValueService, useValue: {} }] }
|
set: { providers: [{ provide: ValueService, useValue: {} }] }
|
||||||
})
|
})
|
||||||
.overrideComponent(TestProvidersComponent, {
|
.overrideComponent(TestProvidersComponent, {
|
||||||
set: { providers: [{ provide: ValueService, useClass: FakeValueService }] }
|
set: { providers: [{ provide: ValueService, useClass: FakeValueService }] }
|
||||||
})
|
})
|
||||||
.createComponent(TestComponent);
|
.createComponent(TestComponent);
|
||||||
|
|
||||||
let testBedProvider: ValueService;
|
let testBedProvider: ValueService;
|
||||||
let tcProvider: ValueService;
|
let tcProvider: ValueService;
|
||||||
@ -496,10 +489,10 @@ describe('demo (with TestBed):', () => {
|
|||||||
const fixture = TestBed.configureTestingModule({
|
const fixture = TestBed.configureTestingModule({
|
||||||
declarations: [ShellComponent, NeedsContentComponent, Child1Component, Child2Component, Child3Component],
|
declarations: [ShellComponent, NeedsContentComponent, Child1Component, Child2Component, Child3Component],
|
||||||
})
|
})
|
||||||
.overrideComponent(ShellComponent, {
|
.overrideComponent(ShellComponent, {
|
||||||
set: {
|
set: {
|
||||||
selector: 'test-shell',
|
selector: 'test-shell',
|
||||||
template: `
|
template: `
|
||||||
<needs-content #nc>
|
<needs-content #nc>
|
||||||
<child-1 #content text="My"></child-1>
|
<child-1 #content text="My"></child-1>
|
||||||
<child-2 #content text="dog"></child-2>
|
<child-2 #content text="dog"></child-2>
|
||||||
@ -508,9 +501,9 @@ describe('demo (with TestBed):', () => {
|
|||||||
<div #content>!</div>
|
<div #content>!</div>
|
||||||
</needs-content>
|
</needs-content>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.createComponent(ShellComponent);
|
.createComponent(ShellComponent);
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
@ -622,7 +615,7 @@ describe('demo (with TestBed):', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// must be async test to see child flow to parent
|
// must be async test to see child flow to parent
|
||||||
it('changed child value flows to parent', waitForAsync(() => {
|
it('changed child value flows to parent', async(() => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
getChild();
|
getChild();
|
||||||
|
|
||||||
@ -632,14 +625,14 @@ describe('demo (with TestBed):', () => {
|
|||||||
// Wait one JS engine turn!
|
// Wait one JS engine turn!
|
||||||
setTimeout(() => resolve(), 0);
|
setTimeout(() => resolve(), 0);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(child.ngOnChangesCounter).toBe(2,
|
expect(child.ngOnChangesCounter).toBe(2,
|
||||||
'expected 2 changes: initial value and changed value');
|
'expected 2 changes: initial value and changed value');
|
||||||
expect(parent.parentValue).toBe('bar',
|
expect(parent.parentValue).toBe('bar',
|
||||||
'parentValue should eq changed parent value');
|
'parentValue should eq changed parent value');
|
||||||
});
|
});
|
||||||
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
import { ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
import {
|
||||||
|
async, ComponentFixture, fakeAsync, inject, TestBed, tick
|
||||||
|
} from '@angular/core/testing';
|
||||||
|
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ActivatedRoute, ActivatedRouteStub, asyncData, click
|
ActivatedRoute, ActivatedRouteStub, asyncData, click, newEvent
|
||||||
} from '../../testing';
|
} from '../../testing';
|
||||||
|
|
||||||
import { Hero } from '../model/hero';
|
import { Hero } from '../model/hero';
|
||||||
@ -33,54 +36,59 @@ describe('HeroDetailComponent', () => {
|
|||||||
function overrideSetup() {
|
function overrideSetup() {
|
||||||
// #docregion hds-spy
|
// #docregion hds-spy
|
||||||
class HeroDetailServiceSpy {
|
class HeroDetailServiceSpy {
|
||||||
testHero: Hero = {id: 42, name: 'Test Hero'};
|
testHero: Hero = {id: 42, name: 'Test Hero' };
|
||||||
|
|
||||||
/* emit cloned test hero */
|
/* emit cloned test hero */
|
||||||
getHero = jasmine.createSpy('getHero').and.callFake(
|
getHero = jasmine.createSpy('getHero').and.callFake(
|
||||||
() => asyncData(Object.assign({}, this.testHero)));
|
() => asyncData(Object.assign({}, this.testHero))
|
||||||
|
);
|
||||||
|
|
||||||
/* emit clone of test hero, with changes merged in */
|
/* emit clone of test hero, with changes merged in */
|
||||||
saveHero = jasmine.createSpy('saveHero')
|
saveHero = jasmine.createSpy('saveHero').and.callFake(
|
||||||
.and.callFake((hero: Hero) => asyncData(Object.assign(this.testHero, hero)));
|
(hero: Hero) => asyncData(Object.assign(this.testHero, hero))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #enddocregion hds-spy
|
// #enddocregion hds-spy
|
||||||
|
|
||||||
// the `id` value is irrelevant because ignored by service stub
|
// the `id` value is irrelevant because ignored by service stub
|
||||||
beforeEach(() => activatedRoute.setParamMap({id: 99999}));
|
beforeEach(() => activatedRoute.setParamMap({ id: 99999 }));
|
||||||
|
|
||||||
// #docregion setup-override
|
// #docregion setup-override
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
const routerSpy = createRouterSpy();
|
const routerSpy = createRouterSpy();
|
||||||
|
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule({
|
imports: [ HeroModule ],
|
||||||
imports: [HeroModule],
|
providers: [
|
||||||
providers: [
|
{ provide: ActivatedRoute, useValue: activatedRoute },
|
||||||
{provide: ActivatedRoute, useValue: activatedRoute},
|
{ provide: Router, useValue: routerSpy},
|
||||||
{provide: Router, useValue: routerSpy},
|
|
||||||
// #enddocregion setup-override
|
// #enddocregion setup-override
|
||||||
// HeroDetailService at this level is IRRELEVANT!
|
// HeroDetailService at this level is IRRELEVANT!
|
||||||
{provide: HeroDetailService, useValue: {}}
|
{ provide: HeroDetailService, useValue: {} }
|
||||||
// #docregion setup-override
|
// #docregion setup-override
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
// Override component's own provider
|
// Override component's own provider
|
||||||
// #docregion override-component-method
|
// #docregion override-component-method
|
||||||
.overrideComponent(
|
.overrideComponent(HeroDetailComponent, {
|
||||||
HeroDetailComponent,
|
set: {
|
||||||
{set: {providers: [{provide: HeroDetailService, useClass: HeroDetailServiceSpy}]}})
|
providers: [
|
||||||
// #enddocregion override-component-method
|
{ provide: HeroDetailService, useClass: HeroDetailServiceSpy }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// #enddocregion override-component-method
|
||||||
|
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
// #enddocregion setup-override
|
// #enddocregion setup-override
|
||||||
|
|
||||||
// #docregion override-tests
|
// #docregion override-tests
|
||||||
let hdsSpy: HeroDetailServiceSpy;
|
let hdsSpy: HeroDetailServiceSpy;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
createComponent();
|
createComponent();
|
||||||
// get the component's injected HeroDetailServiceSpy
|
// get the component's injected HeroDetailServiceSpy
|
||||||
hdsSpy = fixture.debugElement.injector.get(HeroDetailService) as any;
|
hdsSpy = fixture.debugElement.injector.get(HeroDetailService) as any;
|
||||||
@ -95,35 +103,33 @@ function overrideSetup() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should save stub hero change', fakeAsync(() => {
|
it('should save stub hero change', fakeAsync(() => {
|
||||||
const origName = hdsSpy.testHero.name;
|
const origName = hdsSpy.testHero.name;
|
||||||
const newName = 'New Name';
|
const newName = 'New Name';
|
||||||
|
|
||||||
page.nameInput.value = newName;
|
page.nameInput.value = newName;
|
||||||
|
page.nameInput.dispatchEvent(newEvent('input')); // tell Angular
|
||||||
|
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
expect(component.hero.name).toBe(newName, 'component hero has new name');
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
expect(hdsSpy.testHero.name).toBe(origName, 'service hero unchanged before save');
|
||||||
page.nameInput.dispatchEvent(new Event('input')); // tell Angular
|
|
||||||
|
|
||||||
expect(component.hero.name).toBe(newName, 'component hero has new name');
|
click(page.saveBtn);
|
||||||
expect(hdsSpy.testHero.name).toBe(origName, 'service hero unchanged before save');
|
expect(hdsSpy.saveHero.calls.count()).toBe(1, 'saveHero called once');
|
||||||
|
|
||||||
click(page.saveBtn);
|
tick(); // wait for async save to complete
|
||||||
expect(hdsSpy.saveHero.calls.count()).toBe(1, 'saveHero called once');
|
expect(hdsSpy.testHero.name).toBe(newName, 'service hero has new name after save');
|
||||||
|
expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called');
|
||||||
tick(); // wait for async save to complete
|
}));
|
||||||
expect(hdsSpy.testHero.name).toBe(newName, 'service hero has new name after save');
|
|
||||||
expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called');
|
|
||||||
}));
|
|
||||||
// #enddocregion override-tests
|
// #enddocregion override-tests
|
||||||
|
|
||||||
it('fixture injected service is not the component injected service',
|
it('fixture injected service is not the component injected service',
|
||||||
// inject gets the service from the fixture
|
// inject gets the service from the fixture
|
||||||
inject([HeroDetailService], (fixtureService: HeroDetailService) => {
|
inject([HeroDetailService], (fixtureService: HeroDetailService) => {
|
||||||
// use `fixture.debugElement.injector` to get service from component
|
|
||||||
const componentService = fixture.debugElement.injector.get(HeroDetailService);
|
|
||||||
|
|
||||||
expect(fixtureService).not.toBe(componentService, 'service injected from fixture');
|
// use `fixture.debugElement.injector` to get service from component
|
||||||
}));
|
const componentService = fixture.debugElement.injector.get(HeroDetailService);
|
||||||
|
|
||||||
|
expect(fixtureService).not.toBe(componentService, 'service injected from fixture');
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
@ -133,22 +139,21 @@ const firstHero = getTestHeroes()[0];
|
|||||||
|
|
||||||
function heroModuleSetup() {
|
function heroModuleSetup() {
|
||||||
// #docregion setup-hero-module
|
// #docregion setup-hero-module
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
const routerSpy = createRouterSpy();
|
const routerSpy = createRouterSpy();
|
||||||
|
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule({
|
imports: [ HeroModule ],
|
||||||
imports: [HeroModule],
|
// #enddocregion setup-hero-module
|
||||||
// #enddocregion setup-hero-module
|
// declarations: [ HeroDetailComponent ], // NO! DOUBLE DECLARATION
|
||||||
// declarations: [ HeroDetailComponent ], // NO! DOUBLE DECLARATION
|
// #docregion setup-hero-module
|
||||||
// #docregion setup-hero-module
|
providers: [
|
||||||
providers: [
|
{ provide: ActivatedRoute, useValue: activatedRoute },
|
||||||
{provide: ActivatedRoute, useValue: activatedRoute},
|
{ provide: HeroService, useClass: TestHeroService },
|
||||||
{provide: HeroService, useClass: TestHeroService},
|
{ provide: Router, useValue: routerSpy},
|
||||||
{provide: Router, useValue: routerSpy},
|
]
|
||||||
]
|
})
|
||||||
})
|
.compileComponents();
|
||||||
.compileComponents();
|
|
||||||
}));
|
}));
|
||||||
// #enddocregion setup-hero-module
|
// #enddocregion setup-hero-module
|
||||||
|
|
||||||
@ -156,17 +161,17 @@ function heroModuleSetup() {
|
|||||||
describe('when navigate to existing hero', () => {
|
describe('when navigate to existing hero', () => {
|
||||||
let expectedHero: Hero;
|
let expectedHero: Hero;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
expectedHero = firstHero;
|
expectedHero = firstHero;
|
||||||
activatedRoute.setParamMap({id: expectedHero.id});
|
activatedRoute.setParamMap({ id: expectedHero.id });
|
||||||
createComponent();
|
createComponent();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// #docregion selected-tests
|
// #docregion selected-tests
|
||||||
it('should display that hero\'s name', () => {
|
it('should display that hero\'s name', () => {
|
||||||
expect(page.nameDisplay.textContent).toBe(expectedHero.name);
|
expect(page.nameDisplay.textContent).toBe(expectedHero.name);
|
||||||
});
|
});
|
||||||
// #enddocregion route-good-id
|
// #enddocregion route-good-id
|
||||||
|
|
||||||
it('should navigate when click cancel', () => {
|
it('should navigate when click cancel', () => {
|
||||||
click(page.cancelBtn);
|
click(page.cancelBtn);
|
||||||
@ -185,10 +190,10 @@ function heroModuleSetup() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should navigate when click save and save resolves', fakeAsync(() => {
|
it('should navigate when click save and save resolves', fakeAsync(() => {
|
||||||
click(page.saveBtn);
|
click(page.saveBtn);
|
||||||
tick(); // wait for async save to complete
|
tick(); // wait for async save to complete
|
||||||
expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called');
|
expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// #docregion title-case-pipe
|
// #docregion title-case-pipe
|
||||||
it('should convert hero name to Title Case', () => {
|
it('should convert hero name to Title Case', () => {
|
||||||
@ -200,10 +205,9 @@ function heroModuleSetup() {
|
|||||||
// simulate user entering a new name into the input box
|
// simulate user entering a new name into the input box
|
||||||
nameInput.value = 'quick BROWN fOx';
|
nameInput.value = 'quick BROWN fOx';
|
||||||
|
|
||||||
// Dispatch a DOM event so that Angular learns of input value change.
|
// dispatch a DOM event so that Angular learns of input value change.
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
// use newEvent utility function (not provided by Angular) for better browser compatibility
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
nameInput.dispatchEvent(newEvent('input'));
|
||||||
nameInput.dispatchEvent(new Event('input'));
|
|
||||||
|
|
||||||
// Tell Angular to update the display binding through the title pipe
|
// Tell Angular to update the display binding through the title pipe
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@ -211,14 +215,14 @@ function heroModuleSetup() {
|
|||||||
expect(nameDisplay.textContent).toBe('Quick Brown Fox');
|
expect(nameDisplay.textContent).toBe('Quick Brown Fox');
|
||||||
});
|
});
|
||||||
// #enddocregion title-case-pipe
|
// #enddocregion title-case-pipe
|
||||||
// #enddocregion selected-tests
|
// #enddocregion selected-tests
|
||||||
// #docregion route-good-id
|
// #docregion route-good-id
|
||||||
});
|
});
|
||||||
// #enddocregion route-good-id
|
// #enddocregion route-good-id
|
||||||
|
|
||||||
// #docregion route-no-id
|
// #docregion route-no-id
|
||||||
describe('when navigate with no hero id', () => {
|
describe('when navigate with no hero id', () => {
|
||||||
beforeEach(waitForAsync(createComponent));
|
beforeEach(async( createComponent ));
|
||||||
|
|
||||||
it('should have hero.id === 0', () => {
|
it('should have hero.id === 0', () => {
|
||||||
expect(component.hero.id).toBe(0);
|
expect(component.hero.id).toBe(0);
|
||||||
@ -232,8 +236,8 @@ function heroModuleSetup() {
|
|||||||
|
|
||||||
// #docregion route-bad-id
|
// #docregion route-bad-id
|
||||||
describe('when navigate to non-existent hero id', () => {
|
describe('when navigate to non-existent hero id', () => {
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
activatedRoute.setParamMap({id: 99999});
|
activatedRoute.setParamMap({ id: 99999 });
|
||||||
createComponent();
|
createComponent();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -249,10 +253,11 @@ function heroModuleSetup() {
|
|||||||
let service: HeroDetailService;
|
let service: HeroDetailService;
|
||||||
fixture = TestBed.createComponent(HeroDetailComponent);
|
fixture = TestBed.createComponent(HeroDetailComponent);
|
||||||
expect(
|
expect(
|
||||||
// Throws because `inject` only has access to TestBed's injector
|
// Throws because `inject` only has access to TestBed's injector
|
||||||
// which is an ancestor of the component's injector
|
// which is an ancestor of the component's injector
|
||||||
inject([HeroDetailService], (hds: HeroDetailService) => service = hds))
|
inject([HeroDetailService], (hds: HeroDetailService) => service = hds )
|
||||||
.toThrowError(/No provider for HeroDetailService/);
|
)
|
||||||
|
.toThrowError(/No provider for HeroDetailService/);
|
||||||
|
|
||||||
// get `HeroDetailService` with component's own injector
|
// get `HeroDetailService` with component's own injector
|
||||||
service = fixture.debugElement.injector.get(HeroDetailService);
|
service = fixture.debugElement.injector.get(HeroDetailService);
|
||||||
@ -265,31 +270,30 @@ import { FormsModule } from '@angular/forms';
|
|||||||
import { TitleCasePipe } from '../shared/title-case.pipe';
|
import { TitleCasePipe } from '../shared/title-case.pipe';
|
||||||
|
|
||||||
function formsModuleSetup() {
|
function formsModuleSetup() {
|
||||||
// #docregion setup-forms-module
|
// #docregion setup-forms-module
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
const routerSpy = createRouterSpy();
|
const routerSpy = createRouterSpy();
|
||||||
|
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule({
|
imports: [ FormsModule ],
|
||||||
imports: [FormsModule],
|
declarations: [ HeroDetailComponent, TitleCasePipe ],
|
||||||
declarations: [HeroDetailComponent, TitleCasePipe],
|
providers: [
|
||||||
providers: [
|
{ provide: ActivatedRoute, useValue: activatedRoute },
|
||||||
{provide: ActivatedRoute, useValue: activatedRoute},
|
{ provide: HeroService, useClass: TestHeroService },
|
||||||
{provide: HeroService, useClass: TestHeroService},
|
{ provide: Router, useValue: routerSpy},
|
||||||
{provide: Router, useValue: routerSpy},
|
]
|
||||||
]
|
})
|
||||||
})
|
.compileComponents();
|
||||||
.compileComponents();
|
|
||||||
}));
|
}));
|
||||||
// #enddocregion setup-forms-module
|
// #enddocregion setup-forms-module
|
||||||
|
|
||||||
it('should display 1st hero\'s name', waitForAsync(() => {
|
it('should display 1st hero\'s name', async(() => {
|
||||||
const expectedHero = firstHero;
|
const expectedHero = firstHero;
|
||||||
activatedRoute.setParamMap({id: expectedHero.id});
|
activatedRoute.setParamMap({ id: expectedHero.id });
|
||||||
createComponent().then(() => {
|
createComponent().then(() => {
|
||||||
expect(page.nameDisplay.textContent).toBe(expectedHero.name);
|
expect(page.nameDisplay.textContent).toBe(expectedHero.name);
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
@ -297,30 +301,29 @@ import { SharedModule } from '../shared/shared.module';
|
|||||||
|
|
||||||
function sharedModuleSetup() {
|
function sharedModuleSetup() {
|
||||||
// #docregion setup-shared-module
|
// #docregion setup-shared-module
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
const routerSpy = createRouterSpy();
|
const routerSpy = createRouterSpy();
|
||||||
|
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule({
|
imports: [ SharedModule ],
|
||||||
imports: [SharedModule],
|
declarations: [ HeroDetailComponent ],
|
||||||
declarations: [HeroDetailComponent],
|
providers: [
|
||||||
providers: [
|
{ provide: ActivatedRoute, useValue: activatedRoute },
|
||||||
{provide: ActivatedRoute, useValue: activatedRoute},
|
{ provide: HeroService, useClass: TestHeroService },
|
||||||
{provide: HeroService, useClass: TestHeroService},
|
{ provide: Router, useValue: routerSpy},
|
||||||
{provide: Router, useValue: routerSpy},
|
]
|
||||||
]
|
})
|
||||||
})
|
.compileComponents();
|
||||||
.compileComponents();
|
|
||||||
}));
|
}));
|
||||||
// #enddocregion setup-shared-module
|
// #enddocregion setup-shared-module
|
||||||
|
|
||||||
it('should display 1st hero\'s name', waitForAsync(() => {
|
it('should display 1st hero\'s name', async(() => {
|
||||||
const expectedHero = firstHero;
|
const expectedHero = firstHero;
|
||||||
activatedRoute.setParamMap({id: expectedHero.id});
|
activatedRoute.setParamMap({ id: expectedHero.id });
|
||||||
createComponent().then(() => {
|
createComponent().then(() => {
|
||||||
expect(page.nameDisplay.textContent).toBe(expectedHero.name);
|
expect(page.nameDisplay.textContent).toBe(expectedHero.name);
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////// Helpers /////
|
/////////// Helpers /////
|
||||||
@ -344,21 +347,11 @@ function createComponent() {
|
|||||||
// #docregion page
|
// #docregion page
|
||||||
class Page {
|
class Page {
|
||||||
// getter properties wait to query the DOM until called.
|
// getter properties wait to query the DOM until called.
|
||||||
get buttons() {
|
get buttons() { return this.queryAll<HTMLButtonElement>('button'); }
|
||||||
return this.queryAll<HTMLButtonElement>('button');
|
get saveBtn() { return this.buttons[0]; }
|
||||||
}
|
get cancelBtn() { return this.buttons[1]; }
|
||||||
get saveBtn() {
|
get nameDisplay() { return this.query<HTMLElement>('span'); }
|
||||||
return this.buttons[0];
|
get nameInput() { return this.query<HTMLInputElement>('input'); }
|
||||||
}
|
|
||||||
get cancelBtn() {
|
|
||||||
return this.buttons[1];
|
|
||||||
}
|
|
||||||
get nameDisplay() {
|
|
||||||
return this.query<HTMLElement>('span');
|
|
||||||
}
|
|
||||||
get nameInput() {
|
|
||||||
return this.query<HTMLInputElement>('input');
|
|
||||||
}
|
|
||||||
|
|
||||||
gotoListSpy: jasmine.Spy;
|
gotoListSpy: jasmine.Spy;
|
||||||
navigateSpy: jasmine.Spy;
|
navigateSpy: jasmine.Spy;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync
|
import { async, ComponentFixture, fakeAsync, TestBed, tick
|
||||||
} from '@angular/core/testing';
|
} from '@angular/core/testing';
|
||||||
|
|
||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
@ -6,13 +6,14 @@ import { DebugElement } from '@angular/core';
|
|||||||
|
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import { addMatchers } from '../../testing';
|
import { addMatchers, newEvent } from '../../testing';
|
||||||
import { HeroService } from '../model/hero.service';
|
|
||||||
import { getTestHeroes, TestHeroService } from '../model/testing/test-hero.service';
|
import { getTestHeroes, TestHeroService } from '../model/testing/test-hero.service';
|
||||||
|
|
||||||
import { HeroModule } from './hero.module';
|
import { HeroModule } from './hero.module';
|
||||||
import { HeroListComponent } from './hero-list.component';
|
import { HeroListComponent } from './hero-list.component';
|
||||||
import { HighlightDirective } from '../shared/highlight.directive';
|
import { HighlightDirective } from '../shared/highlight.directive';
|
||||||
|
import { HeroService } from '../model/hero.service';
|
||||||
|
|
||||||
const HEROES = getTestHeroes();
|
const HEROES = getTestHeroes();
|
||||||
|
|
||||||
@ -23,20 +24,20 @@ let page: Page;
|
|||||||
/////// Tests //////
|
/////// Tests //////
|
||||||
|
|
||||||
describe('HeroListComponent', () => {
|
describe('HeroListComponent', () => {
|
||||||
beforeEach(waitForAsync(() => {
|
|
||||||
|
beforeEach(async(() => {
|
||||||
addMatchers();
|
addMatchers();
|
||||||
const routerSpy = jasmine.createSpyObj('Router', ['navigate']);
|
const routerSpy = jasmine.createSpyObj('Router', ['navigate']);
|
||||||
|
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule({
|
imports: [HeroModule],
|
||||||
imports: [HeroModule],
|
providers: [
|
||||||
providers: [
|
{ provide: HeroService, useClass: TestHeroService },
|
||||||
{provide: HeroService, useClass: TestHeroService},
|
{ provide: Router, useValue: routerSpy}
|
||||||
{provide: Router, useValue: routerSpy}
|
]
|
||||||
]
|
})
|
||||||
})
|
.compileComponents()
|
||||||
.compileComponents()
|
.then(createComponent);
|
||||||
.then(createComponent);
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should display heroes', () => {
|
it('should display heroes', () => {
|
||||||
@ -51,41 +52,36 @@ describe('HeroListComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should select hero on click', fakeAsync(() => {
|
it('should select hero on click', fakeAsync(() => {
|
||||||
const expectedHero = HEROES[1];
|
const expectedHero = HEROES[1];
|
||||||
const li = page.heroRows[1];
|
const li = page.heroRows[1];
|
||||||
|
li.dispatchEvent(newEvent('click'));
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
tick();
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
// `.toEqual` because selectedHero is clone of expectedHero; see FakeHeroService
|
||||||
li.dispatchEvent(new Event('click'));
|
expect(comp.selectedHero).toEqual(expectedHero);
|
||||||
tick();
|
}));
|
||||||
// `.toEqual` because selectedHero is clone of expectedHero; see FakeHeroService
|
|
||||||
expect(comp.selectedHero).toEqual(expectedHero);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should navigate to selected hero detail on click', fakeAsync(() => {
|
it('should navigate to selected hero detail on click', fakeAsync(() => {
|
||||||
const expectedHero = HEROES[1];
|
const expectedHero = HEROES[1];
|
||||||
const li = page.heroRows[1];
|
const li = page.heroRows[1];
|
||||||
|
li.dispatchEvent(newEvent('click'));
|
||||||
|
tick();
|
||||||
|
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
// should have navigated
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
expect(page.navSpy.calls.any()).toBe(true, 'navigate called');
|
||||||
li.dispatchEvent(new Event('click'));
|
|
||||||
tick();
|
|
||||||
|
|
||||||
// should have navigated
|
// composed hero detail will be URL like 'heroes/42'
|
||||||
expect(page.navSpy.calls.any()).toBe(true, 'navigate called');
|
// expect link array with the route path and hero id
|
||||||
|
// first argument to router.navigate is link array
|
||||||
|
const navArgs = page.navSpy.calls.first().args[0];
|
||||||
|
expect(navArgs[0]).toContain('heroes', 'nav to heroes detail URL');
|
||||||
|
expect(navArgs[1]).toBe(expectedHero.id, 'expected hero.id');
|
||||||
|
|
||||||
// composed hero detail will be URL like 'heroes/42'
|
}));
|
||||||
// expect link array with the route path and hero id
|
|
||||||
// first argument to router.navigate is link array
|
|
||||||
const navArgs = page.navSpy.calls.first().args[0];
|
|
||||||
expect(navArgs[0]).toContain('heroes', 'nav to heroes detail URL');
|
|
||||||
expect(navArgs[1]).toBe(expectedHero.id, 'expected hero.id');
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should find `HighlightDirective` with `By.directive', () => {
|
it('should find `HighlightDirective` with `By.directive', () => {
|
||||||
// #docregion by
|
// #docregion by
|
||||||
// Can find DebugElement either by css selector or by directive
|
// Can find DebugElement either by css selector or by directive
|
||||||
const h2 = fixture.debugElement.query(By.css('h2'));
|
const h2 = fixture.debugElement.query(By.css('h2'));
|
||||||
const directive = fixture.debugElement.query(By.directive(HighlightDirective));
|
const directive = fixture.debugElement.query(By.directive(HighlightDirective));
|
||||||
// #enddocregion by
|
// #enddocregion by
|
||||||
expect(h2).toBe(directive);
|
expect(h2).toBe(directive);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion without-toBlob-macrotask
|
// #docregion without-toBlob-macrotask
|
||||||
import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
import { TestBed, async, tick, fakeAsync } from '@angular/core/testing';
|
||||||
|
|
||||||
import { CanvasComponent } from './canvas.component';
|
import { CanvasComponent } from './canvas.component';
|
||||||
|
|
||||||
describe('CanvasComponent', () => {
|
describe('CanvasComponent', () => {
|
||||||
@ -11,29 +10,29 @@ describe('CanvasComponent', () => {
|
|||||||
(window as any).__zone_symbol__FakeAsyncTestMacroTask = [
|
(window as any).__zone_symbol__FakeAsyncTestMacroTask = [
|
||||||
{
|
{
|
||||||
source: 'HTMLCanvasElement.toBlob',
|
source: 'HTMLCanvasElement.toBlob',
|
||||||
callbackArgs: [{size: 200}],
|
callbackArgs: [{ size: 200 }],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
// #enddocregion enable-toBlob-macrotask
|
// #enddocregion enable-toBlob-macrotask
|
||||||
// #docregion without-toBlob-macrotask
|
// #docregion without-toBlob-macrotask
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule({
|
declarations: [
|
||||||
declarations: [CanvasComponent],
|
CanvasComponent
|
||||||
})
|
],
|
||||||
.compileComponents();
|
}).compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should be able to generate blob data from canvas', fakeAsync(() => {
|
it('should be able to generate blob data from canvas', fakeAsync(() => {
|
||||||
const fixture = TestBed.createComponent(CanvasComponent);
|
const fixture = TestBed.createComponent(CanvasComponent);
|
||||||
const canvasComp = fixture.componentInstance;
|
const canvasComp = fixture.componentInstance;
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(canvasComp.blobSize).toBe(0);
|
expect(canvasComp.blobSize).toBe(0);
|
||||||
|
|
||||||
tick();
|
tick();
|
||||||
expect(canvasComp.blobSize).toBeGreaterThan(0);
|
expect(canvasComp.blobSize).toBeGreaterThan(0);
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
// #enddocregion without-toBlob-macrotask
|
// #enddocregion without-toBlob-macrotask
|
||||||
|
@ -3,6 +3,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
|
|
||||||
import { HighlightDirective } from './highlight.directive';
|
import { HighlightDirective } from './highlight.directive';
|
||||||
|
import { newEvent } from '../../testing';
|
||||||
|
|
||||||
// #docregion test-component
|
// #docregion test-component
|
||||||
@Component({
|
@Component({
|
||||||
@ -58,12 +59,9 @@ describe('HighlightDirective', () => {
|
|||||||
const input = des[2].nativeElement as HTMLInputElement;
|
const input = des[2].nativeElement as HTMLInputElement;
|
||||||
expect(input.style.backgroundColor).toBe('cyan', 'initial backgroundColor');
|
expect(input.style.backgroundColor).toBe('cyan', 'initial backgroundColor');
|
||||||
|
|
||||||
|
// dispatch a DOM event so that Angular responds to the input value change.
|
||||||
input.value = 'green';
|
input.value = 'green';
|
||||||
|
input.dispatchEvent(newEvent('input'));
|
||||||
// Dispatch a DOM event so that Angular responds to the input value change.
|
|
||||||
// In older browsers, such as IE, you might need a CustomEvent instead. See
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill
|
|
||||||
input.dispatchEvent(new Event('input'));
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(input.style.backgroundColor).toBe('green', 'changed backgroundColor');
|
expect(input.style.backgroundColor).toBe('green', 'changed backgroundColor');
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
import { fakeAsync, ComponentFixture, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
import { async, fakeAsync, ComponentFixture, TestBed, tick } from '@angular/core/testing';
|
||||||
|
|
||||||
import { asyncData, asyncError } from '../../testing';
|
import { asyncData, asyncError } from '../../testing';
|
||||||
|
|
||||||
import { of, throwError } from 'rxjs';
|
import { of, throwError } from 'rxjs';
|
||||||
|
|
||||||
import { last } from 'rxjs/operators';
|
import { last } from 'rxjs/operators';
|
||||||
|
|
||||||
import { TwainComponent } from './twain.component';
|
|
||||||
import { TwainService } from './twain.service';
|
import { TwainService } from './twain.service';
|
||||||
|
import { TwainComponent } from './twain.component';
|
||||||
|
|
||||||
describe('TwainComponent', () => {
|
describe('TwainComponent', () => {
|
||||||
let component: TwainComponent;
|
let component: TwainComponent;
|
||||||
@ -31,12 +32,14 @@ describe('TwainComponent', () => {
|
|||||||
// Create a fake TwainService object with a `getQuote()` spy
|
// Create a fake TwainService object with a `getQuote()` spy
|
||||||
const twainService = jasmine.createSpyObj('TwainService', ['getQuote']);
|
const twainService = jasmine.createSpyObj('TwainService', ['getQuote']);
|
||||||
// Make the spy return a synchronous Observable with the test data
|
// Make the spy return a synchronous Observable with the test data
|
||||||
getQuoteSpy = twainService.getQuote.and.returnValue(of(testQuote));
|
getQuoteSpy = twainService.getQuote.and.returnValue( of(testQuote) );
|
||||||
// #enddocregion spy
|
// #enddocregion spy
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [TwainComponent],
|
declarations: [ TwainComponent ],
|
||||||
providers: [{provide: TwainService, useValue: twainService}]
|
providers: [
|
||||||
|
{ provide: TwainService, useValue: twainService }
|
||||||
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
fixture = TestBed.createComponent(TwainComponent);
|
fixture = TestBed.createComponent(TwainComponent);
|
||||||
@ -55,7 +58,7 @@ describe('TwainComponent', () => {
|
|||||||
// The quote would not be immediately available if the service were truly async.
|
// The quote would not be immediately available if the service were truly async.
|
||||||
// #docregion sync-test
|
// #docregion sync-test
|
||||||
it('should show quote after component initialized', () => {
|
it('should show quote after component initialized', () => {
|
||||||
fixture.detectChanges(); // onInit()
|
fixture.detectChanges(); // onInit()
|
||||||
|
|
||||||
// sync spy result shows testQuote immediately after init
|
// sync spy result shows testQuote immediately after init
|
||||||
expect(quoteEl.textContent).toBe(testQuote);
|
expect(quoteEl.textContent).toBe(testQuote);
|
||||||
@ -68,19 +71,20 @@ describe('TwainComponent', () => {
|
|||||||
// Use `fakeAsync` because the component error calls `setTimeout`
|
// Use `fakeAsync` because the component error calls `setTimeout`
|
||||||
// #docregion error-test
|
// #docregion error-test
|
||||||
it('should display error when TwainService fails', fakeAsync(() => {
|
it('should display error when TwainService fails', fakeAsync(() => {
|
||||||
// tell spy to return an error observable
|
// tell spy to return an error observable
|
||||||
getQuoteSpy.and.returnValue(throwError('TwainService test failure'));
|
getQuoteSpy.and.returnValue(
|
||||||
|
throwError('TwainService test failure'));
|
||||||
|
|
||||||
fixture.detectChanges(); // onInit()
|
fixture.detectChanges(); // onInit()
|
||||||
// sync spy errors immediately after init
|
// sync spy errors immediately after init
|
||||||
|
|
||||||
tick(); // flush the component's setTimeout()
|
tick(); // flush the component's setTimeout()
|
||||||
|
|
||||||
fixture.detectChanges(); // update errorMessage within setTimeout()
|
fixture.detectChanges(); // update errorMessage within setTimeout()
|
||||||
|
|
||||||
expect(errorMessage()).toMatch(/test failure/, 'should display error');
|
expect(errorMessage()).toMatch(/test failure/, 'should display error');
|
||||||
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
||||||
}));
|
}));
|
||||||
// #enddocregion error-test
|
// #enddocregion error-test
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -109,28 +113,28 @@ describe('TwainComponent', () => {
|
|||||||
|
|
||||||
// #docregion fake-async-test
|
// #docregion fake-async-test
|
||||||
it('should show quote after getQuote (fakeAsync)', fakeAsync(() => {
|
it('should show quote after getQuote (fakeAsync)', fakeAsync(() => {
|
||||||
fixture.detectChanges(); // ngOnInit()
|
fixture.detectChanges(); // ngOnInit()
|
||||||
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
||||||
|
|
||||||
tick(); // flush the observable to get the quote
|
tick(); // flush the observable to get the quote
|
||||||
fixture.detectChanges(); // update view
|
fixture.detectChanges(); // update view
|
||||||
|
|
||||||
expect(quoteEl.textContent).toBe(testQuote, 'should show quote');
|
expect(quoteEl.textContent).toBe(testQuote, 'should show quote');
|
||||||
expect(errorMessage()).toBeNull('should not show error');
|
expect(errorMessage()).toBeNull('should not show error');
|
||||||
}));
|
}));
|
||||||
// #enddocregion fake-async-test
|
// #enddocregion fake-async-test
|
||||||
|
|
||||||
// #docregion async-test
|
// #docregion async-test
|
||||||
it('should show quote after getQuote (async)', waitForAsync(() => {
|
it('should show quote after getQuote (async)', async(() => {
|
||||||
fixture.detectChanges(); // ngOnInit()
|
fixture.detectChanges(); // ngOnInit()
|
||||||
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
||||||
|
|
||||||
fixture.whenStable().then(() => { // wait for async getQuote
|
fixture.whenStable().then(() => { // wait for async getQuote
|
||||||
fixture.detectChanges(); // update view with quote
|
fixture.detectChanges(); // update view with quote
|
||||||
expect(quoteEl.textContent).toBe(testQuote);
|
expect(quoteEl.textContent).toBe(testQuote);
|
||||||
expect(errorMessage()).toBeNull('should not show error');
|
expect(errorMessage()).toBeNull('should not show error');
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
// #enddocregion async-test
|
// #enddocregion async-test
|
||||||
|
|
||||||
|
|
||||||
@ -138,8 +142,8 @@ describe('TwainComponent', () => {
|
|||||||
it('should show last quote (quote done)', (done: DoneFn) => {
|
it('should show last quote (quote done)', (done: DoneFn) => {
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
component.quote.pipe(last()).subscribe(() => {
|
component.quote.pipe( last() ).subscribe(() => {
|
||||||
fixture.detectChanges(); // update view with quote
|
fixture.detectChanges(); // update view with quote
|
||||||
expect(quoteEl.textContent).toBe(testQuote);
|
expect(quoteEl.textContent).toBe(testQuote);
|
||||||
expect(errorMessage()).toBeNull('should not show error');
|
expect(errorMessage()).toBeNull('should not show error');
|
||||||
done();
|
done();
|
||||||
@ -153,7 +157,7 @@ describe('TwainComponent', () => {
|
|||||||
|
|
||||||
// the spy's most recent call returns the observable with the test quote
|
// the spy's most recent call returns the observable with the test quote
|
||||||
getQuoteSpy.calls.mostRecent().returnValue.subscribe(() => {
|
getQuoteSpy.calls.mostRecent().returnValue.subscribe(() => {
|
||||||
fixture.detectChanges(); // update view with quote
|
fixture.detectChanges(); // update view with quote
|
||||||
expect(quoteEl.textContent).toBe(testQuote);
|
expect(quoteEl.textContent).toBe(testQuote);
|
||||||
expect(errorMessage()).toBeNull('should not show error');
|
expect(errorMessage()).toBeNull('should not show error');
|
||||||
done();
|
done();
|
||||||
@ -163,16 +167,16 @@ describe('TwainComponent', () => {
|
|||||||
|
|
||||||
// #docregion async-error-test
|
// #docregion async-error-test
|
||||||
it('should display error when TwainService fails', fakeAsync(() => {
|
it('should display error when TwainService fails', fakeAsync(() => {
|
||||||
// tell spy to return an async error observable
|
// tell spy to return an async error observable
|
||||||
getQuoteSpy.and.returnValue(asyncError<string>('TwainService test failure'));
|
getQuoteSpy.and.returnValue(asyncError<string>('TwainService test failure'));
|
||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
tick(); // component shows error after a setTimeout()
|
tick(); // component shows error after a setTimeout()
|
||||||
fixture.detectChanges(); // update error message
|
fixture.detectChanges(); // update error message
|
||||||
|
|
||||||
expect(errorMessage()).toMatch(/test failure/, 'should display error');
|
expect(errorMessage()).toMatch(/test failure/, 'should display error');
|
||||||
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
||||||
}));
|
}));
|
||||||
// #enddocregion async-error-test
|
// #enddocregion async-error-test
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -14,6 +14,18 @@ export function advance(f: ComponentFixture<any>): void {
|
|||||||
f.detectChanges();
|
f.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create custom DOM event the old fashioned way
|
||||||
|
*
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/API/Event/initEvent
|
||||||
|
* Although officially deprecated, some browsers (phantom) don't accept the preferred "new Event(eventName)"
|
||||||
|
*/
|
||||||
|
export function newEvent(eventName: string, bubbles = false, cancelable = false) {
|
||||||
|
const evt = document.createEvent('CustomEvent'); // MUST be 'CustomEvent'
|
||||||
|
evt.initCustomEvent(eventName, bubbles, cancelable, null);
|
||||||
|
return evt;
|
||||||
|
}
|
||||||
|
|
||||||
// See https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
|
// See https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button
|
||||||
// #docregion click-event
|
// #docregion click-event
|
||||||
/** Button events to pass to `DebugElement.triggerEventHandler` for RouterLink event handler */
|
/** Button events to pass to `DebugElement.triggerEventHandler` for RouterLink event handler */
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
|
|
||||||
import { HeroSearchComponent } from '../hero-search/hero-search.component';
|
|
||||||
import { HeroService } from '../hero.service';
|
|
||||||
import { HEROES } from '../mock-heroes';
|
|
||||||
|
|
||||||
import { DashboardComponent } from './dashboard.component';
|
import { DashboardComponent } from './dashboard.component';
|
||||||
|
import { HeroSearchComponent } from '../hero-search/hero-search.component';
|
||||||
|
|
||||||
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
|
import { of } from 'rxjs';
|
||||||
|
import { HEROES } from '../mock-heroes';
|
||||||
|
import { HeroService } from '../hero.service';
|
||||||
|
|
||||||
describe('DashboardComponent', () => {
|
describe('DashboardComponent', () => {
|
||||||
let component: DashboardComponent;
|
let component: DashboardComponent;
|
||||||
@ -14,16 +14,23 @@ describe('DashboardComponent', () => {
|
|||||||
let heroService;
|
let heroService;
|
||||||
let getHeroesSpy;
|
let getHeroesSpy;
|
||||||
|
|
||||||
beforeEach(waitForAsync(() => {
|
beforeEach(async(() => {
|
||||||
heroService = jasmine.createSpyObj('HeroService', ['getHeroes']);
|
heroService = jasmine.createSpyObj('HeroService', ['getHeroes']);
|
||||||
getHeroesSpy = heroService.getHeroes.and.returnValue(of(HEROES));
|
getHeroesSpy = heroService.getHeroes.and.returnValue( of(HEROES) );
|
||||||
TestBed
|
TestBed.configureTestingModule({
|
||||||
.configureTestingModule({
|
declarations: [
|
||||||
declarations: [DashboardComponent, HeroSearchComponent],
|
DashboardComponent,
|
||||||
imports: [RouterTestingModule.withRoutes([])],
|
HeroSearchComponent
|
||||||
providers: [{provide: HeroService, useValue: heroService}]
|
],
|
||||||
})
|
imports: [
|
||||||
.compileComponents();
|
RouterTestingModule.withRoutes([])
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
{ provide: HeroService, useValue: heroService }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -40,11 +47,12 @@ describe('DashboardComponent', () => {
|
|||||||
expect(fixture.nativeElement.querySelector('h3').textContent).toEqual('Top Heroes');
|
expect(fixture.nativeElement.querySelector('h3').textContent).toEqual('Top Heroes');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call heroService', waitForAsync(() => {
|
it('should call heroService', async(() => {
|
||||||
expect(getHeroesSpy.calls.any()).toBe(true);
|
expect(getHeroesSpy.calls.any()).toBe(true);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should display 4 links', async(() => {
|
||||||
|
expect(fixture.nativeElement.querySelectorAll('a').length).toEqual(4);
|
||||||
|
}));
|
||||||
|
|
||||||
it('should display 4 links', waitForAsync(() => {
|
|
||||||
expect(fixture.nativeElement.querySelectorAll('a').length).toEqual(4);
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
{
|
{
|
||||||
"extends": "tslint:recommended",
|
"extends": "tslint:recommended",
|
||||||
"rulesDirectory": [
|
|
||||||
"codelyzer"
|
|
||||||
],
|
|
||||||
"rules": {
|
"rules": {
|
||||||
"align": {
|
"align": {
|
||||||
"options": [
|
"options": [
|
||||||
@ -16,6 +13,22 @@
|
|||||||
"deprecation": {
|
"deprecation": {
|
||||||
"severity": "warning"
|
"severity": "warning"
|
||||||
},
|
},
|
||||||
|
"component-class-suffix": true,
|
||||||
|
"component-selector": [
|
||||||
|
true,
|
||||||
|
"element",
|
||||||
|
// TODO: Fix the code and change the prefix to `"app"` (or whatever makes sense).
|
||||||
|
"",
|
||||||
|
"kebab-case"
|
||||||
|
],
|
||||||
|
"contextual-lifecycle": true,
|
||||||
|
"directive-class-suffix": true,
|
||||||
|
"directive-selector": [
|
||||||
|
true,
|
||||||
|
"attribute",
|
||||||
|
["app", "toh"],
|
||||||
|
"camelCase"
|
||||||
|
],
|
||||||
"eofline": true,
|
"eofline": true,
|
||||||
"import-blacklist": [
|
"import-blacklist": [
|
||||||
true,
|
true,
|
||||||
@ -43,8 +56,6 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
// TODO(gkalpak): Fix the code and enable this.
|
|
||||||
// "no-any": true,
|
|
||||||
"no-console": [
|
"no-console": [
|
||||||
true,
|
true,
|
||||||
"debug",
|
"debug",
|
||||||
@ -84,11 +95,6 @@
|
|||||||
"named": "never"
|
"named": "never"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// TODO(gkalpak): Fix the code and enable this.
|
|
||||||
// "typedef": [
|
|
||||||
// true,
|
|
||||||
// "call-signature"
|
|
||||||
// ],
|
|
||||||
"typedef-whitespace": {
|
"typedef-whitespace": {
|
||||||
"options": [
|
"options": [
|
||||||
{
|
{
|
||||||
@ -124,9 +130,6 @@
|
|||||||
"check-typecast"
|
"check-typecast"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"component-class-suffix": true,
|
|
||||||
"contextual-lifecycle": true,
|
|
||||||
"directive-class-suffix": true,
|
|
||||||
"no-conflicting-lifecycle": true,
|
"no-conflicting-lifecycle": true,
|
||||||
"no-host-metadata-property": true,
|
"no-host-metadata-property": true,
|
||||||
"no-input-rename": true,
|
"no-input-rename": true,
|
||||||
@ -138,19 +141,9 @@
|
|||||||
"template-banana-in-box": true,
|
"template-banana-in-box": true,
|
||||||
"template-no-negated-async": true,
|
"template-no-negated-async": true,
|
||||||
"use-lifecycle-interface": true,
|
"use-lifecycle-interface": true,
|
||||||
"use-pipe-transform-interface": true,
|
"use-pipe-transform-interface": true
|
||||||
"directive-selector": [
|
},
|
||||||
true,
|
"rulesDirectory": [
|
||||||
"attribute",
|
"codelyzer"
|
||||||
["app", "toh"],
|
]
|
||||||
"camelCase"
|
|
||||||
],
|
|
||||||
"component-selector": [
|
|
||||||
true,
|
|
||||||
"element",
|
|
||||||
// TODO: Fix the code and change the prefix to `"app"` (or whatever makes sense).
|
|
||||||
"",
|
|
||||||
"kebab-case"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import * as angular from 'angular';
|
import * as angular from 'angular';
|
||||||
import 'angular-route';
|
import 'angular-route';
|
||||||
|
|
||||||
const appModule = angular.module('myApp', [
|
const appName = 'myApp';
|
||||||
|
|
||||||
|
angular.module(appName, [
|
||||||
'ngRoute'
|
'ngRoute'
|
||||||
])
|
])
|
||||||
.config(['$routeProvider', '$locationProvider',
|
.config(['$routeProvider', '$locationProvider',
|
||||||
@ -23,5 +25,5 @@ const appModule = angular.module('myApp', [
|
|||||||
);
|
);
|
||||||
|
|
||||||
export function bootstrap(el: HTMLElement) {
|
export function bootstrap(el: HTMLElement) {
|
||||||
return angular.bootstrap(el, [appModule.name]);
|
return angular.bootstrap(el, [appName]);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||||
|
|
||||||
<script src="node_modules/zone.js/bundles/zone.umd.js"></script>
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.1.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||||
|
|
||||||
<script src="node_modules/zone.js/bundles/zone.umd.js"></script>
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.1.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||||
|
|
||||||
<script src="node_modules/zone.js/bundles/zone.umd.js"></script>
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.1.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||||
|
|
||||||
<script src="node_modules/zone.js/bundles/zone.umd.js"></script>
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.1.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<!-- Polyfills -->
|
<!-- Polyfills -->
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||||
|
|
||||||
<script src="node_modules/zone.js/bundles/zone.umd.js"></script>
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
<script src="systemjs.config.1.js"></script>
|
<script src="systemjs.config.1.js"></script>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user