Compare commits
368 Commits
Author | SHA1 | Date | |
---|---|---|---|
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 |
9
.bazelrc
9
.bazelrc
@ -136,6 +136,15 @@ build:remote --remote_executor=remotebuildexecution.googleapis.com
|
|||||||
# retry mechanism and we do not want to retry unnecessarily if Karma already tried multiple times.
|
# retry mechanism and we do not want to retry unnecessarily if Karma already tried multiple times.
|
||||||
test:saucelabs --flaky_test_attempts=1
|
test:saucelabs --flaky_test_attempts=1
|
||||||
|
|
||||||
|
###############################
|
||||||
|
# NodeJS rules settings
|
||||||
|
# These settings are required for rules_nodejs
|
||||||
|
###############################
|
||||||
|
|
||||||
|
# Turn on managed directories feature in Bazel
|
||||||
|
# This allows us to avoid installing a second copy of node_modules
|
||||||
|
common --experimental_allow_incremental_repository_updates
|
||||||
|
|
||||||
####################################################
|
####################################################
|
||||||
# User bazel configuration
|
# User bazel configuration
|
||||||
# NOTE: This needs to be the *last* entry in the config.
|
# NOTE: This needs to be the *last* entry in the config.
|
||||||
|
@ -30,6 +30,11 @@ var_4: &cache_key_fallback v7-angular-node-12-{{ checksum ".bazelversion" }}
|
|||||||
var_3_win: &cache_key_win v7-angular-win-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
var_3_win: &cache_key_win v7-angular-win-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||||
var_4_win: &cache_key_win_fallback v7-angular-win-node-12-{{ checksum ".bazelversion" }}
|
var_4_win: &cache_key_win_fallback v7-angular-win-node-12-{{ checksum ".bazelversion" }}
|
||||||
|
|
||||||
|
# Cache key for the `components-repo-unit-tests` job. **Note** when updating the SHA in the
|
||||||
|
# cache keys also update the SHA for the "COMPONENTS_REPO_COMMIT" environment variable.
|
||||||
|
var_5: &components_repo_unit_tests_cache_key v7-angular-components-f428c00465dfcf8a020237f22532480eedbd2cb6
|
||||||
|
var_6: &components_repo_unit_tests_cache_key_fallback v7-angular-components-
|
||||||
|
|
||||||
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and
|
# Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and
|
||||||
# `build-ivy-npm-packages`.
|
# `build-ivy-npm-packages`.
|
||||||
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
||||||
@ -151,6 +156,27 @@ commands:
|
|||||||
git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true
|
git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true
|
||||||
git config --global gc.auto 0 || true
|
git config --global gc.auto 0 || true
|
||||||
|
|
||||||
|
init_saucelabs_environment:
|
||||||
|
description: Sets up a domain that resolves to the local host.
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
name: Preparing environment for running tests on Sauce Labs.
|
||||||
|
command: |
|
||||||
|
# For SauceLabs jobs, we set up a domain which resolves to the machine which launched
|
||||||
|
# the tunnel. We do this because devices are sometimes not able to properly resolve
|
||||||
|
# `localhost` or `127.0.0.1` through the SauceLabs tunnel. Using a domain that does not
|
||||||
|
# resolve to anything on SauceLabs VMs ensures that such requests are always resolved
|
||||||
|
# through the tunnel, and resolve to the actual tunnel host machine (i.e. the CircleCI VM).
|
||||||
|
# More context can be found in: https://github.com/angular/angular/pull/35171.
|
||||||
|
setPublicVar SAUCE_LOCALHOST_ALIAS_DOMAIN "angular-ci.local"
|
||||||
|
setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
|
||||||
|
- run:
|
||||||
|
# Sets up a local domain in the machine's host file that resolves to the local
|
||||||
|
# host. This domain is helpful in Sauce Labs tests where devices are not able to
|
||||||
|
# properly resolve `localhost` or `127.0.0.1` through the sauce-connect tunnel.
|
||||||
|
name: Setting up alias domain for local host.
|
||||||
|
command: echo "127.0.0.1 $SAUCE_LOCALHOST_ALIAS_DOMAIN" | sudo tee -a /etc/hosts
|
||||||
|
|
||||||
# Normally this would be an individual job instead of a command.
|
# Normally this would be an individual job instead of a command.
|
||||||
# But startup and setup time for each individual windows job are high enough to discourage
|
# But startup and setup time for each individual windows job are high enough to discourage
|
||||||
# many small jobs, so instead we use a command for setup unless the gain becomes significant.
|
# many small jobs, so instead we use a command for setup unless the gain becomes significant.
|
||||||
@ -246,8 +272,109 @@ jobs:
|
|||||||
- run: yarn -s tslint
|
- run: yarn -s tslint
|
||||||
- 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 commit-message validate-range --range $CI_COMMIT_RANGE
|
- run: yarn -s ng-dev commit-message validate-range --range $CI_COMMIT_RANGE
|
||||||
|
|
||||||
|
test:
|
||||||
|
executor:
|
||||||
|
name: default-executor
|
||||||
|
# Now that large integration tests are running locally in parallel (they can't run on RBE yet
|
||||||
|
# as they require network access for yarn install), this test is running out of memory
|
||||||
|
# consistently with the xlarge machine.
|
||||||
|
# TODO: switch back to xlarge once integration tests are running on remote-exec
|
||||||
|
resource_class: 2xlarge+
|
||||||
|
steps:
|
||||||
|
- custom_attach_workspace
|
||||||
|
- init_environment
|
||||||
|
- install_chrome_libs
|
||||||
|
- install_java
|
||||||
|
- run:
|
||||||
|
command: yarn bazel test //... --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only
|
||||||
|
no_output_timeout: 20m
|
||||||
|
|
||||||
|
# Temporary job to test what will happen when we flip the Ivy flag to true
|
||||||
|
test_ivy_aot:
|
||||||
|
executor:
|
||||||
|
name: default-executor
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- custom_attach_workspace
|
||||||
|
- init_environment
|
||||||
|
- install_chrome_libs
|
||||||
|
# We need to explicitly specify the --symlink_prefix option because otherwise we would
|
||||||
|
# not be able to easily find the output bin directory when uploading artifacts for size
|
||||||
|
# measurements.
|
||||||
|
- run:
|
||||||
|
command: yarn test-ivy-aot //... --symlink_prefix=dist/
|
||||||
|
no_output_timeout: 20m
|
||||||
|
|
||||||
|
# Publish bundle artifacts which will be used to calculate the size change. **Note**: Make
|
||||||
|
# sure that the size plugin from the Angular robot fetches the artifacts from this CircleCI
|
||||||
|
# job (see .github/angular-robot.yml). Additionally any artifacts need to be stored with the
|
||||||
|
# following path format: "{projectName}/{context}/{fileName}". This format is necessary
|
||||||
|
# because otherwise the bot is not able to pick up the artifacts from CircleCI. See:
|
||||||
|
# https://github.com/angular/github-robot/blob/master/functions/src/plugins/size.ts#L392-L394
|
||||||
|
- store_artifacts:
|
||||||
|
path: dist/bin/packages/core/test/bundling/hello_world/bundle.min.js
|
||||||
|
destination: core/hello_world/bundle
|
||||||
|
- store_artifacts:
|
||||||
|
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js
|
||||||
|
destination: core/todo/bundle
|
||||||
|
- store_artifacts:
|
||||||
|
path: dist/bin/packages/core/test/bundling/hello_world/bundle.min.js.br
|
||||||
|
destination: core/hello_world/bundle.br
|
||||||
|
- store_artifacts:
|
||||||
|
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js.br
|
||||||
|
destination: core/todo/bundle.br
|
||||||
|
|
||||||
|
# NOTE: This is currently limited to master builds only. See the `monitoring` configuration.
|
||||||
|
saucelabs_view_engine:
|
||||||
|
executor:
|
||||||
|
name: default-executor
|
||||||
|
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||||
|
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
||||||
|
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- custom_attach_workspace
|
||||||
|
- init_environment
|
||||||
|
- init_saucelabs_environment
|
||||||
|
- run:
|
||||||
|
name: Run Bazel tests on Saucelabs with ViewEngine
|
||||||
|
# See /tools/saucelabs/README.md for more info
|
||||||
|
command: |
|
||||||
|
yarn bazel run //tools/saucelabs:sauce_service_setup
|
||||||
|
TESTS=$(./node_modules/.bin/bazelisk query --output label '(kind(karma_web_test, ...) intersect attr("tags", "saucelabs", ...)) except attr("tags", "ivy-only", ...) except attr("tags", "fixme-saucelabs-ve", ...)')
|
||||||
|
yarn bazel test --config=saucelabs ${TESTS}
|
||||||
|
yarn bazel run //tools/saucelabs:sauce_service_stop
|
||||||
|
no_output_timeout: 40m
|
||||||
|
- notify_webhook_on_fail:
|
||||||
|
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||||
|
|
||||||
|
# NOTE: This is currently limited to master builds only. See the `monitoring` configuration.
|
||||||
|
saucelabs_ivy:
|
||||||
|
executor:
|
||||||
|
name: default-executor
|
||||||
|
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||||
|
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
||||||
|
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- custom_attach_workspace
|
||||||
|
- init_environment
|
||||||
|
- init_saucelabs_environment
|
||||||
|
- run:
|
||||||
|
name: Run Bazel tests on Saucelabs with Ivy
|
||||||
|
# See /tools/saucelabs/README.md for more info
|
||||||
|
command: |
|
||||||
|
yarn bazel run //tools/saucelabs:sauce_service_setup
|
||||||
|
TESTS=$(./node_modules/.bin/bazelisk query --output label '(kind(karma_web_test, ...) intersect attr("tags", "saucelabs", ...)) except attr("tags", "no-ivy-aot", ...) except attr("tags", "fixme-saucelabs-ivy", ...)')
|
||||||
|
yarn bazel test --config=saucelabs --config=ivy ${TESTS}
|
||||||
|
yarn bazel run //tools/saucelabs:sauce_service_stop
|
||||||
|
no_output_timeout: 40m
|
||||||
|
- notify_webhook_on_fail:
|
||||||
|
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||||
|
|
||||||
test_aio:
|
test_aio:
|
||||||
executor: default-executor
|
executor: default-executor
|
||||||
steps:
|
steps:
|
||||||
@ -266,6 +393,10 @@ jobs:
|
|||||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||||
# Run accessibility tests
|
# Run accessibility tests
|
||||||
- run: yarn --cwd aio test-a11y-score-localhost
|
- run: yarn --cwd aio test-a11y-score-localhost
|
||||||
|
# Check the bundle sizes.
|
||||||
|
- run: yarn --cwd aio payload-size
|
||||||
|
# Run unit tests for Firebase redirects
|
||||||
|
- run: yarn --cwd aio redirects-test
|
||||||
|
|
||||||
deploy_aio:
|
deploy_aio:
|
||||||
executor: default-executor
|
executor: default-executor
|
||||||
@ -295,6 +426,8 @@ jobs:
|
|||||||
- run: yarn --cwd aio e2e --configuration=ci
|
- run: yarn --cwd aio e2e --configuration=ci
|
||||||
# Run PWA-score tests
|
# Run PWA-score tests
|
||||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||||
|
# Check the bundle sizes.
|
||||||
|
- run: yarn --cwd aio payload-size aio-local<<# parameters.viewengine >>-viewengine<</ parameters.viewengine >>
|
||||||
|
|
||||||
test_aio_tools:
|
test_aio_tools:
|
||||||
executor: default-executor
|
executor: default-executor
|
||||||
@ -308,6 +441,26 @@ jobs:
|
|||||||
- run: yarn --cwd aio tools-test
|
- run: yarn --cwd aio tools-test
|
||||||
- run: ./aio/aio-builds-setup/scripts/test.sh
|
- run: ./aio/aio-builds-setup/scripts/test.sh
|
||||||
|
|
||||||
|
test_docs_examples:
|
||||||
|
parameters:
|
||||||
|
viewengine:
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
executor:
|
||||||
|
name: default-executor
|
||||||
|
resource_class: xlarge
|
||||||
|
parallelism: 5
|
||||||
|
steps:
|
||||||
|
- custom_attach_workspace
|
||||||
|
- init_environment
|
||||||
|
- install_chrome_libs
|
||||||
|
# Install aio
|
||||||
|
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||||
|
# Run examples tests. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
||||||
|
# Since the parallelism is set to "5", there will be five parallel CircleCI containers.
|
||||||
|
# with either "0", "1", etc as node index. This can be passed to the "--shard" argument.
|
||||||
|
- run: yarn --cwd aio example-e2e --setup --local <<# parameters.viewengine >>--viewengine<</ parameters.viewengine >> --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL} --retry 2
|
||||||
|
|
||||||
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||||
aio_preview:
|
aio_preview:
|
||||||
executor: default-executor
|
executor: default-executor
|
||||||
@ -336,6 +489,7 @@ jobs:
|
|||||||
name: Wait for preview and run tests
|
name: Wait for preview and run tests
|
||||||
command: node aio/scripts/test-preview.js $CI_PULL_REQUEST $CI_COMMIT $CI_AIO_MIN_PWA_SCORE
|
command: node aio/scripts/test-preview.js $CI_PULL_REQUEST $CI_COMMIT $CI_AIO_MIN_PWA_SCORE
|
||||||
|
|
||||||
|
|
||||||
# The `build-npm-packages` tasks exist for backwards-compatibility with old scripts and
|
# The `build-npm-packages` tasks exist for backwards-compatibility with old scripts and
|
||||||
# tests that rely on the pre-Bazel `dist/packages-dist` output structure (build.sh).
|
# tests that rely on the pre-Bazel `dist/packages-dist` output structure (build.sh).
|
||||||
# Having multiple jobs that independently build in this manner duplicates some work; we build
|
# Having multiple jobs that independently build in this manner duplicates some work; we build
|
||||||
@ -347,7 +501,7 @@ jobs:
|
|||||||
build-npm-packages:
|
build-npm-packages:
|
||||||
executor:
|
executor:
|
||||||
name: default-executor
|
name: default-executor
|
||||||
resource_class: medium
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- custom_attach_workspace
|
- custom_attach_workspace
|
||||||
- init_environment
|
- init_environment
|
||||||
@ -369,6 +523,246 @@ jobs:
|
|||||||
- "~/bazel_repository_cache"
|
- "~/bazel_repository_cache"
|
||||||
- "~/.cache/bazelisk"
|
- "~/.cache/bazelisk"
|
||||||
|
|
||||||
|
# Build the ivy npm packages.
|
||||||
|
build-ivy-npm-packages:
|
||||||
|
executor:
|
||||||
|
name: default-executor
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- custom_attach_workspace
|
||||||
|
- init_environment
|
||||||
|
- run: node scripts/build/build-ivy-npm-packages.js
|
||||||
|
|
||||||
|
# Save the npm packages from //packages/... for other workflow jobs to read
|
||||||
|
- persist_to_workspace:
|
||||||
|
root: *workspace_location
|
||||||
|
paths:
|
||||||
|
- ng/dist/packages-dist-ivy-aot
|
||||||
|
- ng/dist/zone.js-dist-ivy-aot
|
||||||
|
|
||||||
|
# This job creates compressed tarballs (`.tgz` files) for all Angular packages and stores them as
|
||||||
|
# build artifacts. This makes it easy to try out changes from a PR build for testing purposes.
|
||||||
|
# More info CircleCI build artifacts: https://circleci.com/docs/2.0/artifacts
|
||||||
|
#
|
||||||
|
# NOTE: Currently, this job only runs for PR builds. See `publish_snapshot` for non-PR builds.
|
||||||
|
publish_packages_as_artifacts:
|
||||||
|
executor: default-executor
|
||||||
|
environment:
|
||||||
|
NG_PACKAGES_DIR: &ng_packages_dir 'dist/packages-dist'
|
||||||
|
NG_PACKAGES_ARCHIVES_DIR: &ng_packages_archives_dir 'dist/packages-dist-archives'
|
||||||
|
ZONEJS_PACKAGES_DIR: &zonejs_packages_dir 'dist/zone.js-dist'
|
||||||
|
ZONEJS_PACKAGES_ARCHIVES_DIR: &zonejs_packages_archives_dir 'dist/zone.js-dist-archives'
|
||||||
|
steps:
|
||||||
|
- custom_attach_workspace
|
||||||
|
- init_environment
|
||||||
|
# Publish `@angular/*` packages.
|
||||||
|
- run:
|
||||||
|
name: Create artifacts for @angular/* packages
|
||||||
|
command: ./scripts/ci/create-package-archives.sh $CI_BRANCH $CI_COMMIT $NG_PACKAGES_DIR $NG_PACKAGES_ARCHIVES_DIR
|
||||||
|
- store_artifacts:
|
||||||
|
path: *ng_packages_archives_dir
|
||||||
|
destination: angular
|
||||||
|
# Publish `zone.js` package.
|
||||||
|
- run:
|
||||||
|
name: Create artifacts for zone.js package
|
||||||
|
command: ./scripts/ci/create-package-archives.sh $CI_BRANCH $CI_COMMIT $ZONEJS_PACKAGES_DIR $ZONEJS_PACKAGES_ARCHIVES_DIR
|
||||||
|
- store_artifacts:
|
||||||
|
path: *zonejs_packages_archives_dir
|
||||||
|
destination: zone.js
|
||||||
|
|
||||||
|
# This job updates the content of repos like github.com/angular/core-builds
|
||||||
|
# for every green build on angular/angular.
|
||||||
|
publish_snapshot:
|
||||||
|
executor: default-executor
|
||||||
|
steps:
|
||||||
|
# See below - ideally this job should not trigger for non-upstream builds.
|
||||||
|
# But since it does, we have to check this condition.
|
||||||
|
- run:
|
||||||
|
name: Skip this job for Pull Requests and Fork builds
|
||||||
|
# Note: Using `CIRCLE_*` env variables (instead of those defined in `env.sh` so that this
|
||||||
|
# step can be run before `init_environment`.
|
||||||
|
command: >
|
||||||
|
if [[ -n "${CIRCLE_PR_NUMBER}" ]] ||
|
||||||
|
[[ "$CIRCLE_PROJECT_USERNAME" != "angular" ]] ||
|
||||||
|
[[ "$CIRCLE_PROJECT_REPONAME" != "angular" ]]; then
|
||||||
|
circleci step halt
|
||||||
|
fi
|
||||||
|
- custom_attach_workspace
|
||||||
|
- init_environment
|
||||||
|
# CircleCI has a config setting to force SSH for all github connections
|
||||||
|
# This is not compatible with our mechanism of using a Personal Access Token
|
||||||
|
# Clear the global setting
|
||||||
|
- run: git config --global --unset "url.ssh://git@github.com.insteadof"
|
||||||
|
- run:
|
||||||
|
name: Decrypt github credentials
|
||||||
|
# We need ensure that the same default digest is used for encoding and decoding with
|
||||||
|
# OpenSSL. OpenSSL versions might have different default digests which can cause
|
||||||
|
# decryption failures based on the installed OpenSSL version. https://stackoverflow.com/a/39641378/4317734
|
||||||
|
command: 'openssl aes-256-cbc -d -in .circleci/github_token -md md5 -k "${KEY}" -out ~/.git_credentials'
|
||||||
|
- run: ./scripts/ci/publish-build-artifacts.sh
|
||||||
|
|
||||||
|
aio_monitoring_stable:
|
||||||
|
executor: default-executor
|
||||||
|
steps:
|
||||||
|
- custom_attach_workspace
|
||||||
|
- init_environment
|
||||||
|
- install_chrome_libs
|
||||||
|
- run: setPublicVar_CI_STABLE_BRANCH
|
||||||
|
- run:
|
||||||
|
name: Check out `aio/` and yarn from the stable branch
|
||||||
|
command: |
|
||||||
|
git fetch origin $CI_STABLE_BRANCH
|
||||||
|
git checkout --force origin/$CI_STABLE_BRANCH -- aio/ .yarn/ .yarnrc
|
||||||
|
# Ignore yarn's engines check, because we checked out `aio/package.json` from the stable
|
||||||
|
# branch and there could be a node version skew, which is acceptable in this monitoring job.
|
||||||
|
- run: yarn config set ignore-engines true
|
||||||
|
- run:
|
||||||
|
name: Run tests against https://angular.io/
|
||||||
|
command: ./aio/scripts/test-production.sh https://angular.io/ $CI_AIO_MIN_PWA_SCORE
|
||||||
|
- notify_webhook_on_fail:
|
||||||
|
webhook_url_env_var: SLACK_CARETAKER_WEBHOOK_URL
|
||||||
|
- notify_webhook_on_fail:
|
||||||
|
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||||
|
|
||||||
|
aio_monitoring_next:
|
||||||
|
executor: default-executor
|
||||||
|
steps:
|
||||||
|
- custom_attach_workspace
|
||||||
|
- init_environment
|
||||||
|
- install_chrome_libs
|
||||||
|
- run:
|
||||||
|
name: Run tests against https://next.angular.io/
|
||||||
|
command: ./aio/scripts/test-production.sh https://next.angular.io/ $CI_AIO_MIN_PWA_SCORE
|
||||||
|
- notify_webhook_on_fail:
|
||||||
|
webhook_url_env_var: SLACK_CARETAKER_WEBHOOK_URL
|
||||||
|
- notify_webhook_on_fail:
|
||||||
|
webhook_url_env_var: SLACK_DEV_INFRA_CI_FAILURES_WEBHOOK_URL
|
||||||
|
|
||||||
|
legacy-unit-tests-saucelabs:
|
||||||
|
executor:
|
||||||
|
name: default-executor
|
||||||
|
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||||
|
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
||||||
|
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- custom_attach_workspace
|
||||||
|
- init_environment
|
||||||
|
- init_saucelabs_environment
|
||||||
|
- run:
|
||||||
|
name: Starting Saucelabs tunnel service
|
||||||
|
command: ./tools/saucelabs/sauce-service.sh run
|
||||||
|
background: true
|
||||||
|
- run: yarn tsc -p packages
|
||||||
|
- run: yarn tsc -p modules
|
||||||
|
- run: yarn bazel build //packages/zone.js:npm_package
|
||||||
|
- run:
|
||||||
|
# Waiting on ready ensures that we don't run tests too early without Saucelabs not being ready.
|
||||||
|
name: Waiting for Saucelabs tunnel to connect
|
||||||
|
command: ./tools/saucelabs/sauce-service.sh ready-wait
|
||||||
|
- run:
|
||||||
|
name: Running tests on Saucelabs.
|
||||||
|
command: |
|
||||||
|
browsers=$(node -e 'console.log(require("./browser-providers.conf").sauceAliases.CI_REQUIRED.join(","))')
|
||||||
|
yarn karma start ./karma-js.conf.js --single-run --browsers=${browsers}
|
||||||
|
- run:
|
||||||
|
name: Stop Saucelabs tunnel service
|
||||||
|
command: ./tools/saucelabs/sauce-service.sh stop
|
||||||
|
|
||||||
|
# Job that runs all unit tests of the `angular/components` repository.
|
||||||
|
components-repo-unit-tests:
|
||||||
|
executor:
|
||||||
|
name: default-executor
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- custom_attach_workspace
|
||||||
|
- init_environment
|
||||||
|
# Restore the cache before cloning the repository because the clone script re-uses
|
||||||
|
# the restored repository if present. This reduces the amount of times the components
|
||||||
|
# repository needs to be cloned (this is slow and increases based on commits in the repo).
|
||||||
|
- restore_cache:
|
||||||
|
keys:
|
||||||
|
- *components_repo_unit_tests_cache_key
|
||||||
|
# Whenever the `angular/components` SHA is updated, the cache key will no longer
|
||||||
|
# match. The fallback cache will still match, and CircleCI will restore the most
|
||||||
|
# recently cached repository folder. Without the fallback cache, we'd need to download
|
||||||
|
# the repository from scratch and it would slow down the job. This is because we can't
|
||||||
|
# clone the repository with reduced `--depth`, but rather need to clone the whole
|
||||||
|
# repository to be able to support arbitrary SHAs.
|
||||||
|
- *components_repo_unit_tests_cache_key_fallback
|
||||||
|
- run:
|
||||||
|
name: "Fetching angular/components repository"
|
||||||
|
command: ./scripts/ci/clone_angular_components_repo.sh
|
||||||
|
- run:
|
||||||
|
# Run yarn install to fetch the Bazel binaries as used in the components repo.
|
||||||
|
name: Installing dependencies.
|
||||||
|
# TODO: remove this once the repo has been updated to use NodeJS v12 and Yarn 1.19.1.
|
||||||
|
# We temporarily ignore the "engines" because the Angular components repository has
|
||||||
|
# minimum dependency on NodeJS v12 and Yarn 1.19.1, but the framework repository uses
|
||||||
|
# older versions.
|
||||||
|
command: yarn --ignore-engines --cwd ${COMPONENTS_REPO_TMP_DIR} install --frozen-lockfile --non-interactive
|
||||||
|
- save_cache:
|
||||||
|
key: *components_repo_unit_tests_cache_key
|
||||||
|
paths:
|
||||||
|
# Temporary directory must be kept in sync with the `$COMPONENTS_REPO_TMP_DIR` env
|
||||||
|
# variable. It needs to be hardcoded here, because env variables interpolation is
|
||||||
|
# not supported.
|
||||||
|
- "/tmp/angular-components-repo"
|
||||||
|
- run:
|
||||||
|
# Updates the `angular/components` `package.json` file to refer to the release output
|
||||||
|
# inside the `packages-dist` directory. Note that it's not necessary to perform a yarn
|
||||||
|
# install as Bazel runs Yarn automatically when needed.
|
||||||
|
name: Setting up release packages.
|
||||||
|
command: node scripts/ci/update-deps-to-dist-packages.js ${COMPONENTS_REPO_TMP_DIR}/package.json dist/packages-dist/
|
||||||
|
- run:
|
||||||
|
name: "Running `angular/components` unit tests"
|
||||||
|
command: ./scripts/ci/run_angular_components_unit_tests.sh
|
||||||
|
|
||||||
|
test_zonejs:
|
||||||
|
executor:
|
||||||
|
name: default-executor
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- custom_attach_workspace
|
||||||
|
- init_environment
|
||||||
|
# Install
|
||||||
|
- run: yarn --cwd packages/zone.js install --frozen-lockfile --non-interactive
|
||||||
|
# Run zone.js tools tests
|
||||||
|
- run: yarn --cwd packages/zone.js promisetest
|
||||||
|
- run: yarn --cwd packages/zone.js promisefinallytest
|
||||||
|
- run: yarn bazel build //packages/zone.js:npm_package &&
|
||||||
|
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/dist/zone-patch-electron.js ./packages/zone.js/test/extra/ &&
|
||||||
|
yarn --cwd packages/zone.js electrontest
|
||||||
|
- run: yarn --cwd packages/zone.js jesttest
|
||||||
|
|
||||||
|
# Windows jobs
|
||||||
|
# Docs: https://circleci.com/docs/2.0/hello-world-windows/
|
||||||
|
test_win:
|
||||||
|
executor: windows-executor
|
||||||
|
steps:
|
||||||
|
- setup_win
|
||||||
|
- run:
|
||||||
|
# Ran into a command parsing problem where `-browser:chromium-local` was converted to
|
||||||
|
# `-browser: chromium-local` (a space was added) in https://circleci.com/gh/angular/angular/357511.
|
||||||
|
# Probably a powershell command parsing thing. There's no problem using a yarn script though.
|
||||||
|
command: yarn circleci-win-ve
|
||||||
|
no_output_timeout: 45m
|
||||||
|
# Save bazel repository cache to use on subsequent runs.
|
||||||
|
# We don't save node_modules because it's faster to use the linux workspace and reinstall.
|
||||||
|
- save_cache:
|
||||||
|
key: *cache_key_win
|
||||||
|
paths:
|
||||||
|
- "C:/Users/circleci/bazel_repository_cache"
|
||||||
|
|
||||||
|
test_ivy_aot_win:
|
||||||
|
executor: windows-executor
|
||||||
|
steps:
|
||||||
|
- setup_win
|
||||||
|
- run:
|
||||||
|
command: yarn circleci-win-ivy
|
||||||
|
no_output_timeout: 45m
|
||||||
|
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
@ -381,9 +775,21 @@ workflows:
|
|||||||
- lint:
|
- lint:
|
||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
|
- test:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
- test_ivy_aot:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
- build-npm-packages:
|
- build-npm-packages:
|
||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
|
- build-ivy-npm-packages:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
- legacy-unit-tests-saucelabs:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
- test_aio:
|
- test_aio:
|
||||||
requires:
|
requires:
|
||||||
- setup
|
- setup
|
||||||
@ -393,9 +799,22 @@ workflows:
|
|||||||
- test_aio_local:
|
- test_aio_local:
|
||||||
requires:
|
requires:
|
||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
|
- test_aio_local:
|
||||||
|
name: test_aio_local_viewengine
|
||||||
|
viewengine: true
|
||||||
|
requires:
|
||||||
|
- build-npm-packages
|
||||||
- test_aio_tools:
|
- test_aio_tools:
|
||||||
requires:
|
requires:
|
||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
|
- test_docs_examples:
|
||||||
|
requires:
|
||||||
|
- build-npm-packages
|
||||||
|
- test_docs_examples:
|
||||||
|
name: test_docs_examples_viewengine
|
||||||
|
viewengine: true
|
||||||
|
requires:
|
||||||
|
- build-npm-packages
|
||||||
- aio_preview:
|
- aio_preview:
|
||||||
# Only run on PR builds. (There can be no previews for non-PR builds.)
|
# Only run on PR builds. (There can be no previews for non-PR builds.)
|
||||||
<<: *only_on_pull_requests
|
<<: *only_on_pull_requests
|
||||||
@ -404,3 +823,78 @@ workflows:
|
|||||||
- test_aio_preview:
|
- test_aio_preview:
|
||||||
requires:
|
requires:
|
||||||
- aio_preview
|
- aio_preview
|
||||||
|
- publish_packages_as_artifacts:
|
||||||
|
requires:
|
||||||
|
- build-npm-packages
|
||||||
|
- publish_snapshot:
|
||||||
|
# Note: no filters on this job because we want it to run for all upstream branches
|
||||||
|
# We'd really like to filter out pull requests here, but not yet available:
|
||||||
|
# https://discuss.circleci.com/t/workflows-pull-request-filter/14396/4
|
||||||
|
# Instead, the job just exits immediately at the first step.
|
||||||
|
requires:
|
||||||
|
# Only publish if tests and integration tests pass
|
||||||
|
- test
|
||||||
|
- test_ivy_aot
|
||||||
|
# Only publish if `aio`/`docs` tests using the locally built Angular packages pass
|
||||||
|
- test_aio_local
|
||||||
|
- test_aio_local_viewengine
|
||||||
|
- test_docs_examples
|
||||||
|
- test_docs_examples_viewengine
|
||||||
|
# Get the artifacts to publish from the build-packages-dist job
|
||||||
|
# since the publishing script expects the legacy outputs layout.
|
||||||
|
- build-npm-packages
|
||||||
|
- build-ivy-npm-packages
|
||||||
|
- legacy-unit-tests-saucelabs
|
||||||
|
- components-repo-unit-tests:
|
||||||
|
requires:
|
||||||
|
- build-npm-packages
|
||||||
|
- test_zonejs:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
# Windows Jobs
|
||||||
|
# These are very slow so we run them on non-PRs only for now.
|
||||||
|
# TODO: remove the filter when CircleCI makes Windows FS faster.
|
||||||
|
# The Windows jobs are only run after their non-windows counterparts finish successfully.
|
||||||
|
# This isn't strictly necessary as there is no artifact dependency, but helps economize
|
||||||
|
# CI resources by not attempting to build when we know should fail.
|
||||||
|
- test_win:
|
||||||
|
<<: *skip_on_pull_requests
|
||||||
|
requires:
|
||||||
|
- test
|
||||||
|
- test_ivy_aot_win:
|
||||||
|
<<: *skip_on_pull_requests
|
||||||
|
requires:
|
||||||
|
- test_ivy_aot
|
||||||
|
|
||||||
|
monitoring:
|
||||||
|
jobs:
|
||||||
|
- setup
|
||||||
|
- aio_monitoring_stable:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
- aio_monitoring_next:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
- saucelabs_ivy:
|
||||||
|
# Testing saucelabs via Bazel currently taking longer than the legacy saucelabs job as it
|
||||||
|
# each karma_web_test target is provisioning and tearing down browsers which is adding
|
||||||
|
# a lot of overhead. Running once daily on master only to avoid wasting resources and
|
||||||
|
# slowing down CI for PRs.
|
||||||
|
# TODO: Run this job on all branches (including PRs) once karma_web_test targets can
|
||||||
|
# share provisioned browsers and we can remove the legacy saucelabs job.
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
- saucelabs_view_engine:
|
||||||
|
# Testing saucelabs via Bazel currently taking longer than the legacy saucelabs job as it
|
||||||
|
# each karma_web_test target is provisioning and tearing down browsers which is adding
|
||||||
|
# a lot of overhead. Running once daily on master only to avoid wasting resources and
|
||||||
|
# slowing down CI for PRs.
|
||||||
|
# TODO: Run this job on all branches (including PRs) once karma_web_test targets can
|
||||||
|
# share provisioned browsers and we can remove the legacy saucelabs job.
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
triggers:
|
||||||
|
- schedule:
|
||||||
|
<<: *only_on_master
|
||||||
|
# Runs monitoring jobs at 10:00AM every day.
|
||||||
|
cron: "0 10 * * *"
|
||||||
|
@ -17,7 +17,7 @@ echo "source $envHelpersPath;" >> $BASH_ENV;
|
|||||||
####################################################################################################
|
####################################################################################################
|
||||||
setPublicVar CI "$CI"
|
setPublicVar CI "$CI"
|
||||||
setPublicVar PROJECT_ROOT "$projectDir";
|
setPublicVar PROJECT_ROOT "$projectDir";
|
||||||
setPublicVar CI_AIO_MIN_PWA_SCORE "62";
|
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
|
||||||
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
||||||
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
||||||
setPublicVar CI_BUILD_URL "$CIRCLE_BUILD_URL";
|
setPublicVar CI_BUILD_URL "$CIRCLE_BUILD_URL";
|
||||||
@ -74,7 +74,7 @@ setPublicVar COMPONENTS_REPO_TMP_DIR "/tmp/angular-components-repo"
|
|||||||
setPublicVar COMPONENTS_REPO_URL "https://github.com/angular/components.git"
|
setPublicVar COMPONENTS_REPO_URL "https://github.com/angular/components.git"
|
||||||
setPublicVar COMPONENTS_REPO_BRANCH "master"
|
setPublicVar COMPONENTS_REPO_BRANCH "master"
|
||||||
# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI `config.yml`.
|
# **NOTE**: When updating the commit SHA, also update the cache key in the CircleCI `config.yml`.
|
||||||
setPublicVar COMPONENTS_REPO_COMMIT "09e68db8ed5b1253f2fe38ff954ef0df019fc25a"
|
setPublicVar COMPONENTS_REPO_COMMIT "f428c00465dfcf8a020237f22532480eedbd2cb6"
|
||||||
|
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
|
69
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
Normal file
69
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
---
|
||||||
|
name: "\U0001F41EBug report"
|
||||||
|
about: Report a bug in the Angular Framework
|
||||||
|
---
|
||||||
|
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
||||||
|
|
||||||
|
Oh hi there! 😄
|
||||||
|
|
||||||
|
To expedite issue processing please search open and closed issues before submitting a new one.
|
||||||
|
Existing issues often contain information about workarounds, resolution, or progress updates.
|
||||||
|
|
||||||
|
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
||||||
|
|
||||||
|
|
||||||
|
# 🐞 bug report
|
||||||
|
|
||||||
|
### Affected Package
|
||||||
|
<!-- Can you pin-point one or more @angular/* packages as the source of the bug? -->
|
||||||
|
<!-- ✍️edit: --> The issue is caused by package @angular/....
|
||||||
|
|
||||||
|
|
||||||
|
### Is this a regression?
|
||||||
|
|
||||||
|
<!-- Did this behavior use to work in the previous version? -->
|
||||||
|
<!-- ✍️--> Yes, the previous version in which this bug was not present was: ....
|
||||||
|
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
<!-- ✍️--> A clear and concise description of the problem...
|
||||||
|
|
||||||
|
|
||||||
|
## 🔬 Minimal Reproduction
|
||||||
|
<!--
|
||||||
|
Please create and share minimal reproduction of the issue starting with this template: https://stackblitz.com/fork/angular-ivy
|
||||||
|
-->
|
||||||
|
<!-- ✍️--> https://stackblitz.com/...
|
||||||
|
|
||||||
|
<!--
|
||||||
|
If StackBlitz is not suitable for reproduction of your issue, please create a minimal GitHub repository with the reproduction of the issue.
|
||||||
|
A good way to make a minimal reproduction is to create a new app via `ng new repro-app` and add the minimum possible code to show the problem.
|
||||||
|
Share the link to the repo below along with step-by-step instructions to reproduce the problem, as well as expected and actual behavior.
|
||||||
|
|
||||||
|
Issues that don't have enough info and can't be reproduced will be closed.
|
||||||
|
|
||||||
|
You can read more about issue submission guidelines here: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-submitting-an-issue
|
||||||
|
-->
|
||||||
|
|
||||||
|
## 🔥 Exception or Error
|
||||||
|
<pre><code>
|
||||||
|
<!-- If the issue is accompanied by an exception or an error, please share it below: -->
|
||||||
|
<!-- ✍️-->
|
||||||
|
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
|
||||||
|
## 🌍 Your Environment
|
||||||
|
|
||||||
|
**Angular Version:**
|
||||||
|
<pre><code>
|
||||||
|
<!-- run `ng version` and paste output below -->
|
||||||
|
<!-- ✍️-->
|
||||||
|
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
**Anything else relevant?**
|
||||||
|
<!-- ✍️Is this a browser specific issue? If so, please specify the browser and version. -->
|
||||||
|
|
||||||
|
<!-- ✍️Do any of these matter: operating system, IDE, package manager, HTTP server, ...? If so, please mention it below. -->
|
32
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
Normal file
32
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
name: "\U0001F680Feature request"
|
||||||
|
about: Suggest a feature for Angular Framework
|
||||||
|
|
||||||
|
---
|
||||||
|
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
||||||
|
|
||||||
|
Oh hi there! 😄
|
||||||
|
|
||||||
|
To expedite issue processing please search open and closed issues before submitting a new one.
|
||||||
|
Existing issues often contain information about workarounds, resolution, or progress updates.
|
||||||
|
|
||||||
|
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
||||||
|
|
||||||
|
|
||||||
|
# 🚀 feature request
|
||||||
|
|
||||||
|
### Relevant Package
|
||||||
|
<!-- Can you pin-point one or more @angular/* packages the are relevant for this feature request? -->
|
||||||
|
<!-- ✍️edit: --> This feature request is for @angular/....
|
||||||
|
|
||||||
|
|
||||||
|
### Description
|
||||||
|
<!-- ✍️--> A clear and concise description of the problem or missing capability...
|
||||||
|
|
||||||
|
|
||||||
|
### Describe the solution you'd like
|
||||||
|
<!-- ✍️--> If you have a solution in mind, please describe it.
|
||||||
|
|
||||||
|
|
||||||
|
### Describe alternatives you've considered
|
||||||
|
<!-- ✍️--> Have you considered any alternative solutions or workarounds?
|
55
.github/ISSUE_TEMPLATE/3-docs-bug.md
vendored
Normal file
55
.github/ISSUE_TEMPLATE/3-docs-bug.md
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
---
|
||||||
|
name: "📚 Docs or angular.io issue report"
|
||||||
|
about: Report an issue in Angular's documentation or angular.io application
|
||||||
|
|
||||||
|
---
|
||||||
|
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
||||||
|
|
||||||
|
Oh hi there! 😄
|
||||||
|
|
||||||
|
To expedite issue processing please search open and closed issues before submitting a new one.
|
||||||
|
Existing issues often contain information about workarounds, resolution, or progress updates.
|
||||||
|
|
||||||
|
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
||||||
|
|
||||||
|
# 📚 Docs or angular.io bug report
|
||||||
|
|
||||||
|
### Description
|
||||||
|
|
||||||
|
<!-- ✍️edit:--> A clear and concise description of the problem...
|
||||||
|
|
||||||
|
|
||||||
|
## 🔬 Minimal Reproduction
|
||||||
|
|
||||||
|
### What's the affected URL?**
|
||||||
|
<!-- ✍️edit:--> https://angular.io/...
|
||||||
|
|
||||||
|
### Reproduction Steps**
|
||||||
|
<!-- If applicable please list the steps to take to reproduce the issue -->
|
||||||
|
<!-- ✍️edit:-->
|
||||||
|
|
||||||
|
### Expected vs Actual Behavior**
|
||||||
|
<!-- If applicable please describe the difference between the expected and actual behavior after following the repro steps. -->
|
||||||
|
<!-- ✍️edit:-->
|
||||||
|
|
||||||
|
|
||||||
|
## 📷Screenshot
|
||||||
|
<!-- Often a screenshot can help to capture the issue better than a long description. -->
|
||||||
|
<!-- ✍️upload a screenshot:-->
|
||||||
|
|
||||||
|
|
||||||
|
## 🔥 Exception or Error
|
||||||
|
<pre><code>
|
||||||
|
<!-- If the issue is accompanied by an exception or an error, please share it below: -->
|
||||||
|
<!-- ✍️-->
|
||||||
|
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
|
||||||
|
## 🌍 Your Environment
|
||||||
|
|
||||||
|
### Browser info
|
||||||
|
<!-- ✍️Is this a browser specific issue? If so, please specify the device, browser, and version. -->
|
||||||
|
|
||||||
|
### Anything else relevant?
|
||||||
|
<!-- ✍️Please provide additional info if necessary. -->
|
11
.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md
vendored
Normal file
11
.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
name: ⚠️ Security issue disclosure
|
||||||
|
about: Report a security issue in Angular Framework, Material, or CLI
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
||||||
|
|
||||||
|
Please read https://angular.io/guide/security#report-issues on how to disclose security related issues.
|
||||||
|
|
||||||
|
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
16
.github/ISSUE_TEMPLATE/5-support-request.md
vendored
Normal file
16
.github/ISSUE_TEMPLATE/5-support-request.md
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
name: "❓Support request"
|
||||||
|
about: Questions and requests for support
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
||||||
|
|
||||||
|
Please do not file questions or support requests on the GitHub issues tracker.
|
||||||
|
|
||||||
|
You can get your questions answered using other communication channels. Please see:
|
||||||
|
https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
|
||||||
|
|
||||||
|
Thank you!
|
||||||
|
|
||||||
|
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
13
.github/ISSUE_TEMPLATE/6-angular-cli.md
vendored
Normal file
13
.github/ISSUE_TEMPLATE/6-angular-cli.md
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
name: "\U0001F6E0️Angular CLI"
|
||||||
|
about: Issues and feature requests for Angular CLI
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
||||||
|
|
||||||
|
Please file any Angular CLI issues at: https://github.com/angular/angular-cli/issues/new
|
||||||
|
|
||||||
|
For the time being, we keep Angular CLI issues in a separate repository.
|
||||||
|
|
||||||
|
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
13
.github/ISSUE_TEMPLATE/7-angular-components.md
vendored
Normal file
13
.github/ISSUE_TEMPLATE/7-angular-components.md
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
name: "\U0001F48EAngular Components"
|
||||||
|
about: Issues and feature requests for Angular Components
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
||||||
|
|
||||||
|
Please file any Angular Components issues at: https://github.com/angular/components/issues/new
|
||||||
|
|
||||||
|
For the time being, we keep Angular Components issues in a separate repository.
|
||||||
|
|
||||||
|
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
|
22
.github/ISSUE_TEMPLATE/8-translate-docs.md
vendored
22
.github/ISSUE_TEMPLATE/8-translate-docs.md
vendored
@ -1,22 +0,0 @@
|
|||||||
---
|
|
||||||
name: "📚Traducir doc al español"
|
|
||||||
about: Solicitud para traducir ciertos docs al español
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
📚Traducir: <!-- ✍️ editar: --> creating-libraries.md
|
|
||||||
|
|
||||||
<!--🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅
|
|
||||||
|
|
||||||
Traducción de la documentación oficial de Angular a español
|
|
||||||
|
|
||||||
🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅🔅-->
|
|
||||||
|
|
||||||
|
|
||||||
## Nombre del archivo:
|
|
||||||
<!-- ✍️ editar: --> creating-libraries.md
|
|
||||||
|
|
||||||
|
|
||||||
## Ruta donde se encuentra el archivo dentro del proyecto de Angular
|
|
||||||
|
|
||||||
<!-- ✍️ editar: --> https://github.com/angular-hispano/angular/blob/master/aio/content/guide/creating-libraries.md
|
|
62
.github/PULL_REQUEST_TEMPLATE.md
vendored
62
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,35 +1,43 @@
|
|||||||
## Lista de Verificación del PR
|
## PR Checklist
|
||||||
Comprueba si tu PR cumple los siguientes requisitos:
|
Please check if your PR fulfills the following requirements:
|
||||||
|
|
||||||
- [ ] El mensaje de commit esta conforme con [nuestras reglas](https://github.com/angular-hispano/angular/blob/master/CONTRIBUTING.md#-formato-para-el-mensaje-de-los-commits)
|
- [ ] The commit message follows our guidelines: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
|
||||||
- [ ] Probe los cambios que agregué (arreglo de bugs / funcionalidades)
|
- [ ] Tests for the changes have been added (for bug fixes / features)
|
||||||
- [ ] Revisé previamente las traducciones o cambios de contenido
|
- [ ] Docs have been added / updated (for bug fixes / features)
|
||||||
- [ ] Consulté el [diccionario de términos](https://github.com/angular-hispano/angular/blob/master/aio/diccionario-de-términos.md) en español
|
|
||||||
- [ ] He creado dos archivos con la extensión correspondiente(.en.md para el archivo en inglés y .md para el Archivo en español)
|
|
||||||
- [ ] He enlazado el commit con el issue correspondiente <!-- ejemplo Fixes #X -->
|
|
||||||
|
|
||||||
|
|
||||||
## Tipo de PR
|
## PR Type
|
||||||
¿Qué tipo de cambio introduce este PR?
|
What kind of change does this PR introduce?
|
||||||
|
|
||||||
<!-- Marca con una "x" las opciones que aplican. -->
|
<!-- Please check the one that applies to this PR using "x". -->
|
||||||
|
|
||||||
- [ ] Bugfix
|
- [ ] Bugfix
|
||||||
- [ ] Funcionalidad
|
- [ ] Feature
|
||||||
- [ ] Actualización de el estilo del código (formato, variables locales)
|
- [ ] Code style update (formatting, local variables)
|
||||||
- [ ] Refactorización (no cambios en la funcionalidad, no cambios en el api)
|
- [ ] Refactoring (no functional changes, no api changes)
|
||||||
- [ ] Cambios relacionados al build
|
- [ ] Build related changes
|
||||||
- [ ] Cambios relacionados al CI (Integración continua)
|
- [ ] CI related changes
|
||||||
- [ ] Cambios en el contenido de la documentación
|
- [ ] Documentation content changes
|
||||||
- [ ] Cambios en la aplicación / infraestructura de angular.io
|
- [ ] angular.io application / infrastructure changes
|
||||||
- [ ] Otro... Por favor describe la:
|
- [ ] Other... Please describe:
|
||||||
|
|
||||||
## ¿Cuál es el comportamiento actual?
|
|
||||||
<!-- Describe el comportamiento actual que está modificando o vincule a un problema relevante.
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
## ¿Cuál es el nuevo comportamiento?
|
## What is the current behavior?
|
||||||
<!--
|
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->
|
||||||
Ejemplo: Archivo en inglés traducido al español
|
|
||||||
-->
|
Issue Number: N/A
|
||||||
|
|
||||||
|
|
||||||
|
## What is the new behavior?
|
||||||
|
|
||||||
|
|
||||||
|
## Does this PR introduce a breaking change?
|
||||||
|
|
||||||
|
- [ ] Yes
|
||||||
|
- [ ] No
|
||||||
|
|
||||||
|
|
||||||
|
<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->
|
||||||
|
|
||||||
|
|
||||||
|
## Other information
|
||||||
|
@ -6,7 +6,7 @@ import {CommitMessageConfig} from '../dev-infra/commit-message/config';
|
|||||||
export const commitMessage: CommitMessageConfig = {
|
export const commitMessage: CommitMessageConfig = {
|
||||||
maxLineLength: 120,
|
maxLineLength: 120,
|
||||||
minBodyLength: 20,
|
minBodyLength: 20,
|
||||||
minBodyLengthTypeExcludes: ['docs', 'upstream'],
|
minBodyLengthTypeExcludes: ['docs'],
|
||||||
types: [
|
types: [
|
||||||
'build',
|
'build',
|
||||||
'ci',
|
'ci',
|
||||||
@ -18,7 +18,6 @@ export const commitMessage: CommitMessageConfig = {
|
|||||||
'release',
|
'release',
|
||||||
'style',
|
'style',
|
||||||
'test',
|
'test',
|
||||||
'upstream',
|
|
||||||
],
|
],
|
||||||
scopes: [
|
scopes: [
|
||||||
'animations',
|
'animations',
|
||||||
|
176
.pullapprove.yml
176
.pullapprove.yml
@ -67,25 +67,6 @@ version: 3
|
|||||||
# Meta field that goes unused by PullApprove to allow for defining aliases to be
|
# Meta field that goes unused by PullApprove to allow for defining aliases to be
|
||||||
# used throughout the config.
|
# used throughout the config.
|
||||||
meta:
|
meta:
|
||||||
# The following groups have no file based conditions and will be initially `active` on all PRs
|
|
||||||
# - `global-approvers`
|
|
||||||
# - `global-docs-approvers`
|
|
||||||
# - `required-minimum-review`
|
|
||||||
#
|
|
||||||
# By checking the number of active/pending/rejected groups when these are excluded, we can determine
|
|
||||||
# if any other groups are matched.
|
|
||||||
#
|
|
||||||
# Note: Because all inactive groups start as pending, we are only checking pending and rejected active groups.
|
|
||||||
#
|
|
||||||
# Also note that the ordering of groups matters in this file. The only groups visible to the current
|
|
||||||
# one are those that appear above it.
|
|
||||||
no-groups-above-this-pending: &no-groups-above-this-pending
|
|
||||||
len(groups.active.pending.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0
|
|
||||||
no-groups-above-this-rejected: &no-groups-above-this-rejected
|
|
||||||
len(groups.active.rejected.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0
|
|
||||||
no-groups-above-this-active: &no-groups-above-this-active
|
|
||||||
len(groups.active.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0
|
|
||||||
|
|
||||||
can-be-global-approved: &can-be-global-approved "\"global-approvers\" not in groups.approved"
|
can-be-global-approved: &can-be-global-approved "\"global-approvers\" not in groups.approved"
|
||||||
can-be-global-docs-approved: &can-be-global-docs-approved "\"global-docs-approvers\" not in groups.approved"
|
can-be-global-docs-approved: &can-be-global-docs-approved "\"global-docs-approvers\" not in groups.approved"
|
||||||
defaults: &defaults
|
defaults: &defaults
|
||||||
@ -115,6 +96,54 @@ pullapprove_conditions:
|
|||||||
|
|
||||||
|
|
||||||
groups:
|
groups:
|
||||||
|
# =========================================================
|
||||||
|
# Require review on all PRs
|
||||||
|
#
|
||||||
|
# All PRs require at least one review. This rule will not
|
||||||
|
# request any reviewers, however will require that at least
|
||||||
|
# one review is provided before the group is satisfied.
|
||||||
|
# =========================================================
|
||||||
|
required-minimum-review:
|
||||||
|
reviews:
|
||||||
|
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
|
||||||
|
author_value: 0 # The author of the PR cannot provide an approval for themself
|
||||||
|
reviewers:
|
||||||
|
users:
|
||||||
|
- aikidave # Dave Shevitz
|
||||||
|
- alan-agius4 # Alan Agius
|
||||||
|
- alxhub # Alex Rickabaugh
|
||||||
|
- AndrewKushnir # Andrew Kushnir
|
||||||
|
- andrewseguin # Andrew Seguin
|
||||||
|
- atscott # Andrew Scott
|
||||||
|
- ayazhafiz # Ayaz Hafiz
|
||||||
|
- clydin # Charles Lyding
|
||||||
|
- crisbeto # Kristiyan Kostadinov
|
||||||
|
- dennispbrown # Denny Brown
|
||||||
|
- devversion # Paul Gschwendtner
|
||||||
|
- dgp1130 # Doug Parker
|
||||||
|
- filipesilva # Filipe Silva
|
||||||
|
- gkalpak # Georgios Kalpakas
|
||||||
|
- gregmagolan # Greg Magolan
|
||||||
|
- IgorMinar # Igor Minar
|
||||||
|
- jbogarthyde # Judy Bogart
|
||||||
|
- jelbourn # Jeremy Elbourn
|
||||||
|
- JiaLiPassion # Jia Li
|
||||||
|
- JoostK # Joost Koehoorn
|
||||||
|
- josephperrott # Joey Perrott
|
||||||
|
- juleskremer # Jules Kremer
|
||||||
|
- kapunahelewong # Kapunahele Wong
|
||||||
|
- kara # Kara Erickson
|
||||||
|
- kyliau # Keen Yee Liau
|
||||||
|
- manughub # Manu Murthy
|
||||||
|
- mgechev # Minko Gechev
|
||||||
|
- mhevery # Miško Hevery
|
||||||
|
- michaelprentice # Michael Prentice
|
||||||
|
- mmalerba # Miles Malerba
|
||||||
|
- petebacondarwin # Pete Bacon Darwin
|
||||||
|
- pkozlowski-opensource # Pawel Kozlowski
|
||||||
|
- StephenFluin # Stephen Fluin
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
# Global Approvers
|
# Global Approvers
|
||||||
#
|
#
|
||||||
@ -151,57 +180,6 @@ groups:
|
|||||||
required: 1
|
required: 1
|
||||||
reviewed_for: required
|
reviewed_for: required
|
||||||
|
|
||||||
# =========================================================
|
|
||||||
# Require review on all PRs
|
|
||||||
#
|
|
||||||
# All PRs require at least one review. This rule will not
|
|
||||||
# request any reviewers, however will require that at least
|
|
||||||
# one review is provided before the group is satisfied.
|
|
||||||
# =========================================================
|
|
||||||
required-minimum-review:
|
|
||||||
conditions:
|
|
||||||
- *can-be-global-approved
|
|
||||||
- *can-be-global-docs-approved
|
|
||||||
reviews:
|
|
||||||
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
|
|
||||||
author_value: 0 # The author of the PR cannot provide an approval for themself
|
|
||||||
reviewers:
|
|
||||||
users:
|
|
||||||
- aikidave # Dave Shevitz
|
|
||||||
- alan-agius4 # Alan Agius
|
|
||||||
- alxhub # Alex Rickabaugh
|
|
||||||
- AndrewKushnir # Andrew Kushnir
|
|
||||||
- andrewseguin # Andrew Seguin
|
|
||||||
- atscott # Andrew Scott
|
|
||||||
- ayazhafiz # Ayaz Hafiz
|
|
||||||
- clydin # Charles Lyding
|
|
||||||
- crisbeto # Kristiyan Kostadinov
|
|
||||||
- dennispbrown # Denny Brown
|
|
||||||
- devversion # Paul Gschwendtner
|
|
||||||
- dgp1130 # Doug Parker
|
|
||||||
- filipesilva # Filipe Silva
|
|
||||||
- gkalpak # Georgios Kalpakas
|
|
||||||
- gregmagolan # Greg Magolan
|
|
||||||
- IgorMinar # Igor Minar
|
|
||||||
- jbogarthyde # Judy Bogart
|
|
||||||
- jelbourn # Jeremy Elbourn
|
|
||||||
- JiaLiPassion # Jia Li
|
|
||||||
- JoostK # Joost Koehoorn
|
|
||||||
- josephperrott # Joey Perrott
|
|
||||||
- juleskremer # Jules Kremer
|
|
||||||
- kapunahelewong # Kapunahele Wong
|
|
||||||
- kara # Kara Erickson
|
|
||||||
- kyliau # Keen Yee Liau
|
|
||||||
- manughub # Manu Murthy
|
|
||||||
- mgechev # Minko Gechev
|
|
||||||
- mhevery # Miško Hevery
|
|
||||||
- mmalerba # Miles Malerba
|
|
||||||
- petebacondarwin # Pete Bacon Darwin
|
|
||||||
- pkozlowski-opensource # Pawel Kozlowski
|
|
||||||
- Splaktar # Michael Prentice
|
|
||||||
- StephenFluin # Stephen Fluin
|
|
||||||
|
|
||||||
# =========================================================
|
# =========================================================
|
||||||
# Framework: Animations
|
# Framework: Animations
|
||||||
# =========================================================
|
# =========================================================
|
||||||
@ -335,7 +313,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/**',
|
||||||
@ -787,21 +764,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
|
||||||
@ -882,7 +844,6 @@ groups:
|
|||||||
- *can-be-global-docs-approved
|
- *can-be-global-docs-approved
|
||||||
- >
|
- >
|
||||||
contains_any_globs(files, [
|
contains_any_globs(files, [
|
||||||
'aio/content/guide/roadmap.md',
|
|
||||||
'aio/content/marketing/**',
|
'aio/content/marketing/**',
|
||||||
'aio/content/images/bios/**',
|
'aio/content/images/bios/**',
|
||||||
'aio/content/images/marketing/**',
|
'aio/content/images/marketing/**',
|
||||||
@ -1110,7 +1071,6 @@ 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',
|
||||||
@ -1163,8 +1123,6 @@ groups:
|
|||||||
public-api:
|
public-api:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *no-groups-above-this-pending
|
|
||||||
- *no-groups-above-this-rejected
|
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- >
|
- >
|
||||||
contains_any_globs(files, [
|
contains_any_globs(files, [
|
||||||
@ -1178,16 +1136,14 @@ groups:
|
|||||||
])
|
])
|
||||||
reviewers:
|
reviewers:
|
||||||
users:
|
users:
|
||||||
- AndrewKushnir
|
|
||||||
- IgorMinar
|
- IgorMinar
|
||||||
- alxhub
|
- alxhub
|
||||||
- atscott
|
|
||||||
- jelbourn
|
- jelbourn
|
||||||
- petebacondarwin
|
- petebacondarwin
|
||||||
- pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
reviews:
|
reviews:
|
||||||
request: 4 # Request reviews from four people
|
request: -1 # request reviews from everyone
|
||||||
required: 3 # Require that three people approve
|
required: 3 # require at least 3 approvals
|
||||||
reviewed_for: required
|
reviewed_for: required
|
||||||
|
|
||||||
|
|
||||||
@ -1197,8 +1153,6 @@ groups:
|
|||||||
size-tracking:
|
size-tracking:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *no-groups-above-this-pending
|
|
||||||
- *no-groups-above-this-rejected
|
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- >
|
- >
|
||||||
contains_any_globs(files, [
|
contains_any_globs(files, [
|
||||||
@ -1206,16 +1160,14 @@ groups:
|
|||||||
])
|
])
|
||||||
reviewers:
|
reviewers:
|
||||||
users:
|
users:
|
||||||
- AndrewKushnir
|
|
||||||
- IgorMinar
|
- IgorMinar
|
||||||
- alxhub
|
- alxhub
|
||||||
- atscott
|
|
||||||
- jelbourn
|
- jelbourn
|
||||||
- petebacondarwin
|
- petebacondarwin
|
||||||
- pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
reviews:
|
reviews:
|
||||||
request: 4 # Request reviews from four people
|
request: -1 # request reviews from everyone
|
||||||
required: 2 # Require that two people approve
|
required: 2 # require at least 2 approvals
|
||||||
reviewed_for: required
|
reviewed_for: required
|
||||||
|
|
||||||
|
|
||||||
@ -1225,8 +1177,6 @@ groups:
|
|||||||
circular-dependencies:
|
circular-dependencies:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
conditions:
|
conditions:
|
||||||
- *no-groups-above-this-pending
|
|
||||||
- *no-groups-above-this-rejected
|
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- >
|
- >
|
||||||
contains_any_globs(files, [
|
contains_any_globs(files, [
|
||||||
@ -1234,11 +1184,9 @@ groups:
|
|||||||
])
|
])
|
||||||
reviewers:
|
reviewers:
|
||||||
users:
|
users:
|
||||||
- AndrewKushnir
|
|
||||||
- IgorMinar
|
- IgorMinar
|
||||||
- alxhub
|
|
||||||
- atscott
|
|
||||||
- jelbourn
|
- jelbourn
|
||||||
|
- josephperrott
|
||||||
- petebacondarwin
|
- petebacondarwin
|
||||||
- pkozlowski-opensource
|
- pkozlowski-opensource
|
||||||
|
|
||||||
@ -1260,10 +1208,7 @@ groups:
|
|||||||
])
|
])
|
||||||
reviewers:
|
reviewers:
|
||||||
users:
|
users:
|
||||||
- AndrewKushnir
|
|
||||||
- IgorMinar
|
- IgorMinar
|
||||||
- alxhub
|
|
||||||
- atscott
|
|
||||||
- jelbourn
|
- jelbourn
|
||||||
- josephperrott
|
- josephperrott
|
||||||
- mhevery
|
- mhevery
|
||||||
@ -1293,10 +1238,13 @@ groups:
|
|||||||
# `global-approvers` can still approve PRs that match this `fallback` rule,
|
# `global-approvers` can still approve PRs that match this `fallback` rule,
|
||||||
# but that should be an exception and not an expectation.
|
# but that should be an exception and not an expectation.
|
||||||
conditions:
|
conditions:
|
||||||
- *no-groups-above-this-active
|
|
||||||
# When any of the `global-*` groups is approved, they cause other groups to deactivate.
|
|
||||||
# In those cases, the condition above would evaluate to `true` while in reality, only a global
|
|
||||||
# approval has been provided. To ensure we don't activate the fallback group in such cases,
|
|
||||||
# ensure that no explicit global approval has been provided.
|
|
||||||
- *can-be-global-approved
|
- *can-be-global-approved
|
||||||
- *can-be-global-docs-approved
|
# The following groups have no conditions and will be `active` on all PRs
|
||||||
|
# - `global-approvers`
|
||||||
|
# - `global-docs-approvers`
|
||||||
|
#
|
||||||
|
# Since this means the minimum number of active groups a PR can have is 2, this
|
||||||
|
# `fallback` group should be matched anytime the number of active groups is at or
|
||||||
|
# below this minimum. This work as a protection to ensure that pullapprove does
|
||||||
|
# not incidently mark a PR as passing without meeting the review criteria.
|
||||||
|
- len(groups.active) <= 2
|
||||||
|
@ -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.
|
||||||
|
300
CHANGELOG.md
300
CHANGELOG.md
@ -1,81 +1,3 @@
|
|||||||
<a name="10.1.0-next.4"></a>
|
|
||||||
# 10.1.0-next.4 (2020-08-04)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **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:** mark `NgModuleFactory` construction as not side effectful ([#38147](https://github.com/angular/angular/issues/38147)) ([7f8c222](https://github.com/angular/angular/commit/7f8c222))
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **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:** 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))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.8"></a>
|
|
||||||
## 10.0.8 (2020-08-04)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **compiler:** add PURE annotation to getInheritedFactory calls ([#38291](https://github.com/angular/angular/issues/38291)) ([03d8e31](https://github.com/angular/angular/commit/03d8e31))
|
|
||||||
* **compiler:** update unparsable character reference entity error messages ([#38319](https://github.com/angular/angular/issues/38319)) ([cea4678](https://github.com/angular/angular/commit/cea4678)), closes [#26067](https://github.com/angular/angular/issues/26067)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.7"></a>
|
|
||||||
## 10.0.7 (2020-07-30)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **compiler:** Metadata should not include methods on Object.prototype ([#38292](https://github.com/angular/angular/issues/38292)) ([879ff08](https://github.com/angular/angular/commit/879ff08))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.0-next.3"></a>
|
|
||||||
# 10.1.0-next.3 (2020-07-28)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **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)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.6"></a>
|
|
||||||
## 10.0.6 (2020-07-28)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **compiler:** share identical stylesheets between components in the same file ([#38213](https://github.com/angular/angular/issues/38213)) ([264950b](https://github.com/angular/angular/commit/264950b)), closes [#38204](https://github.com/angular/angular/issues/38204)
|
|
||||||
* **compiler-cli:** Add support for string literal class members ([#38226](https://github.com/angular/angular/issues/38226)) ([b1e7775](https://github.com/angular/angular/commit/b1e7775))
|
|
||||||
* **core:** `Attribute` decorator `attributeName` is mandatory ([#38131](https://github.com/angular/angular/issues/38131)) ([1c4fcce](https://github.com/angular/angular/commit/1c4fcce)), closes [#32658](https://github.com/angular/angular/issues/32658)
|
|
||||||
* **core:** unify the signature between ngZone and noopZone ([#37581](https://github.com/angular/angular/issues/37581)) ([d5264f5](https://github.com/angular/angular/commit/d5264f5))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.0-next.2"></a>
|
|
||||||
# 10.1.0-next.2 (2020-07-22)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **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)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **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)
|
|
||||||
* **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)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.0.5"></a>
|
<a name="10.0.5"></a>
|
||||||
## 10.0.5 (2020-07-22)
|
## 10.0.5 (2020-07-22)
|
||||||
|
|
||||||
@ -110,61 +32,6 @@
|
|||||||
* **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.1.0-next.1"></a>
|
|
||||||
# 10.1.0-next.1 (2020-07-15)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **bazel:** ng_module rule does not expose flat module information in Ivy ([#36971](https://github.com/angular/angular/issues/36971)) ([1550663](https://github.com/angular/angular/commit/1550663))
|
|
||||||
* **compiler:** check more cases for pipe usage inside host bindings ([#37883](https://github.com/angular/angular/issues/37883)) ([9322b9a](https://github.com/angular/angular/commit/9322b9a)), closes [#34655](https://github.com/angular/angular/issues/34655) [#37610](https://github.com/angular/angular/issues/37610)
|
|
||||||
* **compiler-cli:** ensure file_system handles mixed Windows drives ([#37959](https://github.com/angular/angular/issues/37959)) ([6b31155](https://github.com/angular/angular/commit/6b31155)), closes [#36777](https://github.com/angular/angular/issues/36777)
|
|
||||||
* **language-service:** remove completion for string ([#37983](https://github.com/angular/angular/issues/37983)) ([10aba15](https://github.com/angular/angular/commit/10aba15))
|
|
||||||
* **ngcc:** report a warning if ngcc tries to use a solution-style tsconfig ([#38003](https://github.com/angular/angular/issues/38003)) ([b358495](https://github.com/angular/angular/commit/b358495)), closes [#36386](https://github.com/angular/angular/issues/36386)
|
|
||||||
* **router:** ensure duplicate popstate/hashchange events are handled correctly ([#37674](https://github.com/angular/angular/issues/37674)) ([9185c6e](https://github.com/angular/angular/commit/9185c6e)), closes [/github.com/angular/angular/issues/16710#issuecomment-646919529](https://github.com//github.com/angular/angular/issues/16710/issues/issuecomment-646919529) [#16710](https://github.com/angular/angular/issues/16710)
|
|
||||||
* **service-worker:** correctly handle relative base href ([#37922](https://github.com/angular/angular/issues/37922)) ([d19ef65](https://github.com/angular/angular/commit/d19ef65)), closes [#25055](https://github.com/angular/angular/issues/25055) [#25055](https://github.com/angular/angular/issues/25055)
|
|
||||||
* **service-worker:** correctly serve `ngsw/state` with a non-root SW scope ([#37922](https://github.com/angular/angular/issues/37922)) ([2156bee](https://github.com/angular/angular/commit/2156bee)), closes [#30505](https://github.com/angular/angular/issues/30505)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="10.1.0-next.0"></a>
|
|
||||||
# 10.1.0-next.0 (2020-07-08)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **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)
|
|
||||||
* **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))
|
|
||||||
* **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)
|
|
||||||
* **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))
|
|
||||||
* **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))
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **bazel:** provide LinkablePackageInfo from ng_module ([#37623](https://github.com/angular/angular/issues/37623)) ([6898eab](https://github.com/angular/angular/commit/6898eab))
|
|
||||||
* **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:** 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))
|
|
||||||
* **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)
|
|
||||||
* **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)
|
|
||||||
|
|
||||||
|
|
||||||
### Performance Improvements
|
|
||||||
|
|
||||||
* **compiler-cli:** fix regressions in incremental program reuse ([#37641](https://github.com/angular/angular/issues/37641)) ([5103d90](https://github.com/angular/angular/commit/5103d90))
|
|
||||||
* **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.3"></a>
|
<a name="10.0.3"></a>
|
||||||
## 10.0.3 (2020-07-08)
|
## 10.0.3 (2020-07-08)
|
||||||
@ -176,16 +43,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)
|
||||||
|
|
||||||
@ -297,6 +154,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))
|
||||||
@ -553,30 +411,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)
|
||||||
|
|
||||||
@ -618,7 +452,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)
|
||||||
|
|
||||||
@ -664,7 +497,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)
|
||||||
|
|
||||||
@ -679,8 +511,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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -701,7 +533,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))
|
||||||
|
|
||||||
|
|
||||||
@ -721,7 +553,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))
|
||||||
@ -798,9 +630,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)
|
||||||
@ -809,6 +644,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)
|
||||||
@ -846,13 +682,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))
|
||||||
@ -877,6 +719,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)
|
||||||
@ -1134,7 +977,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)
|
||||||
@ -1265,7 +1108,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))
|
||||||
@ -1344,7 +1187,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)
|
||||||
@ -1374,7 +1217,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))
|
||||||
@ -1431,7 +1274,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))
|
||||||
@ -1540,7 +1383,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))
|
||||||
@ -1582,7 +1425,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))
|
||||||
@ -1961,6 +1804,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))
|
||||||
|
|
||||||
@ -1990,6 +1834,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>
|
||||||
@ -2167,6 +2012,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))
|
||||||
@ -2283,6 +2129,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))
|
||||||
@ -2309,7 +2157,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))
|
||||||
@ -2371,6 +2219,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:
|
||||||
@ -2523,7 +2372,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>
|
||||||
@ -2619,6 +2468,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
|
||||||
|
|
||||||
|
|
||||||
@ -2766,9 +2623,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>
|
||||||
@ -2871,7 +2761,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
|
||||||
@ -3043,6 +2936,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))
|
||||||
@ -3054,6 +2948,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)
|
||||||
@ -3089,6 +2984,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))
|
||||||
@ -3289,6 +3185,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)
|
||||||
@ -3507,7 +3405,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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -3902,6 +3805,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)
|
||||||
@ -3937,12 +3849,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))
|
||||||
@ -4301,6 +4215,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)
|
||||||
@ -4409,6 +4324,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)
|
||||||
|
|
||||||
@ -4644,6 +4560,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))
|
||||||
@ -4660,8 +4577,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))
|
||||||
@ -4686,6 +4605,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))
|
||||||
@ -5423,18 +5343,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))
|
||||||
|
|
||||||
@ -5962,12 +5891,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))
|
||||||
|
|
||||||
|
@ -1,72 +1,12 @@
|
|||||||
# Código de Conducta
|
# Contributor Code of Conduct
|
||||||
|
## Version 0.3b-angular
|
||||||
|
|
||||||
## 1. Propósito
|
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.
|
||||||
|
|
||||||
“Prometemos brindar cortesía y respeto a cualquier persona involucrada en esta comunidad, sin importar el género con el que se identifique, su orientación sexual, limitación física, edad, raza, etnia, religión o nivel de conocimiento. Esperamos que cualquiera que desee contribuir en este proyecto brinde el mismo comportamiento”
|
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.
|
||||||
|
|
||||||
Bajo ese principio queremos enfocar esta comunidad, una comunidad de respeto por el otro, donde cualquiera que sienta pasión por Angular y desee involucrarse con cualquier tipo de actividad deberá ayudar a mantener una atmósfera de cortesía por el otro, respetando los pensamientos, acciones, ideales y propuestas del otro.
|
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.
|
||||||
|
|
||||||
## 2. Comportamiento esperado
|
If any member of the community violates this code of conduct, the maintainers of the Angular project may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate.
|
||||||
|
|
||||||
- Evitar usar expresiones o gestos insultantes, humillantes o intimidatorios para referirnos a otros.
|
If you are subject to or witness unacceptable behavior, or have any other concerns, please email us at [conduct@angular.io](mailto:conduct@angular.io).
|
||||||
- Ejercita la consideración y el respeto en tus comunicaciones y acciones.
|
|
||||||
- Absténte de adoptar una conducta y un lenguaje degradantes, discriminatorios, abusivos o acosadores.
|
|
||||||
- Evitar comportamientos que agredan las expresiones de identidad, género, creencias religiosas, acciones que lastimen o los aíslen a otros.
|
|
||||||
- Evitar comentarios sobre ideas políticas.
|
|
||||||
- No se toleran conductas físicas y actitudes dirigidas al descrédito personal, físico o emocional de cualquier persona.
|
|
||||||
- No se toleran chistes y comentarios excluyentes, sexistas y racistas.
|
|
||||||
- Se rechaza actitudes de hostigamiento.
|
|
||||||
- Se rechaza el acoso: este se entiende como cualquier tipo de comentario verbal que refuerce discriminación por género, identidad y expresión de género, orientación sexual, discapacidad, apariencia física, tamaño corporal, raza, edad o religión en contextos laborales o sociales.
|
|
||||||
- No se tolera el contacto físico y/o la atención sexual no deseada.
|
|
||||||
- Promover la igualdad de oportunidades de formación, educación, intercambio y retroalimentación antes, durante y después de los eventos.
|
|
||||||
- Intenta colaborar en lugar de generar conflicto.
|
|
||||||
- Sé consciente de tu entorno y de tus compañeros participantes. Alerta a líderes de la comunidad si notas una situación peligrosa, alguien en apuros, o violaciones de este Código de Conducta, incluso si parecen intrascendentes.
|
|
||||||
|
|
||||||
## 3. Comportamiento inaceptable
|
|
||||||
Comportamientos inaceptables incluyen: intimidación, acoso, abuso, discriminación, comunicación despectiva o degradante o acciones por cualquier participante en nuestra comunidad ya sea virtual, o en las comunicaciones uno-a-uno que se realizan en el contexto de la comunidad. Por favor ser respetuoso con todos.
|
|
||||||
|
|
||||||
El acoso incluye: comentarios nocivos o perjudiciales, verbales o escritos relacionados con el género, la orientación sexual, raza, religión, discapacidad; uso inadecuado de desnudos y / o imágenes sexuales en espacios públicos (incluyendo la presentación diapositivas); intimidación deliberada, acecho o seguimiento; fotografías o grabaciones acosadoras; interrupción sostenida de charlas y otros eventos; contacto físico inapropiado, y atención sexual no deseada.
|
|
||||||
|
|
||||||
## 4. Consecuencias de comportamiento inaceptable
|
|
||||||
Se espera que personas a quienes se les solicite que detengan su comportamiento inaceptable lo hagan de manera inmediata esto será válido para cualquier miembro de la comunidad.
|
|
||||||
|
|
||||||
En caso de presentarse una violación al código de conducta de manera repetida se tendrá cero tolerancia a este comportamiento por parte de los organizadores.
|
|
||||||
|
|
||||||
Si un miembro de la comunidad participa en una conducta inaceptable, los organizadores pueden tomar cualquier acción que consideren apropiada, hasta e incluyendo una prohibición temporal o expulsión permanente de la comunidad, sin previo aviso.
|
|
||||||
|
|
||||||
Priorizamos la seguridad de las personas marginadas sobre la comodidad de las personas privilegiadas. Nos reservamos el derecho de no actuar sobre las quejas relacionadas con:
|
|
||||||
|
|
||||||
- El "racismo inverso", "sexismo inverso" y "cisfobia".
|
|
||||||
- Comunicación razonable de límites, como "déjame en paz", "vete" o "no estoy discutiendo esto contigo".
|
|
||||||
- Al comunicarse en un "tono", no se encuentra agradable.
|
|
||||||
- Identificando comportamientos o suposiciones racistas, sexistas, cissexistas u opresivas.
|
|
||||||
|
|
||||||
## 5. ¿Qué hacer si se incumple el código de conducta?
|
|
||||||
Si eres víctima o testigo de una conducta inaceptable, o tienes cualquier inquietud, por favor comunícate con el equipo organizador lo antes posible:
|
|
||||||
|
|
||||||
- Mensaje directo: Michael Prentice (@splaktar)
|
|
||||||
- Mensaje directo: Jorge Cano (@jorgeucano)
|
|
||||||
- Mensaje directo: Andrés Villanueva (@villanuevand)
|
|
||||||
- Email: [soporte@angular.lat](mailto:soporte@angular.lat)
|
|
||||||
|
|
||||||
### ¿Qué pasa después?
|
|
||||||
- Una vez haya sido notificada el no cumplimiento de la norma, el equipo de liderazgo se reunirán y analizarán el caso.
|
|
||||||
- Los incidentes presentados se manejarán con discreción.
|
|
||||||
- Los organizadores se comunicarán con la persona que incumplió la norma y tomarán las medidas respectivas.
|
|
||||||
- Se realizará un acompañamiento a la persona agredida y se apoyará.
|
|
||||||
- Si el incidente se hace público, Angular Hispano no se hace responsable de los perjuicios que esto pueda ocasionar en el agresor o el agredido.
|
|
||||||
|
|
||||||
## 6. Alcance
|
|
||||||
Esperamos que todos los participantes de la comunidad (organizadores, voluntarios, contribuyentes pagados o de otro modo; patrocinadores; y otros invitados) se atengan a este Código de Conducta en todos los espacios virtuales y presenciales, así como en todas las comunicaciones de uno-a-uno pertinentes la comunidad.
|
|
||||||
|
|
||||||
### Colaboradores
|
|
||||||
|
|
||||||
- Alejandra Giraldo
|
|
||||||
- Vanessa Marely
|
|
||||||
- Mariano Alvarez
|
|
||||||
- Andrés Villanueva
|
|
||||||
- Michael Prentice
|
|
||||||
- javascript&friends
|
|
||||||
- Angular
|
|
||||||
- She Codes Angular
|
|
||||||
- Colombia dev
|
|
||||||
|
@ -1,359 +0,0 @@
|
|||||||
# Contributing to Angular
|
|
||||||
|
|
||||||
We would love for you to contribute to Angular and help make it even better than it is today!
|
|
||||||
As a contributor, here are the guidelines we would like you to follow:
|
|
||||||
|
|
||||||
- [Code of Conduct](#coc)
|
|
||||||
- [Question or Problem?](#question)
|
|
||||||
- [Issues and Bugs](#issue)
|
|
||||||
- [Feature Requests](#feature)
|
|
||||||
- [Submission Guidelines](#submit)
|
|
||||||
- [Coding Rules](#rules)
|
|
||||||
- [Commit Message Guidelines](#commit)
|
|
||||||
- [Signing the CLA](#cla)
|
|
||||||
|
|
||||||
|
|
||||||
## <a name="coc"></a> Code of Conduct
|
|
||||||
|
|
||||||
Help us keep Angular open and inclusive.
|
|
||||||
Please read and follow our [Code of Conduct][coc].
|
|
||||||
|
|
||||||
|
|
||||||
## <a name="question"></a> Got a Question or Problem?
|
|
||||||
|
|
||||||
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests.
|
|
||||||
Instead, we recommend using [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) to ask support-related questions. When creating a new question on Stack Overflow, make sure to add the `angular` tag.
|
|
||||||
|
|
||||||
Stack Overflow is a much better place to ask questions since:
|
|
||||||
|
|
||||||
- there are thousands of people willing to help on Stack Overflow
|
|
||||||
- questions and answers stay available for public viewing so your question/answer might help someone else
|
|
||||||
- Stack Overflow's voting system assures that the best answers are prominently visible.
|
|
||||||
|
|
||||||
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 gitter channel][gitter].
|
|
||||||
|
|
||||||
|
|
||||||
## <a name="issue"></a> Found a Bug?
|
|
||||||
|
|
||||||
If you find a bug in the source code, you can help us by [submitting an issue](#submit-issue) to our [GitHub Repository][github].
|
|
||||||
Even better, you can [submit a Pull Request](#submit-pr) with a fix.
|
|
||||||
|
|
||||||
|
|
||||||
## <a name="feature"></a> Missing a Feature?
|
|
||||||
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub Repository.
|
|
||||||
If you would like to *implement* a new feature, please consider the size of the change in order to determine the right steps to proceed:
|
|
||||||
|
|
||||||
* For a **Major Feature**, first open an issue and outline your proposal so that it can be discussed.
|
|
||||||
This process allows us to better coordinate our efforts, prevent duplication of work, and help you to craft the change so that it is successfully accepted into the project.
|
|
||||||
|
|
||||||
**Note**: Adding a new topic to the documentation, or significantly re-writing a topic, counts as a major feature.
|
|
||||||
|
|
||||||
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
|
|
||||||
|
|
||||||
|
|
||||||
## <a name="submit"></a> Submission Guidelines
|
|
||||||
|
|
||||||
|
|
||||||
### <a name="submit-issue"></a> Submitting an Issue
|
|
||||||
|
|
||||||
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
|
|
||||||
|
|
||||||
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it.
|
|
||||||
In order to reproduce bugs, we require that you provide a minimal reproduction.
|
|
||||||
Having a minimal reproducible scenario gives us a wealth of important information without going back and forth to you with additional questions.
|
|
||||||
|
|
||||||
A minimal reproduction allows us to quickly confirm a bug (or point out a coding problem) as well as confirm that we are fixing the right problem.
|
|
||||||
|
|
||||||
We require a minimal reproduction to save maintainers' time and ultimately be able to fix more bugs.
|
|
||||||
Often, developers find coding problems themselves while preparing a minimal reproduction.
|
|
||||||
We understand that sometimes it might be hard to extract essential bits of code from a larger codebase but we really need to isolate the problem before we can fix it.
|
|
||||||
|
|
||||||
Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you, we are going to close an issue that doesn't have enough info to be reproduced.
|
|
||||||
|
|
||||||
You can file new issues by selecting from our [new issue templates](https://github.com/angular/angular/issues/new/choose) and filling out the issue template.
|
|
||||||
|
|
||||||
|
|
||||||
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
|
|
||||||
|
|
||||||
Before you submit your Pull Request (PR) consider the following guidelines:
|
|
||||||
|
|
||||||
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR that relates to your submission.
|
|
||||||
You don't want to duplicate existing efforts.
|
|
||||||
|
|
||||||
2. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add.
|
|
||||||
Discussing the design upfront helps to ensure that we're ready to accept your work.
|
|
||||||
|
|
||||||
3. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
|
|
||||||
We cannot accept code without a signed CLA.
|
|
||||||
Make sure you author all contributed Git commits with email address associated with your CLA signature.
|
|
||||||
|
|
||||||
4. Fork the angular/angular repo.
|
|
||||||
|
|
||||||
5. Make your changes in a new git branch:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git checkout -b my-fix-branch master
|
|
||||||
```
|
|
||||||
|
|
||||||
6. Create your patch, **including appropriate test cases**.
|
|
||||||
|
|
||||||
7. Follow our [Coding Rules](#rules).
|
|
||||||
|
|
||||||
8. Run the full Angular test suite, as described in the [developer documentation][dev-doc], and ensure that all tests pass.
|
|
||||||
|
|
||||||
9. Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit).
|
|
||||||
Adherence to these conventions is necessary because release notes are automatically generated from these messages.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git commit -a
|
|
||||||
```
|
|
||||||
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
|
||||||
|
|
||||||
10. Push your branch to GitHub:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git push origin my-fix-branch
|
|
||||||
```
|
|
||||||
|
|
||||||
11. In GitHub, send a pull request to `angular:master`.
|
|
||||||
|
|
||||||
If we ask for changes via code reviews then:
|
|
||||||
|
|
||||||
* 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):
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git rebase master -i
|
|
||||||
git push -f
|
|
||||||
```
|
|
||||||
|
|
||||||
That's it! Thank you for your contribution!
|
|
||||||
|
|
||||||
|
|
||||||
#### 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:
|
|
||||||
|
|
||||||
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git push origin --delete my-fix-branch
|
|
||||||
```
|
|
||||||
|
|
||||||
* Check out the master branch:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git checkout master -f
|
|
||||||
```
|
|
||||||
|
|
||||||
* Delete the local branch:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git branch -D my-fix-branch
|
|
||||||
```
|
|
||||||
|
|
||||||
* Update your master with the latest upstream version:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
git pull --ff upstream master
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## <a name="rules"></a> Coding Rules
|
|
||||||
To ensure consistency throughout the source code, keep these rules in mind as you are working:
|
|
||||||
|
|
||||||
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
|
|
||||||
* All public API methods **must be documented**.
|
|
||||||
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at **100 characters**.
|
|
||||||
|
|
||||||
An automated formatter is available, see [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
|
||||||
|
|
||||||
|
|
||||||
## <a name="commit"></a> Commit Message Format
|
|
||||||
|
|
||||||
*This specification is inspired and supersedes the [AngularJS commit message format][commit-message-format].*
|
|
||||||
|
|
||||||
We have very precise rules over how our Git commit messages must be formatted.
|
|
||||||
This format leads to **easier to read commit history**.
|
|
||||||
|
|
||||||
Each commit message consists of a **header**, a **body**, and a **footer**.
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
<header>
|
|
||||||
<BLANK LINE>
|
|
||||||
<body>
|
|
||||||
<BLANK LINE>
|
|
||||||
<footer>
|
|
||||||
```
|
|
||||||
|
|
||||||
The `header` is mandatory and must conform to the [Commit Message Header](#commit-header) format.
|
|
||||||
|
|
||||||
The `body` is mandatory for all commits except for those of scope "docs".
|
|
||||||
When the body is required it must be at least 20 characters long.
|
|
||||||
|
|
||||||
The `footer` is optional.
|
|
||||||
|
|
||||||
Any line of the commit message cannot be longer than 100 characters.
|
|
||||||
|
|
||||||
|
|
||||||
#### <a href="commit-header"></a>Commit Message Header
|
|
||||||
|
|
||||||
```
|
|
||||||
<type>(<scope>): <short summary>
|
|
||||||
│ │ │
|
|
||||||
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
|
||||||
│ │
|
|
||||||
│ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
|
||||||
│ elements|forms|http|language-service|localize|platform-browser|
|
|
||||||
│ platform-browser-dynamic|platform-server|platform-webworker|
|
|
||||||
│ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
|
|
||||||
│ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
|
|
||||||
│
|
|
||||||
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
|
|
||||||
```
|
|
||||||
|
|
||||||
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
|
|
||||||
|
|
||||||
|
|
||||||
##### Type
|
|
||||||
|
|
||||||
Must be one of the following:
|
|
||||||
|
|
||||||
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
|
||||||
* **ci**: Changes to our CI configuration files and scripts (example scopes: Circle, BrowserStack, SauceLabs)
|
|
||||||
* **docs**: Documentation only changes
|
|
||||||
* **feat**: A new feature
|
|
||||||
* **fix**: A bug fix
|
|
||||||
* **perf**: A code change that improves performance
|
|
||||||
* **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
|
|
||||||
|
|
||||||
|
|
||||||
##### Scope
|
|
||||||
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages).
|
|
||||||
|
|
||||||
The following is the list of supported scopes:
|
|
||||||
|
|
||||||
* `animations`
|
|
||||||
* `bazel`
|
|
||||||
* `benchpress`
|
|
||||||
* `common`
|
|
||||||
* `compiler`
|
|
||||||
* `compiler-cli`
|
|
||||||
* `core`
|
|
||||||
* `elements`
|
|
||||||
* `forms`
|
|
||||||
* `http`
|
|
||||||
* `language-service`
|
|
||||||
* `localize`
|
|
||||||
* `platform-browser`
|
|
||||||
* `platform-browser-dynamic`
|
|
||||||
* `platform-server`
|
|
||||||
* `platform-webworker`
|
|
||||||
* `platform-webworker-dynamic`
|
|
||||||
* `router`
|
|
||||||
* `service-worker`
|
|
||||||
* `upgrade`
|
|
||||||
* `zone.js`
|
|
||||||
|
|
||||||
There are currently a few exceptions to the "use package name" rule:
|
|
||||||
|
|
||||||
* `packaging`: used for changes that change the npm package layout in all of our packages, e.g. public path changes, package.json changes done to all packages, d.ts file/format changes, changes to bundles, etc.
|
|
||||||
|
|
||||||
* `changelog`: used for updating the release notes in CHANGELOG.md
|
|
||||||
|
|
||||||
* `dev-infra`: used for dev-infra related changes within the directories /scripts, /tools and /dev-infra
|
|
||||||
|
|
||||||
* `docs-infra`: used for docs-app (angular.io) related changes within the /aio directory of the repo
|
|
||||||
|
|
||||||
* `migrations`: used for changes to the `ng update` migrations.
|
|
||||||
|
|
||||||
* `ngcc`: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
|
|
||||||
|
|
||||||
* `ve`: used for changes specific to ViewEngine (legacy compiler/renderer).
|
|
||||||
|
|
||||||
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a specific package (e.g. `docs: fix typo in tutorial`).
|
|
||||||
|
|
||||||
|
|
||||||
##### Summary
|
|
||||||
|
|
||||||
Use the summary field to provide a succinct description of the change:
|
|
||||||
|
|
||||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
|
||||||
* don't capitalize the first letter
|
|
||||||
* no dot (.) at the end
|
|
||||||
|
|
||||||
|
|
||||||
#### Commit Message Body
|
|
||||||
|
|
||||||
Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
|
|
||||||
|
|
||||||
Explain the motivation for the change in the commit message body. This commit message should explain _why_ you are making the change.
|
|
||||||
You can include a comparison of the previous behavior with the new behavior in order to illustrate the impact of the change.
|
|
||||||
|
|
||||||
|
|
||||||
#### Commit Message Footer
|
|
||||||
|
|
||||||
The footer can contain information about breaking changes and is also the place to reference GitHub issues, Jira tickets, and other PRs that this commit closes or is related to.
|
|
||||||
|
|
||||||
```
|
|
||||||
BREAKING CHANGE: <breaking change summary>
|
|
||||||
<BLANK LINE>
|
|
||||||
<breaking change description + migration instructions>
|
|
||||||
<BLANK LINE>
|
|
||||||
<BLANK LINE>
|
|
||||||
Fixes #<issue number>
|
|
||||||
```
|
|
||||||
|
|
||||||
Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of the breaking change, a blank line, and a detailed description of the breaking change that also includes migration instructions.
|
|
||||||
|
|
||||||
|
|
||||||
### Revert commits
|
|
||||||
|
|
||||||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit.
|
|
||||||
|
|
||||||
The content of the commit message body should contain:
|
|
||||||
|
|
||||||
- information about the SHA of the commit being reverted in the following format: `This reverts commit <SHA>`,
|
|
||||||
- a clear description of the reason for reverting the commit message.
|
|
||||||
|
|
||||||
|
|
||||||
## <a name="cla"></a> Signing the CLA
|
|
||||||
|
|
||||||
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
|
|
||||||
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
|
|
||||||
|
|
||||||
* For individuals, we have a [simple click-through form][individual-cla].
|
|
||||||
* For corporations, we'll need you to
|
|
||||||
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
|
|
||||||
|
|
||||||
If you have more than one GitHub accounts, or multiple email addresses associated with a single GitHub account, you must sign the CLA using the primary email address of the GitHub account used to author Git commits and send pull requests.
|
|
||||||
|
|
||||||
The following documents can help you sort out issues with GitHub accounts and multiple email addresses:
|
|
||||||
|
|
||||||
* https://help.github.com/articles/setting-your-commit-email-address-in-git/
|
|
||||||
* https://stackoverflow.com/questions/37245303/what-does-usera-committed-with-userb-13-days-ago-on-github-mean
|
|
||||||
* https://help.github.com/articles/about-commit-email-addresses/
|
|
||||||
* https://help.github.com/articles/blocking-command-line-pushes-that-expose-your-personal-email-address/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[angular-group]: https://groups.google.com/forum/#!forum/angular
|
|
||||||
[coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
|
|
||||||
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
|
|
||||||
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
|
|
||||||
[dev-doc]: https://github.com/angular/angular/blob/master/docs/DEVELOPER.md
|
|
||||||
[github]: https://github.com/angular/angular
|
|
||||||
[gitter]: https://gitter.im/angular/angular
|
|
||||||
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
|
||||||
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
|
|
||||||
[jsfiddle]: http://jsfiddle.net
|
|
||||||
[plunker]: http://plnkr.co/edit
|
|
||||||
[runnable]: http://runnable.com
|
|
||||||
[stackoverflow]: http://stackoverflow.com/questions/tagged/angular
|
|
303
CONTRIBUTING.md
303
CONTRIBUTING.md
@ -1,243 +1,243 @@
|
|||||||
# Contribuye a Angular
|
# Contributing to Angular
|
||||||
|
|
||||||
¡Nos encantaría que contribuyeras a Angular y que ayudaras a hacerlo aún mejor de lo que es hoy!
|
We would love for you to contribute to Angular and help make it even better than it is today!
|
||||||
Como colaborador, estos son los lineamientos que nos gustaría que siguieras:
|
As a contributor, here are the guidelines we would like you to follow:
|
||||||
|
|
||||||
- [Código de conducta](#coc)
|
- [Code of Conduct](#coc)
|
||||||
- [¿Preguntas o problemas?](#question)
|
- [Question or Problem?](#question)
|
||||||
- [_Issues_ y _bugs_](#issue)
|
- [Issues and Bugs](#issue)
|
||||||
- [Solicitud de funcionalidades](#feature)
|
- [Feature Requests](#feature)
|
||||||
- [Guía para la creación de issues y PRs](#submit)
|
- [Submission Guidelines](#submit)
|
||||||
- [Reglas del código](#rules)
|
- [Coding Rules](#rules)
|
||||||
- [Convención para el mensaje de los _commits_](#commit)
|
- [Commit Message Guidelines](#commit)
|
||||||
- [Firma del Acuerdo de Licencia de Colaborador (CLA)](#cla)
|
- [Signing the CLA](#cla)
|
||||||
|
|
||||||
|
|
||||||
## <a name="coc"></a> Código de conducta
|
## <a name="coc"></a> Code of Conduct
|
||||||
|
|
||||||
Ayúdanos a mantener Angular abierto e inclusivo.
|
Help us keep Angular open and inclusive.
|
||||||
Por favor lee y sigue nuestro [Código de conducta][coc].
|
Please read and follow our [Code of Conduct][coc].
|
||||||
|
|
||||||
|
|
||||||
## <a name="question"></a> ¿Tienes alguna pregunta o problema?
|
## <a name="question"></a> Got a Question or Problem?
|
||||||
|
|
||||||
No abras *issues* para preguntas de soporte general ya que queremos mantener los *issues* de GitHub para reporte de *bugs* y solicitud de funcionalidades.
|
Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests.
|
||||||
En su lugar, recomendamos utilizar [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) para hacer preguntas relacionadas con soporte. Al crear una nueva pregunta en Stack Overflow, asegúrate de agregar el etiqueta (tag) de `angular`.
|
Instead, we recommend using [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) to ask support-related questions. When creating a new question on Stack Overflow, make sure to add the `angular` tag.
|
||||||
|
|
||||||
Stack Overflow es mucho mejor para hacer preguntas ya que:
|
Stack Overflow is a much better place to ask questions since:
|
||||||
|
|
||||||
- Hay miles de personas dispuestas a ayudar en preguntas y respuestas de Stack Overflow
|
- there are thousands of people willing to help on Stack Overflow
|
||||||
que permanecen disponibles para el público, por lo que tu pregunta o respuesta podría ayudar a otra persona.
|
- questions and answers stay available for public viewing so your question/answer might help someone else
|
||||||
- El sistema de votación de Stack Overflow asegura que las mejores respuestas sobresalgan y sean visibles.
|
- Stack Overflow's voting system assures that the best answers are prominently visible.
|
||||||
|
|
||||||
Para ahorrar tu tiempo y el nuestro, cerraremos sistemáticamente todos los *issues* que sean solicitudes de soporte general y redirigiremos a las personas a 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.
|
||||||
|
|
||||||
Si deseas chatear sobre alguna pregunta en tiempo real, puedes hacerlo a través de nuestro [canal de Gitter][gitter].
|
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> ¿Encontraste un Bug?
|
## <a name="issue"></a> Found a Bug?
|
||||||
|
|
||||||
Si encontraste un error en el código fuente, puedes ayudarnos [creando un *issue*](#submit-issue) en nuestro [repositorio de GitHub][github].
|
If you find a bug in the source code, you can help us by [submitting an issue](#submit-issue) to our [GitHub Repository][github].
|
||||||
O incluso mejor, puedes [crear un *Pull Request*](#submit-pr) con la solución.
|
Even better, you can [submit a Pull Request](#submit-pr) with a fix.
|
||||||
|
|
||||||
|
|
||||||
## <a name="feature"></a> ¿Falta alguna funcionalidad?
|
## <a name="feature"></a> Missing a Feature?
|
||||||
Puedes solicitar una nueva funcionalidad [creando un *issue*](#submit-issue) en nuestro repositorio de GitHub.
|
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub Repository.
|
||||||
Si deseas implementar una nueva funcionalidad, por favor considera el tamaño del cambio para determinar los pasos correctos para continuar:
|
If you would like to *implement* a new feature, please consider the size of the change in order to determine the right steps to proceed:
|
||||||
|
|
||||||
* Para un **cambio significativo**, primero abre un *issue* y describe tu propuesta para que pueda ser discutida.
|
* For a **Major Feature**, first open an issue and outline your proposal so that it can be discussed.
|
||||||
Este proceso nos permite coordinar mejor nuestros esfuerzos, evitar trabajo duplicado y ayudarte a diseñar el cambio para que sea aceptado con éxito en el proyecto.
|
This process allows us to better coordinate our efforts, prevent duplication of work, and help you to craft the change so that it is successfully accepted into the project.
|
||||||
|
|
||||||
**Nota**: Agregar un nuevo tema a la documentación o reescribir significativamente un tema, también cuenta como *cambio significativo*.
|
**Note**: Adding a new topic to the documentation, or significantly re-writing a topic, counts as a major feature.
|
||||||
|
|
||||||
* **Cambios pequeños** pueden ser elaborados y directamente [creados como un _pull request_](#submit-pr).
|
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
|
||||||
|
|
||||||
|
|
||||||
## <a name="submit"></a> Guía para la creación de issues y PRs
|
## <a name="submit"></a> Submission Guidelines
|
||||||
|
|
||||||
|
|
||||||
### <a name="submit-issue"></a> Creación de _issues_
|
### <a name="submit-issue"></a> Submitting an Issue
|
||||||
|
|
||||||
Antes de crear un *issue*, por favor busca en el el *issue tracker*, quizá un *issue* para tu problema ya existe y la discusión puede informarte sobre soluciones alternativas disponibles.
|
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
|
||||||
|
|
||||||
Queremos solucionar todos los problemas lo antes posible, pero antes de corregir un bug necesitamos reproducirlo y confirmarlo.
|
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it.
|
||||||
Para reproducir errores, requerimos que proporciones una reproducción mínima.
|
In order to reproduce bugs, we require that you provide a minimal reproduction.
|
||||||
Tener un escenario reproducible mínimo nos brinda una gran cantidad de información importante sin tener que ir y venir con preguntas adicionales.
|
Having a minimal reproducible scenario gives us a wealth of important information without going back and forth to you with additional questions.
|
||||||
|
|
||||||
Una reproducción mínima nos permite confirmar rápidamente un bug (o señalar un problema de código), así también confirmar que estamos solucionando el problema correcto.
|
A minimal reproduction allows us to quickly confirm a bug (or point out a coding problem) as well as confirm that we are fixing the right problem.
|
||||||
|
|
||||||
Requerimos una reproducción mínima para ahorrar tiempo a los encargados del mantenimiento y en última instancia, poder corregir más bugs.
|
We require a minimal reproduction to save maintainers' time and ultimately be able to fix more bugs.
|
||||||
A menudo los desarrolladores encuentran problemas de código mientras preparan una reproducción mínima.
|
Often, developers find coding problems themselves while preparing a minimal reproduction.
|
||||||
Entendemos que a veces puede ser difícil extraer porciones esenciales de código de un código más grande, pero realmente necesitamos aislar el problema antes de poder solucionarlo.
|
We understand that sometimes it might be hard to extract essential bits of code from a larger codebase but we really need to isolate the problem before we can fix it.
|
||||||
|
|
||||||
Desafortunadamente no podemos investigar/corregir errores sin una reproducción mínima, por lo que si no tenemos tu retroalimentación del bug, vamos a cerrar el *issue* ya que no tiene suficiente información para reproducirse.
|
Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you, we are going to close an issue that doesn't have enough info to be reproduced.
|
||||||
|
|
||||||
Puedes presentar nuevos *issues* seleccionando nuestra [plantilla de _issues_](https://github.com/angular/angular/issues/new/choose) y complentando la plantilla.
|
You can file new issues by selecting from our [new issue templates](https://github.com/angular/angular/issues/new/choose) and filling out the issue template.
|
||||||
|
|
||||||
|
|
||||||
### <a name="submit-pr"></a> Creación de un Pull Requests (PR)
|
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
|
||||||
|
|
||||||
Antes de crear tu Pull Request (PR) considera los siguientes lineamientos:
|
Before you submit your Pull Request (PR) consider the following guidelines:
|
||||||
|
|
||||||
1. Busca en [GitHub](https://github.com/angular/angular/pulls) PRs que estén abiertos o cerrados y que estén relacionados con el que vas a crear.
|
1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR that relates to your submission.
|
||||||
No deseas duplicar los esfuerzos existentes.
|
You don't want to duplicate existing efforts.
|
||||||
|
|
||||||
2. Asegúrate de que el PR describa el problema que estás solucionando o que documente el diseño de la funcionalidad que deseas agregar.
|
2. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add.
|
||||||
Discutir el diseño por adelantado ayuda a garantizar que estemos listos para aceptar tu trabajo.
|
Discussing the design upfront helps to ensure that we're ready to accept your work.
|
||||||
|
|
||||||
3. Por favor firma nuestro [Acuerdo de Licencia de Colaborador (CLA)](#cla) antes de crear PRs.
|
3. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
|
||||||
No podemos aceptar el código sin el Acuerdo de Licencia de Colaborador (CLA) firmado.
|
We cannot accept code without a signed CLA.
|
||||||
Asegúrate de crear todas las contribuciones de Git con la dirección de correo electrónico asociada con tu firma del Acuerdo de Licencia de Colaborador (CLA).
|
Make sure you author all contributed Git commits with email address associated with your CLA signature.
|
||||||
|
|
||||||
4. Haz *fork* del repositorio angular/angular.
|
4. Fork the angular/angular repo.
|
||||||
|
|
||||||
5. Haz tus cambios en una nueva rama de Git:
|
5. Make your changes in a new git branch:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git checkout -b my-fix-branch master
|
git checkout -b my-fix-branch master
|
||||||
```
|
```
|
||||||
|
|
||||||
6. Crea tu correción, **incluyendo casos de prueba apropiados**.
|
6. Create your patch, **including appropriate test cases**.
|
||||||
|
|
||||||
7. Sigue nuestras [Reglas de código](#rules).
|
7. Follow our [Coding Rules](#rules).
|
||||||
|
|
||||||
8. Ejecuta todo el conjunto de pruebas de Angular, tal como está descrito en la [documentación del desarrollador][dev-doc], y asegúrate de que todas las pruebas pasen.
|
8. Run the full Angular test suite, as described in the [developer documentation][dev-doc], and ensure that all tests pass.
|
||||||
|
|
||||||
9. Crea un commit de tus cambios utilizando un mensaje de commit descriptivo que siga nuestra [convención para el mensaje de los commits](#commit).
|
9. Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit).
|
||||||
Es necesario cumplir con estas convenciones porque las notas de las versiones se generan automáticamente a partir de estos mensajes.
|
Adherence to these conventions is necessary because release notes are automatically generated from these messages.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git commit -a
|
git commit -a
|
||||||
```
|
```
|
||||||
Nota: la opción de la línea de comandos de Git `-a` automaticamente hará "add" y "rm" a los archivos editados.
|
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
||||||
|
|
||||||
10. Haz push de tu rama a GitHub:
|
10. Push your branch to GitHub:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git push origin my-fix-branch
|
git push origin my-fix-branch
|
||||||
```
|
```
|
||||||
|
|
||||||
11. En GitHub, crea un pull request a `angular:master`.
|
11. In GitHub, send a pull request to `angular:master`.
|
||||||
|
|
||||||
Si solicitamos cambios a través de revisiones de código, sigue las siguientes indicaciones:
|
If we ask for changes via code reviews then:
|
||||||
|
|
||||||
* Haz los cambios requeridos.
|
* Make the required updates.
|
||||||
* Ejecuta nuevamente el conjunto de pruebas de Angular para asegurar que todas las pruebas aún están pasando.
|
* Re-run the Angular test suites to ensure tests are still passing.
|
||||||
* Haz rebase de tu rama a la rama master y haz push con la opción `-f` a tu repositorio de Github (esto actualizará tu Pull Request):
|
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git rebase master -i
|
git rebase master -i
|
||||||
git push -f
|
git push -f
|
||||||
```
|
```
|
||||||
|
|
||||||
¡Es todo! ¡Muchas gracias por tu contribución!
|
That's it! Thank you for your contribution!
|
||||||
|
|
||||||
|
|
||||||
#### Después del merge de tu pull request
|
#### After your pull request is merged
|
||||||
|
|
||||||
Después de que se hizo merge de tu pull request, puedes eliminar de forma segura tu rama y hacer pull de los cambios del repositorio principal (upstream):
|
After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository:
|
||||||
|
|
||||||
* Elimina la rama remota en GitHub a través de la interfaz de usuario web de GitHub o en tu línea de comandos de la siguiente manera:
|
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git push origin --delete my-fix-branch
|
git push origin --delete my-fix-branch
|
||||||
```
|
```
|
||||||
|
|
||||||
* Muévete a la rama master:
|
* Check out the master branch:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git checkout master -f
|
git checkout master -f
|
||||||
```
|
```
|
||||||
|
|
||||||
* Elimina tu rama local:
|
* Delete the local branch:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git branch -D my-fix-branch
|
git branch -D my-fix-branch
|
||||||
```
|
```
|
||||||
|
|
||||||
* Actualiza tu rama master con la última versión del fork (upstream):
|
* Update your master with the latest upstream version:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git pull --ff upstream master
|
git pull --ff upstream master
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## <a name="rules"></a> Reglas del código
|
## <a name="rules"></a> Coding Rules
|
||||||
Para garantizar la coherencia en todo el código fuente, ten en cuenta estas reglas mientras trabajas:
|
To ensure consistency throughout the source code, keep these rules in mind as you are working:
|
||||||
|
|
||||||
* Todas las funcionalidades o solución de bugs **deben ser probadas** por una o más pruebas (pruebas unitarias).
|
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
|
||||||
* Todos los métodos públicos del API **deben ser documentados**.
|
* All public API methods **must be documented**.
|
||||||
* Seguimos la [guía de estilo JavaScript de Google][js-style-guide], pero cada línea no debe exceder **100 caracteres**.
|
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at **100 characters**.
|
||||||
|
|
||||||
Un formateador automatizado está disponible, revisar [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
An automated formatter is available, see [DEVELOPER.md](docs/DEVELOPER.md#clang-format).
|
||||||
|
|
||||||
|
|
||||||
## <a name="commit"></a> Formato para el mensaje de los commits
|
## <a name="commit"></a> Commit Message Format
|
||||||
|
|
||||||
*Esta especificación está inspirada y reemplaza el [Formato de mensaje de commits de AngularJS][commit-message-format].*
|
*This specification is inspired and supersedes the [AngularJS commit message format][commit-message-format].*
|
||||||
|
|
||||||
Tenemos reglas muy precisas sobre cómo deben formatearse nuestros mensajes de los commits de Git.
|
We have very precise rules over how our Git commit messages must be formatted.
|
||||||
Este formato permite tener **un historial de commits más facil de leer**.
|
This format leads to **easier to read commit history**.
|
||||||
|
|
||||||
Cada mensaje de un commit consta del **header**, el **body**, y el **footer**.
|
Each commit message consists of a **header**, a **body**, and a **footer**.
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
<header>
|
<header>
|
||||||
<LINEA VACIA>
|
<BLANK LINE>
|
||||||
<body>
|
<body>
|
||||||
<LINEA VACIA>
|
<BLANK LINE>
|
||||||
<footer>
|
<footer>
|
||||||
```
|
```
|
||||||
|
|
||||||
El `header` es obligatorio y debe ajustarse al formato del [mensaje del header del commit](#commit-header).
|
The `header` is mandatory and must conform to the [Commit Message Header](#commit-header) format.
|
||||||
|
|
||||||
El `body` es obligatorio para todos los commits excepto los que tenga scope "docs".
|
The `body` is mandatory for all commits except for those of scope "docs".
|
||||||
Cuando el body es requerido debe tener al menos 20 caracteres.
|
When the body is required it must be at least 20 characters long.
|
||||||
|
|
||||||
El `footer` es opcional.
|
The `footer` is optional.
|
||||||
|
|
||||||
Cualquier línea del mensaje del commit no puede tener más de 100 caracteres.
|
Any line of the commit message cannot be longer than 100 characters.
|
||||||
|
|
||||||
|
|
||||||
#### <a href="commit-header"></a>Mensaje del header del commit
|
#### <a href="commit-header"></a>Commit Message Header
|
||||||
|
|
||||||
```
|
```
|
||||||
<tipo>(<alcance>): <resumen>
|
<type>(<scope>): <short summary>
|
||||||
│ │ │
|
│ │ │
|
||||||
│ │ └─⫸ Resumen corto escrito en modo imperativo, tiempo presente. Sin mayúsculas. Sin punto final.
|
│ │ └─⫸ Summary in present tense. Not capitalized. No period at the end.
|
||||||
│ │
|
│ │
|
||||||
│ └─⫸ Alcance del commit: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
│ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core|
|
||||||
│ elements|forms|http|language-service|localize|platform-browser|
|
│ elements|forms|http|language-service|localize|platform-browser|
|
||||||
│ platform-browser-dynamic|platform-server|platform-webworker|
|
│ platform-browser-dynamic|platform-server|platform-webworker|
|
||||||
│ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
|
│ platform-webworker-dynamic|router|service-worker|upgrade|zone.js|
|
||||||
│ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
|
│ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve
|
||||||
│
|
│
|
||||||
└─⫸ Tipo de commit: build|ci|docs|feat|fix|perf|refactor|style|test
|
└─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
|
||||||
```
|
```
|
||||||
|
|
||||||
El `<tipo>` y `<resumen>` son obligatorios, el `(<alcance>)` es opcional.
|
The `<type>` and `<summary>` fields are mandatory, the `(<scope>)` field is optional.
|
||||||
|
|
||||||
|
|
||||||
##### Tipo
|
##### Type
|
||||||
|
|
||||||
El tipo debe ser uno de los siguientes:
|
Must be one of the following:
|
||||||
|
|
||||||
* **build**: cambios que afectan el sistema de compilación o dependencias externas (ejemplos de scopes: gulp, broccoli, npm)
|
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
||||||
* **ci**: cambios en nuestros archivos y scripts de configuración de CI (ejemplos de scopes: Circle, BrowserStack, SauceLabs)
|
* **ci**: Changes to our CI configuration files and scripts (example scopes: Circle, BrowserStack, SauceLabs)
|
||||||
* **docs**: cambios en la documentación
|
* **docs**: Documentation only changes
|
||||||
* **feat**: una nueva funcionalidad
|
* **feat**: A new feature
|
||||||
* **fix**: una solución de un bug
|
* **fix**: A bug fix
|
||||||
* **perf**: un cambio de código que mejora el rendimiento.
|
* **perf**: A code change that improves performance
|
||||||
* **refactor**: un cambio de código que no corrige ningún error ni agrega ninguna funcionalidad
|
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||||
* **style**: cambios que no afectan el significado del código (espacios en blanco, formato, falta de punto y coma, etc.)
|
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
|
||||||
* **test**: se agregan pruebas faltantes o se corrigen pruebas existentes
|
* **test**: Adding missing tests or correcting existing tests
|
||||||
|
|
||||||
|
|
||||||
##### Alcance
|
##### Scope
|
||||||
El alcance debe ser el nombre del paquete npm afectado (tal como lo percibe la persona que lee el registro de cambios generado a partir de los mensajes de commit).
|
The scope should be the name of the npm package affected (as perceived by the person reading the changelog generated from commit messages).
|
||||||
|
|
||||||
La siguiente es la lista de alcances permitidos:
|
The following is the list of supported scopes:
|
||||||
|
|
||||||
* `animations`
|
* `animations`
|
||||||
* `bazel`
|
* `bazel`
|
||||||
@ -261,73 +261,80 @@ La siguiente es la lista de alcances permitidos:
|
|||||||
* `upgrade`
|
* `upgrade`
|
||||||
* `zone.js`
|
* `zone.js`
|
||||||
|
|
||||||
Actualmente hay algunas excepciones a la regla "usar el nombre de paquete":
|
There are currently a few exceptions to the "use package name" rule:
|
||||||
|
|
||||||
* `packaging`: usado para cambios que cambian el diseño de los paquetes de npm en todos nuestros paquetes. Ejemplos: cambios de la ruta públic, package.json cambios hechos a todos los paquetes, cambios a archivos o formatos d.ts, cambios a bundles, etc.
|
* `packaging`: used for changes that change the npm package layout in all of our packages, e.g. public path changes, package.json changes done to all packages, d.ts file/format changes, changes to bundles, etc.
|
||||||
|
|
||||||
* `changelog`: utilizado para actualizar las notas de la versión en CHANGELOG.md
|
* `changelog`: used for updating the release notes in CHANGELOG.md
|
||||||
|
|
||||||
* `dev-infra`: utilizado para cambios relacionados con dev-infra dentro de los directorios /scripts, /tools y /dev-infra
|
* `dev-infra`: used for dev-infra related changes within the directories /scripts, /tools and /dev-infra
|
||||||
|
|
||||||
* `docs-infra`: utilizado para cambios relacionados con la documentación (angular.io) dentro del directorio /aio del repositorio
|
* `docs-infra`: used for docs-app (angular.io) related changes within the /aio directory of the repo
|
||||||
|
|
||||||
* `migrations`: utilizado para los cambios en las migraciones `ng update`.
|
* `migrations`: used for changes to the `ng update` migrations.
|
||||||
|
|
||||||
* `ngcc`: usado para los cambios del [Compilador de compatibilidad de Angular](./packages/compiler-cli/ngcc/README.md)
|
* `ngcc`: used for changes to the [Angular Compatibility Compiler](./packages/compiler-cli/ngcc/README.md)
|
||||||
|
|
||||||
* `ve`: utilizado para cambios específicos de ViewEngine (legacy compiler/renderer).
|
* `ve`: used for changes specific to ViewEngine (legacy compiler/renderer).
|
||||||
|
|
||||||
* alcance vacío: útil para cambios de `style`, `test` y `refactor` que se realizan en todos los paquetes (ejemplo: `style: add missing semicolons`) y para cambios de la documentación que no están relacionados a un paquete en específico(ejemplo: `docs: corrige error gramatical en el tutorial`).
|
* none/empty string: useful for `style`, `test` and `refactor` changes that are done across all packages (e.g. `style: add missing semicolons`) and for docs changes that are not related to a specific package (e.g. `docs: fix typo in tutorial`).
|
||||||
|
|
||||||
|
|
||||||
##### Resumen
|
##### Summary
|
||||||
|
|
||||||
Usa el campo resumen para proporcionar una descripción breve del cambio:
|
Use the summary field to provide a succinct description of the change:
|
||||||
|
|
||||||
* usa el modo imperativo, tiempo presente: "cambia" no "cambió" o "cambios"
|
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||||
* no debe de contener ninguna letra mayúscula
|
* don't capitalize the first letter
|
||||||
* no debe de conter punto (.) al final
|
* no dot (.) at the end
|
||||||
|
|
||||||
|
|
||||||
#### Mensaje del cuerpo del commit
|
#### Commit Message Body
|
||||||
|
|
||||||
Tal como en el resumen, usa el modo imperativo, tiempo presente: "cambia" no "cambió" o "cambios".
|
Just as in the summary, use the imperative, present tense: "fix" not "fixed" nor "fixes".
|
||||||
|
|
||||||
Explica la razón del cambio en el el mensaje del cuerpo del commit. Este mensaje de confirmación debe explicar _por qué_ está realizando el cambio.
|
Explain the motivation for the change in the commit message body. This commit message should explain _why_ you are making the change.
|
||||||
Puedes incluir una comparación del comportamiento anterior con el nuevo comportamiento para ilustrar el impacto del cambio.
|
You can include a comparison of the previous behavior with the new behavior in order to illustrate the impact of the change.
|
||||||
|
|
||||||
|
|
||||||
#### Mensaje del footer del commit
|
#### Commit Message Footer
|
||||||
|
|
||||||
El footer puede contener información sobre cambios significativos y también es el lugar para hacer referencia a issues de GitHub, tickets de Jira y otros PRs que están relacionados con el commit.
|
The footer can contain information about breaking changes and is also the place to reference GitHub issues, Jira tickets, and other PRs that this commit closes or is related to.
|
||||||
|
|
||||||
```
|
```
|
||||||
CAMBIO SIGNIFICATIVO: <resumen del cambio significativo>
|
BREAKING CHANGE: <breaking change summary>
|
||||||
<LINEA VACIA>
|
<BLANK LINE>
|
||||||
<descripción del cambio significativo + instrucciones para la migración>
|
<breaking change description + migration instructions>
|
||||||
<LINEA VACIA>
|
<BLANK LINE>
|
||||||
<LINEA VACIA>
|
<BLANK LINE>
|
||||||
Fix #<issue número>
|
Fixes #<issue number>
|
||||||
```
|
```
|
||||||
|
|
||||||
La sección de cambios significativos debería comenzar con la frase "CAMBIO SIGNIFICATIVO: " seguido de un resumen del cambio significativo, una línea en blanco y una descripción detallada del cambio significativo que también incluya instrucciones de migración.
|
Breaking Change section should start with the phrase "BREAKING CHANGE: " followed by a summary of the breaking change, a blank line, and a detailed description of the breaking change that also includes migration instructions.
|
||||||
|
|
||||||
|
|
||||||
### Revirtiendo commits
|
### Revert commits
|
||||||
|
|
||||||
Si el commit revierte un commit previo, el commit debería comenzar con `revert: `, seguido por el header del commit revertido.
|
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit.
|
||||||
|
|
||||||
El contenido del mensaje del commit debería contener:
|
The content of the commit message body should contain:
|
||||||
|
|
||||||
- Información sobre el SHA del commit que se revierte en el siguiente formato: `Esto revierte el commit <SHA>`,
|
- information about the SHA of the commit being reverted in the following format: `This reverts commit <SHA>`,
|
||||||
- Una descripción clara de la razón para revertir el mensaje del _commit_.
|
- a clear description of the reason for reverting the commit message.
|
||||||
|
|
||||||
|
|
||||||
## <a name="cla"></a> Firma del Acuerdo de Licencia de Colaborador (CLA)
|
## <a name="cla"></a> Signing the CLA
|
||||||
|
|
||||||
Por favor firma nuestro Acuerdo de Licencia de Colaborador (CLA) cuando creas tu primer pull request. Para que cualquier cambio de código sea aceptado, el Acuerdo de Licencia de Colaborador (CLA) debe ser firmado. Es un proceso rápido con nuestro CLA assistant que está integrado con nuestro CI.
|
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
|
||||||
|
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
|
||||||
|
|
||||||
Los siguientes documentos pueden ayudarte a resolver problemas con cuentas de GitHub y múltiples direcciones de correo electrónico:
|
* For individuals, we have a [simple click-through form][individual-cla].
|
||||||
|
* For corporations, we'll need you to
|
||||||
|
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
|
||||||
|
|
||||||
|
If you have more than one GitHub accounts, or multiple email addresses associated with a single GitHub account, you must sign the CLA using the primary email address of the GitHub account used to author Git commits and send pull requests.
|
||||||
|
|
||||||
|
The following documents can help you sort out issues with GitHub accounts and multiple email addresses:
|
||||||
|
|
||||||
* https://help.github.com/articles/setting-your-commit-email-address-in-git/
|
* https://help.github.com/articles/setting-your-commit-email-address-in-git/
|
||||||
* https://stackoverflow.com/questions/37245303/what-does-usera-committed-with-userb-13-days-ago-on-github-mean
|
* https://stackoverflow.com/questions/37245303/what-does-usera-committed-with-userb-13-days-ago-on-github-mean
|
||||||
|
26
README.en.md
26
README.en.md
@ -1,26 +0,0 @@
|
|||||||
[](https://circleci.com/gh/angular/workflows/angular/tree/master)
|
|
||||||
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
|
||||||
[](https://www.npmjs.com/@angular/core)
|
|
||||||
|
|
||||||
|
|
||||||
# Angular
|
|
||||||
|
|
||||||
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages.
|
|
||||||
|
|
||||||
## Quickstart
|
|
||||||
|
|
||||||
[Get started in 5 minutes][quickstart].
|
|
||||||
|
|
||||||
## Changelog
|
|
||||||
|
|
||||||
[Learn about the latest improvements][changelog].
|
|
||||||
|
|
||||||
## Want to help?
|
|
||||||
|
|
||||||
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our
|
|
||||||
guidelines for [contributing][contributing] and then check out one of our issues in the [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help).
|
|
||||||
|
|
||||||
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
|
||||||
[quickstart]: https://angular.io/start
|
|
||||||
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
|
|
||||||
[ng]: https://angular.io
|
|
31
README.md
31
README.md
@ -1,25 +1,26 @@
|
|||||||
# Angular en español
|
[](https://circleci.com/gh/angular/workflows/angular/tree/master)
|
||||||
|
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
[](https://www.npmjs.com/@angular/core)
|
||||||
|
|
||||||
Angular es una plataforma de desarrollo para construir aplicaciones web y móviles que usa
|
|
||||||
TypeScript/JavaScript y otros lenguajes de programación.
|
|
||||||
|
|
||||||
## ¿Quieres ayudar?
|
# Angular
|
||||||
|
|
||||||
### Documentación en español
|
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages.
|
||||||
|
|
||||||
¿Quieres mejorar la documentación? ¡Excelente! Lee nuestras pautas para
|
## Quickstart
|
||||||
[colaborar](CONTRIBUTING.md) y luego revisa algunos de nuestras
|
|
||||||
[issues](https://github.com/angular-hispano/angular/issues).
|
|
||||||
|
|
||||||
### El framework
|
[Get started in 5 minutes][quickstart].
|
||||||
|
|
||||||
La colaboración para corregir errores y agregar funciones en el framework debe realizarse en inglés a través
|
## Changelog
|
||||||
del repositorio [angular/angular](https://github.com/angular/angular) upstream.
|
|
||||||
|
|
||||||
## Guía rápida
|
[Learn about the latest improvements][changelog].
|
||||||
|
|
||||||
[Comienza a usarlo en 5 minutos](https://docs.angular.lat/start).
|
## Want to help?
|
||||||
|
|
||||||
## Registro de cambios (Changelog)
|
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our
|
||||||
|
guidelines for [contributing][contributing] and then check out one of our issues in the [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help).
|
||||||
|
|
||||||
[Últimas mejoras realizadas](CHANGELOG.md).
|
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
||||||
|
[quickstart]: https://angular.io/start
|
||||||
|
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
|
||||||
|
[ng]: https://angular.io
|
||||||
|
167
aio/README.md
167
aio/README.md
@ -1,131 +1,140 @@
|
|||||||
# Proyecto de documentación Angular (https://docs.angular.lat)
|
# Angular documentation project (https://angular.io)
|
||||||
|
|
||||||
Todo en esta carpeta es parte del proyecto de documentación. Esto incluye:
|
Everything in this folder is part of the documentation project. This includes
|
||||||
|
|
||||||
* El sitio web para mostrar la documentación
|
* the web site for displaying the documentation
|
||||||
* La configuración de dgeni para convertir los archivos de origen a archivos renderizados que se pueden vizualizar en el sitio web.
|
* the dgeni configuration for converting source files to rendered files that can be viewed in the web site.
|
||||||
* Las herramientas para establecer ejemplos para el desarrollo; y generar archivos en tiempo real y archivos zip desde los ejemplos.
|
* the tooling for setting up examples for development; and generating live-example and zip files from the examples.
|
||||||
|
|
||||||
## Tareas de desarrollador
|
## Developer tasks
|
||||||
|
|
||||||
Nosotros usamos [Yarn](https://yarnpkg.com) para gestionar las dependencias y crear tareas de compilación.
|
We use [Yarn](https://yarnpkg.com) to manage the dependencies and to run build tasks.
|
||||||
Debes ejecutar todas estas tareas desde la carpeta `angular/aio`.
|
You should run all these tasks from the `angular/aio` folder.
|
||||||
Aquí están las tareas más importantes que podrías necesitar usar:
|
Here are the most important tasks you might need to use:
|
||||||
|
|
||||||
* `yarn` - instalar todas las dependencias.
|
* `yarn` - install all the dependencies.
|
||||||
* `yarn setup` - instalar todas las dependencias, boilerplate, stackblitz, zips y ejecuta dgeni en los documentos.
|
* `yarn setup` - install all the dependencies, boilerplate, stackblitz, zips and run dgeni on the docs.
|
||||||
* `yarn setup-local` - igual que `setup`, pero crea los paquetes de Angular a partir del código y usa estas versiones construidas localmente (en lugar de las recuperadas desde npm) para aio y ejemplos de documentos boilerplate.
|
* `yarn setup-local` - same as `setup`, but build the Angular packages from the source code and use these locally built versions (instead of the ones fetched from npm) for aio and docs examples boilerplate.
|
||||||
|
|
||||||
* `yarn build` - crear una compilación de producción de la aplicación (después de instalar dependencias, boilerplate, etc).
|
* `yarn build` - create a production build of the application (after installing dependencies, boilerplate, etc).
|
||||||
* `yarn build-local` - igual que `build`, pero usa `setup-local` en lugar de `setup`.
|
* `yarn build-local` - same as `build`, but use `setup-local` instead of `setup`.
|
||||||
* `yarn build-local-with-viewengine` - igual que `build-local`, pero además también enciende el modo `ViewEngine` (pre-Ivy) en aio.
|
* `yarn build-local-with-viewengine` - same as `build-local`, but in addition also turns on `ViewEngine` (pre-Ivy) mode in aio.
|
||||||
(Nota: Encender el modo `ViewEngine` en ejemplos de documentos, ver `yarn boilerplate:add:viewengine` abajo.)
|
(Note: To turn on `ViewEngine` mode in docs examples, see `yarn boilerplate:add:viewengine` below.)
|
||||||
|
|
||||||
* `yarn start` - ejecutar un servidor web de desarrollo que observa los archivos; luego crea el doc-viewer y vuelve a cargar la página, según sea necesario.
|
* `yarn start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary.
|
||||||
* `yarn serve-and-sync` - ejecutar ambos, el `docs-watch` y `start` en la misma consola.
|
* `yarn serve-and-sync` - run both the `docs-watch` and `start` in the same console.
|
||||||
* `yarn lint` - comprobar que el código del doc-viewer sigue nuestras reglas de estilo.
|
* `yarn lint` - check that the doc-viewer code follows our style rules.
|
||||||
* `yarn test` - observar todos los archivos de origen, para el doc-viewer, y ejecuta todas las pruebas unitarias cuando haya algún cambio.
|
* `yarn test` - watch all the source files, for the doc-viewer, and run all the unit tests when any change.
|
||||||
* `yarn test --watch=false` -ejecutar todas las pruebas unitarias una sola vez.
|
* `yarn test --watch=false` - run all the unit tests once.
|
||||||
* `yarn e2e` - ejecutar todas las pruebas de e2e para el doc-viewer.
|
* `yarn e2e` - run all the e2e tests for the doc-viewer.
|
||||||
|
|
||||||
* `yarn docs` - generar toda la documentación desde los archivos fuente.
|
* `yarn docs` - generate all the docs from the source files.
|
||||||
* `yarn docs-watch` - observar el código Angular, los archivos de documentación y ejecutar un 'doc-gen' en corto circuito para los documentos que fueron cambiados.
|
* `yarn docs-watch` - watch the Angular source and the docs files and run a short-circuited doc-gen for the docs that changed.
|
||||||
* `yarn docs-lint` - comprobar que el código del documento generado sigue nuestras reglas de estilo.
|
* `yarn docs-lint` - check that the doc gen code follows our style rules.
|
||||||
* `yarn docs-test` - ejecutar las pruebas unitarias para el código de generación de doc.
|
* `yarn docs-test` - run the unit tests for the doc generation code.
|
||||||
|
|
||||||
* `yarn boilerplate:add` - generar todo el código boilerplate para los ejemplos, para que puedan ejecutarse localmente.
|
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally.
|
||||||
* `yarn boilerplate:add:viewengine` - igual que `boilerplate:add` pero también enciende el modo `ViewEngine` (pre-Ivy).
|
* `yarn boilerplate:add:viewengine` - same as `boilerplate:add` but also turns on `ViewEngine` (pre-Ivy) mode.
|
||||||
|
|
||||||
* `yarn boilerplate:remove` - eliminar todo el código boilerplate que fue añadido a través`yarn boilerplate:add`.
|
* `yarn boilerplate:remove` - remove all the boilerplate code that was added via `yarn boilerplate:add`.
|
||||||
* `yarn generate-stackblitz` - generar los archivos stackblitz que están usados por la etiqueta `live-example` en documentos.
|
* `yarn generate-stackblitz` - generate the stackblitz files that are used by the `live-example` tags in the docs.
|
||||||
* `yarn generate-zips` - generar los archivos zip desde los ejemplos. Zip está disponible a través de la etiqueta `live-example` en los documentos.
|
* `yarn generate-zips` - generate the zip files from the examples. Zip available via the `live-example` tags in the docs.
|
||||||
|
|
||||||
* `yarn example-e2e` - ejecutar todas las pruebas e2e para ejemplos. Opciones disponibles:
|
* `yarn example-e2e` - run all e2e tests for examples. Available options:
|
||||||
- `--setup`: generar boilerplate, forzar la actualización del controlador web y otras configuraciones, luego ejecutar las pruebas.
|
- `--setup`: generate boilerplate, force webdriver update & other setup, then run tests.
|
||||||
- `--local`: ejecutar pruebas e2e con la versión local de Angular contenida en la carpeta "dist".
|
- `--local`: run e2e tests with the local version of Angular contained in the "dist" folder.
|
||||||
_Requiere `--setup` para que surta efecto._
|
_Requires `--setup` in order to take effect._
|
||||||
- `--viewengine`: ejecutar pruebas e2e en modo `ViewEngine` (pre-Ivy).
|
- `--viewengine`: run e2e tests in `ViewEngine` (pre-Ivy) mode.
|
||||||
- `--filter=foo`: limitar pruebas e2e a las que contienen la palabra "foo".
|
- `--filter=foo`: limit e2e tests to those containing the word "foo".
|
||||||
|
|
||||||
> **Nota para usuarios Windows**
|
> **Note for Windows users**
|
||||||
>
|
>
|
||||||
> Configurar los ejemplos implica crear algunos [enlaces simbólicos](https://es.wikipedia.org/wiki/Enlace_simb%C3%B3lico) (ver [Aquí](./tools/examples/README.md#symlinked-node_modules) para más detalles). En Windows, esto requiere tener [Habilitado el Modo de desarrollador ](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10) (compatible con Windows 10 o más reciente) o ejecutar los comandos de configuración cómo administrador.
|
> Setting up the examples involves creating some [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link) (see [here](./tools/examples/README.md#symlinked-node_modules) for details). On Windows, this requires to either have [Developer Mode enabled](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10) (supported on Windows 10 or newer) or run the setup commands as administrator.
|
||||||
>
|
>
|
||||||
> Los comandos afectados son:
|
> The affected commands are:
|
||||||
> - `yarn setup` / `yarn setup-*`
|
> - `yarn setup` / `yarn setup-*`
|
||||||
> - `yarn build` / `yarn build-*`
|
> - `yarn build` / `yarn build-*`
|
||||||
> - `yarn boilerplate:add`
|
> - `yarn boilerplate:add`
|
||||||
> - `yarn example-e2e --setup`
|
> - `yarn example-e2e --setup`
|
||||||
|
|
||||||
## Usando ServiceWorker localmente
|
## Using ServiceWorker locally
|
||||||
|
|
||||||
Ejecutando `yarn start` (incluso cuando se apunta explícitamente al modo de producción) no configura el
|
Running `yarn start` (even when explicitly targeting production mode) does not set up the
|
||||||
ServiceWorker. Si quieres probar el ServiceWorker localmente, puedes usar `yarn build` y luego
|
ServiceWorker. If you want to test the ServiceWorker locally, you can use `yarn build` and then
|
||||||
ejecutar los archivos en `dist/` con `yarn http-server dist -p 4200`.
|
serve the files in `dist/` with `yarn http-server dist -p 4200`.
|
||||||
|
|
||||||
|
|
||||||
## Guía de autoría
|
## Guide to authoring
|
||||||
Existen dos tipos de contenido en la documentación:
|
|
||||||
|
|
||||||
* **Documentación de API**: descripciones de los módulos, clases, interfaces, decoradores, etc que son parte de la plataforma Angular.
|
There are two types of content in the documentation:
|
||||||
La documentacion de API está generada directamente desde el código fuente.
|
|
||||||
El código fuente está contenido en archivos TypeScript , almacenados en la carpeta `angular/packages`.
|
|
||||||
Cada elemento de la API puede tener un comentario anterior, el cual contiene etiquetas y contenido de estilos JSDoc.
|
|
||||||
El contenido está escrito en markdown.
|
|
||||||
|
|
||||||
* **Otro contenido**: guias, tutoriales, y otro material de marketing.
|
* **API docs**: descriptions of the modules, classes, interfaces, decorators, etc that make up the Angular platform.
|
||||||
Todos los demás contenidos se escriben utilizando markdown en archivos de texto, ubicados en la carpeta `angular/aio/content`.
|
API docs are generated directly from the source code.
|
||||||
Más específicamente, hay subcarpetas que contienen tipos particulares de contenido: guías, tutoriales y marketing.
|
The source code is contained in TypeScript files, located in the `angular/packages` folder.
|
||||||
|
Each API item may have a preceding comment, which contains JSDoc style tags and content.
|
||||||
|
The content is written in markdown.
|
||||||
|
|
||||||
* **Ejempos de código**: los ejemplos de código deben ser comprobables para garantizar su precisión.
|
* **Other content**: guides, tutorials, and other marketing material.
|
||||||
Además, nuestros ejemplos tienen un aspecto específico y permiten al usuario copiar el código fuente. Para mayor
|
All other content is written using markdown in text files, located in the `angular/aio/content` folder.
|
||||||
ejemplos se representan en una interfaz con pestañas (e.g. template, HTML, y TypeScript en pestañas separadas). Adicionalmente, algunos son ejemplos en acción, que proporcionan enlaces donde se puede editar el código, ejecutar, y/o descargar. Para obtener más detalles sobre cómo trabajar con ejemplos de código, lea los [fragmentos de código](https://docs.angular.lat/guide/docs-style-guide#code-snippets), [código fuente de marcado ](https://docs.angular.lat/guide/docs-style-guide#source-code-markup), y [ ejemplos en acción ](https://docs.angular.lat/guide/docs-style-guide#live-examples) paginas de los [ autores de guías de estilo ](https://docs.angular.lat/guide/docs-style-guide).
|
More specifically, there are sub-folders that contain particular types of content: guides, tutorial and marketing.
|
||||||
|
|
||||||
Usamos la herramienta [dgeni](https://github.com/angular/dgeni) para convertir estos archivos en docs que se pueden ver en el doc-viewer.
|
* **Code examples**: code examples need to be testable to ensure their accuracy.
|
||||||
Las [guías de estilo para Autores](https://docs.angular.lat/guide/docs-style-guide) prescriben pautas para
|
Also, our examples have a specific look and feel and allow the user to copy the source code. For larger
|
||||||
escribir páginas de guía, explica cómo usar la documentación de clases y componentes, y cómo marcar el código fuente para producir fragmentos de código.
|
examples they are rendered in a tabbed interface (e.g. template, HTML, and TypeScript on separate
|
||||||
|
tabs). Additionally, some are live examples, which provide links where the code can be edited, executed, and/or downloaded. For details on working with code examples, please read the [Code snippets](https://angular.io/guide/docs-style-guide#code-snippets), [Source code markup](https://angular.io/guide/docs-style-guide#source-code-markup), and [Live examples](https://angular.io/guide/docs-style-guide#live-examples) pages of the [Authors Style Guide](https://angular.io/guide/docs-style-guide).
|
||||||
|
|
||||||
### Generando documentos completos
|
We use the [dgeni](https://github.com/angular/dgeni) tool to convert these files into docs that can be viewed in the doc-viewer.
|
||||||
|
|
||||||
La principal tarea para generar los documentos es `yarn docs`. Esto procesará todos los archivos fuente (API y otros), extrayendo la documentación y generando archivos JSON que pueden ser consumidos por el doc-viewer.
|
The [Authors Style Guide](https://angular.io/guide/docs-style-guide) prescribes guidelines for
|
||||||
|
writing guide pages, explains how to use the documentation classes and components, and how to markup sample source code to produce code snippets.
|
||||||
|
|
||||||
### Generación parcial de doc para editores
|
### Generating the complete docs
|
||||||
|
|
||||||
La generación completa de documentos puede llevar hasta un minuto. Eso es demasiado lento para la creación y edición eficiente de documentos.
|
The main task for generating the docs is `yarn docs`. This will process all the source files (API and other),
|
||||||
|
extracting the documentation and generating JSON files that can be consumed by the doc-viewer.
|
||||||
|
|
||||||
Puedes ealizar pequeños cambios en un editor inteligente que muestre un markdown con formato:
|
### Partial doc generation for editors
|
||||||
>En VS Code, _Cmd-K, V_ abre la vista previa de markdown en el panel lateral; _Cmd-B_ alterna la barra izquierda
|
|
||||||
|
|
||||||
Puedes también mirar los cambios que se muestran correctamente en el doc-viewer
|
Full doc generation can take up to one minute. That's too slow for efficient document creation and editing.
|
||||||
con un tiempo de ciclo rápido de edición / visualización.
|
|
||||||
|
|
||||||
Para este propósito, usa la tarea `yarn docs-watch`, que observa los cambios en los archivos de origen y solo vuelve a procesar los archivos necesarios para generar los documentos relacionados con el archivo que ha cambiado.
|
You can make small changes in a smart editor that displays formatted markdown:
|
||||||
Dado que esta tarea tiene accesos directos, es mucho más rápido (a menudo menos de 1 segundo) pero no producirá contenido de fidelidad completa. Por ejemplo, los enlaces a otros documentoss y ejemplos de código pueden no mostrarse correctamente. Esto se nota especialmente en los enlaces a otros documentos y en los ejemplos incrustados, que no siempre se representan correctamente.
|
>In VS Code, _Cmd-K, V_ opens markdown preview in side pane; _Cmd-B_ toggles left sidebar
|
||||||
|
|
||||||
La configuración general es la siguiente:
|
You also want to see those changes displayed properly in the doc viewer
|
||||||
|
with a quick, edit/view cycle time.
|
||||||
|
|
||||||
* Abrir una terminal, estar seguro que las dependencias están instaladas; ejecutar una generación inicial del doc; luego iniciar el doc-viewer:
|
For this purpose, use the `yarn docs-watch` task, which watches for changes to source files and only
|
||||||
|
re-processes the files necessary to generate the docs that are related to the file that has changed.
|
||||||
|
Since this task takes shortcuts, it is much faster (often less than 1 second) but it won't produce full
|
||||||
|
fidelity content. For example, links to other docs and code examples may not render correctly. This is
|
||||||
|
most particularly noticed in links to other docs and in the embedded examples, which may not always render
|
||||||
|
correctly.
|
||||||
|
|
||||||
|
The general setup is as follows:
|
||||||
|
|
||||||
|
* Open a terminal, ensure the dependencies are installed; run an initial doc generation; then start the doc-viewer:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn setup
|
yarn setup
|
||||||
yarn start
|
yarn start
|
||||||
```
|
```
|
||||||
|
|
||||||
* Abrir una segunda terminal e iniciar el observador de documentos.
|
* Open a second terminal and start watching the docs
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn docs-watch
|
yarn docs-watch
|
||||||
```
|
```
|
||||||
|
|
||||||
>Alternativamente, prueba el comando fusionado `serve-and-sync` que crea, observa y ejecuta en la misma ventana de la terminal
|
>Alternatively, try the consolidated `serve-and-sync` command that builds, watches and serves in the same terminal window
|
||||||
```bash
|
```bash
|
||||||
yarn serve-and-sync
|
yarn serve-and-sync
|
||||||
```
|
```
|
||||||
|
|
||||||
* Abre un navegador con la siguiente dirección https://localhost:4200/ y navega hasta el documento en el que quieras trabajar.
|
* Open a browser at https://localhost:4200/ and navigate to the document on which you want to work.
|
||||||
Puedes automáticamente abrir el navegador utilizando `yarn start -o` en la primera terminal.
|
You can automatically open the browser by using `yarn start -o` in the first terminal.
|
||||||
|
|
||||||
* Realiza cambios en la página de documentación asociada o en los archivos de ejemplo. Cada vez que un archivo es guardado, la documentación se regenerará, la aplicación se reconstruirá y la página se volverá a cargar.
|
* Make changes to the page's associated doc or example files. Every time a file is saved, the doc will
|
||||||
|
be regenerated, the app will rebuild and the page will reload.
|
||||||
|
|
||||||
*Si recibes un error de compilación acerca de los ejemplos o cualquier otro error, asegúrate de consultar las
|
* If you get a build error complaining about examples or any other odd behavior, be sure to consult
|
||||||
[guías de estilo para Autores](https://angular.io/guide/docs-style-guide) para más información.
|
the [Authors Style Guide](https://angular.io/guide/docs-style-guide).
|
||||||
|
1
aio/content/examples/.gitignore
vendored
1
aio/content/examples/.gitignore
vendored
@ -18,7 +18,6 @@
|
|||||||
**/src/karma.conf.js
|
**/src/karma.conf.js
|
||||||
**/.angular-cli.json
|
**/.angular-cli.json
|
||||||
**/.editorconfig
|
**/.editorconfig
|
||||||
**/.gitignore
|
|
||||||
**/angular.json
|
**/angular.json
|
||||||
**/tsconfig.json
|
**/tsconfig.json
|
||||||
**/bs-config.e2e.json
|
**/bs-config.e2e.json
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Accessibility example e2e tests', () => {
|
describe('Accessibility example e2e tests', () => {
|
||||||
@ -6,11 +8,11 @@ describe('Accessibility example e2e tests', () => {
|
|||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display Accessibility Example', () => {
|
it('should display Accessibility Example', function () {
|
||||||
expect(element(by.css('h1')).getText()).toEqual('Accessibility Example');
|
expect(element(by.css('h1')).getText()).toEqual('Accessibility Example');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should take a number and change progressbar width', () => {
|
it('should take a number and change progressbar width', function () {
|
||||||
element(by.css('input')).sendKeys('16');
|
element(by.css('input')).sendKeys('16');
|
||||||
expect(element(by.css('input')).getAttribute('value')).toEqual('016');
|
expect(element(by.css('input')).getAttribute('value')).toEqual('016');
|
||||||
expect(element(by.css('app-example-progressbar div')).getCssValue('width')).toBe('48px');
|
expect(element(by.css('app-example-progressbar div')).getCssValue('width')).toBe('48px');
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// tslint:disable: no-host-metadata-property
|
|
||||||
// #docregion progressbar-component
|
// #docregion progressbar-component
|
||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('AngularJS to Angular Quick Reference Tests', () => {
|
describe('AngularJS to Angular Quick Reference Tests', function () {
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display no poster images after bootstrap', () => {
|
it('should display no poster images after bootstrap', function () {
|
||||||
testImagesAreDisplayed(false);
|
testImagesAreDisplayed(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display proper movie data', () => {
|
it('should display proper movie data', function () {
|
||||||
// We check only a few samples
|
// We check only a few samples
|
||||||
const expectedSamples: any[] = [
|
let expectedSamples: any[] = [
|
||||||
{row: 0, column: 0, element: 'img', attr: 'src', value: 'images/hero.png', contains: true},
|
{row: 0, column: 0, element: 'img', attr: 'src', value: 'images/hero.png', contains: true},
|
||||||
{row: 0, column: 2, value: 'Celeritas'},
|
{row: 0, column: 2, value: 'Celeritas'},
|
||||||
{row: 1, column: 3, matches: /Dec 1[678], 2015/}, // absorb timezone dif; we care about date format
|
{row: 1, column: 3, matches: /Dec 1[678], 2015/}, // absorb timezone dif; we care about date format
|
||||||
@ -23,17 +25,18 @@ describe('AngularJS to Angular Quick Reference Tests', () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Go through the samples
|
// Go through the samples
|
||||||
const movieRows = getMovieRows();
|
let movieRows = getMovieRows();
|
||||||
for (const sample of expectedSamples) {
|
for (let i = 0; i < expectedSamples.length; i++) {
|
||||||
const tableCell = movieRows.get(sample.row)
|
let sample = expectedSamples[i];
|
||||||
|
let tableCell = movieRows.get(sample.row)
|
||||||
.all(by.tagName('td')).get(sample.column);
|
.all(by.tagName('td')).get(sample.column);
|
||||||
// Check the cell or its nested element
|
// Check the cell or its nested element
|
||||||
const elementToCheck = sample.element
|
let elementToCheck = sample.element
|
||||||
? tableCell.element(by.tagName(sample.element))
|
? tableCell.element(by.tagName(sample.element))
|
||||||
: tableCell;
|
: tableCell;
|
||||||
|
|
||||||
// Check element attribute or text
|
// Check element attribute or text
|
||||||
const valueToCheck = sample.attr
|
let valueToCheck = sample.attr
|
||||||
? elementToCheck.getAttribute(sample.attr)
|
? elementToCheck.getAttribute(sample.attr)
|
||||||
: elementToCheck.getText();
|
: elementToCheck.getText();
|
||||||
|
|
||||||
@ -48,42 +51,42 @@ describe('AngularJS to Angular Quick Reference Tests', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display images after Show Poster', () => {
|
it('should display images after Show Poster', function () {
|
||||||
testPosterButtonClick('Show Poster', true);
|
testPosterButtonClick('Show Poster', true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should hide images after Hide Poster', () => {
|
it('should hide images after Hide Poster', function () {
|
||||||
testPosterButtonClick('Hide Poster', false);
|
testPosterButtonClick('Hide Poster', false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display no movie when no favorite hero is specified', () => {
|
it('should display no movie when no favorite hero is specified', function () {
|
||||||
testFavoriteHero(null, 'Please enter your favorite hero.');
|
testFavoriteHero(null, 'Please enter your favorite hero.');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display no movie for Magneta', () => {
|
it('should display no movie for Magneta', function () {
|
||||||
testFavoriteHero('Magneta', 'No movie, sorry!');
|
testFavoriteHero('Magneta', 'No movie, sorry!');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display a movie for Dr Nice', () => {
|
it('should display a movie for Dr Nice', function () {
|
||||||
testFavoriteHero('Dr Nice', 'Excellent choice!');
|
testFavoriteHero('Dr Nice', 'Excellent choice!');
|
||||||
});
|
});
|
||||||
|
|
||||||
function testImagesAreDisplayed(isDisplayed: boolean) {
|
function testImagesAreDisplayed(isDisplayed: boolean) {
|
||||||
const expectedMovieCount = 3;
|
let expectedMovieCount = 3;
|
||||||
|
|
||||||
const movieRows = getMovieRows();
|
let movieRows = getMovieRows();
|
||||||
expect(movieRows.count()).toBe(expectedMovieCount);
|
expect(movieRows.count()).toBe(expectedMovieCount);
|
||||||
for (let i = 0; i < expectedMovieCount; i++) {
|
for (let i = 0; i < expectedMovieCount; i++) {
|
||||||
const movieImage = movieRows.get(i).element(by.css('td > img'));
|
let movieImage = movieRows.get(i).element(by.css('td > img'));
|
||||||
expect(movieImage.isDisplayed()).toBe(isDisplayed);
|
expect(movieImage.isDisplayed()).toBe(isDisplayed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPosterButtonClick(expectedButtonText: string, isDisplayed: boolean) {
|
function testPosterButtonClick(expectedButtonText: string, isDisplayed: boolean) {
|
||||||
const posterButton = element(by.css('app-movie-list tr > th > button'));
|
let posterButton = element(by.css('app-movie-list tr > th > button'));
|
||||||
expect(posterButton.getText()).toBe(expectedButtonText);
|
expect(posterButton.getText()).toBe(expectedButtonText);
|
||||||
|
|
||||||
posterButton.click().then(() => {
|
posterButton.click().then(function () {
|
||||||
testImagesAreDisplayed(isDisplayed);
|
testImagesAreDisplayed(isDisplayed);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -93,12 +96,12 @@ describe('AngularJS to Angular Quick Reference Tests', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function testFavoriteHero(heroName: string, expectedLabel: string) {
|
function testFavoriteHero(heroName: string, expectedLabel: string) {
|
||||||
const movieListComp = element(by.tagName('app-movie-list'));
|
let movieListComp = element(by.tagName('app-movie-list'));
|
||||||
const heroInput = movieListComp.element(by.tagName('input'));
|
let heroInput = movieListComp.element(by.tagName('input'));
|
||||||
const favoriteHeroLabel = movieListComp.element(by.tagName('h3'));
|
let favoriteHeroLabel = movieListComp.element(by.tagName('h3'));
|
||||||
const resultLabel = movieListComp.element(by.css('span > p'));
|
let resultLabel = movieListComp.element(by.css('span > p'));
|
||||||
|
|
||||||
heroInput.clear().then(() => {
|
heroInput.clear().then(function () {
|
||||||
heroInput.sendKeys(heroName || '');
|
heroInput.sendKeys(heroName || '');
|
||||||
expect(resultLabel.getText()).toBe(expectedLabel);
|
expect(resultLabel.getText()).toBe(expectedLabel);
|
||||||
if (heroName) {
|
if (heroName) {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, ExpectedConditions as EC } from 'protractor';
|
import { browser, ExpectedConditions as EC } from 'protractor';
|
||||||
import { logging } from 'selenium-webdriver';
|
import { logging } from 'selenium-webdriver';
|
||||||
import * as openClose from './open-close.po';
|
import * as openClose from './open-close.po';
|
||||||
|
@ -34,7 +34,7 @@ export class AppComponent {
|
|||||||
|
|
||||||
// #docregion prepare-router-outlet
|
// #docregion prepare-router-outlet
|
||||||
prepareRoute(outlet: RouterOutlet) {
|
prepareRoute(outlet: RouterOutlet) {
|
||||||
return outlet && outlet.activatedRouteData && outlet.activatedRouteData.animation;
|
return outlet && outlet.activatedRouteData && outlet.activatedRouteData['animation'];
|
||||||
}
|
}
|
||||||
|
|
||||||
// #enddocregion prepare-router-outlet
|
// #enddocregion prepare-router-outlet
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
// tslint:disable: variable-name
|
|
||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
|
||||||
import { Component, HostBinding, OnInit } from '@angular/core';
|
import { Component, HostBinding, OnInit } from '@angular/core';
|
||||||
import { trigger, transition, animate, style, query, stagger } from '@angular/animations';
|
import { trigger, transition, animate, style, query, stagger } from '@angular/animations';
|
||||||
import { HEROES } from './mock-heroes';
|
import { HEROES } from './mock-heroes';
|
||||||
@ -54,11 +52,13 @@ export class HeroListPageComponent implements OnInit {
|
|||||||
@HostBinding('@pageAnimations')
|
@HostBinding('@pageAnimations')
|
||||||
public animatePage = true;
|
public animatePage = true;
|
||||||
|
|
||||||
|
_heroes = [];
|
||||||
// #docregion filter-animations
|
// #docregion filter-animations
|
||||||
heroTotal = -1;
|
heroTotal = -1;
|
||||||
// #enddocregion filter-animations
|
// #enddocregion filter-animations
|
||||||
get heroes() { return this._heroes; }
|
get heroes() {
|
||||||
private _heroes = [];
|
return this._heroes;
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this._heroes = HEROES;
|
this._heroes = HEROES;
|
||||||
|
@ -8,7 +8,8 @@ import { trigger, transition, state, animate, style, AnimationEvent } from '@ang
|
|||||||
// #docregion trigger, trigger-wildcard1, trigger-transition
|
// #docregion trigger, trigger-wildcard1, trigger-transition
|
||||||
animations: [
|
animations: [
|
||||||
trigger('openClose', [
|
trigger('openClose', [
|
||||||
// #docregion state1
|
// #enddocregion events1
|
||||||
|
// #docregion state1, events1
|
||||||
// ...
|
// ...
|
||||||
// #enddocregion events1
|
// #enddocregion events1
|
||||||
state('open', style({
|
state('open', style({
|
||||||
@ -33,7 +34,8 @@ import { trigger, transition, state, animate, style, AnimationEvent } from '@ang
|
|||||||
transition('closed => open', [
|
transition('closed => open', [
|
||||||
animate('0.5s')
|
animate('0.5s')
|
||||||
]),
|
]),
|
||||||
// #enddocregion transition2, trigger, component
|
// #enddocregion trigger, component
|
||||||
|
// #enddocregion transition2
|
||||||
// #docregion trigger-wildcard1
|
// #docregion trigger-wildcard1
|
||||||
transition('* => closed', [
|
transition('* => closed', [
|
||||||
animate('1s')
|
animate('1s')
|
||||||
@ -68,9 +70,7 @@ import { trigger, transition, state, animate, style, AnimationEvent } from '@ang
|
|||||||
})
|
})
|
||||||
// #docregion events
|
// #docregion events
|
||||||
export class OpenCloseComponent {
|
export class OpenCloseComponent {
|
||||||
// #enddocregion events1, events, component
|
// #enddocregion events1, events
|
||||||
@Input() logging = false;
|
|
||||||
// #docregion component
|
|
||||||
isOpen = true;
|
isOpen = true;
|
||||||
|
|
||||||
toggle() {
|
toggle() {
|
||||||
@ -78,6 +78,7 @@ export class OpenCloseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// #enddocregion component
|
// #enddocregion component
|
||||||
|
@Input() logging = false;
|
||||||
// #docregion events1, events
|
// #docregion events1, events
|
||||||
onAnimationEvent ( event: AnimationEvent ) {
|
onAnimationEvent ( event: AnimationEvent ) {
|
||||||
// #enddocregion events1, events
|
// #enddocregion events1, events
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { protractor, browser, element, by, ElementFinder } from 'protractor';
|
import { protractor, browser, element, by, ElementFinder } from 'protractor';
|
||||||
|
|
||||||
const nameSuffix = 'X';
|
const nameSuffix = 'X';
|
||||||
@ -19,7 +21,7 @@ describe('Architecture', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it(`has h2 '${expectedH2}'`, () => {
|
it(`has h2 '${expectedH2}'`, () => {
|
||||||
const h2 = element.all(by.css('h2')).map((elt: any) => elt.getText());
|
let h2 = element.all(by.css('h2')).map((elt: any) => elt.getText());
|
||||||
expect(h2).toEqual(expectedH2);
|
expect(h2).toEqual(expectedH2);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -32,42 +34,42 @@ function heroTests() {
|
|||||||
const targetHero: Hero = { id: 2, name: 'Dr Nice' };
|
const targetHero: Hero = { id: 2, name: 'Dr Nice' };
|
||||||
|
|
||||||
it('has the right number of heroes', () => {
|
it('has the right number of heroes', () => {
|
||||||
const page = getPageElts();
|
let page = getPageElts();
|
||||||
expect(page.heroes.count()).toEqual(3);
|
expect(page.heroes.count()).toEqual(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('has no hero details initially', () => {
|
it('has no hero details initially', function () {
|
||||||
const page = getPageElts();
|
let page = getPageElts();
|
||||||
expect(page.heroDetail.isPresent()).toBeFalsy('no hero detail');
|
expect(page.heroDetail.isPresent()).toBeFalsy('no hero detail');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows selected hero details', async () => {
|
it('shows selected hero details', async () => {
|
||||||
await element(by.cssContainingText('li', targetHero.name)).click();
|
await element(by.cssContainingText('li', targetHero.name)).click();
|
||||||
const page = getPageElts();
|
let page = getPageElts();
|
||||||
const hero = await heroFromDetail(page.heroDetail);
|
let hero = await heroFromDetail(page.heroDetail);
|
||||||
expect(hero.id).toEqual(targetHero.id);
|
expect(hero.id).toEqual(targetHero.id);
|
||||||
expect(hero.name).toEqual(targetHero.name);
|
expect(hero.name).toEqual(targetHero.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`shows updated hero name in details`, async () => {
|
it(`shows updated hero name in details`, async () => {
|
||||||
const input = element.all(by.css('input')).first();
|
let input = element.all(by.css('input')).first();
|
||||||
input.sendKeys(nameSuffix);
|
input.sendKeys(nameSuffix);
|
||||||
const page = getPageElts();
|
let page = getPageElts();
|
||||||
const hero = await heroFromDetail(page.heroDetail);
|
let hero = await heroFromDetail(page.heroDetail);
|
||||||
const newName = targetHero.name + nameSuffix;
|
let newName = targetHero.name + nameSuffix;
|
||||||
expect(hero.id).toEqual(targetHero.id);
|
expect(hero.id).toEqual(targetHero.id);
|
||||||
expect(hero.name).toEqual(newName);
|
expect(hero.name).toEqual(newName);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function salesTaxTests() {
|
function salesTaxTests() {
|
||||||
it('has no sales tax initially', () => {
|
it('has no sales tax initially', function () {
|
||||||
const page = getPageElts();
|
let page = getPageElts();
|
||||||
expect(page.salesTaxDetail.isPresent()).toBeFalsy('no sales tax info');
|
expect(page.salesTaxDetail.isPresent()).toBeFalsy('no sales tax info');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows sales tax', async () => {
|
it('shows sales tax', async function () {
|
||||||
const page = getPageElts();
|
let page = getPageElts();
|
||||||
page.salesTaxAmountInput.sendKeys('10', protractor.Key.ENTER);
|
page.salesTaxAmountInput.sendKeys('10', protractor.Key.ENTER);
|
||||||
expect(page.salesTaxDetail.getText()).toEqual('The sales tax is $1.00');
|
expect(page.salesTaxDetail.getText()).toEqual('The sales tax is $1.00');
|
||||||
});
|
});
|
||||||
@ -86,11 +88,13 @@ function getPageElts() {
|
|||||||
|
|
||||||
async function heroFromDetail(detail: ElementFinder): Promise<Hero> {
|
async function heroFromDetail(detail: ElementFinder): Promise<Hero> {
|
||||||
// Get hero id from the first <div>
|
// Get hero id from the first <div>
|
||||||
const id = await detail.all(by.css('div')).first().getText();
|
// let _id = await detail.all(by.css('div')).first().getText();
|
||||||
|
let _id = await detail.all(by.css('div')).first().getText();
|
||||||
// Get name from the h2
|
// Get name from the h2
|
||||||
const name = await detail.element(by.css('h4')).getText();
|
// let _name = await detail.element(by.css('h4')).getText();
|
||||||
|
let _name = await detail.element(by.css('h4')).getText();
|
||||||
return {
|
return {
|
||||||
id: +id.substr(id.indexOf(' ') + 1),
|
id: +_id.substr(_id.indexOf(' ') + 1),
|
||||||
name: name.substr(0, name.lastIndexOf(' ')),
|
name: _name.substr(0, _name.lastIndexOf(' '))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ export class BackendService {
|
|||||||
// TODO: get from the database
|
// TODO: get from the database
|
||||||
return Promise.resolve<Hero[]>(HEROES);
|
return Promise.resolve<Hero[]>(HEROES);
|
||||||
}
|
}
|
||||||
const err = new Error('Cannot get object of this type');
|
let err = new Error('Cannot get object of this type');
|
||||||
this.logger.error(err);
|
this.logger.error(err);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ export class SalesTaxService {
|
|||||||
constructor(private rateService: TaxRateService) { }
|
constructor(private rateService: TaxRateService) { }
|
||||||
|
|
||||||
getVAT(value: string | number) {
|
getVAT(value: string | number) {
|
||||||
const amount = (typeof value === 'string') ?
|
let amount = (typeof value === 'string') ?
|
||||||
parseFloat(value) : value;
|
parseFloat(value) : value;
|
||||||
return (amount || 0) * this.rateService.getRate('VAT');
|
return (amount || 0) * this.rateService.getRate('VAT');
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,34 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Attribute binding example', () => {
|
describe('Attribute binding example', function () {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display Property Binding with Angular', () => {
|
it('should display Property Binding with Angular', function () {
|
||||||
expect(element(by.css('h1')).getText()).toEqual('Attribute, class, and style bindings');
|
expect(element(by.css('h1')).getText()).toEqual('Attribute, class, and style bindings');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display a table', () => {
|
it('should display a table', function() {
|
||||||
expect(element.all(by.css('table')).isPresent()).toBe(true);
|
expect(element.all(by.css('table')).isPresent()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display an Aria button', () => {
|
it('should display an Aria button', function () {
|
||||||
expect(element.all(by.css('button')).get(0).getText()).toBe('Go for it with Aria');
|
expect(element.all(by.css('button')).get(0).getText()).toBe('Go for it with Aria');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display a blue background on div', () => {
|
it('should display a blue background on div', function () {
|
||||||
expect(element.all(by.css('div')).get(1).getCssValue('background-color')).toEqual('rgba(25, 118, 210, 1)');
|
expect(element.all(by.css('div')).get(1).getCssValue('background-color')).toEqual('rgba(25, 118, 210, 1)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display a blue div with a red border', () => {
|
it('should display a blue div with a red border', function () {
|
||||||
expect(element.all(by.css('div')).get(1).getCssValue('border')).toEqual('2px solid rgb(212, 30, 46)');
|
expect(element.all(by.css('div')).get(1).getCssValue('border')).toEqual('2px solid rgb(212, 30, 46)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display a div with many classes', () => {
|
it('should display a div with many classes', function () {
|
||||||
expect(element.all(by.css('div')).get(1).getAttribute('class')).toContain('special');
|
expect(element.all(by.css('div')).get(1).getAttribute('class')).toContain('special');
|
||||||
expect(element.all(by.css('div')).get(1).getAttribute('class')).toContain('clearance');
|
expect(element.all(by.css('div')).get(1).getAttribute('class')).toContain('clearance');
|
||||||
});
|
});
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import { Component, HostBinding } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'comp-with-host-binding',
|
selector: 'comp-with-host-binding',
|
||||||
template: 'I am a component!',
|
template: 'I am a component!',
|
||||||
|
host: {
|
||||||
|
'[class.special]': 'isSpecial',
|
||||||
|
'[style.color]': 'color',
|
||||||
|
'[style.width]': 'width'
|
||||||
|
}
|
||||||
})
|
})
|
||||||
export class CompWithHostBindingComponent {
|
export class CompWithHostBindingComponent {
|
||||||
@HostBinding('class.special')
|
|
||||||
isSpecial = false;
|
isSpecial = false;
|
||||||
|
|
||||||
@HostBinding('style.color')
|
|
||||||
color = 'green';
|
color = 'green';
|
||||||
|
|
||||||
@HostBinding('style.width')
|
|
||||||
width = '200px';
|
width = '200px';
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Attribute directives', () => {
|
describe('Attribute directives', () => {
|
||||||
|
|
||||||
const title = 'My First Attribute Directive';
|
let _title = 'My First Attribute Directive';
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should display correct title: ${title}`, () => {
|
it(`should display correct title: ${_title}`, () => {
|
||||||
expect(element(by.css('h1')).getText()).toEqual(title);
|
expect(element(by.css('h1')).getText()).toEqual(_title);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to select green highlight', () => {
|
it('should be able to select green highlight', () => {
|
||||||
|
@ -3,55 +3,57 @@ import { logging } from 'selenium-webdriver';
|
|||||||
|
|
||||||
describe('Binding syntax e2e tests', () => {
|
describe('Binding syntax e2e tests', () => {
|
||||||
|
|
||||||
beforeEach(() => browser.get(''));
|
beforeEach(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// helper function used to test what's logged to the console
|
// helper function used to test what's logged to the console
|
||||||
async function logChecker(button, contents) {
|
async function logChecker(button, contents) {
|
||||||
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
||||||
const messages = logs.filter(({ message }) => message.indexOf(contents) !== -1 ? true : false);
|
const message = logs.filter(({ message }) => message.indexOf(contents) !== -1 ? true : false);
|
||||||
expect(messages.length).toBeGreaterThan(0);
|
expect(message.length).toBeGreaterThan(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
it('should display Binding syntax', () => {
|
it('should display Binding syntax', function () {
|
||||||
expect(element(by.css('h1')).getText()).toEqual('Binding syntax');
|
expect(element(by.css('h1')).getText()).toEqual('Binding syntax');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display Save button', () => {
|
it('should display Save button', function () {
|
||||||
expect(element.all(by.css('button')).get(0).getText()).toBe('Save');
|
expect(element.all(by.css('button')).get(0).getText()).toBe('Save');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display HTML attributes and DOM properties', () => {
|
it('should display HTML attributes and DOM properties', function () {
|
||||||
expect(element.all(by.css('h2')).get(1).getText()).toBe('HTML attributes and DOM properties');
|
expect(element.all(by.css('h2')).get(1).getText()).toBe('HTML attributes and DOM properties');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display 1. Use the inspector...', () => {
|
it('should display 1. Use the inspector...', function () {
|
||||||
expect(element.all(by.css('p')).get(0).getText()).toContain('1. Use the inspector');
|
expect(element.all(by.css('p')).get(0).getText()).toContain('1. Use the inspector');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display Disabled property vs. attribute', () => {
|
it('should display Disabled property vs. attribute', function () {
|
||||||
expect(element.all(by.css('h3')).get(0).getText()).toBe('Disabled property vs. attribute');
|
expect(element.all(by.css('h3')).get(0).getText()).toBe('Disabled property vs. attribute');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should log a message including Sarah', async () => {
|
it('should log a message including Sarah', async () => {
|
||||||
const attributeButton = element.all(by.css('button')).get(1);
|
let attributeButton = element.all(by.css('button')).get(1);
|
||||||
await attributeButton.click();
|
await attributeButton.click();
|
||||||
const contents = 'Sarah';
|
const contents = 'Sarah';
|
||||||
logChecker(attributeButton, contents);
|
logChecker(attributeButton, contents);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should log a message including Sarah for DOM property', async () => {
|
it('should log a message including Sarah for DOM property', async () => {
|
||||||
const DOMPropertyButton = element.all(by.css('button')).get(2);
|
let DOMPropertyButton = element.all(by.css('button')).get(2);
|
||||||
await DOMPropertyButton.click();
|
await DOMPropertyButton.click();
|
||||||
const contents = 'Sarah';
|
const contents = 'Sarah';
|
||||||
logChecker(DOMPropertyButton, contents);
|
logChecker(DOMPropertyButton, contents);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should log a message including Sally for DOM property', async () => {
|
it('should log a message including Sally for DOM property', async () => {
|
||||||
const DOMPropertyButton = element.all(by.css('button')).get(2);
|
let DOMPropertyButton = element.all(by.css('button')).get(2);
|
||||||
const input = element(by.css('input'));
|
let input = element(by.css('input'));
|
||||||
input.sendKeys('Sally');
|
input.sendKeys('Sally');
|
||||||
await DOMPropertyButton.click();
|
await DOMPropertyButton.click();
|
||||||
const contents = 'Sally';
|
const contents = 'Sally';
|
||||||
@ -59,14 +61,14 @@ describe('Binding syntax e2e tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should log a message that Test Button works', async () => {
|
it('should log a message that Test Button works', async () => {
|
||||||
const testButton = element.all(by.css('button')).get(3);
|
let testButton = element.all(by.css('button')).get(3);
|
||||||
await testButton.click();
|
await testButton.click();
|
||||||
const contents = 'Test';
|
const contents = 'Test';
|
||||||
logChecker(testButton, contents);
|
logChecker(testButton, contents);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should toggle Test Button disabled', async () => {
|
it('should toggle Test Button disabled', async () => {
|
||||||
const toggleButton = element.all(by.css('button')).get(4);
|
let toggleButton = element.all(by.css('button')).get(4);
|
||||||
await toggleButton.click();
|
await toggleButton.click();
|
||||||
const contents = 'true';
|
const contents = 'true';
|
||||||
logChecker(toggleButton, contents);
|
logChecker(toggleButton, contents);
|
||||||
|
@ -26,7 +26,7 @@ export class AppComponent {
|
|||||||
|
|
||||||
toggleDisabled(): any {
|
toggleDisabled(): any {
|
||||||
|
|
||||||
const testButton = document.getElementById('testButton') as HTMLInputElement;
|
let testButton = <HTMLInputElement> document.getElementById('testButton');
|
||||||
testButton.disabled = !testButton.disabled;
|
testButton.disabled = !testButton.disabled;
|
||||||
console.warn(testButton.disabled);
|
console.warn(testButton.disabled);
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,21 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Built-in Directives', () => {
|
describe('Built-in Directives', function () {
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have title Built-in Directives', () => {
|
it('should have title Built-in Directives', function () {
|
||||||
const title = element.all(by.css('h1')).get(0);
|
let title = element.all(by.css('h1')).get(0);
|
||||||
expect(title.getText()).toEqual('Built-in Directives');
|
expect(title.getText()).toEqual('Built-in Directives');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should change first Teapot header', async () => {
|
it('should change first Teapot header', async () => {
|
||||||
const firstLabel = element.all(by.css('p')).get(0);
|
let firstLabel = element.all(by.css('p')).get(0);
|
||||||
const firstInput = element.all(by.css('input')).get(0);
|
let firstInput = element.all(by.css('input')).get(0);
|
||||||
|
|
||||||
expect(firstLabel.getText()).toEqual('Current item name: Teapot');
|
expect(firstLabel.getText()).toEqual('Current item name: Teapot');
|
||||||
firstInput.sendKeys('abc');
|
firstInput.sendKeys('abc');
|
||||||
@ -21,49 +23,49 @@ describe('Built-in Directives', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should modify sentence when modified checkbox checked', () => {
|
it('should modify sentence when modified checkbox checked', function () {
|
||||||
const modifiedChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(1);
|
let modifiedChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(1);
|
||||||
const modifiedSentence = element.all(by.css('div')).get(1);
|
let modifiedSentence = element.all(by.css('div')).get(1);
|
||||||
|
|
||||||
modifiedChkbxLabel.click();
|
modifiedChkbxLabel.click();
|
||||||
expect(modifiedSentence.getText()).toContain('modified');
|
expect(modifiedSentence.getText()).toContain('modified');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should modify sentence when normal checkbox checked', () => {
|
it('should modify sentence when normal checkbox checked', function () {
|
||||||
const normalChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(4);
|
let normalChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(4);
|
||||||
const normalSentence = element.all(by.css('div')).get(7);
|
let normalSentence = element.all(by.css('div')).get(7);
|
||||||
|
|
||||||
normalChkbxLabel.click();
|
normalChkbxLabel.click();
|
||||||
expect(normalSentence.getText()).toContain('normal weight and, extra large');
|
expect(normalSentence.getText()).toContain('normal weight and, extra large');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should toggle app-item-detail', () => {
|
it('should toggle app-item-detail', function () {
|
||||||
const toggleButton = element.all(by.css('button')).get(3);
|
let toggleButton = element.all(by.css('button')).get(3);
|
||||||
const toggledDiv = element.all(by.css('app-item-detail')).get(0);
|
let toggledDiv = element.all(by.css('app-item-detail')).get(0);
|
||||||
|
|
||||||
toggleButton.click();
|
toggleButton.click();
|
||||||
expect(toggledDiv.isDisplayed()).toBe(true);
|
expect(toggledDiv.isDisplayed()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should hide app-item-detail', () => {
|
it('should hide app-item-detail', function () {
|
||||||
const hiddenMessage = element.all(by.css('p')).get(11);
|
let hiddenMessage = element.all(by.css('p')).get(11);
|
||||||
const hiddenDiv = element.all(by.css('app-item-detail')).get(2);
|
let hiddenDiv = element.all(by.css('app-item-detail')).get(2);
|
||||||
|
|
||||||
expect(hiddenMessage.getText()).toContain('in the DOM');
|
expect(hiddenMessage.getText()).toContain('in the DOM');
|
||||||
expect(hiddenDiv.isDisplayed()).toBe(true);
|
expect(hiddenDiv.isDisplayed()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have 10 lists each containing the string Teapot', () => {
|
it('should have 10 lists each containing the string Teapot', function () {
|
||||||
const listDiv = element.all(by.cssContainingText('.box', 'Teapot'));
|
let listDiv = element.all(by.cssContainingText('.box', 'Teapot'));
|
||||||
expect(listDiv.count()).toBe(10);
|
expect(listDiv.count()).toBe(10);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should switch case', () => {
|
it('should switch case', function () {
|
||||||
const tvRadioButton = element.all(by.css('input[type="radio"]')).get(3);
|
let tvRadioButton = element.all(by.css('input[type="radio"]')).get(3);
|
||||||
const tvDiv = element(by.css('app-lost-item'));
|
let tvDiv = element(by.css('app-lost-item'));
|
||||||
|
|
||||||
const fishbowlRadioButton = element.all(by.css('input[type="radio"]')).get(4);
|
let fishbowlRadioButton = element.all(by.css('input[type="radio"]')).get(4);
|
||||||
const fishbowlDiv = element(by.css('app-unknown-item'));
|
let fishbowlDiv = element(by.css('app-unknown-item'));
|
||||||
|
|
||||||
tvRadioButton.click();
|
tvRadioButton.click();
|
||||||
expect(tvDiv.getText()).toContain('Television');
|
expect(tvDiv.getText()).toContain('Television');
|
||||||
|
@ -30,14 +30,6 @@ export class AppComponent implements OnInit {
|
|||||||
itemsWithTrackByCountReset = 0;
|
itemsWithTrackByCountReset = 0;
|
||||||
itemIdIncrement = 1;
|
itemIdIncrement = 1;
|
||||||
|
|
||||||
// #docregion setClasses
|
|
||||||
currentClasses: {};
|
|
||||||
// #enddocregion setClasses
|
|
||||||
|
|
||||||
// #docregion setStyles
|
|
||||||
currentStyles: {};
|
|
||||||
// #enddocregion setStyles
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.resetItems();
|
this.resetItems();
|
||||||
this.setCurrentClasses();
|
this.setCurrentClasses();
|
||||||
@ -50,17 +42,19 @@ export class AppComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// #docregion setClasses
|
// #docregion setClasses
|
||||||
|
currentClasses: {};
|
||||||
setCurrentClasses() {
|
setCurrentClasses() {
|
||||||
// CSS classes: added/removed per current state of component properties
|
// CSS classes: added/removed per current state of component properties
|
||||||
this.currentClasses = {
|
this.currentClasses = {
|
||||||
saveable: this.canSave,
|
'saveable': this.canSave,
|
||||||
modified: !this.isUnchanged,
|
'modified': !this.isUnchanged,
|
||||||
special: this.isSpecial
|
'special': this.isSpecial
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// #enddocregion setClasses
|
// #enddocregion setClasses
|
||||||
|
|
||||||
// #docregion setStyles
|
// #docregion setStyles
|
||||||
|
currentStyles: {};
|
||||||
setCurrentStyles() {
|
setCurrentStyles() {
|
||||||
// CSS styles: set per current state of component properties
|
// CSS styles: set per current state of component properties
|
||||||
this.currentStyles = {
|
this.currentStyles = {
|
||||||
@ -76,7 +70,11 @@ export class AppComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
giveNullCustomerValue() {
|
giveNullCustomerValue() {
|
||||||
this.nullCustomer = 'Kelly';
|
!(this.nullCustomer = null) ? (this.nullCustomer = 'Kelly') : (this.nullCustomer = null);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetNullItem() {
|
||||||
|
this.nullCustomer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
resetItems() {
|
resetItems() {
|
||||||
@ -86,7 +84,7 @@ export class AppComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resetList() {
|
resetList() {
|
||||||
this.resetItems();
|
this.resetItems()
|
||||||
this.itemsWithTrackByCountReset = 0;
|
this.itemsWithTrackByCountReset = 0;
|
||||||
this.itemsNoTrackByCount = ++this.itemsNoTrackByCount;
|
this.itemsNoTrackByCount = ++this.itemsNoTrackByCount;
|
||||||
}
|
}
|
||||||
@ -109,7 +107,7 @@ export class AppComponent implements OnInit {
|
|||||||
trackByItems(index: number, item: Item): number { return item.id; }
|
trackByItems(index: number, item: Item): number { return item.id; }
|
||||||
// #enddocregion trackByItems
|
// #enddocregion trackByItems
|
||||||
|
|
||||||
trackById(index: number, item: any): number { return item.id; }
|
trackById(index: number, item: any): number { return item['id']; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Built Template Functions Example', () => {
|
describe('Built Template Functions Example', function () {
|
||||||
beforeAll(() => {
|
beforeAll(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have title Built-in Template Functions', () => {
|
it('should have title Built-in Template Functions', function () {
|
||||||
const title = element.all(by.css('h1')).get(0);
|
let title = element.all(by.css('h1')).get(0);
|
||||||
expect(title.getText()).toEqual('Built-in Template Functions');
|
expect(title.getText()).toEqual('Built-in Template Functions');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display $any( ) in h2', () => {
|
it('should display $any( ) in h2', function () {
|
||||||
const header = element(by.css('h2'));
|
let header = element(by.css('h2'));
|
||||||
expect(header.getText()).toContain('$any( )');
|
expect(header.getText()).toContain('$any( )');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,85 +1,87 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Component Communication Cookbook Tests', () => {
|
describe('Component Communication Cookbook Tests', function () {
|
||||||
|
|
||||||
// Note: '?e2e' which app can read to know it is running in protractor
|
// Note: '?e2e' which app can read to know it is running in protractor
|
||||||
// e.g. `if (!/e2e/.test(location.search)) { ...`
|
// e.g. `if (!/e2e/.test(location.search)) { ...`
|
||||||
beforeAll(() => {
|
beforeAll(function () {
|
||||||
browser.get('?e2e');
|
browser.get('?e2e');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Parent-to-child communication', () => {
|
describe('Parent-to-child communication', function() {
|
||||||
// #docregion parent-to-child
|
// #docregion parent-to-child
|
||||||
// ...
|
// ...
|
||||||
const heroNames = ['Dr IQ', 'Magneta', 'Bombasto'];
|
let _heroNames = ['Dr IQ', 'Magneta', 'Bombasto'];
|
||||||
const masterName = 'Master';
|
let _masterName = 'Master';
|
||||||
|
|
||||||
it('should pass properties to children properly', () => {
|
it('should pass properties to children properly', function () {
|
||||||
const parent = element.all(by.tagName('app-hero-parent')).get(0);
|
let parent = element.all(by.tagName('app-hero-parent')).get(0);
|
||||||
const heroes = parent.all(by.tagName('app-hero-child'));
|
let heroes = parent.all(by.tagName('app-hero-child'));
|
||||||
|
|
||||||
for (let i = 0; i < heroNames.length; i++) {
|
for (let i = 0; i < _heroNames.length; i++) {
|
||||||
const childTitle = heroes.get(i).element(by.tagName('h3')).getText();
|
let childTitle = heroes.get(i).element(by.tagName('h3')).getText();
|
||||||
const childDetail = heroes.get(i).element(by.tagName('p')).getText();
|
let childDetail = heroes.get(i).element(by.tagName('p')).getText();
|
||||||
expect(childTitle).toEqual(heroNames[i] + ' says:');
|
expect(childTitle).toEqual(_heroNames[i] + ' says:');
|
||||||
expect(childDetail).toContain(masterName);
|
expect(childDetail).toContain(_masterName);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// ...
|
// ...
|
||||||
// #enddocregion parent-to-child
|
// #enddocregion parent-to-child
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Parent-to-child communication with setter', () => {
|
describe('Parent-to-child communication with setter', function() {
|
||||||
// #docregion parent-to-child-setter
|
// #docregion parent-to-child-setter
|
||||||
// ...
|
// ...
|
||||||
it('should display trimmed, non-empty names', () => {
|
it('should display trimmed, non-empty names', function () {
|
||||||
const nonEmptyNameIndex = 0;
|
let _nonEmptyNameIndex = 0;
|
||||||
const nonEmptyName = '"Dr IQ"';
|
let _nonEmptyName = '"Dr IQ"';
|
||||||
const parent = element.all(by.tagName('app-name-parent')).get(0);
|
let parent = element.all(by.tagName('app-name-parent')).get(0);
|
||||||
const hero = parent.all(by.tagName('app-name-child')).get(nonEmptyNameIndex);
|
let hero = parent.all(by.tagName('app-name-child')).get(_nonEmptyNameIndex);
|
||||||
|
|
||||||
const displayName = hero.element(by.tagName('h3')).getText();
|
let displayName = hero.element(by.tagName('h3')).getText();
|
||||||
expect(displayName).toEqual(nonEmptyName);
|
expect(displayName).toEqual(_nonEmptyName);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should replace empty name with default name', () => {
|
it('should replace empty name with default name', function () {
|
||||||
const emptyNameIndex = 1;
|
let _emptyNameIndex = 1;
|
||||||
const defaultName = '"<no name set>"';
|
let _defaultName = '"<no name set>"';
|
||||||
const parent = element.all(by.tagName('app-name-parent')).get(0);
|
let parent = element.all(by.tagName('app-name-parent')).get(0);
|
||||||
const hero = parent.all(by.tagName('app-name-child')).get(emptyNameIndex);
|
let hero = parent.all(by.tagName('app-name-child')).get(_emptyNameIndex);
|
||||||
|
|
||||||
const displayName = hero.element(by.tagName('h3')).getText();
|
let displayName = hero.element(by.tagName('h3')).getText();
|
||||||
expect(displayName).toEqual(defaultName);
|
expect(displayName).toEqual(_defaultName);
|
||||||
});
|
});
|
||||||
// ...
|
// ...
|
||||||
// #enddocregion parent-to-child-setter
|
// #enddocregion parent-to-child-setter
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Parent-to-child communication with ngOnChanges', () => {
|
describe('Parent-to-child communication with ngOnChanges', function() {
|
||||||
// #docregion parent-to-child-onchanges
|
// #docregion parent-to-child-onchanges
|
||||||
// ...
|
// ...
|
||||||
// Test must all execute in this exact order
|
// Test must all execute in this exact order
|
||||||
it('should set expected initial values', () => {
|
it('should set expected initial values', function () {
|
||||||
const actual = getActual();
|
let actual = getActual();
|
||||||
|
|
||||||
const initialLabel = 'Version 1.23';
|
let initialLabel = 'Version 1.23';
|
||||||
const initialLog = 'Initial value of major set to 1, Initial value of minor set to 23';
|
let initialLog = 'Initial value of major set to 1, Initial value of minor set to 23';
|
||||||
|
|
||||||
expect(actual.label).toBe(initialLabel);
|
expect(actual.label).toBe(initialLabel);
|
||||||
expect(actual.count).toBe(1);
|
expect(actual.count).toBe(1);
|
||||||
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', () => {
|
it('should set expected values after clicking \'Minor\' twice', function () {
|
||||||
const repoTag = element(by.tagName('app-version-parent'));
|
let repoTag = element(by.tagName('app-version-parent'));
|
||||||
const newMinorButton = repoTag.all(by.tagName('button')).get(0);
|
let newMinorButton = repoTag.all(by.tagName('button')).get(0);
|
||||||
|
|
||||||
newMinorButton.click().then(() => {
|
newMinorButton.click().then(function() {
|
||||||
newMinorButton.click().then(() => {
|
newMinorButton.click().then(function() {
|
||||||
const actual = getActual();
|
let actual = getActual();
|
||||||
|
|
||||||
const labelAfter2Minor = 'Version 1.25';
|
let labelAfter2Minor = 'Version 1.25';
|
||||||
const logAfter2Minor = 'minor changed from 24 to 25';
|
let logAfter2Minor = 'minor changed from 24 to 25';
|
||||||
|
|
||||||
expect(actual.label).toBe(labelAfter2Minor);
|
expect(actual.label).toBe(labelAfter2Minor);
|
||||||
expect(actual.count).toBe(3);
|
expect(actual.count).toBe(3);
|
||||||
@ -88,15 +90,15 @@ describe('Component Communication Cookbook Tests', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set expected values after clicking \'Major\' once', () => {
|
it('should set expected values after clicking \'Major\' once', function () {
|
||||||
const repoTag = element(by.tagName('app-version-parent'));
|
let repoTag = element(by.tagName('app-version-parent'));
|
||||||
const newMajorButton = repoTag.all(by.tagName('button')).get(1);
|
let newMajorButton = repoTag.all(by.tagName('button')).get(1);
|
||||||
|
|
||||||
newMajorButton.click().then(() => {
|
newMajorButton.click().then(function() {
|
||||||
const actual = getActual();
|
let actual = getActual();
|
||||||
|
|
||||||
const labelAfterMajor = 'Version 2.0';
|
let labelAfterMajor = 'Version 2.0';
|
||||||
const logAfterMajor = 'major changed from 1 to 2, minor changed from 25 to 0';
|
let 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(4);
|
expect(actual.count).toBe(4);
|
||||||
@ -105,14 +107,14 @@ describe('Component Communication Cookbook Tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function getActual() {
|
function getActual() {
|
||||||
const versionTag = element(by.tagName('app-version-child'));
|
let versionTag = element(by.tagName('app-version-child'));
|
||||||
const label = versionTag.element(by.tagName('h3')).getText();
|
let label = versionTag.element(by.tagName('h3')).getText();
|
||||||
const ul = versionTag.element((by.tagName('ul')));
|
let ul = versionTag.element((by.tagName('ul')));
|
||||||
const logs = ul.all(by.tagName('li'));
|
let logs = ul.all(by.tagName('li'));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
label,
|
label: label,
|
||||||
logs,
|
logs: logs,
|
||||||
count: logs.count()
|
count: logs.count()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -121,30 +123,30 @@ describe('Component Communication Cookbook Tests', () => {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Child-to-parent communication', () => {
|
describe('Child-to-parent communication', function() {
|
||||||
// #docregion child-to-parent
|
// #docregion child-to-parent
|
||||||
// ...
|
// ...
|
||||||
it('should not emit the event initially', () => {
|
it('should not emit the event initially', function () {
|
||||||
const voteLabel = element(by.tagName('app-vote-taker'))
|
let voteLabel = element(by.tagName('app-vote-taker'))
|
||||||
.element(by.tagName('h3')).getText();
|
.element(by.tagName('h3')).getText();
|
||||||
expect(voteLabel).toBe('Agree: 0, Disagree: 0');
|
expect(voteLabel).toBe('Agree: 0, Disagree: 0');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should process Agree vote', () => {
|
it('should process Agree vote', function () {
|
||||||
const agreeButton1 = element.all(by.tagName('app-voter')).get(0)
|
let agreeButton1 = element.all(by.tagName('app-voter')).get(0)
|
||||||
.all(by.tagName('button')).get(0);
|
.all(by.tagName('button')).get(0);
|
||||||
agreeButton1.click().then(() => {
|
agreeButton1.click().then(function() {
|
||||||
const voteLabel = element(by.tagName('app-vote-taker'))
|
let voteLabel = element(by.tagName('app-vote-taker'))
|
||||||
.element(by.tagName('h3')).getText();
|
.element(by.tagName('h3')).getText();
|
||||||
expect(voteLabel).toBe('Agree: 1, Disagree: 0');
|
expect(voteLabel).toBe('Agree: 1, Disagree: 0');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should process Disagree vote', () => {
|
it('should process Disagree vote', function () {
|
||||||
const agreeButton1 = element.all(by.tagName('app-voter')).get(1)
|
let agreeButton1 = element.all(by.tagName('app-voter')).get(1)
|
||||||
.all(by.tagName('button')).get(1);
|
.all(by.tagName('button')).get(1);
|
||||||
agreeButton1.click().then(() => {
|
agreeButton1.click().then(function() {
|
||||||
const voteLabel = element(by.tagName('app-vote-taker'))
|
let voteLabel = element(by.tagName('app-vote-taker'))
|
||||||
.element(by.tagName('h3')).getText();
|
.element(by.tagName('h3')).getText();
|
||||||
expect(voteLabel).toBe('Agree: 1, Disagree: 1');
|
expect(voteLabel).toBe('Agree: 1, Disagree: 1');
|
||||||
});
|
});
|
||||||
@ -155,31 +157,31 @@ describe('Component Communication Cookbook Tests', () => {
|
|||||||
|
|
||||||
// Can't run timer tests in protractor because
|
// Can't run timer tests in protractor because
|
||||||
// interaction w/ zones causes all tests to freeze & timeout.
|
// interaction w/ zones causes all tests to freeze & timeout.
|
||||||
xdescribe('Parent calls child via local var', () => {
|
xdescribe('Parent calls child via local var', function() {
|
||||||
countDownTimerTests('countdown-parent-lv');
|
countDownTimerTests('countdown-parent-lv');
|
||||||
});
|
});
|
||||||
|
|
||||||
xdescribe('Parent calls ViewChild', () => {
|
xdescribe('Parent calls ViewChild', function() {
|
||||||
countDownTimerTests('countdown-parent-vc');
|
countDownTimerTests('countdown-parent-vc');
|
||||||
});
|
});
|
||||||
|
|
||||||
function countDownTimerTests(parentTag: string) {
|
function countDownTimerTests(parentTag: string) {
|
||||||
// #docregion countdown-timer-tests
|
// #docregion countdown-timer-tests
|
||||||
// ...
|
// ...
|
||||||
it('timer and parent seconds should match', () => {
|
it('timer and parent seconds should match', function () {
|
||||||
const parent = element(by.tagName(parentTag));
|
let parent = element(by.tagName(parentTag));
|
||||||
const message = parent.element(by.tagName('app-countdown-timer')).getText();
|
let message = parent.element(by.tagName('app-countdown-timer')).getText();
|
||||||
browser.sleep(10); // give `seconds` a chance to catchup with `message`
|
browser.sleep(10); // give `seconds` a chance to catchup with `message`
|
||||||
const seconds = parent.element(by.className('seconds')).getText();
|
let seconds = parent.element(by.className('seconds')).getText();
|
||||||
expect(message).toContain(seconds);
|
expect(message).toContain(seconds);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should stop the countdown', () => {
|
it('should stop the countdown', function () {
|
||||||
const parent = element(by.tagName(parentTag));
|
let parent = element(by.tagName(parentTag));
|
||||||
const stopButton = parent.all(by.tagName('button')).get(1);
|
let stopButton = parent.all(by.tagName('button')).get(1);
|
||||||
|
|
||||||
stopButton.click().then(() => {
|
stopButton.click().then(function() {
|
||||||
const message = parent.element(by.tagName('app-countdown-timer')).getText();
|
let message = parent.element(by.tagName('app-countdown-timer')).getText();
|
||||||
expect(message).toContain('Holding');
|
expect(message).toContain('Holding');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -188,39 +190,39 @@ describe('Component Communication Cookbook Tests', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
describe('Parent and children communicate via a service', () => {
|
describe('Parent and children communicate via a service', function() {
|
||||||
// #docregion bidirectional-service
|
// #docregion bidirectional-service
|
||||||
// ...
|
// ...
|
||||||
it('should announce a mission', () => {
|
it('should announce a mission', function () {
|
||||||
const missionControl = element(by.tagName('app-mission-control'));
|
let missionControl = element(by.tagName('app-mission-control'));
|
||||||
const announceButton = missionControl.all(by.tagName('button')).get(0);
|
let announceButton = missionControl.all(by.tagName('button')).get(0);
|
||||||
announceButton.click().then(() => {
|
announceButton.click().then(function () {
|
||||||
const history = missionControl.all(by.tagName('li'));
|
let history = missionControl.all(by.tagName('li'));
|
||||||
expect(history.count()).toBe(1);
|
expect(history.count()).toBe(1);
|
||||||
expect(history.get(0).getText()).toMatch(/Mission.* announced/);
|
expect(history.get(0).getText()).toMatch(/Mission.* announced/);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should confirm the mission by Lovell', () => {
|
it('should confirm the mission by Lovell', function () {
|
||||||
testConfirmMission(1, 2, 'Lovell');
|
testConfirmMission(1, 2, 'Lovell');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should confirm the mission by Haise', () => {
|
it('should confirm the mission by Haise', function () {
|
||||||
testConfirmMission(3, 3, 'Haise');
|
testConfirmMission(3, 3, 'Haise');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should confirm the mission by Swigert', () => {
|
it('should confirm the mission by Swigert', function () {
|
||||||
testConfirmMission(2, 4, 'Swigert');
|
testConfirmMission(2, 4, 'Swigert');
|
||||||
});
|
});
|
||||||
|
|
||||||
function testConfirmMission(buttonIndex: number, expectedLogCount: number, astronaut: string) {
|
function testConfirmMission(buttonIndex: number, expectedLogCount: number, astronaut: string) {
|
||||||
const confirmedLog = ' confirmed the mission';
|
let _confirmedLog = ' confirmed the mission';
|
||||||
const missionControl = element(by.tagName('app-mission-control'));
|
let missionControl = element(by.tagName('app-mission-control'));
|
||||||
const confirmButton = missionControl.all(by.tagName('button')).get(buttonIndex);
|
let confirmButton = missionControl.all(by.tagName('button')).get(buttonIndex);
|
||||||
confirmButton.click().then(() => {
|
confirmButton.click().then(function () {
|
||||||
const history = missionControl.all(by.tagName('li'));
|
let history = missionControl.all(by.tagName('li'));
|
||||||
expect(history.count()).toBe(expectedLogCount);
|
expect(history.count()).toBe(expectedLogCount);
|
||||||
expect(history.get(expectedLogCount - 1).getText()).toBe(astronaut + confirmedLog);
|
expect(history.get(expectedLogCount - 1).getText()).toBe(astronaut + _confirmedLog);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// ...
|
// ...
|
||||||
|
@ -15,7 +15,7 @@ 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[] = [
|
let directives: any[] = [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
AstronautComponent,
|
AstronautComponent,
|
||||||
CountdownTimerComponent,
|
CountdownTimerComponent,
|
||||||
@ -30,7 +30,7 @@ const directives: any[] = [
|
|||||||
VoteTakerComponent
|
VoteTakerComponent
|
||||||
];
|
];
|
||||||
|
|
||||||
const schemas: any[] = [];
|
let schemas: any[] = [];
|
||||||
|
|
||||||
// Include Countdown examples
|
// Include Countdown examples
|
||||||
// unless in e2e tests which they break.
|
// unless in e2e tests which they break.
|
||||||
@ -49,6 +49,6 @@ if (!/e2e/.test(location.search)) {
|
|||||||
],
|
],
|
||||||
declarations: directives,
|
declarations: directives,
|
||||||
bootstrap: [ AppComponent ],
|
bootstrap: [ AppComponent ],
|
||||||
schemas
|
schemas: schemas
|
||||||
})
|
})
|
||||||
export class AppModule { }
|
export class AppModule { }
|
||||||
|
@ -12,6 +12,6 @@ import { Hero } from './hero';
|
|||||||
})
|
})
|
||||||
export class HeroChildComponent {
|
export class HeroChildComponent {
|
||||||
@Input() hero: Hero;
|
@Input() hero: Hero;
|
||||||
@Input('master') masterName: string; // tslint:disable-line: no-input-rename
|
@Input('master') masterName: string;
|
||||||
}
|
}
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
@ -34,7 +34,7 @@ export class MissionControlComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
announce() {
|
announce() {
|
||||||
const mission = this.missions[this.nextMission++];
|
let mission = this.missions[this.nextMission++];
|
||||||
this.missionService.announceMission(mission);
|
this.missionService.announceMission(mission);
|
||||||
this.history.push(`Mission "${mission}" announced`);
|
this.history.push(`Mission "${mission}" announced`);
|
||||||
if (this.nextMission >= this.missions.length) { this.nextMission = 0; }
|
if (this.nextMission >= this.missions.length) { this.nextMission = 0; }
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// tslint:disable: variable-name
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input } from '@angular/core';
|
||||||
|
|
||||||
@ -7,11 +6,13 @@ import { Component, Input } from '@angular/core';
|
|||||||
template: '<h3>"{{name}}"</h3>'
|
template: '<h3>"{{name}}"</h3>'
|
||||||
})
|
})
|
||||||
export class NameChildComponent {
|
export class NameChildComponent {
|
||||||
|
private _name = '';
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
get name(): string { return this._name; }
|
|
||||||
set name(name: string) {
|
set name(name: string) {
|
||||||
this._name = (name && name.trim()) || '<no name set>';
|
this._name = (name && name.trim()) || '<no name set>';
|
||||||
}
|
}
|
||||||
private _name = '';
|
|
||||||
|
get name(): string { return this._name; }
|
||||||
}
|
}
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
@ -18,14 +18,14 @@ export class VersionChildComponent implements OnChanges {
|
|||||||
changeLog: string[] = [];
|
changeLog: string[] = [];
|
||||||
|
|
||||||
ngOnChanges(changes: {[propKey: string]: SimpleChange}) {
|
ngOnChanges(changes: {[propKey: string]: SimpleChange}) {
|
||||||
const log: string[] = [];
|
let log: string[] = [];
|
||||||
for (const propName in changes) {
|
for (let propName in changes) {
|
||||||
const changedProp = changes[propName];
|
let changedProp = changes[propName];
|
||||||
const to = JSON.stringify(changedProp.currentValue);
|
let to = JSON.stringify(changedProp.currentValue);
|
||||||
if (changedProp.isFirstChange()) {
|
if (changedProp.isFirstChange()) {
|
||||||
log.push(`Initial value of ${propName} set to ${to}`);
|
log.push(`Initial value of ${propName} set to ${to}`);
|
||||||
} else {
|
} else {
|
||||||
const from = JSON.stringify(changedProp.previousValue);
|
let from = JSON.stringify(changedProp.previousValue);
|
||||||
log.push(`${propName} changed from ${from} to ${to}`);
|
log.push(`${propName} changed from ${from} to ${to}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Component Style Tests', () => {
|
describe('Component Style Tests', function () {
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('scopes component styles to component view', () => {
|
it('scopes component styles to component view', function() {
|
||||||
const componentH1 = element(by.css('app-root > h1'));
|
let componentH1 = element(by.css('app-root > h1'));
|
||||||
const externalH1 = element(by.css('body > h1'));
|
let externalH1 = element(by.css('body > h1'));
|
||||||
|
|
||||||
// Note: sometimes webdriver returns the fontWeight as "normal",
|
// Note: sometimes webdriver returns the fontWeight as "normal",
|
||||||
// other times as "400", both of which are equal in CSS terms.
|
// other times as "400", both of which are equal in CSS terms.
|
||||||
@ -17,49 +19,49 @@ describe('Component Style Tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('allows styling :host element', () => {
|
it('allows styling :host element', function() {
|
||||||
const host = element(by.css('app-hero-details'));
|
let host = element(by.css('app-hero-details'));
|
||||||
|
|
||||||
expect(host.getCssValue('borderWidth')).toEqual('1px');
|
expect(host.getCssValue('borderWidth')).toEqual('1px');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('supports :host() in function form', () => {
|
it('supports :host() in function form', function() {
|
||||||
const host = element(by.css('app-hero-details'));
|
let host = element(by.css('app-hero-details'));
|
||||||
|
|
||||||
host.element(by.buttonText('Activate')).click();
|
host.element(by.buttonText('Activate')).click();
|
||||||
expect(host.getCssValue('borderWidth')).toEqual('3px');
|
expect(host.getCssValue('borderWidth')).toEqual('3px');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows conditional :host-context() styling', () => {
|
it('allows conditional :host-context() styling', function() {
|
||||||
const h2 = element(by.css('app-hero-details h2'));
|
let h2 = element(by.css('app-hero-details h2'));
|
||||||
|
|
||||||
expect(h2.getCssValue('backgroundColor')).toEqual('rgba(238, 238, 255, 1)'); // #eeeeff
|
expect(h2.getCssValue('backgroundColor')).toEqual('rgba(238, 238, 255, 1)'); // #eeeeff
|
||||||
});
|
});
|
||||||
|
|
||||||
it('styles both view and content children with /deep/', () => {
|
it('styles both view and content children with /deep/', function() {
|
||||||
const viewH3 = element(by.css('app-hero-team h3'));
|
let viewH3 = element(by.css('app-hero-team h3'));
|
||||||
const contentH3 = element(by.css('app-hero-controls h3'));
|
let contentH3 = element(by.css('app-hero-controls h3'));
|
||||||
|
|
||||||
expect(viewH3.getCssValue('fontStyle')).toEqual('italic');
|
expect(viewH3.getCssValue('fontStyle')).toEqual('italic');
|
||||||
expect(contentH3.getCssValue('fontStyle')).toEqual('italic');
|
expect(contentH3.getCssValue('fontStyle')).toEqual('italic');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('includes styles loaded with CSS @import', () => {
|
it('includes styles loaded with CSS @import', function() {
|
||||||
const host = element(by.css('app-hero-details'));
|
let host = element(by.css('app-hero-details'));
|
||||||
|
|
||||||
expect(host.getCssValue('padding')).toEqual('10px');
|
expect(host.getCssValue('padding')).toEqual('10px');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('processes template inline styles', () => {
|
it('processes template inline styles', function() {
|
||||||
const button = element(by.css('app-hero-controls button'));
|
let button = element(by.css('app-hero-controls button'));
|
||||||
const externalButton = element(by.css('body > button'));
|
let externalButton = element(by.css('body > button'));
|
||||||
expect(button.getCssValue('backgroundColor')).toEqual('rgba(255, 255, 255, 1)'); // #ffffff
|
expect(button.getCssValue('backgroundColor')).toEqual('rgba(255, 255, 255, 1)'); // #ffffff
|
||||||
expect(externalButton.getCssValue('backgroundColor')).not.toEqual('rgba(255, 255, 255, 1)');
|
expect(externalButton.getCssValue('backgroundColor')).not.toEqual('rgba(255, 255, 255, 1)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('processes template <link>s', () => {
|
it('processes template <link>s', function() {
|
||||||
const li = element(by.css('app-hero-team li:first-child'));
|
let li = element(by.css('app-hero-team li:first-child'));
|
||||||
const externalLi = element(by.css('body > ul li'));
|
let externalLi = element(by.css('body > ul li'));
|
||||||
|
|
||||||
expect(li.getCssValue('listStyleType')).toEqual('square');
|
expect(li.getCssValue('listStyleType')).toEqual('square');
|
||||||
expect(externalLi.getCssValue('listStyleType')).not.toEqual('square');
|
expect(externalLi.getCssValue('listStyleType')).not.toEqual('square');
|
||||||
|
@ -1,74 +1,76 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Dependency Injection Cookbook', () => {
|
describe('Dependency Injection Cookbook', function () {
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render Logged in User example', () => {
|
it('should render Logged in User example', function () {
|
||||||
const loggedInUser = element.all(by.xpath('//h3[text()="Logged in user"]')).get(0);
|
let loggedInUser = element.all(by.xpath('//h3[text()="Logged in user"]')).get(0);
|
||||||
expect(loggedInUser).toBeDefined();
|
expect(loggedInUser).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('"Bombasto" should be the logged in user', () => {
|
it('"Bombasto" should be the logged in user', function () {
|
||||||
const loggedInUser = element.all(by.xpath('//div[text()="Name: Bombasto"]')).get(0);
|
let loggedInUser = element.all(by.xpath('//div[text()="Name: Bombasto"]')).get(0);
|
||||||
expect(loggedInUser).toBeDefined();
|
expect(loggedInUser).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render sorted heroes', () => {
|
it('should render sorted heroes', function () {
|
||||||
const sortedHeroes = element.all(by.xpath('//h3[text()="Sorted Heroes" and position()=1]')).get(0);
|
let sortedHeroes = element.all(by.xpath('//h3[text()="Sorted Heroes" and position()=1]')).get(0);
|
||||||
expect(sortedHeroes).toBeDefined();
|
expect(sortedHeroes).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Dr Nice should be in sorted heroes', () => {
|
it('Dr Nice should be in sorted heroes', function () {
|
||||||
const sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Dr Nice" and position()=2]')).get(0);
|
let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Dr Nice" and position()=2]')).get(0);
|
||||||
expect(sortedHero).toBeDefined();
|
expect(sortedHero).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('RubberMan should be in sorted heroes', () => {
|
it('RubberMan should be in sorted heroes', function () {
|
||||||
const sortedHero = element.all(by.xpath('//sorted-heroes/[text()="RubberMan" and position()=3]')).get(0);
|
let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="RubberMan" and position()=3]')).get(0);
|
||||||
expect(sortedHero).toBeDefined();
|
expect(sortedHero).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Magma should be in sorted heroes', () => {
|
it('Magma should be in sorted heroes', function () {
|
||||||
const sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Magma"]')).get(0);
|
let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Magma"]')).get(0);
|
||||||
expect(sortedHero).toBeDefined();
|
expect(sortedHero).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render Hero of the Month', () => {
|
it('should render Hero of the Month', function () {
|
||||||
const heroOfTheMonth = element.all(by.xpath('//h3[text()="Hero of the month"]')).get(0);
|
let heroOfTheMonth = element.all(by.xpath('//h3[text()="Hero of the month"]')).get(0);
|
||||||
expect(heroOfTheMonth).toBeDefined();
|
expect(heroOfTheMonth).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render Hero Bios', () => {
|
it('should render Hero Bios', function () {
|
||||||
const heroBios = element.all(by.xpath('//h3[text()="Hero Bios"]')).get(0);
|
let heroBios = element.all(by.xpath('//h3[text()="Hero Bios"]')).get(0);
|
||||||
expect(heroBios).toBeDefined();
|
expect(heroBios).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render Magma\'s description in Hero Bios', () => {
|
it('should render Magma\'s description in Hero Bios', function () {
|
||||||
const magmaText = element.all(by.xpath('//textarea[text()="Hero of all trades"]')).get(0);
|
let magmaText = element.all(by.xpath('//textarea[text()="Hero of all trades"]')).get(0);
|
||||||
expect(magmaText).toBeDefined();
|
expect(magmaText).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render Magma\'s phone in Hero Bios and Contacts', () => {
|
it('should render Magma\'s phone in Hero Bios and Contacts', function () {
|
||||||
const magmaPhone = element.all(by.xpath('//div[text()="Phone #: 555-555-5555"]')).get(0);
|
let magmaPhone = element.all(by.xpath('//div[text()="Phone #: 555-555-5555"]')).get(0);
|
||||||
expect(magmaPhone).toBeDefined();
|
expect(magmaPhone).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render Hero-of-the-Month runner-ups', () => {
|
it('should render Hero-of-the-Month runner-ups', function () {
|
||||||
const runnersUp = element(by.id('rups1')).getText();
|
let runnersUp = element(by.id('rups1')).getText();
|
||||||
expect(runnersUp).toContain('RubberMan, Dr Nice');
|
expect(runnersUp).toContain('RubberMan, Dr Nice');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render DateLogger log entry in Hero-of-the-Month', () => {
|
it('should render DateLogger log entry in Hero-of-the-Month', function () {
|
||||||
const logs = element.all(by.id('logs')).get(0).getText();
|
let logs = element.all(by.id('logs')).get(0).getText();
|
||||||
expect(logs).toContain('INFO: starting up at');
|
expect(logs).toContain('INFO: starting up at');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should highlight Hero Bios and Contacts container when mouseover', () => {
|
it('should highlight Hero Bios and Contacts container when mouseover', function () {
|
||||||
const target = element(by.css('div[appHighlight="yellow"]'));
|
let target = element(by.css('div[appHighlight="yellow"]'));
|
||||||
const yellow = 'rgba(255, 255, 0, 1)';
|
let yellow = 'rgba(255, 255, 0, 1)';
|
||||||
|
|
||||||
expect(target.getCssValue('background-color')).not.toEqual(yellow);
|
expect(target.getCssValue('background-color')).not.toEqual(yellow);
|
||||||
|
|
||||||
@ -79,25 +81,25 @@ describe('Dependency Injection Cookbook', () => {
|
|||||||
browser.wait(() => target.getCssValue('background-color').then(c => c === yellow), 2000);
|
browser.wait(() => target.getCssValue('background-color').then(c => c === yellow), 2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('in Parent Finder', () => {
|
describe('in Parent Finder', function () {
|
||||||
const cathy1 = element(by.css('alex cathy'));
|
let cathy1 = element(by.css('alex cathy'));
|
||||||
const craig1 = element(by.css('alex craig'));
|
let craig1 = element(by.css('alex craig'));
|
||||||
const carol1 = element(by.css('alex carol p'));
|
let carol1 = element(by.css('alex carol p'));
|
||||||
const carol2 = element(by.css('barry carol p'));
|
let carol2 = element(by.css('barry carol p'));
|
||||||
|
|
||||||
it('"Cathy" should find "Alex" via the component class', () => {
|
it('"Cathy" should find "Alex" via the component class', function () {
|
||||||
expect(cathy1.getText()).toContain('Found Alex via the component');
|
expect(cathy1.getText()).toContain('Found Alex via the component');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('"Craig" should not find "Alex" via the base class', () => {
|
it('"Craig" should not find "Alex" via the base class', function () {
|
||||||
expect(craig1.getText()).toContain('Did not find Alex via the base');
|
expect(craig1.getText()).toContain('Did not find Alex via the base');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('"Carol" within "Alex" should have "Alex" parent', () => {
|
it('"Carol" within "Alex" should have "Alex" parent', function () {
|
||||||
expect(carol1.getText()).toContain('Alex');
|
expect(carol1.getText()).toContain('Alex');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('"Carol" within "Barry" should have "Barry" parent', () => {
|
it('"Carol" within "Barry" should have "Barry" parent', function () {
|
||||||
expect(carol2.getText()).toContain('Barry');
|
expect(carol2.getText()).toContain('Barry');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -42,11 +42,11 @@ const declarations = [
|
|||||||
ParentFinderComponent,
|
ParentFinderComponent,
|
||||||
];
|
];
|
||||||
|
|
||||||
const componentListA = [ AliceComponent, AlexComponent ];
|
const a_components = [AliceComponent, AlexComponent ];
|
||||||
|
|
||||||
const componentListB = [ BarryComponent, BethComponent, BobComponent ];
|
const b_components = [ BarryComponent, BethComponent, BobComponent ];
|
||||||
|
|
||||||
const componentListC = [
|
const c_components = [
|
||||||
CarolComponent, ChrisComponent, CraigComponent,
|
CarolComponent, ChrisComponent, CraigComponent,
|
||||||
CathyComponent
|
CathyComponent
|
||||||
];
|
];
|
||||||
@ -61,9 +61,9 @@ const componentListC = [
|
|||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
declarations,
|
declarations,
|
||||||
componentListA,
|
a_components,
|
||||||
componentListB,
|
b_components,
|
||||||
componentListC,
|
c_components,
|
||||||
StorageComponent,
|
StorageComponent,
|
||||||
],
|
],
|
||||||
bootstrap: [ AppComponent ],
|
bootstrap: [ AppComponent ],
|
||||||
|
@ -3,7 +3,7 @@ import { Hero } from './hero';
|
|||||||
|
|
||||||
export class HeroData {
|
export class HeroData {
|
||||||
createDb() {
|
createDb() {
|
||||||
const heroes = [
|
let heroes = [
|
||||||
new Hero(1, 'Windstorm'),
|
new Hero(1, 'Windstorm'),
|
||||||
new Hero(2, 'Bombasto'),
|
new Hero(2, 'Bombasto'),
|
||||||
new Hero(3, 'Magneta'),
|
new Hero(3, 'Magneta'),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
// tslint:disable: component-selector space-before-function-paren
|
/* tslint:disable:no-unused-variable component-selector-name one-line check-open-brace */
|
||||||
|
/* tslint:disable:*/
|
||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
import { Component, forwardRef, Optional, SkipSelf } from '@angular/core';
|
import { Component, forwardRef, Optional, SkipSelf } from '@angular/core';
|
||||||
@ -19,7 +20,8 @@ const DifferentParent = Parent;
|
|||||||
// The `parentType` defaults to `Parent` when omitting the second parameter.
|
// The `parentType` defaults to `Parent` when omitting the second parameter.
|
||||||
// #docregion provide-the-parent
|
// #docregion provide-the-parent
|
||||||
export function provideParent
|
export function provideParent
|
||||||
// #enddocregion provide-the-parent
|
// #enddocregion provide-parent, provide-the-parent
|
||||||
|
// #docregion provide-parent
|
||||||
(component: any, parentType?: any) {
|
(component: any, parentType?: any) {
|
||||||
return { provide: parentType || Parent, useExisting: forwardRef(() => component) };
|
return { provide: parentType || Parent, useExisting: forwardRef(() => component) };
|
||||||
}
|
}
|
||||||
|
@ -22,5 +22,5 @@ export function runnersUpFactory(take: number) {
|
|||||||
.join(', ');
|
.join(', ');
|
||||||
// #docregion factory-synopsis
|
// #docregion factory-synopsis
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
// #enddocregion factory-synopsis
|
// #enddocregion factory-synopsis
|
||||||
|
@ -24,7 +24,7 @@ export class UserContextService {
|
|||||||
// #enddocregion ctor, injectables
|
// #enddocregion ctor, injectables
|
||||||
|
|
||||||
loadUser(userId: number) {
|
loadUser(userId: number) {
|
||||||
const user = this.userService.getUserById(userId);
|
let user = this.userService.getUserById(userId);
|
||||||
this.name = user.name;
|
this.name = user.name;
|
||||||
this.role = user.role;
|
this.role = user.role;
|
||||||
|
|
||||||
|
@ -1,196 +1,202 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, element, by, ElementFinder } from 'protractor';
|
import { browser, element, by, ElementFinder } from 'protractor';
|
||||||
|
|
||||||
describe('Dependency Injection Tests', () => {
|
describe('Dependency Injection Tests', function () {
|
||||||
|
|
||||||
let expectedMsg: string;
|
let expectedMsg: string;
|
||||||
let expectedMsgRx: RegExp;
|
let expectedMsgRx: RegExp;
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Cars:', () => {
|
describe('Cars:', function() {
|
||||||
|
|
||||||
it('DI car displays as expected', () => {
|
it('DI car displays as expected', function () {
|
||||||
expectedMsg = 'DI car with 4 cylinders and Flintstone tires.';
|
expectedMsg = 'DI car with 4 cylinders and Flintstone tires.';
|
||||||
expect(element(by.css('#di')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#di')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('No DI car displays as expected', () => {
|
it('No DI car displays as expected', function () {
|
||||||
expectedMsg = 'No DI car with 4 cylinders and Flintstone tires.';
|
expectedMsg = 'No DI car with 4 cylinders and Flintstone tires.';
|
||||||
expect(element(by.css('#nodi')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#nodi')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Injector car displays as expected', () => {
|
it('Injector car displays as expected', function () {
|
||||||
expectedMsg = 'Injector car with 4 cylinders and Flintstone tires.';
|
expectedMsg = 'Injector car with 4 cylinders and Flintstone tires.';
|
||||||
expect(element(by.css('#injector')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#injector')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Factory car displays as expected', () => {
|
it('Factory car displays as expected', function () {
|
||||||
expectedMsg = 'Factory car with 4 cylinders and Flintstone tires.';
|
expectedMsg = 'Factory car with 4 cylinders and Flintstone tires.';
|
||||||
expect(element(by.css('#factory')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#factory')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Simple car displays as expected', () => {
|
it('Simple car displays as expected', function () {
|
||||||
expectedMsg = 'Simple car with 4 cylinders and Flintstone tires.';
|
expectedMsg = 'Simple car with 4 cylinders and Flintstone tires.';
|
||||||
expect(element(by.css('#simple')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#simple')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Super car displays as expected', () => {
|
it('Super car displays as expected', function () {
|
||||||
expectedMsg = 'Super car with 12 cylinders and Flintstone tires.';
|
expectedMsg = 'Super car with 12 cylinders and Flintstone tires.';
|
||||||
expect(element(by.css('#super')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#super')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Test car displays as expected', () => {
|
it('Test car displays as expected', function () {
|
||||||
expectedMsg = 'Test car with 8 cylinders and YokoGoodStone tires.';
|
expectedMsg = 'Test car with 8 cylinders and YokoGoodStone tires.';
|
||||||
expect(element(by.css('#test')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#test')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Other Injections:', () => {
|
describe('Other Injections:', function() {
|
||||||
it('DI car displays as expected', () => {
|
it('DI car displays as expected', function () {
|
||||||
expectedMsg = 'DI car with 4 cylinders and Flintstone tires.';
|
expectedMsg = 'DI car with 4 cylinders and Flintstone tires.';
|
||||||
expect(element(by.css('#car')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#car')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Hero displays as expected', () => {
|
it('Hero displays as expected', function () {
|
||||||
expectedMsg = 'Dr Nice';
|
expectedMsg = 'Dr Nice';
|
||||||
expect(element(by.css('#hero')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#hero')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Optional injection displays as expected', () => {
|
it('Optional injection displays as expected', function () {
|
||||||
expectedMsg = 'R.O.U.S.\'s? I don\'t think they exist!';
|
expectedMsg = 'R.O.U.S.\'s? I don\'t think they exist!';
|
||||||
expect(element(by.css('#rodent')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#rodent')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Tests:', () => {
|
describe('Tests:', function() {
|
||||||
|
|
||||||
it('Tests display as expected', () => {
|
it('Tests display as expected', function () {
|
||||||
expectedMsgRx = /Tests passed/;
|
expectedMsgRx = /Tests passed/;
|
||||||
expect(element(by.css('#tests')).getText()).toMatch(expectedMsgRx);
|
expect(element(by.css('#tests')).getText()).toMatch(expectedMsgRx);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Provider variations:', () => {
|
describe('Provider variations:', function() {
|
||||||
|
|
||||||
it('P1 (class) displays as expected', () => {
|
it('P1 (class) displays as expected', function () {
|
||||||
expectedMsg = 'Hello from logger provided with Logger class';
|
expectedMsg = 'Hello from logger provided with Logger class';
|
||||||
expect(element(by.css('#p1')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#p1')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('P3 (provide) displays as expected', () => {
|
it('P3 (provide) displays as expected', function () {
|
||||||
expectedMsg = 'Hello from logger provided with useClass:Logger';
|
expectedMsg = 'Hello from logger provided with useClass:Logger';
|
||||||
expect(element(by.css('#p3')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#p3')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('P4 (useClass:BetterLogger) displays as expected', () => {
|
it('P4 (useClass:BetterLogger) displays as expected', function () {
|
||||||
expectedMsg = 'Hello from logger provided with useClass:BetterLogger';
|
expectedMsg = 'Hello from logger provided with useClass:BetterLogger';
|
||||||
expect(element(by.css('#p4')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#p4')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('P5 (useClass:EvenBetterLogger - dependency) displays as expected', () => {
|
it('P5 (useClass:EvenBetterLogger - dependency) displays as expected', function () {
|
||||||
expectedMsg = 'Message to Bob: Hello from EvenBetterlogger';
|
expectedMsg = 'Message to Bob: Hello from EvenBetterlogger';
|
||||||
expect(element(by.css('#p5')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#p5')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('P6a (no alias) displays as expected', () => {
|
it('P6a (no alias) displays as expected', function () {
|
||||||
expectedMsg = 'Hello OldLogger (but we want NewLogger)';
|
expectedMsg = 'Hello OldLogger (but we want NewLogger)';
|
||||||
expect(element(by.css('#p6a')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#p6a')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('P6b (alias) displays as expected', () => {
|
it('P6b (alias) displays as expected', function () {
|
||||||
expectedMsg = 'Hello from NewLogger (via aliased OldLogger)';
|
expectedMsg = 'Hello from NewLogger (via aliased OldLogger)';
|
||||||
expect(element(by.css('#p6b')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#p6b')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('P7 (useValue) displays as expected', () => {
|
it('P7 (useValue) displays as expected', function () {
|
||||||
expectedMsg = 'Silent logger says "Shhhhh!". Provided via "useValue"';
|
expectedMsg = 'Silent logger says "Shhhhh!". Provided via "useValue"';
|
||||||
expect(element(by.css('#p7')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#p7')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('P8 (useFactory) displays as expected', () => {
|
it('P8 (useFactory) displays as expected', function () {
|
||||||
expectedMsg = 'Hero service injected successfully via heroServiceProvider';
|
expectedMsg = 'Hero service injected successfully via heroServiceProvider';
|
||||||
expect(element(by.css('#p8')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#p8')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('P9 (InjectionToken) displays as expected', () => {
|
it('P9 (InjectionToken) displays as expected', function () {
|
||||||
expectedMsg = 'APP_CONFIG Application title is Dependency Injection';
|
expectedMsg = 'APP_CONFIG Application title is Dependency Injection';
|
||||||
expect(element(by.css('#p9')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#p9')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('P10 (optional dependency) displays as expected', () => {
|
it('P10 (optional dependency) displays as expected', function () {
|
||||||
expectedMsg = 'Optional logger was not available';
|
expectedMsg = 'Optional logger was not available';
|
||||||
expect(element(by.css('#p10')).getText()).toEqual(expectedMsg);
|
expect(element(by.css('#p10')).getText()).toEqual(expectedMsg);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('User/Heroes:', () => {
|
describe('User/Heroes:', function() {
|
||||||
it('User is Bob - unauthorized', () => {
|
it('User is Bob - unauthorized', function () {
|
||||||
expectedMsgRx = /Bob, is not authorized/;
|
expectedMsgRx = /Bob, is not authorized/;
|
||||||
expect(element(by.css('#user')).getText()).toMatch(expectedMsgRx);
|
expect(element(by.css('#user')).getText()).toMatch(expectedMsgRx);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have button', () => {
|
it('should have button', function () {
|
||||||
expect(element.all(by.cssContainingText('button', 'Next User'))
|
expect(element.all(by.cssContainingText('button', 'Next User'))
|
||||||
.get(0).isDisplayed()).toBe(true, '\'Next User\' button should be displayed');
|
.get(0).isDisplayed()).toBe(true, '\'Next User\' button should be displayed');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('unauthorized user should have multiple unauthorized heroes', () => {
|
it('unauthorized user should have multiple unauthorized heroes', function () {
|
||||||
const heroes = element.all(by.css('#unauthorized app-hero-list div'));
|
let heroes = element.all(by.css('#unauthorized app-hero-list div'));
|
||||||
expect(heroes.count()).toBeGreaterThan(0);
|
expect(heroes.count()).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('unauthorized user should have no secret heroes', () => {
|
it('unauthorized user should have no secret heroes', function () {
|
||||||
const heroes = element.all(by.css('#unauthorized app-hero-list div'));
|
let heroes = element.all(by.css('#unauthorized app-hero-list div'));
|
||||||
expect(heroes.count()).toBeGreaterThan(0);
|
expect(heroes.count()).toBeGreaterThan(0);
|
||||||
|
|
||||||
const filteredHeroes = heroes.filter((elem: ElementFinder, index: number) => {
|
let filteredHeroes = heroes.filter((elem: ElementFinder, index: number) => {
|
||||||
return elem.getText().then((text: string) => /secret/.test(text));
|
return elem.getText().then((text: string) => {
|
||||||
|
return /secret/.test(text);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(filteredHeroes.count()).toEqual(0);
|
expect(filteredHeroes.count()).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('unauthorized user should have no authorized heroes listed', () => {
|
it('unauthorized user should have no authorized heroes listed', function () {
|
||||||
expect(element.all(by.css('#authorized app-hero-list div')).count()).toEqual(0);
|
expect(element.all(by.css('#authorized app-hero-list div')).count()).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('after button click', () => {
|
describe('after button click', function() {
|
||||||
|
|
||||||
beforeAll((done: any) => {
|
beforeAll(function (done: any) {
|
||||||
const buttonEle = element.all(by.cssContainingText('button', 'Next User')).get(0);
|
let buttonEle = element.all(by.cssContainingText('button', 'Next User')).get(0);
|
||||||
buttonEle.click().then(done, done);
|
buttonEle.click().then(done, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('User is Alice - authorized', () => {
|
it('User is Alice - authorized', function () {
|
||||||
expectedMsgRx = /Alice, is authorized/;
|
expectedMsgRx = /Alice, is authorized/;
|
||||||
expect(element(by.css('#user')).getText()).toMatch(expectedMsgRx);
|
expect(element(by.css('#user')).getText()).toMatch(expectedMsgRx);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('authorized user should have multiple authorized heroes ', () => {
|
it('authorized user should have multiple authorized heroes ', function () {
|
||||||
const heroes = element.all(by.css('#authorized app-hero-list div'));
|
let heroes = element.all(by.css('#authorized app-hero-list div'));
|
||||||
expect(heroes.count()).toBeGreaterThan(0);
|
expect(heroes.count()).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('authorized user should have multiple authorized heroes with tree-shakeable HeroesService', () => {
|
it('authorized user should have multiple authorized heroes with tree-shakeable HeroesService', function () {
|
||||||
const heroes = element.all(by.css('#tspAuthorized app-hero-list div'));
|
let heroes = element.all(by.css('#tspAuthorized app-hero-list div'));
|
||||||
expect(heroes.count()).toBeGreaterThan(0);
|
expect(heroes.count()).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('authorized user should have secret heroes', () => {
|
it('authorized user should have secret heroes', function () {
|
||||||
const heroes = element.all(by.css('#authorized app-hero-list div'));
|
let heroes = element.all(by.css('#authorized app-hero-list div'));
|
||||||
expect(heroes.count()).toBeGreaterThan(0);
|
expect(heroes.count()).toBeGreaterThan(0);
|
||||||
|
|
||||||
const filteredHeroes = heroes.filter((elem: ElementFinder, index: number) => {
|
let filteredHeroes = heroes.filter(function(elem: ElementFinder, index: number) {
|
||||||
return elem.getText().then((text: string) => /secret/.test(text));
|
return elem.getText().then(function(text: string) {
|
||||||
|
return /secret/.test(text);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(filteredHeroes.count()).toBeGreaterThan(0);
|
expect(filteredHeroes.count()).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('authorized user should have no unauthorized heroes listed', () => {
|
it('authorized user should have no unauthorized heroes listed', function () {
|
||||||
expect(element.all(by.css('#unauthorized app-hero-list div')).count()).toEqual(0);
|
expect(element.all(by.css('#unauthorized app-hero-list div')).count()).toEqual(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -7,7 +7,7 @@ import { Car, Engine, Tires } from './car';
|
|||||||
export function simpleCar() {
|
export function simpleCar() {
|
||||||
// #docregion car-ctor-instantiation
|
// #docregion car-ctor-instantiation
|
||||||
// Simple car with 4 cylinders and Flintstone tires.
|
// Simple car with 4 cylinders and Flintstone tires.
|
||||||
const car = new Car(new Engine(), new Tires());
|
let car = new Car(new Engine(), new Tires());
|
||||||
// #enddocregion car-ctor-instantiation
|
// #enddocregion car-ctor-instantiation
|
||||||
car.description = 'Simple';
|
car.description = 'Simple';
|
||||||
return car;
|
return car;
|
||||||
@ -20,12 +20,11 @@ class Engine2 {
|
|||||||
constructor(public cylinders: number) { }
|
constructor(public cylinders: number) { }
|
||||||
}
|
}
|
||||||
// #enddocregion car-ctor-instantiation-with-param
|
// #enddocregion car-ctor-instantiation-with-param
|
||||||
|
|
||||||
export function superCar() {
|
export function superCar() {
|
||||||
// #docregion car-ctor-instantiation-with-param
|
// #docregion car-ctor-instantiation-with-param
|
||||||
// Super car with 12 cylinders and Flintstone tires.
|
// Super car with 12 cylinders and Flintstone tires.
|
||||||
const bigCylinders = 12;
|
let bigCylinders = 12;
|
||||||
const car = new Car(new Engine2(bigCylinders), new Tires());
|
let car = new Car(new Engine2(bigCylinders), new Tires());
|
||||||
// #enddocregion car-ctor-instantiation-with-param
|
// #enddocregion car-ctor-instantiation-with-param
|
||||||
car.description = 'Super';
|
car.description = 'Super';
|
||||||
return car;
|
return car;
|
||||||
@ -40,7 +39,7 @@ class MockTires extends Tires { make = 'YokoGoodStone'; }
|
|||||||
export function testCar() {
|
export function testCar() {
|
||||||
// #docregion car-ctor-instantiation-with-mocks
|
// #docregion car-ctor-instantiation-with-mocks
|
||||||
// Test car with 8 cylinders and YokoGoodStone tires.
|
// Test car with 8 cylinders and YokoGoodStone tires.
|
||||||
const car = new Car(new MockEngine(), new MockTires());
|
let car = new Car(new MockEngine(), new MockTires());
|
||||||
// #enddocregion car-ctor-instantiation-with-mocks
|
// #enddocregion car-ctor-instantiation-with-mocks
|
||||||
car.description = 'Test';
|
car.description = 'Test';
|
||||||
return car;
|
return car;
|
||||||
|
@ -4,7 +4,7 @@ import { Engine, Tires, Car } from './car';
|
|||||||
// BAD pattern!
|
// BAD pattern!
|
||||||
export class CarFactory {
|
export class CarFactory {
|
||||||
createCar() {
|
createCar() {
|
||||||
const car = new Car(this.createEngine(), this.createTires());
|
let car = new Car(this.createEngine(), this.createTires());
|
||||||
car.description = 'Factory';
|
car.description = 'Factory';
|
||||||
return car;
|
return car;
|
||||||
}
|
}
|
||||||
|
@ -26,14 +26,14 @@ export function useInjector() {
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
// #docregion injector-call
|
// #docregion injector-call
|
||||||
const car = injector.get(Car);
|
let car = injector.get(Car);
|
||||||
// #enddocregion injector-call, injector-create-and-call
|
// #enddocregion injector-call, injector-create-and-call
|
||||||
car.description = 'Injector';
|
car.description = 'Injector';
|
||||||
|
|
||||||
injector = Injector.create({
|
injector = Injector.create({
|
||||||
providers: [{ provide: Logger, deps: [] }]
|
providers: [{ provide: Logger, deps: [] }]
|
||||||
});
|
});
|
||||||
const logger = injector.get(Logger);
|
let logger = injector.get(Logger);
|
||||||
logger.log('Injector car.drive() said: ' + car.drive());
|
logger.log('Injector car.drive() said: ' + car.drive());
|
||||||
return car;
|
return car;
|
||||||
}
|
}
|
||||||
|
@ -27,9 +27,9 @@ import { useInjector } from './car-injector';
|
|||||||
providers: [Car, Engine, Tires]
|
providers: [Car, Engine, Tires]
|
||||||
})
|
})
|
||||||
export class CarComponent {
|
export class CarComponent {
|
||||||
factoryCar = (new CarFactory()).createCar();
|
factoryCar = (new CarFactory).createCar();
|
||||||
injectorCar = useInjector();
|
injectorCar = useInjector();
|
||||||
noDiCar = new CarNoDi();
|
noDiCar = new CarNoDi;
|
||||||
simpleCar = simpleCar();
|
simpleCar = simpleCar();
|
||||||
superCar = superCar();
|
superCar = superCar();
|
||||||
testCar = testCar();
|
testCar = testCar();
|
||||||
|
@ -5,7 +5,7 @@ import { Logger } from '../logger.service';
|
|||||||
import { UserService } from '../user.service';
|
import { UserService } from '../user.service';
|
||||||
|
|
||||||
// #docregion factory
|
// #docregion factory
|
||||||
const heroServiceFactory = (logger: Logger, userService: UserService) => {
|
let heroServiceFactory = (logger: Logger, userService: UserService) => {
|
||||||
return new HeroService(logger, userService.user.isAuthorized);
|
return new HeroService(logger, userService.user.isAuthorized);
|
||||||
};
|
};
|
||||||
// #enddocregion factory
|
// #enddocregion factory
|
||||||
|
@ -17,7 +17,7 @@ export class HeroService {
|
|||||||
private isAuthorized: boolean) { }
|
private isAuthorized: boolean) { }
|
||||||
|
|
||||||
getHeroes() {
|
getHeroes() {
|
||||||
const auth = this.isAuthorized ? 'authorized ' : 'unauthorized';
|
let auth = this.isAuthorized ? 'authorized ' : 'unauthorized';
|
||||||
this.logger.log(`Getting heroes for ${auth} user.`);
|
this.logger.log(`Getting heroes for ${auth} user.`);
|
||||||
return HEROES.filter(hero => this.isAuthorized || !hero.isSecret);
|
return HEROES.filter(hero => this.isAuthorized || !hero.isSecret);
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ export class InjectorComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get rodent() {
|
get rodent() {
|
||||||
const rousDontExist = `R.O.U.S.'s? I don't think they exist!`;
|
let rousDontExist = `R.O.U.S.'s? I don't think they exist!`;
|
||||||
return this.injector.get(ROUS, rousDontExist);
|
return this.injector.get(ROUS, rousDontExist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ const template = '{{log}}';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'provider-1',
|
selector: 'provider-1',
|
||||||
template,
|
template: template,
|
||||||
// #docregion providers-1, providers-logger
|
// #docregion providers-1, providers-logger
|
||||||
providers: [Logger]
|
providers: [Logger]
|
||||||
// #enddocregion providers-1, providers-logger
|
// #enddocregion providers-1, providers-logger
|
||||||
@ -35,7 +35,7 @@ export class Provider1Component {
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'provider-3',
|
selector: 'provider-3',
|
||||||
template,
|
template: template,
|
||||||
providers:
|
providers:
|
||||||
// #docregion providers-3
|
// #docregion providers-3
|
||||||
[{ provide: Logger, useClass: Logger }]
|
[{ provide: Logger, useClass: Logger }]
|
||||||
@ -54,7 +54,7 @@ export class BetterLogger extends Logger {}
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'provider-4',
|
selector: 'provider-4',
|
||||||
template,
|
template: template,
|
||||||
providers:
|
providers:
|
||||||
// #docregion providers-4
|
// #docregion providers-4
|
||||||
[{ provide: Logger, useClass: BetterLogger }]
|
[{ provide: Logger, useClass: BetterLogger }]
|
||||||
@ -76,7 +76,7 @@ export class EvenBetterLogger extends Logger {
|
|||||||
constructor(private userService: UserService) { super(); }
|
constructor(private userService: UserService) { super(); }
|
||||||
|
|
||||||
log(message: string) {
|
log(message: string) {
|
||||||
const name = this.userService.user.name;
|
let name = this.userService.user.name;
|
||||||
super.log(`Message to ${name}: ${message}`);
|
super.log(`Message to ${name}: ${message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,7 +84,7 @@ export class EvenBetterLogger extends Logger {
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'provider-5',
|
selector: 'provider-5',
|
||||||
template,
|
template: template,
|
||||||
providers:
|
providers:
|
||||||
// #docregion providers-5
|
// #docregion providers-5
|
||||||
[ UserService,
|
[ UserService,
|
||||||
@ -107,12 +107,12 @@ export class OldLogger {
|
|||||||
logs: string[] = [];
|
logs: string[] = [];
|
||||||
log(message: string) {
|
log(message: string) {
|
||||||
throw new Error('Should not call the old logger!');
|
throw new Error('Should not call the old logger!');
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'provider-6a',
|
selector: 'provider-6a',
|
||||||
template,
|
template: template,
|
||||||
providers:
|
providers:
|
||||||
// #docregion providers-6a
|
// #docregion providers-6a
|
||||||
[ NewLogger,
|
[ NewLogger,
|
||||||
@ -135,7 +135,7 @@ export class Provider6aComponent {
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'provider-6b',
|
selector: 'provider-6b',
|
||||||
template,
|
template: template,
|
||||||
providers:
|
providers:
|
||||||
// #docregion providers-6b
|
// #docregion providers-6b
|
||||||
[ NewLogger,
|
[ NewLogger,
|
||||||
@ -168,7 +168,7 @@ export const SilentLogger = {
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'provider-7',
|
selector: 'provider-7',
|
||||||
template,
|
template: template,
|
||||||
providers:
|
providers:
|
||||||
// #docregion providers-7
|
// #docregion providers-7
|
||||||
[{ provide: Logger, useValue: SilentLogger }]
|
[{ provide: Logger, useValue: SilentLogger }]
|
||||||
@ -186,7 +186,7 @@ export class Provider7Component {
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'provider-8',
|
selector: 'provider-8',
|
||||||
template,
|
template: template,
|
||||||
providers: [heroServiceProvider, Logger, UserService]
|
providers: [heroServiceProvider, Logger, UserService]
|
||||||
})
|
})
|
||||||
export class Provider8Component {
|
export class Provider8Component {
|
||||||
@ -202,7 +202,7 @@ export class Provider8Component {
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'provider-9',
|
selector: 'provider-9',
|
||||||
template,
|
template: template,
|
||||||
/*
|
/*
|
||||||
// #docregion providers-9-interface
|
// #docregion providers-9-interface
|
||||||
// FAIL! Can't use interface as provider token
|
// FAIL! Can't use interface as provider token
|
||||||
@ -237,11 +237,11 @@ export class Provider9Component implements OnInit {
|
|||||||
import { Optional } from '@angular/core';
|
import { Optional } from '@angular/core';
|
||||||
// #enddocregion import-optional
|
// #enddocregion import-optional
|
||||||
|
|
||||||
const someMessage = 'Hello from the injected logger';
|
let some_message = 'Hello from the injected logger';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'provider-10',
|
selector: 'provider-10',
|
||||||
template,
|
template: template,
|
||||||
providers: [{ provide: Logger, useValue: null }]
|
providers: [{ provide: Logger, useValue: null }]
|
||||||
})
|
})
|
||||||
export class Provider10Component implements OnInit {
|
export class Provider10Component implements OnInit {
|
||||||
@ -249,7 +249,7 @@ export class Provider10Component implements OnInit {
|
|||||||
// #docregion provider-10-ctor
|
// #docregion provider-10-ctor
|
||||||
constructor(@Optional() private logger?: Logger) {
|
constructor(@Optional() private logger?: Logger) {
|
||||||
if (this.logger) {
|
if (this.logger) {
|
||||||
this.logger.log(someMessage);
|
this.logger.log(some_message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion provider-10-ctor
|
// #enddocregion provider-10-ctor
|
||||||
|
@ -43,7 +43,7 @@ var testResults: {pass: string; message: string};
|
|||||||
|
|
||||||
function expect(actual: any) {
|
function expect(actual: any) {
|
||||||
return {
|
return {
|
||||||
toEqual: (expected: any) => {
|
toEqual: function(expected: any){
|
||||||
testResults = actual === expected ?
|
testResults = actual === expected ?
|
||||||
{pass: 'passed', message: testName} :
|
{pass: 'passed', message: testName} :
|
||||||
{pass: 'failed', message: `${testName}; expected ${actual} to equal ${expected}.`};
|
{pass: 'failed', message: `${testName}; expected ${actual} to equal ${expected}.`};
|
||||||
|
@ -8,8 +8,8 @@ export class User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: get the user; don't 'new' it.
|
// TODO: get the user; don't 'new' it.
|
||||||
const alice = new User('Alice', true);
|
let alice = new User('Alice', true);
|
||||||
const bob = new User('Bob', false);
|
let bob = new User('Bob', false);
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
@ -1,27 +1,29 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Displaying Data Tests', () => {
|
describe('Displaying Data Tests', function () {
|
||||||
const title = 'Tour of Heroes';
|
let _title = 'Tour of Heroes';
|
||||||
const defaultHero = 'Windstorm';
|
let _defaultHero = 'Windstorm';
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display correct title: ' + title, () => {
|
it('should display correct title: ' + _title, function () {
|
||||||
expect(element(by.css('h1')).getText()).toEqual(title);
|
expect(element(by.css('h1')).getText()).toEqual(_title);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have correct default hero: ' + defaultHero, () => {
|
it('should have correct default hero: ' + _defaultHero, function () {
|
||||||
expect(element(by.css('h2')).getText()).toContain(defaultHero);
|
expect(element(by.css('h2')).getText()).toContain(_defaultHero);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have heroes', () => {
|
it('should have heroes', function () {
|
||||||
const heroEls = element.all(by.css('li'));
|
let heroEls = element.all(by.css('li'));
|
||||||
expect(heroEls.count()).not.toBe(0, 'should have heroes');
|
expect(heroEls.count()).not.toBe(0, 'should have heroes');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display "there are many heroes!"', () => {
|
it('should display "there are many heroes!"', function () {
|
||||||
expect(element(by.css('ul ~ p')).getText()).toContain('There are many heroes!');
|
expect(element(by.css('ul ~ p')).getText()).toContain('There are many heroes!');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Docs Style Guide', () => {
|
describe('Docs Style Guide', function () {
|
||||||
const title = 'Authors Style Guide Sample';
|
let _title = 'Authors Style Guide Sample';
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display correct title: ' + title, () => {
|
it('should display correct title: ' + _title, function () {
|
||||||
expect(element(by.css('h1')).getText()).toEqual(title);
|
expect(element(by.css('h1')).getText()).toEqual(_title);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
/* tslint:disable:quotemark */
|
/* tslint:disable:quotemark */
|
||||||
describe('Dynamic Component Loader', () => {
|
describe('Dynamic Component Loader', function () {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load ad banner', () => {
|
it('should load ad banner', function () {
|
||||||
const headline = element(by.xpath("//h4[text()='Featured Hero Profile']"));
|
let headline = element(by.xpath("//h4[text()='Featured Hero Profile']"));
|
||||||
const name = element(by.xpath("//h3[text()='Bombasto']"));
|
let name = element(by.xpath("//h3[text()='Bombasto']"));
|
||||||
const bio = element(by.xpath("//p[text()='Brave as they come']"));
|
let bio = element(by.xpath("//p[text()='Brave as they come']"));
|
||||||
|
|
||||||
expect(name).toBeDefined();
|
expect(name).toBeDefined();
|
||||||
expect(headline).toBeDefined();
|
expect(headline).toBeDefined();
|
||||||
|
@ -11,7 +11,7 @@ import { AdComponent } from './ad.component';
|
|||||||
template: `
|
template: `
|
||||||
<div class="ad-banner-example">
|
<div class="ad-banner-example">
|
||||||
<h3>Advertisements</h3>
|
<h3>Advertisements</h3>
|
||||||
<ng-template adHost></ng-template>
|
<ng-template ad-host></ng-template>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
// #enddocregion ad-host
|
// #enddocregion ad-host
|
||||||
@ -43,8 +43,8 @@ export class AdBannerComponent implements OnInit, OnDestroy {
|
|||||||
const viewContainerRef = this.adHost.viewContainerRef;
|
const viewContainerRef = this.adHost.viewContainerRef;
|
||||||
viewContainerRef.clear();
|
viewContainerRef.clear();
|
||||||
|
|
||||||
const componentRef = viewContainerRef.createComponent<AdComponent>(componentFactory);
|
const componentRef = viewContainerRef.createComponent(componentFactory);
|
||||||
componentRef.instance.data = adItem.data;
|
(<AdComponent>componentRef.instance).data = adItem.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
getAds() {
|
getAds() {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
// tslint:disable: directive-selector
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { Directive, ViewContainerRef } from '@angular/core';
|
import { Directive, ViewContainerRef } from '@angular/core';
|
||||||
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[adHost]',
|
selector: '[ad-host]',
|
||||||
})
|
})
|
||||||
export class AdDirective {
|
export class AdDirective {
|
||||||
constructor(public viewContainerRef: ViewContainerRef) { }
|
constructor(public viewContainerRef: ViewContainerRef) { }
|
||||||
|
@ -1,25 +1,27 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
/* tslint:disable:quotemark */
|
/* tslint:disable:quotemark */
|
||||||
describe('Dynamic Form', () => {
|
describe('Dynamic Form', function () {
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should submit form', () => {
|
it('should submit form', function () {
|
||||||
const firstNameElement = element.all(by.css('input[id=firstName]')).get(0);
|
let firstNameElement = element.all(by.css('input[id=firstName]')).get(0);
|
||||||
expect(firstNameElement.getAttribute('value')).toEqual('Bombasto');
|
expect(firstNameElement.getAttribute('value')).toEqual('Bombasto');
|
||||||
|
|
||||||
const emailElement = element.all(by.css('input[id=emailAddress]')).get(0);
|
let emailElement = element.all(by.css('input[id=emailAddress]')).get(0);
|
||||||
const email = 'test@test.com';
|
let email = 'test@test.com';
|
||||||
emailElement.sendKeys(email);
|
emailElement.sendKeys(email);
|
||||||
expect(emailElement.getAttribute('value')).toEqual(email);
|
expect(emailElement.getAttribute('value')).toEqual(email);
|
||||||
|
|
||||||
element(by.css('select option[value="solid"]')).click();
|
element(by.css('select option[value="solid"]')).click();
|
||||||
|
|
||||||
const saveButton = element.all(by.css('button')).get(0);
|
let saveButton = element.all(by.css('button')).get(0);
|
||||||
saveButton.click().then(() => {
|
saveButton.click().then(function() {
|
||||||
expect(element(by.xpath("//strong[contains(text(),'Saved the following values')]")).isPresent()).toBe(true);
|
expect(element(by.xpath("//strong[contains(text(),'Saved the following values')]")).isPresent()).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -10,14 +10,13 @@ export class QuestionBase<T> {
|
|||||||
options: {key: string, value: string}[];
|
options: {key: string, value: string}[];
|
||||||
|
|
||||||
constructor(options: {
|
constructor(options: {
|
||||||
value?: T;
|
value?: T,
|
||||||
key?: string;
|
key?: string,
|
||||||
label?: string;
|
label?: string,
|
||||||
required?: boolean;
|
required?: boolean,
|
||||||
order?: number;
|
order?: number,
|
||||||
controlType?: string;
|
controlType?: string,
|
||||||
type?: string;
|
type?: string
|
||||||
options?: {key: string, value: string}[];
|
|
||||||
} = {}) {
|
} = {}) {
|
||||||
this.value = options.value;
|
this.value = options.value;
|
||||||
this.key = options.key || '';
|
this.key = options.key || '';
|
||||||
@ -26,6 +25,5 @@ export class QuestionBase<T> {
|
|||||||
this.order = options.order === undefined ? 1 : options.order;
|
this.order = options.order === undefined ? 1 : options.order;
|
||||||
this.controlType = options.controlType || '';
|
this.controlType = options.controlType || '';
|
||||||
this.type = options.type || '';
|
this.type = options.type || '';
|
||||||
this.options = options.options || [];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ export class QuestionControlService {
|
|||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
toFormGroup(questions: QuestionBase<string>[] ) {
|
toFormGroup(questions: QuestionBase<string>[] ) {
|
||||||
const group: any = {};
|
let group: any = {};
|
||||||
|
|
||||||
questions.forEach(question => {
|
questions.forEach(question => {
|
||||||
group[question.key] = question.required ? new FormControl(question.value || '', Validators.required)
|
group[question.key] = question.required ? new FormControl(question.value || '', Validators.required)
|
||||||
|
@ -3,4 +3,10 @@ import { QuestionBase } from './question-base';
|
|||||||
|
|
||||||
export class DropdownQuestion extends QuestionBase<string> {
|
export class DropdownQuestion extends QuestionBase<string> {
|
||||||
controlType = 'dropdown';
|
controlType = 'dropdown';
|
||||||
|
options: {key: string, value: string}[] = [];
|
||||||
|
|
||||||
|
constructor(options: {} = {}) {
|
||||||
|
super(options);
|
||||||
|
this.options = options['options'] || [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,10 @@ import { QuestionBase } from './question-base';
|
|||||||
|
|
||||||
export class TextboxQuestion extends QuestionBase<string> {
|
export class TextboxQuestion extends QuestionBase<string> {
|
||||||
controlType = 'textbox';
|
controlType = 'textbox';
|
||||||
|
type: string;
|
||||||
|
|
||||||
|
constructor(options: {} = {}) {
|
||||||
|
super(options);
|
||||||
|
this.type = options['type'] || '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ export class QuestionService {
|
|||||||
// TODO: get from a remote source of question metadata
|
// TODO: get from a remote source of question metadata
|
||||||
getQuestions() {
|
getQuestions() {
|
||||||
|
|
||||||
const questions: QuestionBase<string>[] = [
|
let questions: QuestionBase<string>[] = [
|
||||||
|
|
||||||
new DropdownQuestion({
|
new DropdownQuestion({
|
||||||
key: 'brave',
|
key: 'brave',
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, by, element, ElementFinder, ExpectedConditions as EC } from 'protractor';
|
import { browser, by, element, ElementFinder, ExpectedConditions as EC } from 'protractor';
|
||||||
|
|
||||||
/* tslint:disable:quotemark */
|
/* tslint:disable:quotemark */
|
||||||
@ -14,7 +16,7 @@ describe('Elements', () => {
|
|||||||
const waitForText = (elem: ElementFinder) => {
|
const waitForText = (elem: ElementFinder) => {
|
||||||
// Waiting for the element to have some text, makes the tests less flaky.
|
// Waiting for the element to have some text, makes the tests less flaky.
|
||||||
browser.wait(async () => /\S/.test(await elem.getText()), 5000);
|
browser.wait(async () => /\S/.test(await elem.getText()), 5000);
|
||||||
};
|
}
|
||||||
|
|
||||||
beforeEach(() => browser.get(''));
|
beforeEach(() => browser.get(''));
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
// tslint:disable: variable-name
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
// #docregion
|
|
||||||
import { Component, EventEmitter, HostBinding, Input, Output } from '@angular/core';
|
|
||||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -9,6 +7,9 @@ import { animate, state, style, transition, trigger } from '@angular/animations'
|
|||||||
<span>Popup: {{message}}</span>
|
<span>Popup: {{message}}</span>
|
||||||
<button (click)="closed.next()">✖</button>
|
<button (click)="closed.next()">✖</button>
|
||||||
`,
|
`,
|
||||||
|
host: {
|
||||||
|
'[@state]': 'state',
|
||||||
|
},
|
||||||
animations: [
|
animations: [
|
||||||
trigger('state', [
|
trigger('state', [
|
||||||
state('opened', style({transform: 'translateY(0%)'})),
|
state('opened', style({transform: 'translateY(0%)'})),
|
||||||
@ -38,16 +39,15 @@ import { animate, state, style, transition, trigger } from '@angular/animations'
|
|||||||
`]
|
`]
|
||||||
})
|
})
|
||||||
export class PopupComponent {
|
export class PopupComponent {
|
||||||
@HostBinding('@state')
|
|
||||||
state: 'opened' | 'closed' = 'closed';
|
state: 'opened' | 'closed' = 'closed';
|
||||||
|
|
||||||
@Input()
|
@Input()
|
||||||
get message(): string { return this._message; }
|
|
||||||
set message(message: string) {
|
set message(message: string) {
|
||||||
this._message = message;
|
this._message = message;
|
||||||
this.state = 'opened';
|
this.state = 'opened';
|
||||||
}
|
}
|
||||||
private _message: string;
|
get message(): string { return this._message; }
|
||||||
|
_message: string;
|
||||||
|
|
||||||
@Output()
|
@Output()
|
||||||
closed = new EventEmitter();
|
closed = new EventEmitter();
|
||||||
|
@ -1,24 +1,26 @@
|
|||||||
import { browser, element, by } from 'protractor';
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
describe('Event binding example', () => {
|
import { browser, element, by, protractor } from 'protractor';
|
||||||
|
|
||||||
beforeEach(() => {
|
describe('Event binding example', function () {
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
const saveButton = element.all(by.css('button')).get(0);
|
let saveButton = element.all(by.css('button')).get(0);
|
||||||
const onSaveButton = element.all(by.css('button')).get(1);
|
let onSaveButton = element.all(by.css('button')).get(1);
|
||||||
const myClick = element.all(by.css('button')).get(2);
|
let myClick = element.all(by.css('button')).get(2);
|
||||||
const deleteButton = element.all(by.css('button')).get(3);
|
let deleteButton = element.all(by.css('button')).get(3);
|
||||||
const saveNoProp = element.all(by.css('button')).get(4);
|
let saveNoProp = element.all(by.css('button')).get(4);
|
||||||
const saveProp = element.all(by.css('button')).get(5);
|
let saveProp = element.all(by.css('button')).get(5);
|
||||||
|
|
||||||
|
|
||||||
it('should display Event Binding with Angular', () => {
|
it('should display Event Binding with Angular', function () {
|
||||||
expect(element(by.css('h1')).getText()).toEqual('Event Binding');
|
expect(element(by.css('h1')).getText()).toEqual('Event Binding');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display 6 buttons', () => {
|
it('should display 6 buttons', function() {
|
||||||
expect(saveButton.getText()).toBe('Save');
|
expect(saveButton.getText()).toBe('Save');
|
||||||
expect(onSaveButton.getText()).toBe('on-click Save');
|
expect(onSaveButton.getText()).toBe('on-click Save');
|
||||||
expect(myClick.getText()).toBe('click with myClick');
|
expect(myClick.getText()).toBe('click with myClick');
|
||||||
@ -27,23 +29,24 @@ describe('Event binding example', () => {
|
|||||||
expect(saveProp.getText()).toBe('Save with propagation');
|
expect(saveProp.getText()).toBe('Save with propagation');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support user input', () => {
|
it('should support user input', function () {
|
||||||
const input = element(by.css('input'));
|
let input = element(by.css('input'));
|
||||||
const bindingResult = element.all(by.css('h4')).get(1);
|
let bindingResult = element.all(by.css('h4')).get(1);
|
||||||
expect(bindingResult.getText()).toEqual('Result: teapot');
|
expect(bindingResult.getText()).toEqual('Result: teapot');
|
||||||
input.sendKeys('abc');
|
input.sendKeys('abc');
|
||||||
expect(bindingResult.getText()).toEqual('Result: teapotabc');
|
expect(bindingResult.getText()).toEqual('Result: teapotabc');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should hide the item img', async () => {
|
it('should hide the item img', async () => {
|
||||||
|
let deleteButton = element.all(by.css('button')).get(3);
|
||||||
await deleteButton.click();
|
await deleteButton.click();
|
||||||
browser.switchTo().alert().accept();
|
browser.switchTo().alert().accept();
|
||||||
expect(element.all(by.css('img')).get(0).getCssValue('display')).toEqual('none');
|
expect(element.all(by.css('img')).get(0).getCssValue('display')).toEqual('none');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show two alerts', async () => {
|
it('should show two alerts', async () => {
|
||||||
const parentDiv = element.all(by.css('.parent-div'));
|
let parentDiv = element.all(by.css('.parent-div'));
|
||||||
const childDiv = element.all(by.css('div > div')).get(1);
|
let childDiv = element.all(by.css('div > div')).get(1);
|
||||||
await parentDiv.click();
|
await parentDiv.click();
|
||||||
browser.switchTo().alert().accept();
|
browser.switchTo().alert().accept();
|
||||||
expect(childDiv.getText()).toEqual('Click me too! (child)');
|
expect(childDiv.getText()).toEqual('Click me too! (child)');
|
||||||
|
@ -12,7 +12,7 @@ export class AppComponent {
|
|||||||
clickMessage = '';
|
clickMessage = '';
|
||||||
|
|
||||||
onSave(event?: KeyboardEvent) {
|
onSave(event?: KeyboardEvent) {
|
||||||
const evtMsg = event ? ' Event target is ' + (event.target as HTMLElement).textContent : '';
|
const evtMsg = event ? ' Event target is ' + (<HTMLElement>event.target).textContent : '';
|
||||||
alert('Saved.' + evtMsg);
|
alert('Saved.' + evtMsg);
|
||||||
if (event) { event.stopPropagation(); }
|
if (event) { event.stopPropagation(); }
|
||||||
}
|
}
|
||||||
@ -22,7 +22,7 @@ export class AppComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClickMe(event?: KeyboardEvent) {
|
onClickMe(event?: KeyboardEvent) {
|
||||||
const evtMsg = event ? ' Event target class is ' + (event.target as HTMLElement).className : '';
|
const evtMsg = event ? ' Event target class is ' + (<HTMLElement>event.target).className : '';
|
||||||
alert('Click me.' + evtMsg);
|
alert('Click me.' + evtMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// tslint:disable: directive-selector
|
/* tslint:disable use-output-property-decorator directive-class-suffix */
|
||||||
import { Directive, ElementRef, EventEmitter, Output } from '@angular/core';
|
import { Directive, ElementRef, EventEmitter, Output } from '@angular/core';
|
||||||
|
|
||||||
@Directive({selector: '[myClick]'})
|
@Directive({selector: '[myClick]'})
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
|
'use strict'; // necessary for node!
|
||||||
|
|
||||||
import { browser, element, by, protractor, ElementFinder, ElementArrayFinder } from 'protractor';
|
import { browser, element, by, protractor, ElementFinder, ElementArrayFinder } from 'protractor';
|
||||||
|
|
||||||
// THESE TESTS ARE INCOMPLETE
|
// THESE TESTS ARE INCOMPLETE
|
||||||
describe('Form Validation Tests', () => {
|
describe('Form Validation Tests', function () {
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -50,11 +52,11 @@ let page: {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function getPage(sectionTag: string) {
|
function getPage(sectionTag: string) {
|
||||||
const section = element(by.css(sectionTag));
|
let section = element(by.css(sectionTag));
|
||||||
const buttons = section.all(by.css('button'));
|
let buttons = section.all(by.css('button'));
|
||||||
|
|
||||||
page = {
|
page = {
|
||||||
section,
|
section: section,
|
||||||
form: section.element(by.css('form')),
|
form: section.element(by.css('form')),
|
||||||
title: section.element(by.css('h1')),
|
title: section.element(by.css('h1')),
|
||||||
nameInput: section.element(by.css('#name')),
|
nameInput: section.element(by.css('#name')),
|
||||||
@ -71,31 +73,31 @@ function getPage(sectionTag: string) {
|
|||||||
|
|
||||||
function tests(title: string) {
|
function tests(title: string) {
|
||||||
|
|
||||||
it('should display correct title', () => {
|
it('should display correct title', function () {
|
||||||
expect(page.title.getText()).toContain(title);
|
expect(page.title.getText()).toContain(title);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not display submitted message before submit', () => {
|
it('should not display submitted message before submit', function () {
|
||||||
expect(page.heroSubmitted.isElementPresent(by.css('p'))).toBe(false);
|
expect(page.heroSubmitted.isElementPresent(by.css('p'))).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have form buttons', () => {
|
it('should have form buttons', function () {
|
||||||
expect(page.heroFormButtons.count()).toEqual(2);
|
expect(page.heroFormButtons.count()).toEqual(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have error at start', () => {
|
it('should have error at start', function () {
|
||||||
expectFormIsInvalid();
|
expectFormIsInvalid();
|
||||||
});
|
});
|
||||||
|
|
||||||
// it('showForm', () => {
|
// it('showForm', function () {
|
||||||
// page.form.getInnerHtml().then(html => console.log(html));
|
// page.form.getInnerHtml().then(html => console.log(html));
|
||||||
// });
|
// });
|
||||||
|
|
||||||
it('should have disabled submit button', () => {
|
it('should have disabled submit button', function () {
|
||||||
expect(page.heroFormButtons.get(0).isEnabled()).toBe(false);
|
expect(page.heroFormButtons.get(0).isEnabled()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('resetting name to valid name should clear errors', () => {
|
it('resetting name to valid name should clear errors', function () {
|
||||||
const ele = page.nameInput;
|
const ele = page.nameInput;
|
||||||
expect(ele.isPresent()).toBe(true, 'nameInput should exist');
|
expect(ele.isPresent()).toBe(true, 'nameInput should exist');
|
||||||
ele.clear();
|
ele.clear();
|
||||||
@ -103,7 +105,7 @@ function tests(title: string) {
|
|||||||
expectFormIsValid();
|
expectFormIsValid();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should produce "required" error after clearing name', () => {
|
it('should produce "required" error after clearing name', function () {
|
||||||
page.nameInput.clear();
|
page.nameInput.clear();
|
||||||
// page.alterEgoInput.click(); // to blur ... didn't work
|
// page.alterEgoInput.click(); // to blur ... didn't work
|
||||||
page.nameInput.sendKeys('x', protractor.Key.BACK_SPACE); // ugh!
|
page.nameInput.sendKeys('x', protractor.Key.BACK_SPACE); // ugh!
|
||||||
@ -111,37 +113,37 @@ function tests(title: string) {
|
|||||||
expect(page.errorMessages.get(0).getText()).toContain('required');
|
expect(page.errorMessages.get(0).getText()).toContain('required');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should produce "at least 4 characters" error when name="x"', () => {
|
it('should produce "at least 4 characters" error when name="x"', function () {
|
||||||
page.nameInput.clear();
|
page.nameInput.clear();
|
||||||
page.nameInput.sendKeys('x'); // too short
|
page.nameInput.sendKeys('x'); // too short
|
||||||
expectFormIsInvalid();
|
expectFormIsInvalid();
|
||||||
expect(page.errorMessages.get(0).getText()).toContain('at least 4 characters');
|
expect(page.errorMessages.get(0).getText()).toContain('at least 4 characters');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('resetting name to valid name again should clear errors', () => {
|
it('resetting name to valid name again should clear errors', function () {
|
||||||
page.nameInput.sendKeys(testName);
|
page.nameInput.sendKeys(testName);
|
||||||
expectFormIsValid();
|
expectFormIsValid();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have enabled submit button', () => {
|
it('should have enabled submit button', function () {
|
||||||
const submitBtn = page.heroFormButtons.get(0);
|
const submitBtn = page.heroFormButtons.get(0);
|
||||||
expect(submitBtn.isEnabled()).toBe(true);
|
expect(submitBtn.isEnabled()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should hide form after submit', () => {
|
it('should hide form after submit', function () {
|
||||||
page.heroFormButtons.get(0).click();
|
page.heroFormButtons.get(0).click();
|
||||||
expect(page.heroFormButtons.get(0).isDisplayed()).toBe(false);
|
expect(page.heroFormButtons.get(0).isDisplayed()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('submitted form should be displayed', () => {
|
it('submitted form should be displayed', function () {
|
||||||
expect(page.heroSubmitted.isElementPresent(by.css('p'))).toBe(true);
|
expect(page.heroSubmitted.isElementPresent(by.css('p'))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('submitted form should have new hero name', () => {
|
it('submitted form should have new hero name', function () {
|
||||||
expect(page.heroSubmitted.getText()).toContain(testName);
|
expect(page.heroSubmitted.getText()).toContain(testName);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('clicking edit button should reveal form again', () => {
|
it('clicking edit button should reveal form again', function () {
|
||||||
const newFormBtn = page.heroSubmitted.element(by.css('button'));
|
const newFormBtn = page.heroSubmitted.element(by.css('button'));
|
||||||
newFormBtn.click();
|
newFormBtn.click();
|
||||||
expect(page.heroSubmitted.isElementPresent(by.css('p')))
|
expect(page.heroSubmitted.isElementPresent(by.css('p')))
|
||||||
@ -160,7 +162,7 @@ function expectFormIsInvalid() {
|
|||||||
|
|
||||||
function triggerAlterEgoValidation() {
|
function triggerAlterEgoValidation() {
|
||||||
// alterEgo has updateOn set to 'blur', click outside of the input to trigger the blur event
|
// alterEgo has updateOn set to 'blur', click outside of the input to trigger the blur event
|
||||||
element(by.css('app-root')).click();
|
element(by.css('app-root')).click()
|
||||||
}
|
}
|
||||||
|
|
||||||
function waitForAlterEgoValidation() {
|
function waitForAlterEgoValidation() {
|
||||||
@ -171,7 +173,7 @@ function waitForAlterEgoValidation() {
|
|||||||
function bobTests() {
|
function bobTests() {
|
||||||
const emsg = 'Name cannot be Bob.';
|
const emsg = 'Name cannot be Bob.';
|
||||||
|
|
||||||
it('should produce "no bob" error after setting name to "Bobby"', () => {
|
it('should produce "no bob" error after setting name to "Bobby"', function () {
|
||||||
// Re-populate select element
|
// Re-populate select element
|
||||||
page.powerSelect.click();
|
page.powerSelect.click();
|
||||||
page.powerOption.click();
|
page.powerOption.click();
|
||||||
@ -182,7 +184,7 @@ function bobTests() {
|
|||||||
expect(page.errorMessages.get(0).getText()).toBe(emsg);
|
expect(page.errorMessages.get(0).getText()).toBe(emsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be ok again with valid name', () => {
|
it('should be ok again with valid name', function () {
|
||||||
page.nameInput.clear();
|
page.nameInput.clear();
|
||||||
page.nameInput.sendKeys(testName);
|
page.nameInput.sendKeys(testName);
|
||||||
expectFormIsValid();
|
expectFormIsValid();
|
||||||
@ -192,7 +194,7 @@ function bobTests() {
|
|||||||
function asyncValidationTests() {
|
function asyncValidationTests() {
|
||||||
const emsg = 'Alter ego is already taken.';
|
const emsg = 'Alter ego is already taken.';
|
||||||
|
|
||||||
it(`should produce "${emsg}" error after setting alterEgo to Eric`, () => {
|
it(`should produce "${emsg}" error after setting alterEgo to Eric`, function () {
|
||||||
page.alterEgoInput.clear();
|
page.alterEgoInput.clear();
|
||||||
page.alterEgoInput.sendKeys('Eric');
|
page.alterEgoInput.sendKeys('Eric');
|
||||||
|
|
||||||
@ -203,7 +205,7 @@ function asyncValidationTests() {
|
|||||||
expect(page.alterEgoErrors.getText()).toBe(emsg);
|
expect(page.alterEgoErrors.getText()).toBe(emsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be ok again with different values', () => {
|
it('should be ok again with different values', function () {
|
||||||
page.alterEgoInput.clear();
|
page.alterEgoInput.clear();
|
||||||
page.alterEgoInput.sendKeys('John');
|
page.alterEgoInput.sendKeys('John');
|
||||||
|
|
||||||
@ -218,7 +220,7 @@ function asyncValidationTests() {
|
|||||||
function crossValidationTests() {
|
function crossValidationTests() {
|
||||||
const emsg = 'Name cannot match alter ego.';
|
const emsg = 'Name cannot match alter ego.';
|
||||||
|
|
||||||
it(`should produce "${emsg}" error after setting name and alter ego to the same value`, () => {
|
it(`should produce "${emsg}" error after setting name and alter ego to the same value`, function () {
|
||||||
page.nameInput.clear();
|
page.nameInput.clear();
|
||||||
page.nameInput.sendKeys('Batman');
|
page.nameInput.sendKeys('Batman');
|
||||||
|
|
||||||
@ -232,7 +234,7 @@ function crossValidationTests() {
|
|||||||
expect(page.crossValidationErrorMessage.getText()).toBe(emsg);
|
expect(page.crossValidationErrorMessage.getText()).toBe(emsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be ok again with different values', () => {
|
it('should be ok again with different values', function () {
|
||||||
page.nameInput.clear();
|
page.nameInput.clear();
|
||||||
page.nameInput.sendKeys('Batman');
|
page.nameInput.sendKeys('Batman');
|
||||||
|
|
||||||
|
@ -22,13 +22,13 @@ export class HeroFormReactiveComponent implements OnInit {
|
|||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
// #docregion custom-validator
|
// #docregion custom-validator
|
||||||
this.heroForm = new FormGroup({
|
this.heroForm = new FormGroup({
|
||||||
name: new FormControl(this.hero.name, [
|
'name': new FormControl(this.hero.name, [
|
||||||
Validators.required,
|
Validators.required,
|
||||||
Validators.minLength(4),
|
Validators.minLength(4),
|
||||||
forbiddenNameValidator(/bob/i) // <-- Here's how you pass in the custom validator.
|
forbiddenNameValidator(/bob/i) // <-- Here's how you pass in the custom validator.
|
||||||
]),
|
]),
|
||||||
alterEgo: new FormControl(this.hero.alterEgo),
|
'alterEgo': new FormControl(this.hero.alterEgo),
|
||||||
power: new FormControl(this.hero.power, Validators.required)
|
'power': new FormControl(this.hero.power, Validators.required)
|
||||||
});
|
});
|
||||||
// #enddocregion custom-validator
|
// #enddocregion custom-validator
|
||||||
|
|
||||||
|
@ -22,16 +22,16 @@ export class HeroFormReactiveComponent implements OnInit {
|
|||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
// #docregion async-validation
|
// #docregion async-validation
|
||||||
this.heroForm = new FormGroup({
|
this.heroForm = new FormGroup({
|
||||||
name: new FormControl(this.hero.name, [
|
'name': new FormControl(this.hero.name, [
|
||||||
Validators.required,
|
Validators.required,
|
||||||
Validators.minLength(4),
|
Validators.minLength(4),
|
||||||
forbiddenNameValidator(/bob/i)
|
forbiddenNameValidator(/bob/i)
|
||||||
]),
|
]),
|
||||||
alterEgo: new FormControl(this.hero.alterEgo, {
|
'alterEgo': new FormControl(this.hero.alterEgo, {
|
||||||
asyncValidators: [this.alterEgoValidator.validate.bind(this.alterEgoValidator)],
|
asyncValidators: [this.alterEgoValidator.validate.bind(this.alterEgoValidator)],
|
||||||
updateOn: 'blur'
|
updateOn: 'blur'
|
||||||
}),
|
}),
|
||||||
power: new FormControl(this.hero.power, Validators.required)
|
'power': new FormControl(this.hero.power, Validators.required)
|
||||||
});
|
});
|
||||||
// #enddocregion async-validation
|
// #enddocregion async-validation
|
||||||
}
|
}
|
||||||
|
@ -21,16 +21,16 @@ export class HeroFormReactiveComponent implements OnInit {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.heroForm = new FormGroup({
|
this.heroForm = new FormGroup({
|
||||||
name: new FormControl(this.hero.name, [
|
'name': new FormControl(this.hero.name, [
|
||||||
Validators.required,
|
Validators.required,
|
||||||
Validators.minLength(4),
|
Validators.minLength(4),
|
||||||
forbiddenNameValidator(/bob/i)
|
forbiddenNameValidator(/bob/i)
|
||||||
]),
|
]),
|
||||||
alterEgo: new FormControl(this.hero.alterEgo, {
|
'alterEgo': new FormControl(this.hero.alterEgo, {
|
||||||
asyncValidators: [this.alterEgoValidator.validate.bind(this.alterEgoValidator)],
|
asyncValidators: [this.alterEgoValidator.validate.bind(this.alterEgoValidator)],
|
||||||
updateOn: 'blur'
|
updateOn: 'blur'
|
||||||
}),
|
}),
|
||||||
power: new FormControl(this.hero.power, Validators.required)
|
'power': new FormControl(this.hero.power, Validators.required)
|
||||||
}, { validators: identityRevealedValidator }); // <-- add custom validator at the FormGroup level
|
}, { validators: identityRevealedValidator }); // <-- add custom validator at the FormGroup level
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import { AbstractControl, NG_VALIDATORS, Validator, ValidatorFn, Validators } fr
|
|||||||
export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
|
export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
|
||||||
return (control: AbstractControl): {[key: string]: any} | null => {
|
return (control: AbstractControl): {[key: string]: any} | null => {
|
||||||
const forbidden = nameRe.test(control.value);
|
const forbidden = nameRe.test(control.value);
|
||||||
return forbidden ? {forbiddenName: {value: control.value}} : null;
|
return forbidden ? {'forbiddenName': {value: control.value}} : null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// #enddocregion custom-validator
|
// #enddocregion custom-validator
|
||||||
|
@ -8,7 +8,7 @@ export const identityRevealedValidator: ValidatorFn = (control: FormGroup): Vali
|
|||||||
const name = control.get('name');
|
const name = control.get('name');
|
||||||
const alterEgo = control.get('alterEgo');
|
const alterEgo = control.get('alterEgo');
|
||||||
|
|
||||||
return name && alterEgo && name.value === alterEgo.value ? { identityRevealed: true } : null;
|
return name && alterEgo && name.value === alterEgo.value ? { 'identityRevealed': true } : null;
|
||||||
};
|
};
|
||||||
// #enddocregion cross-validation-validator
|
// #enddocregion cross-validation-validator
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ export const identityRevealedValidator: ValidatorFn = (control: FormGroup): Vali
|
|||||||
})
|
})
|
||||||
export class IdentityRevealedValidatorDirective implements Validator {
|
export class IdentityRevealedValidatorDirective implements Validator {
|
||||||
validate(control: AbstractControl): ValidationErrors {
|
validate(control: AbstractControl): ValidationErrors {
|
||||||
return identityRevealedValidator(control);
|
return identityRevealedValidator(control)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion cross-validation-directive
|
// #enddocregion cross-validation-directive
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Forms Overview Tests', () => {
|
describe('Forms Overview Tests', function () {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,27 +1,27 @@
|
|||||||
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();
|
||||||
|
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
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();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
export function createNewEvent(eventName: string, bubbles = false, cancelable = false) {
|
export function createNewEvent(eventName: string, bubbles = false, cancelable = false) {
|
||||||
const evt = document.createEvent('CustomEvent');
|
let evt = document.createEvent('CustomEvent');
|
||||||
evt.initCustomEvent(eventName, bubbles, cancelable, null);
|
evt.initCustomEvent(eventName, bubbles, cancelable, null);
|
||||||
return evt;
|
return evt;
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
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({
|
||||||
|
imports: [ FormsModule ],
|
||||||
|
declarations: [ FavoriteColorComponent ]
|
||||||
|
})
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -1,60 +1,60 @@
|
|||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Forms Tests', () => {
|
describe('Forms Tests', function () {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(function () {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display correct title', () => {
|
it('should display correct title', function () {
|
||||||
expect(element.all(by.css('h1')).get(0).getText()).toEqual('Hero Form');
|
expect(element.all(by.css('h1')).get(0).getText()).toEqual('Hero Form');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should not display message before submit', () => {
|
it('should not display message before submit', function () {
|
||||||
const ele = element(by.css('h2'));
|
let ele = element(by.css('h2'));
|
||||||
expect(ele.isDisplayed()).toBe(false);
|
expect(ele.isDisplayed()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should hide form after submit', () => {
|
it('should hide form after submit', function () {
|
||||||
const ele = element.all(by.css('h1')).get(0);
|
let ele = element.all(by.css('h1')).get(0);
|
||||||
expect(ele.isDisplayed()).toBe(true);
|
expect(ele.isDisplayed()).toBe(true);
|
||||||
const b = element.all(by.css('button[type=submit]')).get(0);
|
let b = element.all(by.css('button[type=submit]')).get(0);
|
||||||
b.click().then(() => {
|
b.click().then(function() {
|
||||||
expect(ele.isDisplayed()).toBe(false);
|
expect(ele.isDisplayed()).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display message after submit', () => {
|
it('should display message after submit', function () {
|
||||||
const b = element.all(by.css('button[type=submit]')).get(0);
|
let b = element.all(by.css('button[type=submit]')).get(0);
|
||||||
b.click().then(() => {
|
b.click().then(function() {
|
||||||
expect(element(by.css('h2')).getText()).toContain('You submitted the following');
|
expect(element(by.css('h2')).getText()).toContain('You submitted the following');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should hide form after submit', () => {
|
it('should hide form after submit', function () {
|
||||||
const alterEgoEle = element.all(by.css('input[name=alterEgo]')).get(0);
|
let alterEgoEle = element.all(by.css('input[name=alterEgo]')).get(0);
|
||||||
expect(alterEgoEle.isDisplayed()).toBe(true);
|
expect(alterEgoEle.isDisplayed()).toBe(true);
|
||||||
const submitButtonEle = element.all(by.css('button[type=submit]')).get(0);
|
let submitButtonEle = element.all(by.css('button[type=submit]')).get(0);
|
||||||
submitButtonEle.click().then(() => {
|
submitButtonEle.click().then(function() {
|
||||||
expect(alterEgoEle.isDisplayed()).toBe(false);
|
expect(alterEgoEle.isDisplayed()).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reflect submitted data after submit', () => {
|
it('should reflect submitted data after submit', function () {
|
||||||
const test = 'testing 1 2 3';
|
let test = 'testing 1 2 3';
|
||||||
let newValue: string;
|
let newValue: string;
|
||||||
const alterEgoEle = element.all(by.css('input[name=alterEgo]')).get(0);
|
let alterEgoEle = element.all(by.css('input[name=alterEgo]')).get(0);
|
||||||
alterEgoEle.getAttribute('value').then((value: string) => {
|
alterEgoEle.getAttribute('value').then(function(value: string) {
|
||||||
alterEgoEle.sendKeys(test);
|
alterEgoEle.sendKeys(test);
|
||||||
newValue = value + test;
|
newValue = value + test;
|
||||||
expect(alterEgoEle.getAttribute('value')).toEqual(newValue);
|
expect(alterEgoEle.getAttribute('value')).toEqual(newValue);
|
||||||
const b = element.all(by.css('button[type=submit]')).get(0);
|
let b = element.all(by.css('button[type=submit]')).get(0);
|
||||||
return b.click();
|
return b.click();
|
||||||
}).then(() => {
|
}).then(function() {
|
||||||
const alterEgoTextEle = element(by.cssContainingText('div', 'Alter Ego'));
|
let alterEgoTextEle = element(by.cssContainingText('div', 'Alter Ego'));
|
||||||
expect(alterEgoTextEle.isPresent()).toBe(true, 'cannot locate "Alter Ego" label');
|
expect(alterEgoTextEle.isPresent()).toBe(true, 'cannot locate "Alter Ego" label');
|
||||||
const divEle = element(by.cssContainingText('div', newValue));
|
let divEle = element(by.cssContainingText('div', newValue));
|
||||||
expect(divEle.isPresent()).toBe(true, 'cannot locate div with this text: ' + newValue);
|
expect(divEle.isPresent()).toBe(true, 'cannot locate div with this text: ' + newValue);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -35,7 +35,7 @@ export class HeroFormComponent {
|
|||||||
|
|
||||||
skyDog(): Hero {
|
skyDog(): Hero {
|
||||||
// #docregion SkyDog
|
// #docregion SkyDog
|
||||||
const myHero = new Hero(42, 'SkyDog',
|
let myHero = new Hero(42, 'SkyDog',
|
||||||
'Fetch any object at any distance',
|
'Fetch any object at any distance',
|
||||||
'Leslie Rollover');
|
'Leslie Rollover');
|
||||||
console.log('My hero is called ' + myHero.name); // "My hero is called SkyDog"
|
console.log('My hero is called ' + myHero.name); // "My hero is called SkyDog"
|
||||||
@ -48,9 +48,9 @@ export class HeroFormComponent {
|
|||||||
// Reveal in html:
|
// Reveal in html:
|
||||||
// Name via form.controls = {{showFormControls(heroForm)}}
|
// Name via form.controls = {{showFormControls(heroForm)}}
|
||||||
showFormControls(form: any) {
|
showFormControls(form: any) {
|
||||||
return form && form.controls.name &&
|
return form && form.controls['name'] &&
|
||||||
// #docregion form-controls
|
// #docregion form-controls
|
||||||
form.controls.name.value; // Dr. IQ
|
form.controls['name'].value; // Dr. IQ
|
||||||
// #enddocregion form-controls
|
// #enddocregion form-controls
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
describe('Getting Started V0', () => {
|
describe('Getting Started V0', () => {
|
||||||
beforeEach(() => browser.get('/'));
|
beforeEach(() => {
|
||||||
|
return browser.get('/');
|
||||||
|
});
|
||||||
|
|
||||||
it('should display "My Store" in the top bar', async() => {
|
it('should display "My Store" in the top bar', async() => {
|
||||||
const title = await element(by.css('app-root app-top-bar h1')).getText();
|
const title = await element(by.css('app-root app-top-bar h1')).getText();
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, element, by, ExpectedConditions as EC, logging, ElementFinder, ElementArrayFinder } from 'protractor';
|
import { browser, element, by, ExpectedConditions as EC, logging, ElementFinder, ElementArrayFinder } from 'protractor';
|
||||||
|
|
||||||
describe('Getting Started', () => {
|
describe('Getting Started', () => {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
import { browser, by, element } from 'protractor';
|
import { browser, by, element } from 'protractor';
|
||||||
|
|
||||||
describe('Hierarchical dependency injection', () => {
|
describe('Hierarchical dependency injection', () => {
|
||||||
@ -7,7 +9,7 @@ describe('Hierarchical dependency injection', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('Heroes Scenario', () => {
|
describe('Heroes Scenario', () => {
|
||||||
const page = {
|
let page = {
|
||||||
heroName: '',
|
heroName: '',
|
||||||
income: '',
|
income: '',
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// tslint:disable: no-output-native
|
|
||||||
// #docregion
|
// #docregion
|
||||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
import { HeroTaxReturn } from './hero';
|
import { HeroTaxReturn } from './hero';
|
||||||
@ -31,9 +30,9 @@ export class HeroTaxReturnComponent {
|
|||||||
onCanceled() {
|
onCanceled() {
|
||||||
this.flashMessage('Canceled');
|
this.flashMessage('Canceled');
|
||||||
this.heroTaxReturnService.restoreTaxReturn();
|
this.heroTaxReturnService.restoreTaxReturn();
|
||||||
}
|
};
|
||||||
|
|
||||||
onClose() { this.close.emit(); }
|
onClose() { this.close.emit(); };
|
||||||
|
|
||||||
onSaved() {
|
onSaved() {
|
||||||
this.flashMessage('Saved');
|
this.flashMessage('Saved');
|
||||||
|
@ -24,11 +24,11 @@ const page = {
|
|||||||
uploadMessage: element(by.css('app-uploader p'))
|
uploadMessage: element(by.css('app-uploader p'))
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkLogForMessage = (message: string) => {
|
let checkLogForMessage = (message: string) => {
|
||||||
expect(page.logList.getText()).toContain(message);
|
expect(page.logList.getText()).toContain(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Http Tests', () => {
|
describe('Http Tests', function() {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
@ -40,8 +40,8 @@ export class ConfigComponent {
|
|||||||
this.configService.getConfig_1()
|
this.configService.getConfig_1()
|
||||||
// #docregion v1, v1_callback
|
// #docregion v1, v1_callback
|
||||||
.subscribe((data: Config) => this.config = {
|
.subscribe((data: Config) => this.config = {
|
||||||
heroesUrl: data.heroesUrl,
|
heroesUrl: data['heroesUrl'],
|
||||||
textfile: data.textfile
|
textfile: data['textfile']
|
||||||
});
|
});
|
||||||
// #enddocregion v1_callback
|
// #enddocregion v1_callback
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user