Compare commits

..

44 Commits

Author SHA1 Message Date
63149810c1 docs: translate guide/creating-libraries 2020-08-24 21:19:26 -04:00
e3bc073f7b Merge branch 'creating-libraries' of github.com:angular-hispano/angular into creating-libraries 2020-08-23 20:06:24 -04:00
4b9b094c47 docs: translate guide/creating-libraries 2020-08-23 20:03:23 -04:00
75e59cc837 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:29:18 -04:00
6ad701074a Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:29:07 -04:00
fb4df0a54c Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:28:52 -04:00
7b0fba0983 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:28:40 -04:00
7bd65e5f1b Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:28:29 -04:00
c90d9fd468 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:28:18 -04:00
4bd3debef2 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:28:06 -04:00
43b1210f86 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:27:53 -04:00
189686bea1 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:26:38 -04:00
66592ac5a3 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:26:26 -04:00
066da01295 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:26:12 -04:00
03ca38a478 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:26:04 -04:00
6452285a71 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:25:56 -04:00
a81e82028a Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:25:14 -04:00
958d06fa69 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:25:05 -04:00
15b311ac9f Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:24:56 -04:00
5717054caa Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:24:44 -04:00
44cf633cb1 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:24:30 -04:00
957e152656 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:24:22 -04:00
9ccf7631c6 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:24:06 -04:00
225fdf9ac8 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:23:58 -04:00
b206732b25 Update aio/content/guide/creating-libraries.es.md
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
2020-08-23 19:23:35 -04:00
efef4b7dc1 docs: translate guide/creating-libraries 2020-08-21 03:59:48 -04:00
92c7145139 fix(pr): template (#47)
Co-authored-by: Alejandro Lora <alejandrofpo@gmail.com>
Co-authored-by: Andrés Villanueva <andresvillanuevab@gmail.com>
Co-authored-by: Michael Prentice <splaktar@gmail.com>
2020-07-30 03:57:48 -04:00
d133525502 docs: update typo for bootstraping word 2020-07-28 23:43:28 -04:00
cd1817bf6d Update aio/content/guide/cheatsheet.md
Co-authored-by: Pato <11162114+devpato@users.noreply.github.com>
2020-07-28 23:43:28 -04:00
0d1491b1a6 docs: implement feedback PR 2020-07-28 23:43:28 -04:00
f67774d84b Update aio/content/guide/cheatsheet.md
Co-authored-by: Pato <11162114+devpato@users.noreply.github.com>
2020-07-28 23:43:28 -04:00
37668d159e docs: translat cheatsheet.md file to Spanish 2020-07-28 23:43:28 -04:00
38554288f5 docs(readme): aplicar sugerencias de revisión de código 2020-07-28 23:23:46 -04:00
04dcc3bceb Update README.md
Traducción del README.md al español.
2020-07-28 23:23:46 -04:00
0910a2fc0d fix(file): based on pr comments 2020-07-28 23:18:53 -04:00
3325cb2f86 fix(code): based on comments from PR reviewrs 2020-07-28 23:18:53 -04:00
a1e8443bfb fix(files): removed unecessary files 2020-07-28 23:18:53 -04:00
599d34b41e fix(comment): based on PR 2020-07-28 23:18:53 -04:00
7fd1733882 fix(pr): comments 2020-07-28 23:18:53 -04:00
2e42123870 fix(merge): conflict 2020-07-28 23:18:53 -04:00
4cbb90daf7 feat(github): traduccion de templates para issues 2020-07-28 23:18:53 -04:00
cf2663b034 docs: translate the app-shell.md file (#41)
* docs: translate the app-shell.md file

* Update aio/content/guide/app-shell.md

Co-authored-by: Christian Morante <christianmorante@outlook.com>

* Update aio/content/guide/app-shell.md

Co-authored-by: Christian Morante <christianmorante@outlook.com>

* Update aio/content/guide/app-shell.md

Co-authored-by: Christian Morante <christianmorante@outlook.com>

* add PR feedback

* docs: update 'usted'-'tú' (Grammatical person)

Co-authored-by: Christian Morante <christianmorante@outlook.com>
2020-07-27 16:21:00 -04:00
95681b16bd fix(docs): changed the way to express the idea
Changed the way to express the idea from "usted" to "tu"
2020-07-26 20:43:54 -04:00
e620827fa8 docs: traducir página de inicio, navegación, cuadro de búsqueda y pie de página 2020-07-23 01:50:03 -04:00
1047 changed files with 14403 additions and 27096 deletions

View File

@ -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.
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
# NOTE: This needs to be the *last* entry in the config.

View File

@ -32,8 +32,8 @@ var_4_win: &cache_key_win_fallback v7-angular-win-node-12-{{ checksum ".bazelver
# 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 v9-angular-components-09e68db8ed5b1253f2fe38ff954ef0df019fc25a
var_6: &components_repo_unit_tests_cache_key_fallback v9-angular-components-
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
# `build-ivy-npm-packages`.
@ -656,18 +656,6 @@ jobs:
- run: yarn tsc -p packages
- run: yarn tsc -p modules
- run: yarn bazel build //packages/zone.js:npm_package
# Build test fixtures for a test that rely on Bazel-generated fixtures. Note that disabling
# specific tests which are reliant on such generated fixtures is not an option as SystemJS
# in the Saucelabs legacy job always fetches referenced files, even if the imports would be
# guarded by an check to skip in the Saucelabs legacy job. We should be good running such
# test in all supported browsers on Saucelabs anyway until this job can be removed.
- run:
name: Preparing Bazel-generated fixtures required in legacy tests
command: |
yarn bazel build //packages/core/test:downleveled_es5_fixture
# Needed for the ES5 downlevel reflector test in `packages/core/test/reflection`.
cp dist/bin/packages/core/test/reflection/es5_downleveled_inheritance_fixture.js \
dist/all/@angular/core/test/reflection/es5_downleveled_inheritance_fixture.js
- 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

View File

@ -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_BRANCH "master"
# **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"
####################################################################################################

View File

@ -1,69 +0,0 @@
---
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. -->

View File

@ -1,32 +0,0 @@
---
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?

View File

@ -1,55 +0,0 @@
---
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. -->

View File

@ -1,11 +0,0 @@
---
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.
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑

View File

@ -1,16 +0,0 @@
---
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!
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑

View File

@ -1,13 +0,0 @@
---
name: "\U0001F6E0Angular 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.
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑

View File

@ -1,13 +0,0 @@
---
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.
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑

View File

@ -0,0 +1,22 @@
---
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

View File

@ -1,43 +1,35 @@
## PR Checklist
Please check if your PR fulfills the following requirements:
## Lista de Verificación del PR
Comprueba si tu PR cumple los siguientes requisitos:
- [ ] The commit message follows our guidelines: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
- [ ] Tests for the changes have been added (for bug fixes / features)
- [ ] Docs have been added / updated (for bug fixes / features)
- [ ] El mensaje de commit conforme con [nuestras reglas](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit)
- [ ] Prueba los cambios que agregaste (arreglo de bugs / funcionalidades)
- [ ] Revisa tus traducciones o cambios de contenido
- [ ] Consulté el [diccionario de términos](https://github.com/angular-hispano/angular/issues/9) en español
- [ ] Se han creado dos archivos con la extensión correspondiente(.en.md para el archivo en inglés y .md para el Archivo en español)
- [ ] PR enlazada con el issue correspondiente
## PR Type
What kind of change does this PR introduce?
## Tipo de PR
¿Qué tipo de cambio introduce este PR?
<!-- Please check the one that applies to this PR using "x". -->
<!-- Marca con una "x" las opciones que aplican. -->
- [ ] Bugfix
- [ ] Feature
- [ ] Code style update (formatting, local variables)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Documentation content changes
- [ ] angular.io application / infrastructure changes
- [ ] Other... Please describe:
- [ ] Funcionalidad
- [ ] Actualizar el estilo del código (formato, variables locales)
- [ ] Refactorización (no cambios en la funcionalidad, no cambios en el api)
- [ ] Cambios relacionados al build
- [ ] Cambios relacionados al CI (Integración continua)
- [ ] Cambios en el contenido de la documentación
- [ ] Cambios en la aplicación / infrastructura de angular.io
- [ ] Otro... Por favor describela:
## ¿Cuál es el comportamiento actual?
<!-- Describe el comportamiento actual que está modificando o vincule a un problema relevante.
-->
## What is the current behavior?
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->
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
## ¿Cuál es el nuevo comportamiento?
<!--
Ejemplo: Archivo en inglés traducido al español
-->

View File

@ -73,14 +73,15 @@ merge:
- "packages/zone.js/scripts/**"
# comment that will be added to a PR when there is a conflict, leave empty or set to false to disable
mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.\nPlease help to unblock it by resolving these conflicts. Thanks!"
mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.
\nPlease help to unblock it by resolving these conflicts. Thanks!"
# label to monitor
mergeLabel: "action: merge"
mergeLabel: "PR action: merge"
# adding any of these labels will also add the merge label
mergeLinkedLabels:
- "action: merge-assistance"
- "PR action: merge-assistance"
# list of checks that will determine if the merge label can be added
checks:
@ -93,17 +94,17 @@ merge:
# whether the PR shouldn't have a conflict with the base branch
noConflict: true
# list of labels that a PR needs to have, checked with a regexp (e.g. "target:" will work for the label "target: master")
# list of labels that a PR needs to have, checked with a regexp (e.g. "PR target:" will work for the label "PR target: master")
requiredLabels:
- "target: *"
- "PR target: *"
- "cla: yes"
# list of labels that a PR shouldn't have, checked after the required labels with a regexp
forbiddenLabels:
- "target: TBD"
- "action: cleanup"
- "action: review"
- "state: blocked"
- "PR target: TBD"
- "PR action: cleanup"
- "PR action: review"
- "PR state: blocked"
- "cla: no"
# list of PR statuses that need to be successful
@ -120,7 +121,12 @@ merge:
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
# {{PLACEHOLDER}} will be replaced by the list of failing checks
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:\n{{PLACEHOLDER}}\n\n**If you want your PR to be merged, it has to pass all the CI checks.**\n\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:
\n{{PLACEHOLDER}}
\n
\n**If you want your PR to be merged, it has to pass all the CI checks.**
\n
\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
# options for the triage plugin
triage:
@ -180,4 +186,4 @@ rerunCircleCI:
# set to true to disable
disabled: false
# the label which when added triggers a rerun of the default CircleCI workflow
triggerRerunLabel: "action: rerun CI at HEAD"
triggerRerunLabel: "PR action: rerun CI at HEAD"

View File

@ -1,19 +0,0 @@
import {CaretakerConfig} from '../dev-infra/caretaker/config';
/** The configuration for `ng-dev caretaker` commands. */
export const caretaker: CaretakerConfig = {
githubQueries: [
{
name: 'Merge Queue',
query: `is:pr is:open status:success label:"action: merge"`,
},
{
name: 'Merge Assistance Queue',
query: `is:pr is:open status:success label:"action: merge-assistance"`,
},
{
name: 'Primary Triage Queue',
query: `is:open is:issue no:milestone`,
}
]
};

View File

@ -7,6 +7,18 @@ export const commitMessage: CommitMessageConfig = {
maxLineLength: 120,
minBodyLength: 20,
minBodyLengthTypeExcludes: ['docs'],
types: [
'build',
'ci',
'docs',
'feat',
'fix',
'perf',
'refactor',
'release',
'style',
'test',
],
scopes: [
'animations',
'bazel',

View File

@ -1,4 +1,3 @@
import {caretaker} from './caretaker';
import {commitMessage} from './commit-message';
import {format} from './format';
import {github} from './github';
@ -9,5 +8,4 @@ module.exports = {
format,
github,
merge,
caretaker,
};

View File

@ -1,25 +1,38 @@
import {DevInfraMergeConfig} from '../dev-infra/pr/merge/config';
import {getDefaultTargetLabelConfiguration} from '../dev-infra/pr/merge/defaults';
import {github} from './github';
import {MergeConfig} from '../dev-infra/pr/merge/config';
/**
* Configuration for the merge tool in `ng-dev`. This sets up the labels which
* are respected by the merge script (e.g. the target labels).
*/
export const merge: DevInfraMergeConfig['merge'] = async api => {
export const merge = (): MergeConfig => {
// TODO: resume dynamically determining patch branch
const patch = '10.0.x';
return {
githubApiMerge: false,
claSignedLabel: 'cla: yes',
mergeReadyLabel: /^action: merge(-assistance)?/,
caretakerNoteLabel: 'action: merge-assistance',
mergeReadyLabel: /^PR action: merge(-assistance)?/,
caretakerNoteLabel: 'PR action: merge-assistance',
commitMessageFixupLabel: 'commit message fixup',
labels: await getDefaultTargetLabelConfiguration(api, github, '@angular/core'),
labels: [
{
pattern: 'PR target: master-only',
branches: ['master'],
},
{
pattern: 'PR target: patch-only',
branches: [patch],
},
{
pattern: 'PR target: master & patch',
branches: ['master', patch],
},
],
requiredBaseCommits: {
// PRs that target either `master` or the patch branch, need to be rebased
// on top of the latest commit message validation fix.
// These SHAs are the commits that update the required license text in the header.
'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a',
'10.0.x': '27b95ba64a5d99757f4042073fd1860e20e3ed24',
[patch]: '27b95ba64a5d99757f4042073fd1860e20e3ed24'
},
};
};

View File

@ -67,25 +67,6 @@ version: 3
# Meta field that goes unused by PullApprove to allow for defining aliases to be
# used throughout the config.
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-docs-approved: &can-be-global-docs-approved "\"global-docs-approvers\" not in groups.approved"
defaults: &defaults
@ -509,8 +490,8 @@ groups:
- >
contains_any_globs(files, [
'packages/core/src/i18n/**',
'packages/core/src/render3/i18n/**',
'packages/core/src/render3/instructions/i18n.ts',
'packages/core/src/render3/i18n.ts',
'packages/core/src/render3/i18n.md',
'packages/core/src/render3/interfaces/i18n.ts',
'packages/common/locales/**',
'packages/common/src/i18n/**',
@ -882,7 +863,6 @@ groups:
- *can-be-global-docs-approved
- >
contains_any_globs(files, [
'aio/content/guide/roadmap.md',
'aio/content/marketing/**',
'aio/content/images/bios/**',
'aio/content/images/marketing/**',
@ -1110,7 +1090,6 @@ groups:
'dev-infra/**',
'docs/BAZEL.md',
'docs/CARETAKER.md',
'docs/CODING_STANDARDS.md',
'docs/COMMITTER.md',
'docs/DEBUG.md',
'docs/DEBUG_COMPONENTS_REPO_IVY.md',
@ -1163,8 +1142,6 @@ groups:
public-api:
<<: *defaults
conditions:
- *no-groups-above-this-pending
- *no-groups-above-this-rejected
- *can-be-global-approved
- >
contains_any_globs(files, [
@ -1178,16 +1155,14 @@ groups:
])
reviewers:
users:
- AndrewKushnir
- IgorMinar
- alxhub
- atscott
- jelbourn
- petebacondarwin
- pkozlowski-opensource
reviews:
request: 4 # Request reviews from four people
required: 3 # Require that three people approve
request: -1 # request reviews from everyone
required: 3 # require at least 3 approvals
reviewed_for: required
@ -1197,8 +1172,6 @@ groups:
size-tracking:
<<: *defaults
conditions:
- *no-groups-above-this-pending
- *no-groups-above-this-rejected
- *can-be-global-approved
- >
contains_any_globs(files, [
@ -1206,16 +1179,14 @@ groups:
])
reviewers:
users:
- AndrewKushnir
- IgorMinar
- alxhub
- atscott
- jelbourn
- petebacondarwin
- pkozlowski-opensource
reviews:
request: 4 # Request reviews from four people
required: 2 # Require that two people approve
request: -1 # request reviews from everyone
required: 2 # require at least 2 approvals
reviewed_for: required
@ -1225,8 +1196,6 @@ groups:
circular-dependencies:
<<: *defaults
conditions:
- *no-groups-above-this-pending
- *no-groups-above-this-rejected
- *can-be-global-approved
- >
contains_any_globs(files, [
@ -1234,11 +1203,9 @@ groups:
])
reviewers:
users:
- AndrewKushnir
- IgorMinar
- alxhub
- atscott
- jelbourn
- josephperrott
- petebacondarwin
- pkozlowski-opensource
@ -1260,10 +1227,7 @@ groups:
])
reviewers:
users:
- AndrewKushnir
- IgorMinar
- alxhub
- atscott
- jelbourn
- josephperrott
- mhevery
@ -1293,7 +1257,14 @@ groups:
# `global-approvers` can still approve PRs that match this `fallback` rule,
# but that should be an exception and not an expectation.
conditions:
- *no-groups-above-this-active
# 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 groups when these are excluded, we can determine
# if any other groups are matched.
- len(groups.active.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0
# 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,

View File

@ -1,192 +1,3 @@
<a name="10.1.0"></a>
# 10.1.0 (2020-09-02)
### Features
* **bazel:** provide LinkablePackageInfo from ng_module ([#37623](https://github.com/angular/angular/issues/37623)) ([6898eab](https://github.com/angular/angular/commit/6898eab))
* **common:** add ReadonlyMap in place of Map in keyValuePipe ([#37311](https://github.com/angular/angular/issues/37311)) ([3373453](https://github.com/angular/angular/commit/3373453)), closes [#37308](https://github.com/angular/angular/issues/37308)
* **compiler-cli:** add `SourceFile.getOriginalLocation()` to sourcemaps package ([#32912](https://github.com/angular/angular/issues/32912)) ([6abb8d0](https://github.com/angular/angular/commit/6abb8d0))
* **compiler-cli:** Add compiler option to report errors when assigning to restricted input fields ([#38249](https://github.com/angular/angular/issues/38249)) ([71138f6](https://github.com/angular/angular/commit/71138f6))
* **compiler-cli:** add support for TypeScript 4.0 ([#38076](https://github.com/angular/angular/issues/38076)) ([0fc44e0](https://github.com/angular/angular/commit/0fc44e0))
* **compiler-cli:** explain why an expression cannot be used in AOT compilations ([#37587](https://github.com/angular/angular/issues/37587)) ([712f1bd](https://github.com/angular/angular/commit/712f1bd))
* **compiler:** support unary operators for more accurate type checking ([#37918](https://github.com/angular/angular/issues/37918)) ([874792d](https://github.com/angular/angular/commit/874792d)), closes [#20845](https://github.com/angular/angular/issues/20845) [#36178](https://github.com/angular/angular/issues/36178)
* **core:** rename async to waitForAsync to avoid confusing ([#37583](https://github.com/angular/angular/issues/37583)) ([8f07429](https://github.com/angular/angular/commit/8f07429))
* **core:** support injection token as predicate in queries ([#37506](https://github.com/angular/angular/issues/37506)) ([97dc85b](https://github.com/angular/angular/commit/97dc85b)), closes [#21152](https://github.com/angular/angular/issues/21152) [#36144](https://github.com/angular/angular/issues/36144)
* **core:** update reference and doc to change `async` to `waitAsync`. ([#37583](https://github.com/angular/angular/issues/37583)) ([8fbf40b](https://github.com/angular/angular/commit/8fbf40b))
* **forms:** AbstractControl to store raw validators in addition to combined validators function ([#37881](https://github.com/angular/angular/issues/37881)) ([ad7046b](https://github.com/angular/angular/commit/ad7046b))
* **localize:** allow duplicate messages to be handled during extraction ([#38082](https://github.com/angular/angular/issues/38082)) ([cf9a47b](https://github.com/angular/angular/commit/cf9a47b)), closes [#38077](https://github.com/angular/angular/issues/38077)
* **localize:** expose `canParse()` diagnostics ([#37909](https://github.com/angular/angular/issues/37909)) ([ec32eba](https://github.com/angular/angular/commit/ec32eba)), closes [#37901](https://github.com/angular/angular/issues/37901)
* **localize:** implement message extraction tool ([#32912](https://github.com/angular/angular/issues/32912)) ([190561d](https://github.com/angular/angular/commit/190561d))
* **platform-browser:** Allow `sms`-URLs ([#31463](https://github.com/angular/angular/issues/31463)) ([fc5c34d](https://github.com/angular/angular/commit/fc5c34d)), closes [#31462](https://github.com/angular/angular/issues/31462)
* **platform-server:** add option for absolute URL HTTP support ([#37539](https://github.com/angular/angular/issues/37539)) ([d37049a](https://github.com/angular/angular/commit/d37049a)), closes [#37071](https://github.com/angular/angular/issues/37071)
* **router:** better warning message when a router outlet has not been instantiated ([#30246](https://github.com/angular/angular/issues/30246)) ([1609815](https://github.com/angular/angular/commit/1609815))
### Bug Fixes
* **bazel:** fix integration test for bazel building ([#38629](https://github.com/angular/angular/issues/38629)) ([dd82f2f](https://github.com/angular/angular/commit/dd82f2f))
* **common:** date pipe gives wrong week number ([#37632](https://github.com/angular/angular/issues/37632)) ([ef1fb6d](https://github.com/angular/angular/commit/ef1fb6d)), closes [#33961](https://github.com/angular/angular/issues/33961)
* **common:** narrow `NgIf` context variables in template type checker ([#36627](https://github.com/angular/angular/issues/36627)) ([9c8bc4a](https://github.com/angular/angular/commit/9c8bc4a))
* **compiler-cli:** avoid creating value expressions for symbols from type-only imports ([#37912](https://github.com/angular/angular/issues/37912)) ([18098d3](https://github.com/angular/angular/commit/18098d3)), closes [#37900](https://github.com/angular/angular/issues/37900)
* **compiler-cli:** ensure source-maps can handle webpack:// protocol ([#32912](https://github.com/angular/angular/issues/32912)) ([decd95e](https://github.com/angular/angular/commit/decd95e))
* **compiler-cli:** only read source-map comment from last line ([#32912](https://github.com/angular/angular/issues/32912)) ([07a07e3](https://github.com/angular/angular/commit/07a07e3))
* **compiler-cli:** type-check inputs that include undefined when there's coercion members ([#38273](https://github.com/angular/angular/issues/38273)) ([7525f3a](https://github.com/angular/angular/commit/7525f3a))
* **compiler:** incorrectly inferring namespace for HTML nodes inside SVG ([#38477](https://github.com/angular/angular/issues/38477)) ([0dda97e](https://github.com/angular/angular/commit/0dda97e)), closes [#37218](https://github.com/angular/angular/issues/37218)
* **compiler:** mark `NgModuleFactory` construction as not side effectful ([#38147](https://github.com/angular/angular/issues/38147)) ([7f8c222](https://github.com/angular/angular/commit/7f8c222))
* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#35464](https://github.com/angular/angular/issues/35464)) ([737506e](https://github.com/angular/angular/commit/737506e)), closes [#30497](https://github.com/angular/angular/issues/30497)
* **core:** detect DI parameters in JIT mode for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([ca07da4](https://github.com/angular/angular/commit/ca07da4)), closes [#38453](https://github.com/angular/angular/issues/38453)
* **core:** determine required DOMParser feature availability ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([c509243](https://github.com/angular/angular/commit/c509243))
* **core:** do not trigger CSP alert/report in Firefox and Chrome ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([b950d46](https://github.com/angular/angular/commit/b950d46)), closes [#25214](https://github.com/angular/angular/issues/25214)
* **core:** move generated i18n statements to the `consts` field of ComponentDef ([#38404](https://github.com/angular/angular/issues/38404)) ([cb05c01](https://github.com/angular/angular/commit/cb05c01))
* **elements:** run strategy methods in correct zone ([#37814](https://github.com/angular/angular/issues/37814)) ([8df888d](https://github.com/angular/angular/commit/8df888d)), closes [#24181](https://github.com/angular/angular/issues/24181)
* **forms:** handle form groups/arrays own pending async validation ([#22575](https://github.com/angular/angular/issues/22575)) ([77b62a5](https://github.com/angular/angular/commit/77b62a5)), closes [#10064](https://github.com/angular/angular/issues/10064)
* **language-service:** non-existent module format in package output ([#37623](https://github.com/angular/angular/issues/37623)) ([413a0fb](https://github.com/angular/angular/commit/413a0fb))
* **localize:** ensure required XLIFF parameters are serialized ([#38575](https://github.com/angular/angular/issues/38575)) ([f0af387](https://github.com/angular/angular/commit/f0af387)), closes [#38570](https://github.com/angular/angular/issues/38570)
* **localize:** extract the correct message ids ([#38498](https://github.com/angular/angular/issues/38498)) ([ac461e1](https://github.com/angular/angular/commit/ac461e1))
* **localize:** render ICU placeholders in extracted translation files ([#38484](https://github.com/angular/angular/issues/38484)) ([81c3e80](https://github.com/angular/angular/commit/81c3e80))
* **localize:** render text of extracted placeholders ([#38536](https://github.com/angular/angular/issues/38536)) ([14e90be](https://github.com/angular/angular/commit/14e90be))
* **ngcc:** detect synthesized delegate constructors for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([3b9c802](https://github.com/angular/angular/commit/3b9c802)), closes [#38453](https://github.com/angular/angular/issues/38453) [#38453](https://github.com/angular/angular/issues/38453)
* **router:** defer loading of wildcard module until needed ([#38348](https://github.com/angular/angular/issues/38348)) ([8f708b5](https://github.com/angular/angular/commit/8f708b5)), closes [#25494](https://github.com/angular/angular/issues/25494)
* **router:** fix navigation ignoring logic to compare to the browser url ([#37716](https://github.com/angular/angular/issues/37716)) ([a5ffca0](https://github.com/angular/angular/commit/a5ffca0)), closes [#16710](https://github.com/angular/angular/issues/16710) [#13586](https://github.com/angular/angular/issues/13586)
* **router:** properly compare array queryParams for equality ([#37709](https://github.com/angular/angular/issues/37709)) ([#37860](https://github.com/angular/angular/issues/37860)) ([1801d0c](https://github.com/angular/angular/commit/1801d0c))
* **router:** remove parenthesis for primary outlet segment after removing auxiliary outlet segment ([#24656](https://github.com/angular/angular/issues/24656)) ([#37163](https://github.com/angular/angular/issues/37163)) ([71f008f](https://github.com/angular/angular/commit/71f008f))
* **router:** restore 'history.state' object for navigations coming from Angular router ([#28108](https://github.com/angular/angular/issues/28108)) ([#28176](https://github.com/angular/angular/issues/28176)) ([df76a20](https://github.com/angular/angular/commit/df76a20))
* **router:** support lazy loading for empty path named outlets ([#38379](https://github.com/angular/angular/issues/38379)) ([7ad3264](https://github.com/angular/angular/commit/7ad3264)), closes [#12842](https://github.com/angular/angular/issues/12842)
### Code Refactoring
* **router:** export DefaultRouteReuseStrategy to Router public_api ([#31575](https://github.com/angular/angular/issues/31575)) ([ca79880](https://github.com/angular/angular/commit/ca79880))
### Performance Improvements
* **compiler-cli:** don't emit template guards when child scope is empty ([#38418](https://github.com/angular/angular/issues/38418)) ([1388c17](https://github.com/angular/angular/commit/1388c17))
* **compiler-cli:** fix regressions in incremental program reuse ([#37641](https://github.com/angular/angular/issues/37641)) ([5103d90](https://github.com/angular/angular/commit/5103d90))
* **compiler-cli:** only generate directive declarations when used ([#38418](https://github.com/angular/angular/issues/38418)) ([fb8f4b4](https://github.com/angular/angular/commit/fb8f4b4))
* **compiler-cli:** only generate type-check code for referenced DOM elements ([#38418](https://github.com/angular/angular/issues/38418)) ([f42e6ce](https://github.com/angular/angular/commit/f42e6ce))
* **forms:** use internal `ngDevMode` flag to tree-shake error messages in prod builds ([#37821](https://github.com/angular/angular/issues/37821)) ([201a546](https://github.com/angular/angular/commit/201a546)), closes [#37697](https://github.com/angular/angular/issues/37697)
* **ngcc:** shortcircuit tokenizing in ESM dependency host ([#37639](https://github.com/angular/angular/issues/37639)) ([bd7f440](https://github.com/angular/angular/commit/bd7f440))
* **ngcc:** use `EntryPointManifest` to speed up noop `ProgramBaseEntryPointFinder` ([#37665](https://github.com/angular/angular/issues/37665)) ([9318e23](https://github.com/angular/angular/commit/9318e23))
* **router:** apply prioritizedGuardValue operator to optimize CanLoad guards ([#37523](https://github.com/angular/angular/issues/37523)) ([d7dd295](https://github.com/angular/angular/commit/d7dd295))
<a name="10.0.14"></a>
## 10.0.14 (2020-08-26)
<a name="10.0.12"></a>
## 10.0.12 (2020-08-24)
### Bug Fixes
* **compiler-cli:** adding references to const enums in runtime code ([#38542](https://github.com/angular/angular/issues/38542)) ([814b436](https://github.com/angular/angular/commit/814b436)), closes [#38513](https://github.com/angular/angular/issues/38513)
* **core:** remove closing body tag from inert DOM builder ([#38454](https://github.com/angular/angular/issues/38454)) ([5528536](https://github.com/angular/angular/commit/5528536))
* **localize:** include the last placeholder in parsed translation text ([#38452](https://github.com/angular/angular/issues/38452)) ([57d1a48](https://github.com/angular/angular/commit/57d1a48))
* **localize:** parse all parts of a translation with nested HTML ([#38452](https://github.com/angular/angular/issues/38452)) ([07b99f5](https://github.com/angular/angular/commit/07b99f5)), closes [#38422](https://github.com/angular/angular/issues/38422)
### Features
* **language-service:** introduce hybrid visitor to locate AST node ([#38540](https://github.com/angular/angular/issues/38540)) ([66d8c22](https://github.com/angular/angular/commit/66d8c22))
<a name="10.0.11"></a>
## 10.0.11 (2020-08-19)
### Bug Fixes
* **router:** ensure routerLinkActive updates when associated routerLinks change (resubmit of [#38349](https://github.com/angular/angular/issues/38349)) ([#38511](https://github.com/angular/angular/issues/38511)) ([0af9533](https://github.com/angular/angular/commit/0af9533)), closes [#18469](https://github.com/angular/angular/issues/18469)
<a name="10.0.10"></a>
## 10.0.10 (2020-08-17)
### Bug Fixes
* **common:** Allow scrolling when browser supports scrollTo ([#38468](https://github.com/angular/angular/issues/38468)) ([b32126c](https://github.com/angular/angular/commit/b32126c)), closes [#30630](https://github.com/angular/angular/issues/30630)
* **core:** detect DI parameters in JIT mode for downleveled ES2015 classes ([#38500](https://github.com/angular/angular/issues/38500)) ([863acb6](https://github.com/angular/angular/commit/863acb6)), closes [#38453](https://github.com/angular/angular/issues/38453)
* **core:** error if CSS custom property in host binding has number in name ([#38432](https://github.com/angular/angular/issues/38432)) ([cb83b8a](https://github.com/angular/angular/commit/cb83b8a)), closes [#37292](https://github.com/angular/angular/issues/37292)
* **core:** fix multiple nested views removal from ViewContainerRef ([#38317](https://github.com/angular/angular/issues/38317)) ([d5e09f4](https://github.com/angular/angular/commit/d5e09f4)), closes [#38201](https://github.com/angular/angular/issues/38201)
* **ngcc:** detect synthesized delegate constructors for downleveled ES2015 classes ([#38500](https://github.com/angular/angular/issues/38500)) ([f3dd6c2](https://github.com/angular/angular/commit/f3dd6c2)), closes [#38453](https://github.com/angular/angular/issues/38453) [#38453](https://github.com/angular/angular/issues/38453)
* **router:** ensure routerLinkActive updates when associated routerLinks change ([#38349](https://github.com/angular/angular/issues/38349)) ([989e8a1](https://github.com/angular/angular/commit/989e8a1)), closes [#18469](https://github.com/angular/angular/issues/18469)
<a name="10.0.9"></a>
## 10.0.9 (2020-08-12)
### Bug Fixes
* **common:** ensure scrollRestoration is writable ([#30630](https://github.com/angular/angular/issues/30630)) ([#38357](https://github.com/angular/angular/issues/38357)) ([58f4b3a](https://github.com/angular/angular/commit/58f4b3a)), closes [#30629](https://github.com/angular/angular/issues/30629)
* **compiler:** evaluate safe navigation expressions in correct binding order ([#37911](https://github.com/angular/angular/issues/37911)) ([f5b9d87](https://github.com/angular/angular/commit/f5b9d87)), closes [#37194](https://github.com/angular/angular/issues/37194)
* **compiler-cli:** avoid creating value expressions for symbols from type-only imports ([#38415](https://github.com/angular/angular/issues/38415)) ([ca2b4bc](https://github.com/angular/angular/commit/ca2b4bc)), closes [#37912](https://github.com/angular/angular/issues/37912)
* **compiler-cli:** infer quote expressions as any type in type checker ([#37917](https://github.com/angular/angular/issues/37917)) ([5b87c67](https://github.com/angular/angular/commit/5b87c67)), closes [#36568](https://github.com/angular/angular/issues/36568)
* **compiler-cli:** mark eager `NgModuleFactory` construction as not side effectful ([#38320](https://github.com/angular/angular/issues/38320)) ([016a41b](https://github.com/angular/angular/commit/016a41b)), closes [#38147](https://github.com/angular/angular/issues/38147)
* **compiler-cli:** match wrapHost parameter types within plugin interface ([#38004](https://github.com/angular/angular/issues/38004)) ([df01a82](https://github.com/angular/angular/commit/df01a82))
* **compiler-cli:** preserve quotes in class member names ([#38387](https://github.com/angular/angular/issues/38387)) ([c9acb7b](https://github.com/angular/angular/commit/c9acb7b)), closes [#38311](https://github.com/angular/angular/issues/38311)
* **core:** prevent NgModule scope being overwritten in JIT compiler ([#37795](https://github.com/angular/angular/issues/37795)) ([3acebdc](https://github.com/angular/angular/commit/3acebdc)), closes [#37105](https://github.com/angular/angular/issues/37105)
* **core:** queries not matching string injection tokens ([#38321](https://github.com/angular/angular/issues/38321)) ([32109dc](https://github.com/angular/angular/commit/32109dc)), closes [#38313](https://github.com/angular/angular/issues/38313) [#38315](https://github.com/angular/angular/issues/38315)
* **core:** Store the currently selected ICU in `LView` ([#38345](https://github.com/angular/angular/issues/38345)) ([ee5123f](https://github.com/angular/angular/commit/ee5123f))
* **platform-server:** remove styles added by ServerStylesHost on destruction ([#38367](https://github.com/angular/angular/issues/38367)) ([7f11149](https://github.com/angular/angular/commit/7f11149))
* **router:** prevent calling unsubscribe on undefined subscription in RouterPreloader ([#38344](https://github.com/angular/angular/issues/38344)) ([4151314](https://github.com/angular/angular/commit/4151314))
* **service-worker:** fix the chrome debugger syntax highlighter ([#38332](https://github.com/angular/angular/issues/38332)) ([f5d5bac](https://github.com/angular/angular/commit/f5d5bac))
<a name="10.0.8"></a>
## 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.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.0.5"></a>
## 10.0.5 (2020-07-22)
### Bug Fixes
* **compiler:** properly associate source spans for implicitly closed elements ([#38126](https://github.com/angular/angular/issues/38126)) ([e80278c](https://github.com/angular/angular/commit/e80278c)), closes [#36118](https://github.com/angular/angular/issues/36118)
* **compiler-cli:** ensure file_system handles mixed Windows drives ([#38030](https://github.com/angular/angular/issues/38030)) ([dba4023](https://github.com/angular/angular/commit/dba4023)), closes [#36777](https://github.com/angular/angular/issues/36777)
* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#38119](https://github.com/angular/angular/issues/38119)) ([14b4718](https://github.com/angular/angular/commit/14b4718)), closes [#30497](https://github.com/angular/angular/issues/30497)
* **core:** error due to integer overflow when there are too many host bindings ([#38014](https://github.com/angular/angular/issues/38014)) ([7b6e73c](https://github.com/angular/angular/commit/7b6e73c)), closes [#37876](https://github.com/angular/angular/issues/37876) [#37876](https://github.com/angular/angular/issues/37876)
* **core:** incorrectly validating properties on ng-content and ng-container ([#37773](https://github.com/angular/angular/issues/37773)) ([17ddab9](https://github.com/angular/angular/commit/17ddab9))
<a name="10.0.4"></a>
## 10.0.4 (2020-07-15)
@ -207,6 +18,62 @@
* **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>
## 10.0.3 (2020-07-08)

View File

@ -230,6 +230,7 @@ Must be one of the following:
* **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

View File

@ -5,22 +5,21 @@
# Angular
Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages.
Angular es una plataforma de desarrollo para construir aplicaciones web y móviles que usa TypeScript/JavaScript y otros lenguajes de programación.
## Quickstart
## Guía rápida
[Get started in 5 minutes][quickstart].
[Comienza a usarlo en 5 minutos][quickstart].
## Changelog
## Registro de cambios (Changelog)
[Learn about the latest improvements][changelog].
[Últimas mejoras realizadas][changelog].
## Want to help?
## ¿Quieres ayudar?
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).
¿Quieres encontrar fallos, colaborar con código, o mejorar la documentación? ¡Excelente! Lee nuestras
pautas para [colaborar][contributing] y luego revisa algunos de nuestras incidencias (issues) en [ayuda comunitaria](https://github.com/angular-hispano/angular/labels/ayuda%20comunitaria).
[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md
[quickstart]: https://angular.io/start
[contributing]: https://github.com/angular-hispano/angular/blob/master/CONTRIBUTING.md
[quickstart]: https://docs.angular.lat/start
[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md
[ng]: https://angular.io

View File

@ -18,7 +18,6 @@
**/src/karma.conf.js
**/.angular-cli.json
**/.editorconfig
**/.gitignore
**/angular.json
**/tsconfig.json
**/bs-config.e2e.json

View File

@ -1,3 +1,5 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor';
describe('Accessibility example e2e tests', () => {
@ -6,11 +8,11 @@ describe('Accessibility example e2e tests', () => {
browser.get('');
});
it('should display Accessibility Example', () => {
it('should display Accessibility Example', function () {
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');
expect(element(by.css('input')).getAttribute('value')).toEqual('016');
expect(element(by.css('app-example-progressbar div')).getCssValue('width')).toBe('48px');

View File

@ -1,4 +1,3 @@
// tslint:disable: no-host-metadata-property
// #docregion progressbar-component
import { Component, Input } from '@angular/core';

View File

@ -1,18 +1,20 @@
'use strict'; // necessary for es6 output in node
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('');
});
it('should display no poster images after bootstrap', () => {
it('should display no poster images after bootstrap', function () {
testImagesAreDisplayed(false);
});
it('should display proper movie data', () => {
it('should display proper movie data', function () {
// 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: 2, value: 'Celeritas'},
{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
const movieRows = getMovieRows();
for (const sample of expectedSamples) {
const tableCell = movieRows.get(sample.row)
let movieRows = getMovieRows();
for (let i = 0; i < expectedSamples.length; i++) {
let sample = expectedSamples[i];
let tableCell = movieRows.get(sample.row)
.all(by.tagName('td')).get(sample.column);
// Check the cell or its nested element
const elementToCheck = sample.element
let elementToCheck = sample.element
? tableCell.element(by.tagName(sample.element))
: tableCell;
// Check element attribute or text
const valueToCheck = sample.attr
let valueToCheck = sample.attr
? elementToCheck.getAttribute(sample.attr)
: 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);
});
it('should hide images after Hide Poster', () => {
it('should hide images after Hide Poster', function () {
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.');
});
it('should display no movie for Magneta', () => {
it('should display no movie for Magneta', function () {
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!');
});
function testImagesAreDisplayed(isDisplayed: boolean) {
const expectedMovieCount = 3;
let expectedMovieCount = 3;
const movieRows = getMovieRows();
let movieRows = getMovieRows();
expect(movieRows.count()).toBe(expectedMovieCount);
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);
}
}
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);
posterButton.click().then(() => {
posterButton.click().then(function () {
testImagesAreDisplayed(isDisplayed);
});
}
@ -93,12 +96,12 @@ describe('AngularJS to Angular Quick Reference Tests', () => {
}
function testFavoriteHero(heroName: string, expectedLabel: string) {
const movieListComp = element(by.tagName('app-movie-list'));
const heroInput = movieListComp.element(by.tagName('input'));
const favoriteHeroLabel = movieListComp.element(by.tagName('h3'));
const resultLabel = movieListComp.element(by.css('span > p'));
let movieListComp = element(by.tagName('app-movie-list'));
let heroInput = movieListComp.element(by.tagName('input'));
let favoriteHeroLabel = movieListComp.element(by.tagName('h3'));
let resultLabel = movieListComp.element(by.css('span > p'));
heroInput.clear().then(() => {
heroInput.clear().then(function () {
heroInput.sendKeys(heroName || '');
expect(resultLabel.getText()).toBe(expectedLabel);
if (heroName) {

View File

@ -1,3 +1,5 @@
'use strict'; // necessary for es6 output in node
import { browser, ExpectedConditions as EC } from 'protractor';
import { logging } from 'selenium-webdriver';
import * as openClose from './open-close.po';

View File

@ -34,7 +34,7 @@ export class AppComponent {
// #docregion prepare-router-outlet
prepareRoute(outlet: RouterOutlet) {
return outlet && outlet.activatedRouteData && outlet.activatedRouteData.animation;
return outlet && outlet.activatedRouteData && outlet.activatedRouteData['animation'];
}
// #enddocregion prepare-router-outlet

View File

@ -1,6 +1,4 @@
// tslint:disable: variable-name
// #docplaster
// #docregion
import { Component, HostBinding, OnInit } from '@angular/core';
import { trigger, transition, animate, style, query, stagger } from '@angular/animations';
import { HEROES } from './mock-heroes';
@ -54,11 +52,13 @@ export class HeroListPageComponent implements OnInit {
@HostBinding('@pageAnimations')
public animatePage = true;
_heroes = [];
// #docregion filter-animations
heroTotal = -1;
// #enddocregion filter-animations
get heroes() { return this._heroes; }
private _heroes = [];
get heroes() {
return this._heroes;
}
ngOnInit() {
this._heroes = HEROES;

View File

@ -8,7 +8,8 @@ import { trigger, transition, state, animate, style, AnimationEvent } from '@ang
// #docregion trigger, trigger-wildcard1, trigger-transition
animations: [
trigger('openClose', [
// #docregion state1
// #enddocregion events1
// #docregion state1, events1
// ...
// #enddocregion events1
state('open', style({
@ -33,7 +34,8 @@ import { trigger, transition, state, animate, style, AnimationEvent } from '@ang
transition('closed => open', [
animate('0.5s')
]),
// #enddocregion transition2, trigger, component
// #enddocregion trigger, component
// #enddocregion transition2
// #docregion trigger-wildcard1
transition('* => closed', [
animate('1s')
@ -68,9 +70,7 @@ import { trigger, transition, state, animate, style, AnimationEvent } from '@ang
})
// #docregion events
export class OpenCloseComponent {
// #enddocregion events1, events, component
@Input() logging = false;
// #docregion component
// #enddocregion events1, events
isOpen = true;
toggle() {
@ -78,6 +78,7 @@ export class OpenCloseComponent {
}
// #enddocregion component
@Input() logging = false;
// #docregion events1, events
onAnimationEvent ( event: AnimationEvent ) {
// #enddocregion events1, events

View File

@ -1,3 +1,5 @@
'use strict'; // necessary for es6 output in node
import { protractor, browser, element, by, ElementFinder } from 'protractor';
const nameSuffix = 'X';
@ -19,7 +21,7 @@ describe('Architecture', () => {
});
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);
});
@ -32,42 +34,42 @@ function heroTests() {
const targetHero: Hero = { id: 2, name: 'Dr Nice' };
it('has the right number of heroes', () => {
const page = getPageElts();
let page = getPageElts();
expect(page.heroes.count()).toEqual(3);
});
it('has no hero details initially', () => {
const page = getPageElts();
it('has no hero details initially', function () {
let page = getPageElts();
expect(page.heroDetail.isPresent()).toBeFalsy('no hero detail');
});
it('shows selected hero details', async () => {
await element(by.cssContainingText('li', targetHero.name)).click();
const page = getPageElts();
const hero = await heroFromDetail(page.heroDetail);
let page = getPageElts();
let hero = await heroFromDetail(page.heroDetail);
expect(hero.id).toEqual(targetHero.id);
expect(hero.name).toEqual(targetHero.name);
});
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);
const page = getPageElts();
const hero = await heroFromDetail(page.heroDetail);
const newName = targetHero.name + nameSuffix;
let page = getPageElts();
let hero = await heroFromDetail(page.heroDetail);
let newName = targetHero.name + nameSuffix;
expect(hero.id).toEqual(targetHero.id);
expect(hero.name).toEqual(newName);
});
}
function salesTaxTests() {
it('has no sales tax initially', () => {
const page = getPageElts();
it('has no sales tax initially', function () {
let page = getPageElts();
expect(page.salesTaxDetail.isPresent()).toBeFalsy('no sales tax info');
});
it('shows sales tax', async () => {
const page = getPageElts();
it('shows sales tax', async function () {
let page = getPageElts();
page.salesTaxAmountInput.sendKeys('10', protractor.Key.ENTER);
expect(page.salesTaxDetail.getText()).toEqual('The sales tax is $1.00');
});
@ -86,11 +88,13 @@ function getPageElts() {
async function heroFromDetail(detail: ElementFinder): Promise<Hero> {
// 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
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 {
id: +id.substr(id.indexOf(' ') + 1),
name: name.substr(0, name.lastIndexOf(' ')),
id: +_id.substr(_id.indexOf(' ') + 1),
name: _name.substr(0, _name.lastIndexOf(' '))
};
}

View File

@ -18,7 +18,7 @@ export class BackendService {
// TODO: get from the database
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);
throw err;
}

View File

@ -7,7 +7,7 @@ export class SalesTaxService {
constructor(private rateService: TaxRateService) { }
getVAT(value: string | number) {
const amount = (typeof value === 'string') ?
let amount = (typeof value === 'string') ?
parseFloat(value) : value;
return (amount || 0) * this.rateService.getRate('VAT');
}

View File

@ -1,32 +1,34 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor';
describe('Attribute binding example', () => {
describe('Attribute binding example', function () {
beforeEach(() => {
beforeEach(function () {
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');
});
it('should display a table', () => {
it('should display a table', function() {
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');
});
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)');
});
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)');
});
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('clearance');
});

View File

@ -1,16 +1,16 @@
import { Component, HostBinding } from '@angular/core';
import { Component } from '@angular/core';
@Component({
selector: 'comp-with-host-binding',
template: 'I am a component!',
host: {
'[class.special]': 'isSpecial',
'[style.color]': 'color',
'[style.width]': 'width'
}
})
export class CompWithHostBindingComponent {
@HostBinding('class.special')
isSpecial = false;
@HostBinding('style.color')
color = 'green';
@HostBinding('style.width')
width = '200px';
}

View File

@ -1,15 +1,17 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor';
describe('Attribute directives', () => {
const title = 'My First Attribute Directive';
let _title = 'My First Attribute Directive';
beforeAll(() => {
browser.get('');
});
it(`should display correct title: ${title}`, () => {
expect(element(by.css('h1')).getText()).toEqual(title);
it(`should display correct title: ${_title}`, () => {
expect(element(by.css('h1')).getText()).toEqual(_title);
});
it('should be able to select green highlight', () => {

View File

@ -3,55 +3,57 @@ import { logging } from 'selenium-webdriver';
describe('Binding syntax e2e tests', () => {
beforeEach(() => browser.get(''));
beforeEach(function () {
browser.get('');
});
// helper function used to test what's logged to the console
async function logChecker(button, contents) {
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
const messages = logs.filter(({ message }) => message.indexOf(contents) !== -1 ? true : false);
expect(messages.length).toBeGreaterThan(0);
const message = logs.filter(({ message }) => message.indexOf(contents) !== -1 ? true : false);
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');
});
it('should display Save button', () => {
it('should display Save button', function () {
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');
});
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');
});
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');
});
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();
const contents = 'Sarah';
logChecker(attributeButton, contents);
});
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();
const contents = 'Sarah';
logChecker(DOMPropertyButton, contents);
});
it('should log a message including Sally for DOM property', async () => {
const DOMPropertyButton = element.all(by.css('button')).get(2);
const input = element(by.css('input'));
let DOMPropertyButton = element.all(by.css('button')).get(2);
let input = element(by.css('input'));
input.sendKeys('Sally');
await DOMPropertyButton.click();
const contents = 'Sally';
@ -59,14 +61,14 @@ describe('Binding syntax e2e tests', () => {
});
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();
const contents = 'Test';
logChecker(testButton, contents);
});
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();
const contents = 'true';
logChecker(toggleButton, contents);

View File

@ -26,7 +26,7 @@ export class AppComponent {
toggleDisabled(): any {
const testButton = document.getElementById('testButton') as HTMLInputElement;
let testButton = <HTMLInputElement> document.getElementById('testButton');
testButton.disabled = !testButton.disabled;
console.warn(testButton.disabled);
}

View File

@ -1,19 +1,21 @@
'use strict';
import { browser, element, by } from 'protractor';
describe('Built-in Directives', () => {
describe('Built-in Directives', function () {
beforeAll(() => {
beforeAll(function () {
browser.get('');
});
it('should have title Built-in Directives', () => {
const title = element.all(by.css('h1')).get(0);
it('should have title Built-in Directives', function () {
let title = element.all(by.css('h1')).get(0);
expect(title.getText()).toEqual('Built-in Directives');
});
it('should change first Teapot header', async () => {
const firstLabel = element.all(by.css('p')).get(0);
const firstInput = element.all(by.css('input')).get(0);
let firstLabel = element.all(by.css('p')).get(0);
let firstInput = element.all(by.css('input')).get(0);
expect(firstLabel.getText()).toEqual('Current item name: Teapot');
firstInput.sendKeys('abc');
@ -21,49 +23,49 @@ describe('Built-in Directives', () => {
});
it('should modify sentence when modified checkbox checked', () => {
const modifiedChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(1);
const modifiedSentence = element.all(by.css('div')).get(1);
it('should modify sentence when modified checkbox checked', function () {
let modifiedChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(1);
let modifiedSentence = element.all(by.css('div')).get(1);
modifiedChkbxLabel.click();
expect(modifiedSentence.getText()).toContain('modified');
});
it('should modify sentence when normal checkbox checked', () => {
const normalChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(4);
const normalSentence = element.all(by.css('div')).get(7);
it('should modify sentence when normal checkbox checked', function () {
let normalChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(4);
let normalSentence = element.all(by.css('div')).get(7);
normalChkbxLabel.click();
expect(normalSentence.getText()).toContain('normal weight and, extra large');
});
it('should toggle app-item-detail', () => {
const toggleButton = element.all(by.css('button')).get(3);
const toggledDiv = element.all(by.css('app-item-detail')).get(0);
it('should toggle app-item-detail', function () {
let toggleButton = element.all(by.css('button')).get(3);
let toggledDiv = element.all(by.css('app-item-detail')).get(0);
toggleButton.click();
expect(toggledDiv.isDisplayed()).toBe(true);
});
it('should hide app-item-detail', () => {
const hiddenMessage = element.all(by.css('p')).get(11);
const hiddenDiv = element.all(by.css('app-item-detail')).get(2);
it('should hide app-item-detail', function () {
let hiddenMessage = element.all(by.css('p')).get(11);
let hiddenDiv = element.all(by.css('app-item-detail')).get(2);
expect(hiddenMessage.getText()).toContain('in the DOM');
expect(hiddenDiv.isDisplayed()).toBe(true);
});
it('should have 10 lists each containing the string Teapot', () => {
const listDiv = element.all(by.cssContainingText('.box', 'Teapot'));
it('should have 10 lists each containing the string Teapot', function () {
let listDiv = element.all(by.cssContainingText('.box', 'Teapot'));
expect(listDiv.count()).toBe(10);
});
it('should switch case', () => {
const tvRadioButton = element.all(by.css('input[type="radio"]')).get(3);
const tvDiv = element(by.css('app-lost-item'));
it('should switch case', function () {
let tvRadioButton = element.all(by.css('input[type="radio"]')).get(3);
let tvDiv = element(by.css('app-lost-item'));
const fishbowlRadioButton = element.all(by.css('input[type="radio"]')).get(4);
const fishbowlDiv = element(by.css('app-unknown-item'));
let fishbowlRadioButton = element.all(by.css('input[type="radio"]')).get(4);
let fishbowlDiv = element(by.css('app-unknown-item'));
tvRadioButton.click();
expect(tvDiv.getText()).toContain('Television');

View File

@ -30,14 +30,6 @@ export class AppComponent implements OnInit {
itemsWithTrackByCountReset = 0;
itemIdIncrement = 1;
// #docregion setClasses
currentClasses: {};
// #enddocregion setClasses
// #docregion setStyles
currentStyles: {};
// #enddocregion setStyles
ngOnInit() {
this.resetItems();
this.setCurrentClasses();
@ -50,17 +42,19 @@ export class AppComponent implements OnInit {
}
// #docregion setClasses
currentClasses: {};
setCurrentClasses() {
// CSS classes: added/removed per current state of component properties
this.currentClasses = {
saveable: this.canSave,
modified: !this.isUnchanged,
special: this.isSpecial
'saveable': this.canSave,
'modified': !this.isUnchanged,
'special': this.isSpecial
};
}
// #enddocregion setClasses
// #docregion setStyles
currentStyles: {};
setCurrentStyles() {
// CSS styles: set per current state of component properties
this.currentStyles = {
@ -76,7 +70,11 @@ export class AppComponent implements OnInit {
}
giveNullCustomerValue() {
this.nullCustomer = 'Kelly';
!(this.nullCustomer = null) ? (this.nullCustomer = 'Kelly') : (this.nullCustomer = null);
}
resetNullItem() {
this.nullCustomer = null;
}
resetItems() {
@ -86,7 +84,7 @@ export class AppComponent implements OnInit {
}
resetList() {
this.resetItems();
this.resetItems()
this.itemsWithTrackByCountReset = 0;
this.itemsNoTrackByCount = ++this.itemsNoTrackByCount;
}
@ -109,7 +107,7 @@ export class AppComponent implements OnInit {
trackByItems(index: number, item: Item): number { return item.id; }
// #enddocregion trackByItems
trackById(index: number, item: any): number { return item.id; }
trackById(index: number, item: any): number { return item['id']; }
}

View File

@ -1,17 +1,19 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor';
describe('Built Template Functions Example', () => {
beforeAll(() => {
describe('Built Template Functions Example', function () {
beforeAll(function () {
browser.get('');
});
it('should have title Built-in Template Functions', () => {
const title = element.all(by.css('h1')).get(0);
it('should have title Built-in Template Functions', function () {
let title = element.all(by.css('h1')).get(0);
expect(title.getText()).toEqual('Built-in Template Functions');
});
it('should display $any( ) in h2', () => {
const header = element(by.css('h2'));
it('should display $any( ) in h2', function () {
let header = element(by.css('h2'));
expect(header.getText()).toContain('$any( )');
});

View File

@ -1,85 +1,87 @@
'use strict'; // necessary for es6 output in node
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
// e.g. `if (!/e2e/.test(location.search)) { ...`
beforeAll(() => {
beforeAll(function () {
browser.get('?e2e');
});
describe('Parent-to-child communication', () => {
describe('Parent-to-child communication', function() {
// #docregion parent-to-child
// ...
const heroNames = ['Dr IQ', 'Magneta', 'Bombasto'];
const masterName = 'Master';
let _heroNames = ['Dr IQ', 'Magneta', 'Bombasto'];
let _masterName = 'Master';
it('should pass properties to children properly', () => {
const parent = element.all(by.tagName('app-hero-parent')).get(0);
const heroes = parent.all(by.tagName('app-hero-child'));
it('should pass properties to children properly', function () {
let parent = element.all(by.tagName('app-hero-parent')).get(0);
let heroes = parent.all(by.tagName('app-hero-child'));
for (let i = 0; i < heroNames.length; i++) {
const childTitle = heroes.get(i).element(by.tagName('h3')).getText();
const childDetail = heroes.get(i).element(by.tagName('p')).getText();
expect(childTitle).toEqual(heroNames[i] + ' says:');
expect(childDetail).toContain(masterName);
for (let i = 0; i < _heroNames.length; i++) {
let childTitle = heroes.get(i).element(by.tagName('h3')).getText();
let childDetail = heroes.get(i).element(by.tagName('p')).getText();
expect(childTitle).toEqual(_heroNames[i] + ' says:');
expect(childDetail).toContain(_masterName);
}
});
// ...
// #enddocregion parent-to-child
});
describe('Parent-to-child communication with setter', () => {
describe('Parent-to-child communication with setter', function() {
// #docregion parent-to-child-setter
// ...
it('should display trimmed, non-empty names', () => {
const nonEmptyNameIndex = 0;
const nonEmptyName = '"Dr IQ"';
const parent = element.all(by.tagName('app-name-parent')).get(0);
const hero = parent.all(by.tagName('app-name-child')).get(nonEmptyNameIndex);
it('should display trimmed, non-empty names', function () {
let _nonEmptyNameIndex = 0;
let _nonEmptyName = '"Dr IQ"';
let parent = element.all(by.tagName('app-name-parent')).get(0);
let hero = parent.all(by.tagName('app-name-child')).get(_nonEmptyNameIndex);
const displayName = hero.element(by.tagName('h3')).getText();
expect(displayName).toEqual(nonEmptyName);
let displayName = hero.element(by.tagName('h3')).getText();
expect(displayName).toEqual(_nonEmptyName);
});
it('should replace empty name with default name', () => {
const emptyNameIndex = 1;
const defaultName = '"<no name set>"';
const parent = element.all(by.tagName('app-name-parent')).get(0);
const hero = parent.all(by.tagName('app-name-child')).get(emptyNameIndex);
it('should replace empty name with default name', function () {
let _emptyNameIndex = 1;
let _defaultName = '"<no name set>"';
let parent = element.all(by.tagName('app-name-parent')).get(0);
let hero = parent.all(by.tagName('app-name-child')).get(_emptyNameIndex);
const displayName = hero.element(by.tagName('h3')).getText();
expect(displayName).toEqual(defaultName);
let displayName = hero.element(by.tagName('h3')).getText();
expect(displayName).toEqual(_defaultName);
});
// ...
// #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
// ...
// Test must all execute in this exact order
it('should set expected initial values', () => {
const actual = getActual();
it('should set expected initial values', function () {
let actual = getActual();
const initialLabel = 'Version 1.23';
const initialLog = 'Initial value of major set to 1, Initial value of minor set to 23';
let initialLabel = 'Version 1.23';
let initialLog = 'Initial value of major set to 1, Initial value of minor set to 23';
expect(actual.label).toBe(initialLabel);
expect(actual.count).toBe(1);
expect(actual.logs.get(0).getText()).toBe(initialLog);
});
it('should set expected values after clicking \'Minor\' twice', () => {
const repoTag = element(by.tagName('app-version-parent'));
const newMinorButton = repoTag.all(by.tagName('button')).get(0);
it('should set expected values after clicking \'Minor\' twice', function () {
let repoTag = element(by.tagName('app-version-parent'));
let newMinorButton = repoTag.all(by.tagName('button')).get(0);
newMinorButton.click().then(() => {
newMinorButton.click().then(() => {
const actual = getActual();
newMinorButton.click().then(function() {
newMinorButton.click().then(function() {
let actual = getActual();
const labelAfter2Minor = 'Version 1.25';
const logAfter2Minor = 'minor changed from 24 to 25';
let labelAfter2Minor = 'Version 1.25';
let logAfter2Minor = 'minor changed from 24 to 25';
expect(actual.label).toBe(labelAfter2Minor);
expect(actual.count).toBe(3);
@ -88,15 +90,15 @@ describe('Component Communication Cookbook Tests', () => {
});
});
it('should set expected values after clicking \'Major\' once', () => {
const repoTag = element(by.tagName('app-version-parent'));
const newMajorButton = repoTag.all(by.tagName('button')).get(1);
it('should set expected values after clicking \'Major\' once', function () {
let repoTag = element(by.tagName('app-version-parent'));
let newMajorButton = repoTag.all(by.tagName('button')).get(1);
newMajorButton.click().then(() => {
const actual = getActual();
newMajorButton.click().then(function() {
let actual = getActual();
const labelAfterMajor = 'Version 2.0';
const logAfterMajor = 'major changed from 1 to 2, minor changed from 25 to 0';
let labelAfterMajor = 'Version 2.0';
let logAfterMajor = 'major changed from 1 to 2, minor changed from 25 to 0';
expect(actual.label).toBe(labelAfterMajor);
expect(actual.count).toBe(4);
@ -105,14 +107,14 @@ describe('Component Communication Cookbook Tests', () => {
});
function getActual() {
const versionTag = element(by.tagName('app-version-child'));
const label = versionTag.element(by.tagName('h3')).getText();
const ul = versionTag.element((by.tagName('ul')));
const logs = ul.all(by.tagName('li'));
let versionTag = element(by.tagName('app-version-child'));
let label = versionTag.element(by.tagName('h3')).getText();
let ul = versionTag.element((by.tagName('ul')));
let logs = ul.all(by.tagName('li'));
return {
label,
logs,
label: label,
logs: logs,
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
// ...
it('should not emit the event initially', () => {
const voteLabel = element(by.tagName('app-vote-taker'))
it('should not emit the event initially', function () {
let voteLabel = element(by.tagName('app-vote-taker'))
.element(by.tagName('h3')).getText();
expect(voteLabel).toBe('Agree: 0, Disagree: 0');
});
it('should process Agree vote', () => {
const agreeButton1 = element.all(by.tagName('app-voter')).get(0)
it('should process Agree vote', function () {
let agreeButton1 = element.all(by.tagName('app-voter')).get(0)
.all(by.tagName('button')).get(0);
agreeButton1.click().then(() => {
const voteLabel = element(by.tagName('app-vote-taker'))
agreeButton1.click().then(function() {
let voteLabel = element(by.tagName('app-vote-taker'))
.element(by.tagName('h3')).getText();
expect(voteLabel).toBe('Agree: 1, Disagree: 0');
});
});
it('should process Disagree vote', () => {
const agreeButton1 = element.all(by.tagName('app-voter')).get(1)
it('should process Disagree vote', function () {
let agreeButton1 = element.all(by.tagName('app-voter')).get(1)
.all(by.tagName('button')).get(1);
agreeButton1.click().then(() => {
const voteLabel = element(by.tagName('app-vote-taker'))
agreeButton1.click().then(function() {
let voteLabel = element(by.tagName('app-vote-taker'))
.element(by.tagName('h3')).getText();
expect(voteLabel).toBe('Agree: 1, Disagree: 1');
});
@ -155,31 +157,31 @@ describe('Component Communication Cookbook Tests', () => {
// Can't run timer tests in protractor because
// 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');
});
xdescribe('Parent calls ViewChild', () => {
xdescribe('Parent calls ViewChild', function() {
countDownTimerTests('countdown-parent-vc');
});
function countDownTimerTests(parentTag: string) {
// #docregion countdown-timer-tests
// ...
it('timer and parent seconds should match', () => {
const parent = element(by.tagName(parentTag));
const message = parent.element(by.tagName('app-countdown-timer')).getText();
it('timer and parent seconds should match', function () {
let parent = element(by.tagName(parentTag));
let message = parent.element(by.tagName('app-countdown-timer')).getText();
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);
});
it('should stop the countdown', () => {
const parent = element(by.tagName(parentTag));
const stopButton = parent.all(by.tagName('button')).get(1);
it('should stop the countdown', function () {
let parent = element(by.tagName(parentTag));
let stopButton = parent.all(by.tagName('button')).get(1);
stopButton.click().then(() => {
const message = parent.element(by.tagName('app-countdown-timer')).getText();
stopButton.click().then(function() {
let message = parent.element(by.tagName('app-countdown-timer')).getText();
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
// ...
it('should announce a mission', () => {
const missionControl = element(by.tagName('app-mission-control'));
const announceButton = missionControl.all(by.tagName('button')).get(0);
announceButton.click().then(() => {
const history = missionControl.all(by.tagName('li'));
it('should announce a mission', function () {
let missionControl = element(by.tagName('app-mission-control'));
let announceButton = missionControl.all(by.tagName('button')).get(0);
announceButton.click().then(function () {
let history = missionControl.all(by.tagName('li'));
expect(history.count()).toBe(1);
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');
});
it('should confirm the mission by Haise', () => {
it('should confirm the mission by Haise', function () {
testConfirmMission(3, 3, 'Haise');
});
it('should confirm the mission by Swigert', () => {
it('should confirm the mission by Swigert', function () {
testConfirmMission(2, 4, 'Swigert');
});
function testConfirmMission(buttonIndex: number, expectedLogCount: number, astronaut: string) {
const confirmedLog = ' confirmed the mission';
const missionControl = element(by.tagName('app-mission-control'));
const confirmButton = missionControl.all(by.tagName('button')).get(buttonIndex);
confirmButton.click().then(() => {
const history = missionControl.all(by.tagName('li'));
let _confirmedLog = ' confirmed the mission';
let missionControl = element(by.tagName('app-mission-control'));
let confirmButton = missionControl.all(by.tagName('button')).get(buttonIndex);
confirmButton.click().then(function () {
let history = missionControl.all(by.tagName('li'));
expect(history.count()).toBe(expectedLogCount);
expect(history.get(expectedLogCount - 1).getText()).toBe(astronaut + confirmedLog);
expect(history.get(expectedLogCount - 1).getText()).toBe(astronaut + _confirmedLog);
});
}
// ...

View File

@ -15,7 +15,7 @@ import { VersionParentComponent } from './version-parent.component';
import { VoterComponent } from './voter.component';
import { VoteTakerComponent } from './votetaker.component';
const directives: any[] = [
let directives: any[] = [
AppComponent,
AstronautComponent,
CountdownTimerComponent,
@ -30,7 +30,7 @@ const directives: any[] = [
VoteTakerComponent
];
const schemas: any[] = [];
let schemas: any[] = [];
// Include Countdown examples
// unless in e2e tests which they break.
@ -49,6 +49,6 @@ if (!/e2e/.test(location.search)) {
],
declarations: directives,
bootstrap: [ AppComponent ],
schemas
schemas: schemas
})
export class AppModule { }

View File

@ -12,6 +12,6 @@ import { Hero } from './hero';
})
export class HeroChildComponent {
@Input() hero: Hero;
@Input('master') masterName: string; // tslint:disable-line: no-input-rename
@Input('master') masterName: string;
}
// #enddocregion

View File

@ -34,7 +34,7 @@ export class MissionControlComponent {
}
announce() {
const mission = this.missions[this.nextMission++];
let mission = this.missions[this.nextMission++];
this.missionService.announceMission(mission);
this.history.push(`Mission "${mission}" announced`);
if (this.nextMission >= this.missions.length) { this.nextMission = 0; }

View File

@ -1,4 +1,3 @@
// tslint:disable: variable-name
// #docregion
import { Component, Input } from '@angular/core';
@ -7,11 +6,13 @@ import { Component, Input } from '@angular/core';
template: '<h3>"{{name}}"</h3>'
})
export class NameChildComponent {
private _name = '';
@Input()
get name(): string { return this._name; }
set name(name: string) {
this._name = (name && name.trim()) || '<no name set>';
}
private _name = '';
get name(): string { return this._name; }
}
// #enddocregion

View File

@ -18,14 +18,14 @@ export class VersionChildComponent implements OnChanges {
changeLog: string[] = [];
ngOnChanges(changes: {[propKey: string]: SimpleChange}) {
const log: string[] = [];
for (const propName in changes) {
const changedProp = changes[propName];
const to = JSON.stringify(changedProp.currentValue);
let log: string[] = [];
for (let propName in changes) {
let changedProp = changes[propName];
let to = JSON.stringify(changedProp.currentValue);
if (changedProp.isFirstChange()) {
log.push(`Initial value of ${propName} set to ${to}`);
} else {
const from = JSON.stringify(changedProp.previousValue);
let from = JSON.stringify(changedProp.previousValue);
log.push(`${propName} changed from ${from} to ${to}`);
}
}

View File

@ -1,14 +1,16 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor';
describe('Component Style Tests', () => {
describe('Component Style Tests', function () {
beforeAll(() => {
beforeAll(function () {
browser.get('');
});
it('scopes component styles to component view', () => {
const componentH1 = element(by.css('app-root > h1'));
const externalH1 = element(by.css('body > h1'));
it('scopes component styles to component view', function() {
let componentH1 = element(by.css('app-root > h1'));
let externalH1 = element(by.css('body > h1'));
// Note: sometimes webdriver returns the fontWeight as "normal",
// 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', () => {
const host = element(by.css('app-hero-details'));
it('allows styling :host element', function() {
let host = element(by.css('app-hero-details'));
expect(host.getCssValue('borderWidth')).toEqual('1px');
});
it('supports :host() in function form', () => {
const host = element(by.css('app-hero-details'));
it('supports :host() in function form', function() {
let host = element(by.css('app-hero-details'));
host.element(by.buttonText('Activate')).click();
expect(host.getCssValue('borderWidth')).toEqual('3px');
});
it('allows conditional :host-context() styling', () => {
const h2 = element(by.css('app-hero-details h2'));
it('allows conditional :host-context() styling', function() {
let h2 = element(by.css('app-hero-details h2'));
expect(h2.getCssValue('backgroundColor')).toEqual('rgba(238, 238, 255, 1)'); // #eeeeff
});
it('styles both view and content children with /deep/', () => {
const viewH3 = element(by.css('app-hero-team h3'));
const contentH3 = element(by.css('app-hero-controls h3'));
it('styles both view and content children with /deep/', function() {
let viewH3 = element(by.css('app-hero-team h3'));
let contentH3 = element(by.css('app-hero-controls h3'));
expect(viewH3.getCssValue('fontStyle')).toEqual('italic');
expect(contentH3.getCssValue('fontStyle')).toEqual('italic');
});
it('includes styles loaded with CSS @import', () => {
const host = element(by.css('app-hero-details'));
it('includes styles loaded with CSS @import', function() {
let host = element(by.css('app-hero-details'));
expect(host.getCssValue('padding')).toEqual('10px');
});
it('processes template inline styles', () => {
const button = element(by.css('app-hero-controls button'));
const externalButton = element(by.css('body > button'));
it('processes template inline styles', function() {
let button = element(by.css('app-hero-controls button'));
let externalButton = element(by.css('body > button'));
expect(button.getCssValue('backgroundColor')).toEqual('rgba(255, 255, 255, 1)'); // #ffffff
expect(externalButton.getCssValue('backgroundColor')).not.toEqual('rgba(255, 255, 255, 1)');
});
it('processes template <link>s', () => {
const li = element(by.css('app-hero-team li:first-child'));
const externalLi = element(by.css('body > ul li'));
it('processes template <link>s', function() {
let li = element(by.css('app-hero-team li:first-child'));
let externalLi = element(by.css('body > ul li'));
expect(li.getCssValue('listStyleType')).toEqual('square');
expect(externalLi.getCssValue('listStyleType')).not.toEqual('square');

View File

@ -1,74 +1,76 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor';
describe('Dependency Injection Cookbook', () => {
describe('Dependency Injection Cookbook', function () {
beforeAll(() => {
beforeAll(function () {
browser.get('');
});
it('should render Logged in User example', () => {
const loggedInUser = element.all(by.xpath('//h3[text()="Logged in user"]')).get(0);
it('should render Logged in User example', function () {
let loggedInUser = element.all(by.xpath('//h3[text()="Logged in user"]')).get(0);
expect(loggedInUser).toBeDefined();
});
it('"Bombasto" should be the logged in user', () => {
const loggedInUser = element.all(by.xpath('//div[text()="Name: Bombasto"]')).get(0);
it('"Bombasto" should be the logged in user', function () {
let loggedInUser = element.all(by.xpath('//div[text()="Name: Bombasto"]')).get(0);
expect(loggedInUser).toBeDefined();
});
it('should render sorted heroes', () => {
const sortedHeroes = element.all(by.xpath('//h3[text()="Sorted Heroes" and position()=1]')).get(0);
it('should render sorted heroes', function () {
let sortedHeroes = element.all(by.xpath('//h3[text()="Sorted Heroes" and position()=1]')).get(0);
expect(sortedHeroes).toBeDefined();
});
it('Dr Nice should be in sorted heroes', () => {
const sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Dr Nice" and position()=2]')).get(0);
it('Dr Nice should be in sorted heroes', function () {
let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Dr Nice" and position()=2]')).get(0);
expect(sortedHero).toBeDefined();
});
it('RubberMan should be in sorted heroes', () => {
const sortedHero = element.all(by.xpath('//sorted-heroes/[text()="RubberMan" and position()=3]')).get(0);
it('RubberMan should be in sorted heroes', function () {
let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="RubberMan" and position()=3]')).get(0);
expect(sortedHero).toBeDefined();
});
it('Magma should be in sorted heroes', () => {
const sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Magma"]')).get(0);
it('Magma should be in sorted heroes', function () {
let sortedHero = element.all(by.xpath('//sorted-heroes/[text()="Magma"]')).get(0);
expect(sortedHero).toBeDefined();
});
it('should render Hero of the Month', () => {
const heroOfTheMonth = element.all(by.xpath('//h3[text()="Hero of the month"]')).get(0);
it('should render Hero of the Month', function () {
let heroOfTheMonth = element.all(by.xpath('//h3[text()="Hero of the month"]')).get(0);
expect(heroOfTheMonth).toBeDefined();
});
it('should render Hero Bios', () => {
const heroBios = element.all(by.xpath('//h3[text()="Hero Bios"]')).get(0);
it('should render Hero Bios', function () {
let heroBios = element.all(by.xpath('//h3[text()="Hero Bios"]')).get(0);
expect(heroBios).toBeDefined();
});
it('should render Magma\'s description in Hero Bios', () => {
const magmaText = element.all(by.xpath('//textarea[text()="Hero of all trades"]')).get(0);
it('should render Magma\'s description in Hero Bios', function () {
let magmaText = element.all(by.xpath('//textarea[text()="Hero of all trades"]')).get(0);
expect(magmaText).toBeDefined();
});
it('should render Magma\'s phone in Hero Bios and Contacts', () => {
const magmaPhone = element.all(by.xpath('//div[text()="Phone #: 555-555-5555"]')).get(0);
it('should render Magma\'s phone in Hero Bios and Contacts', function () {
let magmaPhone = element.all(by.xpath('//div[text()="Phone #: 555-555-5555"]')).get(0);
expect(magmaPhone).toBeDefined();
});
it('should render Hero-of-the-Month runner-ups', () => {
const runnersUp = element(by.id('rups1')).getText();
it('should render Hero-of-the-Month runner-ups', function () {
let runnersUp = element(by.id('rups1')).getText();
expect(runnersUp).toContain('RubberMan, Dr Nice');
});
it('should render DateLogger log entry in Hero-of-the-Month', () => {
const logs = element.all(by.id('logs')).get(0).getText();
it('should render DateLogger log entry in Hero-of-the-Month', function () {
let logs = element.all(by.id('logs')).get(0).getText();
expect(logs).toContain('INFO: starting up at');
});
it('should highlight Hero Bios and Contacts container when mouseover', () => {
const target = element(by.css('div[appHighlight="yellow"]'));
const yellow = 'rgba(255, 255, 0, 1)';
it('should highlight Hero Bios and Contacts container when mouseover', function () {
let target = element(by.css('div[appHighlight="yellow"]'));
let yellow = 'rgba(255, 255, 0, 1)';
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);
});
describe('in Parent Finder', () => {
const cathy1 = element(by.css('alex cathy'));
const craig1 = element(by.css('alex craig'));
const carol1 = element(by.css('alex carol p'));
const carol2 = element(by.css('barry carol p'));
describe('in Parent Finder', function () {
let cathy1 = element(by.css('alex cathy'));
let craig1 = element(by.css('alex craig'));
let carol1 = element(by.css('alex 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');
});
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');
});
it('"Carol" within "Alex" should have "Alex" parent', () => {
it('"Carol" within "Alex" should have "Alex" parent', function () {
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');
});
});

View File

@ -42,11 +42,11 @@ const declarations = [
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,
CathyComponent
];
@ -61,9 +61,9 @@ const componentListC = [
],
declarations: [
declarations,
componentListA,
componentListB,
componentListC,
a_components,
b_components,
c_components,
StorageComponent,
],
bootstrap: [ AppComponent ],

View File

@ -3,7 +3,7 @@ import { Hero } from './hero';
export class HeroData {
createDb() {
const heroes = [
let heroes = [
new Hero(1, 'Windstorm'),
new Hero(2, 'Bombasto'),
new Hero(3, 'Magneta'),

View File

@ -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
// #docregion
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.
// #docregion provide-the-parent
export function provideParent
// #enddocregion provide-the-parent
// #enddocregion provide-parent, provide-the-parent
// #docregion provide-parent
(component: any, parentType?: any) {
return { provide: parentType || Parent, useExisting: forwardRef(() => component) };
}

View File

@ -22,5 +22,5 @@ export function runnersUpFactory(take: number) {
.join(', ');
// #docregion factory-synopsis
};
}
};
// #enddocregion factory-synopsis

View File

@ -24,7 +24,7 @@ export class UserContextService {
// #enddocregion ctor, injectables
loadUser(userId: number) {
const user = this.userService.getUserById(userId);
let user = this.userService.getUserById(userId);
this.name = user.name;
this.role = user.role;

View File

@ -1,196 +1,202 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by, ElementFinder } from 'protractor';
describe('Dependency Injection Tests', () => {
describe('Dependency Injection Tests', function () {
let expectedMsg: string;
let expectedMsgRx: RegExp;
beforeAll(() => {
beforeAll(function () {
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.';
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.';
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.';
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.';
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.';
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.';
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.';
expect(element(by.css('#test')).getText()).toEqual(expectedMsg);
});
});
describe('Other Injections:', () => {
it('DI car displays as expected', () => {
describe('Other Injections:', function() {
it('DI car displays as expected', function () {
expectedMsg = 'DI car with 4 cylinders and Flintstone tires.';
expect(element(by.css('#car')).getText()).toEqual(expectedMsg);
});
it('Hero displays as expected', () => {
it('Hero displays as expected', function () {
expectedMsg = 'Dr Nice';
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!';
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/;
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';
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';
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';
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';
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)';
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)';
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"';
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';
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';
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';
expect(element(by.css('#p10')).getText()).toEqual(expectedMsg);
});
});
describe('User/Heroes:', () => {
it('User is Bob - unauthorized', () => {
describe('User/Heroes:', function() {
it('User is Bob - unauthorized', function () {
expectedMsgRx = /Bob, is not authorized/;
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'))
.get(0).isDisplayed()).toBe(true, '\'Next User\' button should be displayed');
});
it('unauthorized user should have multiple unauthorized heroes', () => {
const heroes = element.all(by.css('#unauthorized app-hero-list div'));
it('unauthorized user should have multiple unauthorized heroes', function () {
let heroes = element.all(by.css('#unauthorized app-hero-list div'));
expect(heroes.count()).toBeGreaterThan(0);
});
it('unauthorized user should have no secret heroes', () => {
const heroes = element.all(by.css('#unauthorized app-hero-list div'));
it('unauthorized user should have no secret heroes', function () {
let heroes = element.all(by.css('#unauthorized app-hero-list div'));
expect(heroes.count()).toBeGreaterThan(0);
const filteredHeroes = heroes.filter((elem: ElementFinder, index: number) => {
return elem.getText().then((text: string) => /secret/.test(text));
let filteredHeroes = heroes.filter((elem: ElementFinder, index: number) => {
return elem.getText().then((text: string) => {
return /secret/.test(text);
});
});
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);
});
describe('after button click', () => {
describe('after button click', function() {
beforeAll((done: any) => {
const buttonEle = element.all(by.cssContainingText('button', 'Next User')).get(0);
beforeAll(function (done: any) {
let buttonEle = element.all(by.cssContainingText('button', 'Next User')).get(0);
buttonEle.click().then(done, done);
});
it('User is Alice - authorized', () => {
it('User is Alice - authorized', function () {
expectedMsgRx = /Alice, is authorized/;
expect(element(by.css('#user')).getText()).toMatch(expectedMsgRx);
});
it('authorized user should have multiple authorized heroes ', () => {
const heroes = element.all(by.css('#authorized app-hero-list div'));
it('authorized user should have multiple authorized heroes ', function () {
let heroes = element.all(by.css('#authorized app-hero-list div'));
expect(heroes.count()).toBeGreaterThan(0);
});
it('authorized user should have multiple authorized heroes with tree-shakeable HeroesService', () => {
const heroes = element.all(by.css('#tspAuthorized app-hero-list div'));
it('authorized user should have multiple authorized heroes with tree-shakeable HeroesService', function () {
let heroes = element.all(by.css('#tspAuthorized app-hero-list div'));
expect(heroes.count()).toBeGreaterThan(0);
});
it('authorized user should have secret heroes', () => {
const heroes = element.all(by.css('#authorized app-hero-list div'));
it('authorized user should have secret heroes', function () {
let heroes = element.all(by.css('#authorized app-hero-list div'));
expect(heroes.count()).toBeGreaterThan(0);
const filteredHeroes = heroes.filter((elem: ElementFinder, index: number) => {
return elem.getText().then((text: string) => /secret/.test(text));
let filteredHeroes = heroes.filter(function(elem: ElementFinder, index: number) {
return elem.getText().then(function(text: string) {
return /secret/.test(text);
});
});
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);
});
});

View File

@ -7,7 +7,7 @@ import { Car, Engine, Tires } from './car';
export function simpleCar() {
// #docregion car-ctor-instantiation
// 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
car.description = 'Simple';
return car;
@ -20,12 +20,11 @@ class Engine2 {
constructor(public cylinders: number) { }
}
// #enddocregion car-ctor-instantiation-with-param
export function superCar() {
// #docregion car-ctor-instantiation-with-param
// Super car with 12 cylinders and Flintstone tires.
const bigCylinders = 12;
const car = new Car(new Engine2(bigCylinders), new Tires());
let bigCylinders = 12;
let car = new Car(new Engine2(bigCylinders), new Tires());
// #enddocregion car-ctor-instantiation-with-param
car.description = 'Super';
return car;
@ -40,7 +39,7 @@ class MockTires extends Tires { make = 'YokoGoodStone'; }
export function testCar() {
// #docregion car-ctor-instantiation-with-mocks
// 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
car.description = 'Test';
return car;

View File

@ -4,7 +4,7 @@ import { Engine, Tires, Car } from './car';
// BAD pattern!
export class CarFactory {
createCar() {
const car = new Car(this.createEngine(), this.createTires());
let car = new Car(this.createEngine(), this.createTires());
car.description = 'Factory';
return car;
}

View File

@ -26,14 +26,14 @@ export function useInjector() {
]
});
// #docregion injector-call
const car = injector.get(Car);
let car = injector.get(Car);
// #enddocregion injector-call, injector-create-and-call
car.description = 'Injector';
injector = Injector.create({
providers: [{ provide: Logger, deps: [] }]
});
const logger = injector.get(Logger);
let logger = injector.get(Logger);
logger.log('Injector car.drive() said: ' + car.drive());
return car;
}

View File

@ -27,9 +27,9 @@ import { useInjector } from './car-injector';
providers: [Car, Engine, Tires]
})
export class CarComponent {
factoryCar = (new CarFactory()).createCar();
factoryCar = (new CarFactory).createCar();
injectorCar = useInjector();
noDiCar = new CarNoDi();
noDiCar = new CarNoDi;
simpleCar = simpleCar();
superCar = superCar();
testCar = testCar();

View File

@ -5,7 +5,7 @@ import { Logger } from '../logger.service';
import { UserService } from '../user.service';
// #docregion factory
const heroServiceFactory = (logger: Logger, userService: UserService) => {
let heroServiceFactory = (logger: Logger, userService: UserService) => {
return new HeroService(logger, userService.user.isAuthorized);
};
// #enddocregion factory

View File

@ -17,7 +17,7 @@ export class HeroService {
private isAuthorized: boolean) { }
getHeroes() {
const auth = this.isAuthorized ? 'authorized ' : 'unauthorized';
let auth = this.isAuthorized ? 'authorized ' : 'unauthorized';
this.logger.log(`Getting heroes for ${auth} user.`);
return HEROES.filter(hero => this.isAuthorized || !hero.isSecret);
}

View File

@ -36,7 +36,7 @@ export class InjectorComponent implements OnInit {
}
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);
}
}

View File

@ -18,7 +18,7 @@ const template = '{{log}}';
@Component({
selector: 'provider-1',
template,
template: template,
// #docregion providers-1, providers-logger
providers: [Logger]
// #enddocregion providers-1, providers-logger
@ -35,7 +35,7 @@ export class Provider1Component {
@Component({
selector: 'provider-3',
template,
template: template,
providers:
// #docregion providers-3
[{ provide: Logger, useClass: Logger }]
@ -54,7 +54,7 @@ export class BetterLogger extends Logger {}
@Component({
selector: 'provider-4',
template,
template: template,
providers:
// #docregion providers-4
[{ provide: Logger, useClass: BetterLogger }]
@ -76,7 +76,7 @@ export class EvenBetterLogger extends Logger {
constructor(private userService: UserService) { super(); }
log(message: string) {
const name = this.userService.user.name;
let name = this.userService.user.name;
super.log(`Message to ${name}: ${message}`);
}
}
@ -84,7 +84,7 @@ export class EvenBetterLogger extends Logger {
@Component({
selector: 'provider-5',
template,
template: template,
providers:
// #docregion providers-5
[ UserService,
@ -107,12 +107,12 @@ export class OldLogger {
logs: string[] = [];
log(message: string) {
throw new Error('Should not call the old logger!');
}
};
}
@Component({
selector: 'provider-6a',
template,
template: template,
providers:
// #docregion providers-6a
[ NewLogger,
@ -135,7 +135,7 @@ export class Provider6aComponent {
@Component({
selector: 'provider-6b',
template,
template: template,
providers:
// #docregion providers-6b
[ NewLogger,
@ -168,7 +168,7 @@ export const SilentLogger = {
@Component({
selector: 'provider-7',
template,
template: template,
providers:
// #docregion providers-7
[{ provide: Logger, useValue: SilentLogger }]
@ -186,7 +186,7 @@ export class Provider7Component {
@Component({
selector: 'provider-8',
template,
template: template,
providers: [heroServiceProvider, Logger, UserService]
})
export class Provider8Component {
@ -202,7 +202,7 @@ export class Provider8Component {
@Component({
selector: 'provider-9',
template,
template: template,
/*
// #docregion providers-9-interface
// FAIL! Can't use interface as provider token
@ -237,11 +237,11 @@ export class Provider9Component implements OnInit {
import { Optional } from '@angular/core';
// #enddocregion import-optional
const someMessage = 'Hello from the injected logger';
let some_message = 'Hello from the injected logger';
@Component({
selector: 'provider-10',
template,
template: template,
providers: [{ provide: Logger, useValue: null }]
})
export class Provider10Component implements OnInit {
@ -249,7 +249,7 @@ export class Provider10Component implements OnInit {
// #docregion provider-10-ctor
constructor(@Optional() private logger?: Logger) {
if (this.logger) {
this.logger.log(someMessage);
this.logger.log(some_message);
}
}
// #enddocregion provider-10-ctor

View File

@ -43,7 +43,7 @@ var testResults: {pass: string; message: string};
function expect(actual: any) {
return {
toEqual: (expected: any) => {
toEqual: function(expected: any){
testResults = actual === expected ?
{pass: 'passed', message: testName} :
{pass: 'failed', message: `${testName}; expected ${actual} to equal ${expected}.`};

View File

@ -8,8 +8,8 @@ export class User {
}
// TODO: get the user; don't 'new' it.
const alice = new User('Alice', true);
const bob = new User('Bob', false);
let alice = new User('Alice', true);
let bob = new User('Bob', false);
@Injectable({
providedIn: 'root'

View File

@ -1,27 +1,29 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor';
describe('Displaying Data Tests', () => {
const title = 'Tour of Heroes';
const defaultHero = 'Windstorm';
describe('Displaying Data Tests', function () {
let _title = 'Tour of Heroes';
let _defaultHero = 'Windstorm';
beforeAll(() => {
beforeAll(function () {
browser.get('');
});
it('should display correct title: ' + title, () => {
expect(element(by.css('h1')).getText()).toEqual(title);
it('should display correct title: ' + _title, function () {
expect(element(by.css('h1')).getText()).toEqual(_title);
});
it('should have correct default hero: ' + defaultHero, () => {
expect(element(by.css('h2')).getText()).toContain(defaultHero);
it('should have correct default hero: ' + _defaultHero, function () {
expect(element(by.css('h2')).getText()).toContain(_defaultHero);
});
it('should have heroes', () => {
const heroEls = element.all(by.css('li'));
it('should have heroes', function () {
let heroEls = element.all(by.css('li'));
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!');
});
});

View File

@ -1,13 +1,15 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor';
describe('Docs Style Guide', () => {
const title = 'Authors Style Guide Sample';
describe('Docs Style Guide', function () {
let _title = 'Authors Style Guide Sample';
beforeAll(() => {
beforeAll(function () {
browser.get('');
});
it('should display correct title: ' + title, () => {
expect(element(by.css('h1')).getText()).toEqual(title);
it('should display correct title: ' + _title, function () {
expect(element(by.css('h1')).getText()).toEqual(_title);
});
});

View File

@ -1,16 +1,18 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor';
/* tslint:disable:quotemark */
describe('Dynamic Component Loader', () => {
describe('Dynamic Component Loader', function () {
beforeEach(() => {
beforeEach(function () {
browser.get('');
});
it('should load ad banner', () => {
const headline = element(by.xpath("//h4[text()='Featured Hero Profile']"));
const name = element(by.xpath("//h3[text()='Bombasto']"));
const bio = element(by.xpath("//p[text()='Brave as they come']"));
it('should load ad banner', function () {
let headline = element(by.xpath("//h4[text()='Featured Hero Profile']"));
let name = element(by.xpath("//h3[text()='Bombasto']"));
let bio = element(by.xpath("//p[text()='Brave as they come']"));
expect(name).toBeDefined();
expect(headline).toBeDefined();

View File

@ -11,7 +11,7 @@ import { AdComponent } from './ad.component';
template: `
<div class="ad-banner-example">
<h3>Advertisements</h3>
<ng-template adHost></ng-template>
<ng-template ad-host></ng-template>
</div>
`
// #enddocregion ad-host
@ -43,8 +43,8 @@ export class AdBannerComponent implements OnInit, OnDestroy {
const viewContainerRef = this.adHost.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent<AdComponent>(componentFactory);
componentRef.instance.data = adItem.data;
const componentRef = viewContainerRef.createComponent(componentFactory);
(<AdComponent>componentRef.instance).data = adItem.data;
}
getAds() {

View File

@ -1,9 +1,8 @@
// tslint:disable: directive-selector
// #docregion
import { Directive, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[adHost]',
selector: '[ad-host]',
})
export class AdDirective {
constructor(public viewContainerRef: ViewContainerRef) { }

View File

@ -1,25 +1,27 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor';
/* tslint:disable:quotemark */
describe('Dynamic Form', () => {
describe('Dynamic Form', function () {
beforeAll(() => {
beforeAll(function () {
browser.get('');
});
it('should submit form', () => {
const firstNameElement = element.all(by.css('input[id=firstName]')).get(0);
it('should submit form', function () {
let firstNameElement = element.all(by.css('input[id=firstName]')).get(0);
expect(firstNameElement.getAttribute('value')).toEqual('Bombasto');
const emailElement = element.all(by.css('input[id=emailAddress]')).get(0);
const email = 'test@test.com';
let emailElement = element.all(by.css('input[id=emailAddress]')).get(0);
let email = 'test@test.com';
emailElement.sendKeys(email);
expect(emailElement.getAttribute('value')).toEqual(email);
element(by.css('select option[value="solid"]')).click();
const saveButton = element.all(by.css('button')).get(0);
saveButton.click().then(() => {
let saveButton = element.all(by.css('button')).get(0);
saveButton.click().then(function() {
expect(element(by.xpath("//strong[contains(text(),'Saved the following values')]")).isPresent()).toBe(true);
});
});

View File

@ -10,14 +10,13 @@ export class QuestionBase<T> {
options: {key: string, value: string}[];
constructor(options: {
value?: T;
key?: string;
label?: string;
required?: boolean;
order?: number;
controlType?: string;
type?: string;
options?: {key: string, value: string}[];
value?: T,
key?: string,
label?: string,
required?: boolean,
order?: number,
controlType?: string,
type?: string
} = {}) {
this.value = options.value;
this.key = options.key || '';
@ -26,6 +25,5 @@ export class QuestionBase<T> {
this.order = options.order === undefined ? 1 : options.order;
this.controlType = options.controlType || '';
this.type = options.type || '';
this.options = options.options || [];
}
}

View File

@ -9,7 +9,7 @@ export class QuestionControlService {
constructor() { }
toFormGroup(questions: QuestionBase<string>[] ) {
const group: any = {};
let group: any = {};
questions.forEach(question => {
group[question.key] = question.required ? new FormControl(question.value || '', Validators.required)

View File

@ -3,4 +3,10 @@ import { QuestionBase } from './question-base';
export class DropdownQuestion extends QuestionBase<string> {
controlType = 'dropdown';
options: {key: string, value: string}[] = [];
constructor(options: {} = {}) {
super(options);
this.options = options['options'] || [];
}
}

View File

@ -3,4 +3,10 @@ import { QuestionBase } from './question-base';
export class TextboxQuestion extends QuestionBase<string> {
controlType = 'textbox';
type: string;
constructor(options: {} = {}) {
super(options);
this.type = options['type'] || '';
}
}

View File

@ -12,7 +12,7 @@ export class QuestionService {
// TODO: get from a remote source of question metadata
getQuestions() {
const questions: QuestionBase<string>[] = [
let questions: QuestionBase<string>[] = [
new DropdownQuestion({
key: 'brave',

View File

@ -1,3 +1,5 @@
'use strict'; // necessary for es6 output in node
import { browser, by, element, ElementFinder, ExpectedConditions as EC } from 'protractor';
/* tslint:disable:quotemark */
@ -14,7 +16,7 @@ describe('Elements', () => {
const waitForText = (elem: ElementFinder) => {
// Waiting for the element to have some text, makes the tests less flaky.
browser.wait(async () => /\S/.test(await elem.getText()), 5000);
};
}
beforeEach(() => browser.get(''));

View File

@ -1,6 +1,4 @@
// tslint:disable: variable-name
// #docregion
import { Component, EventEmitter, HostBinding, Input, Output } from '@angular/core';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
@Component({
@ -9,6 +7,9 @@ import { animate, state, style, transition, trigger } from '@angular/animations'
<span>Popup: {{message}}</span>
<button (click)="closed.next()">&#x2716;</button>
`,
host: {
'[@state]': 'state',
},
animations: [
trigger('state', [
state('opened', style({transform: 'translateY(0%)'})),
@ -38,16 +39,15 @@ import { animate, state, style, transition, trigger } from '@angular/animations'
`]
})
export class PopupComponent {
@HostBinding('@state')
state: 'opened' | 'closed' = 'closed';
@Input()
get message(): string { return this._message; }
set message(message: string) {
this._message = message;
this.state = 'opened';
}
private _message: string;
get message(): string { return this._message; }
_message: string;
@Output()
closed = new EventEmitter();

View File

@ -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('');
});
const saveButton = element.all(by.css('button')).get(0);
const onSaveButton = element.all(by.css('button')).get(1);
const myClick = element.all(by.css('button')).get(2);
const deleteButton = element.all(by.css('button')).get(3);
const saveNoProp = element.all(by.css('button')).get(4);
const saveProp = element.all(by.css('button')).get(5);
let saveButton = element.all(by.css('button')).get(0);
let onSaveButton = element.all(by.css('button')).get(1);
let myClick = element.all(by.css('button')).get(2);
let deleteButton = element.all(by.css('button')).get(3);
let saveNoProp = element.all(by.css('button')).get(4);
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');
});
it('should display 6 buttons', () => {
it('should display 6 buttons', function() {
expect(saveButton.getText()).toBe('Save');
expect(onSaveButton.getText()).toBe('on-click Save');
expect(myClick.getText()).toBe('click with myClick');
@ -27,23 +29,24 @@ describe('Event binding example', () => {
expect(saveProp.getText()).toBe('Save with propagation');
});
it('should support user input', () => {
const input = element(by.css('input'));
const bindingResult = element.all(by.css('h4')).get(1);
it('should support user input', function () {
let input = element(by.css('input'));
let bindingResult = element.all(by.css('h4')).get(1);
expect(bindingResult.getText()).toEqual('Result: teapot');
input.sendKeys('abc');
expect(bindingResult.getText()).toEqual('Result: teapotabc');
});
it('should hide the item img', async () => {
let deleteButton = element.all(by.css('button')).get(3);
await deleteButton.click();
browser.switchTo().alert().accept();
expect(element.all(by.css('img')).get(0).getCssValue('display')).toEqual('none');
});
it('should show two alerts', async () => {
const parentDiv = element.all(by.css('.parent-div'));
const childDiv = element.all(by.css('div > div')).get(1);
let parentDiv = element.all(by.css('.parent-div'));
let childDiv = element.all(by.css('div > div')).get(1);
await parentDiv.click();
browser.switchTo().alert().accept();
expect(childDiv.getText()).toEqual('Click me too! (child)');

View File

@ -12,7 +12,7 @@ export class AppComponent {
clickMessage = '';
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);
if (event) { event.stopPropagation(); }
}
@ -22,7 +22,7 @@ export class AppComponent {
}
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);
}

View File

@ -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';
@Directive({selector: '[myClick]'})

View File

@ -1,9 +1,11 @@
'use strict'; // necessary for node!
import { browser, element, by, protractor, ElementFinder, ElementArrayFinder } from 'protractor';
// THESE TESTS ARE INCOMPLETE
describe('Form Validation Tests', () => {
describe('Form Validation Tests', function () {
beforeAll(() => {
beforeAll(function () {
browser.get('');
});
@ -50,11 +52,11 @@ let page: {
};
function getPage(sectionTag: string) {
const section = element(by.css(sectionTag));
const buttons = section.all(by.css('button'));
let section = element(by.css(sectionTag));
let buttons = section.all(by.css('button'));
page = {
section,
section: section,
form: section.element(by.css('form')),
title: section.element(by.css('h1')),
nameInput: section.element(by.css('#name')),
@ -71,31 +73,31 @@ function getPage(sectionTag: string) {
function tests(title: string) {
it('should display correct title', () => {
it('should display correct title', function () {
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);
});
it('should have form buttons', () => {
it('should have form buttons', function () {
expect(page.heroFormButtons.count()).toEqual(2);
});
it('should have error at start', () => {
it('should have error at start', function () {
expectFormIsInvalid();
});
// it('showForm', () => {
// it('showForm', function () {
// 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);
});
it('resetting name to valid name should clear errors', () => {
it('resetting name to valid name should clear errors', function () {
const ele = page.nameInput;
expect(ele.isPresent()).toBe(true, 'nameInput should exist');
ele.clear();
@ -103,7 +105,7 @@ function tests(title: string) {
expectFormIsValid();
});
it('should produce "required" error after clearing name', () => {
it('should produce "required" error after clearing name', function () {
page.nameInput.clear();
// page.alterEgoInput.click(); // to blur ... didn't work
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');
});
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.sendKeys('x'); // too short
expectFormIsInvalid();
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);
expectFormIsValid();
});
it('should have enabled submit button', () => {
it('should have enabled submit button', function () {
const submitBtn = page.heroFormButtons.get(0);
expect(submitBtn.isEnabled()).toBe(true);
});
it('should hide form after submit', () => {
it('should hide form after submit', function () {
page.heroFormButtons.get(0).click();
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);
});
it('submitted form should have new hero name', () => {
it('submitted form should have new hero name', function () {
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'));
newFormBtn.click();
expect(page.heroSubmitted.isElementPresent(by.css('p')))
@ -160,7 +162,7 @@ function expectFormIsInvalid() {
function triggerAlterEgoValidation() {
// 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() {
@ -171,7 +173,7 @@ function waitForAlterEgoValidation() {
function bobTests() {
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
page.powerSelect.click();
page.powerOption.click();
@ -182,7 +184,7 @@ function bobTests() {
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.sendKeys(testName);
expectFormIsValid();
@ -192,7 +194,7 @@ function bobTests() {
function asyncValidationTests() {
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.sendKeys('Eric');
@ -203,7 +205,7 @@ function asyncValidationTests() {
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.sendKeys('John');
@ -218,7 +220,7 @@ function asyncValidationTests() {
function crossValidationTests() {
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.sendKeys('Batman');
@ -232,7 +234,7 @@ function crossValidationTests() {
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.sendKeys('Batman');

View File

@ -22,13 +22,13 @@ export class HeroFormReactiveComponent implements OnInit {
ngOnInit(): void {
// #docregion custom-validator
this.heroForm = new FormGroup({
name: new FormControl(this.hero.name, [
'name': new FormControl(this.hero.name, [
Validators.required,
Validators.minLength(4),
forbiddenNameValidator(/bob/i) // <-- Here's how you pass in the custom validator.
]),
alterEgo: new FormControl(this.hero.alterEgo),
power: new FormControl(this.hero.power, Validators.required)
'alterEgo': new FormControl(this.hero.alterEgo),
'power': new FormControl(this.hero.power, Validators.required)
});
// #enddocregion custom-validator

View File

@ -22,16 +22,16 @@ export class HeroFormReactiveComponent implements OnInit {
ngOnInit(): void {
// #docregion async-validation
this.heroForm = new FormGroup({
name: new FormControl(this.hero.name, [
'name': new FormControl(this.hero.name, [
Validators.required,
Validators.minLength(4),
forbiddenNameValidator(/bob/i)
]),
alterEgo: new FormControl(this.hero.alterEgo, {
'alterEgo': new FormControl(this.hero.alterEgo, {
asyncValidators: [this.alterEgoValidator.validate.bind(this.alterEgoValidator)],
updateOn: 'blur'
}),
power: new FormControl(this.hero.power, Validators.required)
'power': new FormControl(this.hero.power, Validators.required)
});
// #enddocregion async-validation
}

View File

@ -21,16 +21,16 @@ export class HeroFormReactiveComponent implements OnInit {
ngOnInit(): void {
this.heroForm = new FormGroup({
name: new FormControl(this.hero.name, [
'name': new FormControl(this.hero.name, [
Validators.required,
Validators.minLength(4),
forbiddenNameValidator(/bob/i)
]),
alterEgo: new FormControl(this.hero.alterEgo, {
'alterEgo': new FormControl(this.hero.alterEgo, {
asyncValidators: [this.alterEgoValidator.validate.bind(this.alterEgoValidator)],
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
}

View File

@ -7,7 +7,7 @@ import { AbstractControl, NG_VALIDATORS, Validator, ValidatorFn, Validators } fr
export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} | null => {
const forbidden = nameRe.test(control.value);
return forbidden ? {forbiddenName: {value: control.value}} : null;
return forbidden ? {'forbiddenName': {value: control.value}} : null;
};
}
// #enddocregion custom-validator

View File

@ -8,7 +8,7 @@ export const identityRevealedValidator: ValidatorFn = (control: FormGroup): Vali
const name = control.get('name');
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
@ -19,7 +19,7 @@ export const identityRevealedValidator: ValidatorFn = (control: FormGroup): Vali
})
export class IdentityRevealedValidatorDirective implements Validator {
validate(control: AbstractControl): ValidationErrors {
return identityRevealedValidator(control);
return identityRevealedValidator(control)
}
}
// #enddocregion cross-validation-directive

View File

@ -1,8 +1,8 @@
import { browser, element, by } from 'protractor';
describe('Forms Overview Tests', () => {
describe('Forms Overview Tests', function () {
beforeEach(() => {
beforeEach(function () {
browser.get('');
});

View File

@ -1,27 +1,27 @@
import { TestBed, waitForAsync } from '@angular/core/testing';
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { ReactiveModule } from './reactive/reactive.module';
import { TemplateModule } from './template/template.module';
import { ReactiveModule } from './reactive/reactive.module';
describe('AppComponent', () => {
beforeEach(waitForAsync(() => {
TestBed
.configureTestingModule({
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ReactiveModule, TemplateModule],
declarations: [AppComponent],
})
.compileComponents();
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', waitForAsync(() => {
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
}));
it('should render title', waitForAsync(() => {
it('should render title', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();

View File

@ -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 { createNewEvent } from '../../shared/utils';
import { FavoriteColorComponent } from './favorite-color.component';
import { createNewEvent } from '../../shared/utils';
describe('Favorite Color Component', () => {
let component: FavoriteColorComponent;
let fixture: ComponentFixture<FavoriteColorComponent>;
beforeEach(waitForAsync(() => {
TestBed
.configureTestingModule(
{imports: [ReactiveFormsModule], declarations: [FavoriteColorComponent]})
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ ReactiveFormsModule ],
declarations: [ FavoriteColorComponent ]
})
.compileComponents();
}));

View File

@ -1,5 +1,5 @@
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);
return evt;
}

View File

@ -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 { createNewEvent } from '../../shared/utils';
import { FavoriteColorComponent } from './favorite-color.component';
import { createNewEvent } from '../../shared/utils';
describe('FavoriteColorComponent', () => {
let component: FavoriteColorComponent;
let fixture: ComponentFixture<FavoriteColorComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({imports: [FormsModule], declarations: [FavoriteColorComponent]})
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ FormsModule ],
declarations: [ FavoriteColorComponent ]
})
.compileComponents();
}));

View File

@ -1,60 +1,60 @@
import { browser, element, by } from 'protractor';
describe('Forms Tests', () => {
describe('Forms Tests', function () {
beforeEach(() => {
beforeEach(function () {
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');
});
it('should not display message before submit', () => {
const ele = element(by.css('h2'));
it('should not display message before submit', function () {
let ele = element(by.css('h2'));
expect(ele.isDisplayed()).toBe(false);
});
it('should hide form after submit', () => {
const ele = element.all(by.css('h1')).get(0);
it('should hide form after submit', function () {
let ele = element.all(by.css('h1')).get(0);
expect(ele.isDisplayed()).toBe(true);
const b = element.all(by.css('button[type=submit]')).get(0);
b.click().then(() => {
let b = element.all(by.css('button[type=submit]')).get(0);
b.click().then(function() {
expect(ele.isDisplayed()).toBe(false);
});
});
it('should display message after submit', () => {
const b = element.all(by.css('button[type=submit]')).get(0);
b.click().then(() => {
it('should display message after submit', function () {
let b = element.all(by.css('button[type=submit]')).get(0);
b.click().then(function() {
expect(element(by.css('h2')).getText()).toContain('You submitted the following');
});
});
it('should hide form after submit', () => {
const alterEgoEle = element.all(by.css('input[name=alterEgo]')).get(0);
it('should hide form after submit', function () {
let alterEgoEle = element.all(by.css('input[name=alterEgo]')).get(0);
expect(alterEgoEle.isDisplayed()).toBe(true);
const submitButtonEle = element.all(by.css('button[type=submit]')).get(0);
submitButtonEle.click().then(() => {
let submitButtonEle = element.all(by.css('button[type=submit]')).get(0);
submitButtonEle.click().then(function() {
expect(alterEgoEle.isDisplayed()).toBe(false);
});
});
it('should reflect submitted data after submit', () => {
const test = 'testing 1 2 3';
it('should reflect submitted data after submit', function () {
let test = 'testing 1 2 3';
let newValue: string;
const alterEgoEle = element.all(by.css('input[name=alterEgo]')).get(0);
alterEgoEle.getAttribute('value').then((value: string) => {
let alterEgoEle = element.all(by.css('input[name=alterEgo]')).get(0);
alterEgoEle.getAttribute('value').then(function(value: string) {
alterEgoEle.sendKeys(test);
newValue = value + test;
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();
}).then(() => {
const alterEgoTextEle = element(by.cssContainingText('div', 'Alter Ego'));
}).then(function() {
let alterEgoTextEle = element(by.cssContainingText('div', 'Alter Ego'));
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);
});
});

View File

@ -35,7 +35,7 @@ export class HeroFormComponent {
skyDog(): Hero {
// #docregion SkyDog
const myHero = new Hero(42, 'SkyDog',
let myHero = new Hero(42, 'SkyDog',
'Fetch any object at any distance',
'Leslie Rollover');
console.log('My hero is called ' + myHero.name); // "My hero is called SkyDog"
@ -48,9 +48,9 @@ export class HeroFormComponent {
// Reveal in html:
// Name via form.controls = {{showFormControls(heroForm)}}
showFormControls(form: any) {
return form && form.controls.name &&
return form && form.controls['name'] &&
// #docregion form-controls
form.controls.name.value; // Dr. IQ
form.controls['name'].value; // Dr. IQ
// #enddocregion form-controls
}

View File

@ -1,7 +1,11 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor';
describe('Getting Started V0', () => {
beforeEach(() => browser.get('/'));
beforeEach(() => {
return browser.get('/');
});
it('should display "My Store" in the top bar', async() => {
const title = await element(by.css('app-root app-top-bar h1')).getText();

View File

@ -1,3 +1,5 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by, ExpectedConditions as EC, logging, ElementFinder, ElementArrayFinder } from 'protractor';
describe('Getting Started', () => {

View File

@ -1,3 +1,5 @@
'use strict'; // necessary for es6 output in node
import { browser, by, element } from 'protractor';
describe('Hierarchical dependency injection', () => {
@ -7,7 +9,7 @@ describe('Hierarchical dependency injection', () => {
});
describe('Heroes Scenario', () => {
const page = {
let page = {
heroName: '',
income: '',

View File

@ -1,4 +1,3 @@
// tslint:disable: no-output-native
// #docregion
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { HeroTaxReturn } from './hero';
@ -31,9 +30,9 @@ export class HeroTaxReturnComponent {
onCanceled() {
this.flashMessage('Canceled');
this.heroTaxReturnService.restoreTaxReturn();
}
};
onClose() { this.close.emit(); }
onClose() { this.close.emit(); };
onSaved() {
this.flashMessage('Saved');

View File

@ -24,11 +24,11 @@ const page = {
uploadMessage: element(by.css('app-uploader p'))
};
const checkLogForMessage = (message: string) => {
let checkLogForMessage = (message: string) => {
expect(page.logList.getText()).toContain(message);
};
describe('Http Tests', () => {
describe('Http Tests', function() {
beforeEach(() => {
browser.get('');
});

View File

@ -40,8 +40,8 @@ export class ConfigComponent {
this.configService.getConfig_1()
// #docregion v1, v1_callback
.subscribe((data: Config) => this.config = {
heroesUrl: data.heroesUrl,
textfile: data.textfile
heroesUrl: data['heroesUrl'],
textfile: data['textfile']
});
// #enddocregion v1_callback
}

View File

@ -16,7 +16,7 @@ import { HttpErrorHandler, HandleError } from '../http-error-handler.service';
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
Authorization: 'my-auth-token'
'Authorization': 'my-auth-token'
})
};
// #enddocregion http-options

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