From 00f3b71de2b3cf16aee5228b94b6edc2ceb6cb9b Mon Sep 17 00:00:00 2001 From: Ricardo Chavarria Date: Fri, 24 Oct 2025 12:27:08 -0600 Subject: [PATCH] translate: translations for testing guides Fixes #54 --- .../src/app/routing/sub-navigation-data.ts | 30 +- .../guide/testing/attribute-directives.en.md | 53 ++ .../guide/testing/attribute-directives.md | 52 +- .../content/guide/testing/code-coverage.en.md | 57 ++ .../content/guide/testing/code-coverage.md | 30 +- .../component-harnesses-overview.en.md | 31 + .../testing/component-harnesses-overview.md | 30 +- ...onent-harnesses-testing-environments.en.md | 62 ++ ...omponent-harnesses-testing-environments.md | 66 +- .../guide/testing/components-basics.en.md | 181 ++++ .../guide/testing/components-basics.md | 162 ++-- .../guide/testing/components-scenarios.en.md | 809 ++++++++++++++++++ .../guide/testing/components-scenarios.md | 699 ++++++++------- .../creating-component-harnesses.en.md | 277 ++++++ .../testing/creating-component-harnesses.md | 120 +-- .../src/content/guide/testing/debugging.en.md | 17 + .../src/content/guide/testing/debugging.md | 24 +- .../testing/experimental-unit-test.en.md | 83 ++ .../guide/testing/experimental-unit-test.md | 50 +- .../src/content/guide/testing/overview.en.md | 125 +++ adev-es/src/content/guide/testing/overview.md | 120 +-- adev-es/src/content/guide/testing/pipes.en.md | 28 + adev-es/src/content/guide/testing/pipes.md | 28 +- .../src/content/guide/testing/services.en.md | 129 +++ adev-es/src/content/guide/testing/services.md | 114 +-- .../testing/using-component-harnesses.en.md | 220 +++++ .../testing/using-component-harnesses.md | 146 ++-- .../content/guide/testing/utility-apis.en.md | 151 ++++ .../src/content/guide/testing/utility-apis.md | 172 ++-- 29 files changed, 3142 insertions(+), 924 deletions(-) create mode 100644 adev-es/src/content/guide/testing/attribute-directives.en.md create mode 100644 adev-es/src/content/guide/testing/code-coverage.en.md create mode 100644 adev-es/src/content/guide/testing/component-harnesses-overview.en.md create mode 100644 adev-es/src/content/guide/testing/component-harnesses-testing-environments.en.md create mode 100644 adev-es/src/content/guide/testing/components-basics.en.md create mode 100644 adev-es/src/content/guide/testing/components-scenarios.en.md create mode 100644 adev-es/src/content/guide/testing/creating-component-harnesses.en.md create mode 100644 adev-es/src/content/guide/testing/debugging.en.md create mode 100644 adev-es/src/content/guide/testing/experimental-unit-test.en.md create mode 100644 adev-es/src/content/guide/testing/overview.en.md create mode 100644 adev-es/src/content/guide/testing/pipes.en.md create mode 100644 adev-es/src/content/guide/testing/services.en.md create mode 100644 adev-es/src/content/guide/testing/using-component-harnesses.en.md create mode 100644 adev-es/src/content/guide/testing/utility-apis.en.md diff --git a/adev-es/src/app/routing/sub-navigation-data.ts b/adev-es/src/app/routing/sub-navigation-data.ts index fb15704..39ce07b 100644 --- a/adev-es/src/app/routing/sub-navigation-data.ts +++ b/adev-es/src/app/routing/sub-navigation-data.ts @@ -510,51 +510,51 @@ const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ ], }, { - label: 'Testing', + label: 'Pruebas', children: [ { - label: 'Overview', + label: 'Visión general', path: 'guide/testing', contentPath: 'guide/testing/overview', }, { - label: 'Code coverage', + label: 'Cobertura de código', path: 'guide/testing/code-coverage', contentPath: 'guide/testing/code-coverage', }, { - label: 'Testing services', + label: 'Pruebas de servicios', path: 'guide/testing/services', contentPath: 'guide/testing/services', }, { - label: 'Basics of testing components', + label: 'Fundamentos de pruebas de componentes', path: 'guide/testing/components-basics', contentPath: 'guide/testing/components-basics', }, { - label: 'Component testing scenarios', + label: 'Escenarios de pruebas de componentes', path: 'guide/testing/components-scenarios', contentPath: 'guide/testing/components-scenarios', }, { - label: 'Testing attribute directives', + label: 'Pruebas de directivas de atributo', path: 'guide/testing/attribute-directives', contentPath: 'guide/testing/attribute-directives', }, { - label: 'Testing pipes', + label: 'Pruebas de pipes', path: 'guide/testing/pipes', contentPath: 'guide/testing/pipes', }, { - label: 'Testing routing and navigation', + label: 'Pruebas de enrutamiento y navegación', path: 'guide/routing/testing', contentPath: 'guide/routing/testing', status: 'new', }, { - label: 'Debugging tests', + label: 'Depuración de pruebas', path: 'guide/testing/debugging', contentPath: 'guide/testing/debugging', }, @@ -564,27 +564,27 @@ const DOCS_SUB_NAVIGATION_DATA: NavigationItem[] = [ contentPath: 'guide/testing/utility-apis', }, { - label: 'Experimental unit testing integration', + label: 'Integración experimental de pruebas unitarias', path: 'guide/testing/unit-tests', contentPath: 'guide/testing/experimental-unit-test', }, { - label: 'Component harnesses overview', + label: 'Visión general de component harnesses', path: 'guide/testing/component-harnesses-overview', contentPath: 'guide/testing/component-harnesses-overview', }, { - label: 'Using component harnesses in tests', + label: 'Usando component harnesses en pruebas', path: 'guide/testing/using-component-harnesses', contentPath: 'guide/testing/using-component-harnesses', }, { - label: 'Creating harnesses for your components', + label: 'Creando harnesses para tus componentes', path: 'guide/testing/creating-component-harnesses', contentPath: 'guide/testing/creating-component-harnesses', }, { - label: 'Adding harness support for additional testing environments', + label: 'Agregar soporte de harness para entornos de pruebas adicionales', path: 'guide/testing/component-harnesses-testing-environments', contentPath: 'guide/testing/component-harnesses-testing-environments', }, diff --git a/adev-es/src/content/guide/testing/attribute-directives.en.md b/adev-es/src/content/guide/testing/attribute-directives.en.md new file mode 100644 index 0000000..f605c75 --- /dev/null +++ b/adev-es/src/content/guide/testing/attribute-directives.en.md @@ -0,0 +1,53 @@ + +# Testing Attribute Directives + +An *attribute directive* modifies the behavior of an element, component or another directive. +Its name reflects the way the directive is applied: as an attribute on a host element. + +## Testing the `HighlightDirective` + +The sample application's `HighlightDirective` sets the background color of an element based on either a data bound color or a default color \(lightgray\). +It also sets a custom property of the element \(`customProperty`\) to `true` for no reason other than to show that it can. + + + +It's used throughout the application, perhaps most simply in the `AboutComponent`: + + + +Testing the specific use of the `HighlightDirective` within the `AboutComponent` requires only the techniques explored in the ["Nested component tests"](guide/testing/components-scenarios#nested-component-tests) section of [Component testing scenarios](guide/testing/components-scenarios). + + + +However, testing a single use case is unlikely to explore the full range of a directive's capabilities. +Finding and testing all components that use the directive is tedious, brittle, and almost as unlikely to afford full coverage. + +*Class-only tests* might be helpful, but attribute directives like this one tend to manipulate the DOM. +Isolated unit tests don't touch the DOM and, therefore, do not inspire confidence in the directive's efficacy. + +A better solution is to create an artificial test component that demonstrates all ways to apply the directive. + + + +HighlightDirective spec in action + +HELPFUL: The `` case binds the `HighlightDirective` to the name of a color value in the input box. +The initial value is the word "cyan" which should be the background color of the input box. + +Here are some tests of this component: + + + +A few techniques are noteworthy: + +* The `By.directive` predicate is a great way to get the elements that have this directive *when their element types are unknown* +* The [`:not` pseudo-class](https://developer.mozilla.org/docs/Web/CSS/:not) in `By.css('h2:not([highlight])')` helps find `

` elements that *do not* have the directive. + `By.css('*:not([highlight])')` finds *any* element that does not have the directive. + +* `DebugElement.styles` affords access to element styles even in the absence of a real browser, thanks to the `DebugElement` abstraction. + But feel free to exploit the `nativeElement` when that seems easier or more clear than the abstraction. + +* Angular adds a directive to the injector of the element to which it is applied. + The test for the default color uses the injector of the second `

` to get its `HighlightDirective` instance and its `defaultColor`. + +* `DebugElement.properties` affords access to the artificial custom property that is set by the directive diff --git a/adev-es/src/content/guide/testing/attribute-directives.md b/adev-es/src/content/guide/testing/attribute-directives.md index f605c75..e7d047c 100644 --- a/adev-es/src/content/guide/testing/attribute-directives.md +++ b/adev-es/src/content/guide/testing/attribute-directives.md @@ -1,53 +1,53 @@ -# Testing Attribute Directives +# Probar directivas de atributo -An *attribute directive* modifies the behavior of an element, component or another directive. -Its name reflects the way the directive is applied: as an attribute on a host element. +Una *directiva de atributo* modifica el comportamiento de un elemento, componente u otra directiva. +Su nombre refleja la forma en que se aplica la directiva: como un atributo en un elemento host. -## Testing the `HighlightDirective` +## Probar la `HighlightDirective` -The sample application's `HighlightDirective` sets the background color of an element based on either a data bound color or a default color \(lightgray\). -It also sets a custom property of the element \(`customProperty`\) to `true` for no reason other than to show that it can. +La `HighlightDirective` de la aplicación de muestra establece el color de fondo de un elemento basado en un color vinculado a datos o un color predeterminado \(lightgray\). +También establece una propiedad personalizada del elemento \(`customProperty`\) a `true` sin otra razón que mostrar que puede hacerlo. -It's used throughout the application, perhaps most simply in the `AboutComponent`: +Se usa en toda la aplicación, quizás más simplemente en el `AboutComponent`: -Testing the specific use of the `HighlightDirective` within the `AboutComponent` requires only the techniques explored in the ["Nested component tests"](guide/testing/components-scenarios#nested-component-tests) section of [Component testing scenarios](guide/testing/components-scenarios). +Probar el uso específico de la `HighlightDirective` dentro del `AboutComponent` requiere solo las técnicas exploradas en la sección ["Pruebas de componentes anidados"](guide/testing/components-scenarios#nested-component-tests) de [Escenarios de prueba de componentes](guide/testing/components-scenarios). -However, testing a single use case is unlikely to explore the full range of a directive's capabilities. -Finding and testing all components that use the directive is tedious, brittle, and almost as unlikely to afford full coverage. +Sin embargo, probar un solo caso de uso es poco probable que explore el rango completo de las capacidades de una directiva. +Encontrar y probar todos los componentes que usan la directiva es tedioso, frágil y casi tan poco probable de ofrecer cobertura completa. -*Class-only tests* might be helpful, but attribute directives like this one tend to manipulate the DOM. -Isolated unit tests don't touch the DOM and, therefore, do not inspire confidence in the directive's efficacy. +Las *pruebas solo de clase* podrían ser útiles, pero las directivas de atributo como esta tienden a manipular el DOM. +Las pruebas unitarias aisladas no tocan el DOM y, por lo tanto, no inspiran confianza en la eficacia de la directiva. -A better solution is to create an artificial test component that demonstrates all ways to apply the directive. +Una mejor solución es crear un componente de prueba artificial que demuestre todas las formas de aplicar la directiva. -HighlightDirective spec in action +HighlightDirective spec en acción -HELPFUL: The `` case binds the `HighlightDirective` to the name of a color value in the input box. -The initial value is the word "cyan" which should be the background color of the input box. +ÚTIL: El caso `` vincula la `HighlightDirective` al nombre de un valor de color en el cuadro de entrada. +El valor inicial es la palabra "cyan" que debería ser el color de fondo del cuadro de entrada. -Here are some tests of this component: +Aquí hay algunas pruebas de este componente: -A few techniques are noteworthy: +Algunas técnicas son dignas de mención: -* The `By.directive` predicate is a great way to get the elements that have this directive *when their element types are unknown* -* The [`:not` pseudo-class](https://developer.mozilla.org/docs/Web/CSS/:not) in `By.css('h2:not([highlight])')` helps find `

` elements that *do not* have the directive. - `By.css('*:not([highlight])')` finds *any* element that does not have the directive. +* El predicado `By.directive` es una excelente manera de obtener los elementos que tienen esta directiva *cuando sus tipos de elemento son desconocidos* +* La [pseudo-clase `:not`](https://developer.mozilla.org/docs/Web/CSS/:not) en `By.css('h2:not([highlight])')` ayuda a encontrar elementos `

` que *no* tienen la directiva. + `By.css('*:not([highlight])')` encuentra *cualquier* elemento que no tenga la directiva. -* `DebugElement.styles` affords access to element styles even in the absence of a real browser, thanks to the `DebugElement` abstraction. - But feel free to exploit the `nativeElement` when that seems easier or more clear than the abstraction. +* `DebugElement.styles` permite el acceso a los estilos del elemento incluso en ausencia de un navegador real, gracias a la abstracción `DebugElement`. + Pero siéntete libre de explotar el `nativeElement` cuando eso parezca más fácil o más claro que la abstracción. -* Angular adds a directive to the injector of the element to which it is applied. - The test for the default color uses the injector of the second `

` to get its `HighlightDirective` instance and its `defaultColor`. +* Angular agrega una directiva al injector del elemento al que se aplica. + La prueba para el color predeterminado usa el injector del segundo `

` para obtener su instancia de `HighlightDirective` y su `defaultColor`. -* `DebugElement.properties` affords access to the artificial custom property that is set by the directive +* `DebugElement.properties` permite el acceso a la propiedad personalizada artificial que se establece por la directiva diff --git a/adev-es/src/content/guide/testing/code-coverage.en.md b/adev-es/src/content/guide/testing/code-coverage.en.md new file mode 100644 index 0000000..2ea638b --- /dev/null +++ b/adev-es/src/content/guide/testing/code-coverage.en.md @@ -0,0 +1,57 @@ + +# Find out how much code you're testing + +The Angular CLI can run unit tests and create code coverage reports. +Code coverage reports show you any parts of your code base that might not be properly tested by your unit tests. + +To generate a coverage report run the following command in the root of your project. + + +ng test --no-watch --code-coverage + + +When the tests are complete, the command creates a new `/coverage` directory in the project. +Open the `index.html` file to see a report with your source code and code coverage values. + +If you want to create code-coverage reports every time you test, set the following option in the Angular CLI configuration file, `angular.json`: + + +"test": { + "options": { + "codeCoverage": true + } +} + + +## Code coverage enforcement + +The code coverage percentages let you estimate how much of your code is tested. +If your team decides on a set minimum amount to be unit tested, enforce this minimum with the Angular CLI. + +For example, suppose you want the code base to have a minimum of 80% code coverage. +To enable this, open the [Karma](https://karma-runner.github.io) test platform configuration file, `karma.conf.js`, and add the `check` property in the `coverageReporter:` key. + + +coverageReporter: { + dir: require('path').join(__dirname, './coverage/'), + subdir: '.', + reporters: [ + { type: 'html' }, + { type: 'text-summary' } + ], + check: { + global: { + statements: 80, + branches: 80, + functions: 80, + lines: 80 + } + } +} + + +HELPFUL: Read more about creating and fine tuning Karma configuration in the [testing guide](guide/testing#configuration). + +The `check` property causes the tool to enforce a minimum of 80% code coverage when the unit tests are run in the project. + +Read more on coverage configuration options in the [karma coverage documentation](https://github.com/karma-runner/karma-coverage/blob/master/docs/configuration.md). diff --git a/adev-es/src/content/guide/testing/code-coverage.md b/adev-es/src/content/guide/testing/code-coverage.md index 2ea638b..cffedf8 100644 --- a/adev-es/src/content/guide/testing/code-coverage.md +++ b/adev-es/src/content/guide/testing/code-coverage.md @@ -1,19 +1,19 @@ -# Find out how much code you're testing +# Descubrir cuánto código estás probando -The Angular CLI can run unit tests and create code coverage reports. -Code coverage reports show you any parts of your code base that might not be properly tested by your unit tests. +Angular CLI puede ejecutar pruebas unitarias y crear reportes de cobertura de código. +Los reportes de cobertura de código te muestran cualquier parte de tu código base que podría no estar correctamente probada por tus pruebas unitarias. -To generate a coverage report run the following command in the root of your project. +Para generar un reporte de cobertura ejecuta el siguiente comando en la raíz de tu proyecto. ng test --no-watch --code-coverage -When the tests are complete, the command creates a new `/coverage` directory in the project. -Open the `index.html` file to see a report with your source code and code coverage values. +Cuando las pruebas estén completas, el comando crea un nuevo directorio `/coverage` en el proyecto. +Abre el archivo `index.html` para ver un reporte con tu código fuente y valores de cobertura de código. -If you want to create code-coverage reports every time you test, set the following option in the Angular CLI configuration file, `angular.json`: +Si quieres crear reportes de cobertura de código cada vez que pruebas, establece la siguiente opción en el archivo de configuración de Angular CLI, `angular.json`: "test": { @@ -23,13 +23,13 @@ If you want to create code-coverage reports every time you test, set the followi } -## Code coverage enforcement +## Aplicación de cobertura de código -The code coverage percentages let you estimate how much of your code is tested. -If your team decides on a set minimum amount to be unit tested, enforce this minimum with the Angular CLI. +Los porcentajes de cobertura de código te permiten estimar cuánto de tu código está probado. +Si tu equipo decide sobre una cantidad mínima establecida para ser probada unitariamente, aplica este mínimo con Angular CLI. -For example, suppose you want the code base to have a minimum of 80% code coverage. -To enable this, open the [Karma](https://karma-runner.github.io) test platform configuration file, `karma.conf.js`, and add the `check` property in the `coverageReporter:` key. +Por ejemplo, supón que quieres que la base de código tenga un mínimo de 80% de cobertura de código. +Para habilitar esto, abre el archivo de configuración de la plataforma de pruebas [Karma](https://karma-runner.github.io), `karma.conf.js`, y agrega la propiedad `check` en la clave `coverageReporter:`. coverageReporter: { @@ -50,8 +50,8 @@ coverageReporter: { } -HELPFUL: Read more about creating and fine tuning Karma configuration in the [testing guide](guide/testing#configuration). +ÚTIL: Lee más sobre crear y ajustar la configuración de Karma en la [guía de pruebas](guide/testing#configuration). -The `check` property causes the tool to enforce a minimum of 80% code coverage when the unit tests are run in the project. +La propiedad `check` hace que la herramienta aplique un mínimo de 80% de cobertura de código cuando las pruebas unitarias se ejecutan en el proyecto. -Read more on coverage configuration options in the [karma coverage documentation](https://github.com/karma-runner/karma-coverage/blob/master/docs/configuration.md). +Lee más sobre opciones de configuración de cobertura en la [documentación de karma coverage](https://github.com/karma-runner/karma-coverage/blob/master/docs/configuration.md). diff --git a/adev-es/src/content/guide/testing/component-harnesses-overview.en.md b/adev-es/src/content/guide/testing/component-harnesses-overview.en.md new file mode 100644 index 0000000..a1cc469 --- /dev/null +++ b/adev-es/src/content/guide/testing/component-harnesses-overview.en.md @@ -0,0 +1,31 @@ +# Component harnesses overview + +A component harness is a class that allows tests to interact with components the way an end user does via a supported API. You can create test harnesses for any component, ranging from small reusable widgets to full pages. + +Harnesses offer several benefits: + +- They make tests less brittle by insulating themselves against implementation details of a component, such as its DOM structure +- They make tests become more readable and easier to maintain +- They can be used across multiple testing environments + + +// Example of test with a harness for a component called MyButtonComponent +it('should load button with exact text', async () => { + const button = await loader.getHarness(MyButtonComponentHarness); + expect(await button.getText()).toBe('Confirm'); +}); + + +Component harnesses are especially useful for shared UI widgets. Developers often write tests that depend on private implementation details of widgets, such as DOM structure and CSS classes. Those dependencies make tests brittle and hard to maintain. Harnesses offer an alternative— a supported API that interacts with the widget the same way an end-user does. Widget implementation changes now become less likely to break user tests. For example, [Angular Material](https://material.angular.dev/components/categories) provides a test harness for each component in the library. + +Component harnesses support multiple testing environments. You can use the same harness implementation in both unit and end-to-end tests. Test authors only need to learn one API and component authors don't have to maintain separate unit and end-to-end test implementations. + +Many developers can be categorized by one of the following developer type categories: test authors, component harness authors, and harness environment authors. Use the table below to find the most relevant section in this guide based on these categories: + +| Developer Type | Description | Relevant Section | +| :-------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------- | +| Test Authors | Developers that use component harnesses written by someone else to test their application. For example, this could be an app developer who uses a third-party menu component and needs to interact with the menu in a unit test. | [Using component harnesses in tests](guide/testing/using-component-harnesses) | +| Component harness authors | Developers who maintain some reusable Angular components and want to create a test harness for its users to use in their tests. For example, an author of a third party Angular component library or a developer who maintains a set of common components for a large Angular application. | [Creating component harnesses for your components](guide/testing/creating-component-harnesses) | +| Harness environment authors | Developers who want to add support for using component harnesses in additional testing environments. For information on supported testing environments out-of-the-box, see the [test harness environments and loaders](guide/testing/using-component-harnesses#test-harness-environments-and-loaders). | [Adding support for additional testing environments](guide/testing/component-harnesses-testing-environments) | + +For the full API reference, please see the [Angular CDK's component harness API reference page](/api#angular_cdk_testing). diff --git a/adev-es/src/content/guide/testing/component-harnesses-overview.md b/adev-es/src/content/guide/testing/component-harnesses-overview.md index a1cc469..a7ff8f4 100644 --- a/adev-es/src/content/guide/testing/component-harnesses-overview.md +++ b/adev-es/src/content/guide/testing/component-harnesses-overview.md @@ -1,31 +1,31 @@ -# Component harnesses overview +# Visión general de component harnesses -A component harness is a class that allows tests to interact with components the way an end user does via a supported API. You can create test harnesses for any component, ranging from small reusable widgets to full pages. +Un component harness es una clase que permite a las pruebas interactuar con componentes de la manera en que un usuario final lo hace a través de una API soportada. Puedes crear test harnesses para cualquier componente, desde pequeños widgets reutilizables hasta páginas completas. -Harnesses offer several benefits: +Los harnesses ofrecen varios beneficios: -- They make tests less brittle by insulating themselves against implementation details of a component, such as its DOM structure -- They make tests become more readable and easier to maintain -- They can be used across multiple testing environments +- Hacen que las pruebas sean menos frágiles al aislarse contra detalles de implementación de un componente, como su estructura DOM +- Hacen que las pruebas se vuelvan más legibles y más fáciles de mantener +- Pueden usarse en múltiples entornos de pruebas -// Example of test with a harness for a component called MyButtonComponent +// Ejemplo de prueba con un harness para un componente llamado MyButtonComponent it('should load button with exact text', async () => { const button = await loader.getHarness(MyButtonComponentHarness); expect(await button.getText()).toBe('Confirm'); }); -Component harnesses are especially useful for shared UI widgets. Developers often write tests that depend on private implementation details of widgets, such as DOM structure and CSS classes. Those dependencies make tests brittle and hard to maintain. Harnesses offer an alternative— a supported API that interacts with the widget the same way an end-user does. Widget implementation changes now become less likely to break user tests. For example, [Angular Material](https://material.angular.dev/components/categories) provides a test harness for each component in the library. +Los component harnesses son especialmente útiles para widgets de UI compartidos. Los desarrolladores a menudo escriben pruebas que dependen de detalles privados de implementación de widgets, como estructura DOM y clases CSS. Esas dependencias hacen que las pruebas sean frágiles y difíciles de mantener. Los harnesses ofrecen una alternativa— una API soportada que interactúa con el widget de la misma manera que un usuario final lo hace. Los cambios de implementación del widget ahora se vuelven menos propensos a romper las pruebas de usuario. Por ejemplo, [Angular Material](https://material.angular.dev/components/categories) proporciona un test harness para cada componente en la librería. -Component harnesses support multiple testing environments. You can use the same harness implementation in both unit and end-to-end tests. Test authors only need to learn one API and component authors don't have to maintain separate unit and end-to-end test implementations. +Los component harnesses soportan múltiples entornos de pruebas. Puedes usar la misma implementación de harness en pruebas tanto unitarias como end-to-end. Los autores de pruebas solo necesitan aprender una API y los autores de componentes no tienen que mantener implementaciones de prueba unitaria y end-to-end separadas. -Many developers can be categorized by one of the following developer type categories: test authors, component harness authors, and harness environment authors. Use the table below to find the most relevant section in this guide based on these categories: +Muchos desarrolladores pueden categorizarse por una de las siguientes categorías de tipo de desarrollador: autores de pruebas, autores de component harness y autores de entornos de harness. Usa la tabla a continuación para encontrar la sección más relevante en esta guía basada en estas categorías: -| Developer Type | Description | Relevant Section | +| Tipo de Desarrollador | Descripción | Sección Relevante | | :-------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------- | -| Test Authors | Developers that use component harnesses written by someone else to test their application. For example, this could be an app developer who uses a third-party menu component and needs to interact with the menu in a unit test. | [Using component harnesses in tests](guide/testing/using-component-harnesses) | -| Component harness authors | Developers who maintain some reusable Angular components and want to create a test harness for its users to use in their tests. For example, an author of a third party Angular component library or a developer who maintains a set of common components for a large Angular application. | [Creating component harnesses for your components](guide/testing/creating-component-harnesses) | -| Harness environment authors | Developers who want to add support for using component harnesses in additional testing environments. For information on supported testing environments out-of-the-box, see the [test harness environments and loaders](guide/testing/using-component-harnesses#test-harness-environments-and-loaders). | [Adding support for additional testing environments](guide/testing/component-harnesses-testing-environments) | +| Autores de pruebas | Desarrolladores que usan component harnesses escritos por alguien más para probar su aplicación. Por ejemplo, esto podría ser un desarrollador de aplicaciones que usa un componente de menú de terceros y necesita interactuar con el menú en una prueba unitaria. | [Usar component harnesses en pruebas](guide/testing/using-component-harnesses) | +| Autores de component harness | Desarrolladores que mantienen algunos componentes Angular reutilizables y quieren crear un test harness para que sus usuarios lo usen en sus pruebas. Por ejemplo, un autor de una librería de componentes Angular de terceros o un desarrollador que mantiene un conjunto de componentes comunes para una aplicación Angular grande. | [Crear component harnesses para tus componentes](guide/testing/creating-component-harnesses) | +| Autores de entornos de harness | Desarrolladores que quieren agregar soporte para usar component harnesses en entornos de pruebas adicionales. Para información sobre entornos de pruebas soportados de forma inmediata, consulta los [entornos de test harness y loaders](guide/testing/using-component-harnesses#test-harness-environments-and-loaders). | [Agregar soporte para entornos de pruebas adicionales](guide/testing/component-harnesses-testing-environments) | -For the full API reference, please see the [Angular CDK's component harness API reference page](/api#angular_cdk_testing). +Para la referencia completa de la API, consulta la [página de referencia de la API de component harness del CDK de Angular](/api#angular_cdk_testing). diff --git a/adev-es/src/content/guide/testing/component-harnesses-testing-environments.en.md b/adev-es/src/content/guide/testing/component-harnesses-testing-environments.en.md new file mode 100644 index 0000000..75fa6de --- /dev/null +++ b/adev-es/src/content/guide/testing/component-harnesses-testing-environments.en.md @@ -0,0 +1,62 @@ +# Adding harness support for additional testing environments + +## Before you start + +TIP: This guide assumes you've already read the [component harnesses overview guide](guide/testing/component-harnesses-overview). Read that first if you're new to using component harnesses. + +### When does adding support for a test environment make sense? + +To use component harnesses in the following environments, you can use Angular CDK's two built-in environments: + +- Unit tests +- WebDriver end-to-end tests + +To use a supported testing environment, read the [Creating harnesses for your components guide](guide/testing/creating-component-harnesses). + +Otherwise, to add support for other environments, you need to define how to interact with a DOM element and how DOM interactions work in your environment. Continue reading to learn more. + +### CDK Installation + +The [Component Dev Kit (CDK)](https://material.angular.dev/cdk/categories) is a set of behavior primitives for building components. To use the component harnesses, first install `@angular/cdk` from npm. You can do this from your terminal using the Angular CLI: + + + ng add @angular/cdk + + +## Creating a `TestElement` implementation + +Every test environment must define a `TestElement` implementation. The `TestElement` interface serves as an environment-agnostic representation of a DOM element. It enables harnesses to interact with DOM elements regardless of the underlying environment. Because some environments don't support interacting with DOM elements synchronously (e.g. WebDriver), all `TestElement` methods are asynchronous, returning a `Promise` with the result of the operation. + +`TestElement` offers a number of methods to interact with the underlying DOM such as `blur()`, `click()`, `getAttribute()`, and more. See the [TestElement API reference page](/api/cdk/testing/TestElement) for the full list of methods. + +The `TestElement` interface consists largely of methods that resemble methods available on `HTMLElement`. Similar methods exist in most test environments, which makes implementing the methods fairly straightforward. However, one important difference to note when implementing the `sendKeys` method, is that the key codes in the `TestKey` enum likely differ from the key codes used in the test environment. Environment authors should maintain a mapping from `TestKey` codes to the codes used in the particular testing environment. + +The [UnitTestElement](/api/cdk/testing/testbed/UnitTestElement) and [SeleniumWebDriverElement](/api/cdk/testing/selenium-webdriver/SeleniumWebDriverElement) implementations in Angular CDK serve as good examples of implementations of this interface. + +## Creating a `HarnessEnvironment` implementation + +Test authors use `HarnessEnvironment` to create component harness instances for use in tests. `HarnessEnvironment` is an abstract class that must be extended to create a concrete subclass for the new environment. When supporting a new test environment, create a `HarnessEnvironment` subclass that adds concrete implementations for all abstract members. + +`HarnessEnvironment` has a generic type parameter: `HarnessEnvironment`. This parameter, `E`, represents the raw element type of the environment. For example, this parameter is Element for unit test environments. + +The following are the abstract methods that must be implemented: + +| Method | Description | +| :----------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `abstract getDocumentRoot(): E` | Gets the root element for the environment (e.g. `document.body`). | +| `abstract createTestElement(element: E): TestElement` | Creates a `TestElement` for the given raw element. | +| `abstract createEnvironment(element: E): HarnessEnvironment` | Creates a `HarnessEnvironment` rooted at the given raw element. | +| `abstract getAllRawElements(selector: string): Promise` | Gets all of the raw elements under the root element of the environment matching the given selector. | +| `abstract forceStabilize(): Promise` | Gets a `Promise` that resolves when the `NgZone` is stable. Additionally, if applicable, tells `NgZone` to stabilize (e.g. calling `flush()` in a `fakeAsync` test). | +| `abstract waitForTasksOutsideAngular(): Promise` | Gets a `Promise` that resolves when the parent zone of `NgZone` is stable. | + +In addition to implementing the missing methods, this class should provide a way for test authors to get `ComponentHarness` instances. You should define a protected constructor and provide a static method called `loader` that returns a `HarnessLoader` instance. This allows test authors to write code like: `SomeHarnessEnvironment.loader().getHarness(...)`. Depending on the needs of the particular environment, the class may provide several different static methods or require arguments to be passed. (e.g. the `loader` method on `TestbedHarnessEnvironment` takes a `ComponentFixture`, and the class provides additional static methods called `documentRootLoader` and `harnessForFixture`). + +The [`TestbedHarnessEnvironment`](/api/cdk/testing/testbed/TestbedHarnessEnvironment) and [SeleniumWebDriverHarnessEnvironment](/api/cdk/testing/selenium-webdriver/SeleniumWebDriverHarnessEnvironment) implementations in Angular CDK serve as good examples of implementations of this interface. + +## Handling auto change detection + +In order to support the `manualChangeDetection` and parallel APIs, your environment should install a handler for the auto change detection status. + +When your environment wants to start handling the auto change detection status it can call `handleAutoChangeDetectionStatus(handler)`. The handler function will receive a `AutoChangeDetectionStatus` which has two properties `isDisabled` and `onDetectChangesNow()`. See the [AutoChangeDetectionStatus API reference page](/api/cdk/testing/AutoChangeDetectionStatus) for more information. +If your environment wants to stop handling auto change detection status it can call `stopHandlingAutoChangeDetectionStatus()`. diff --git a/adev-es/src/content/guide/testing/component-harnesses-testing-environments.md b/adev-es/src/content/guide/testing/component-harnesses-testing-environments.md index 75fa6de..f4118f1 100644 --- a/adev-es/src/content/guide/testing/component-harnesses-testing-environments.md +++ b/adev-es/src/content/guide/testing/component-harnesses-testing-environments.md @@ -1,62 +1,62 @@ -# Adding harness support for additional testing environments +# Agregar soporte de harness para entornos de pruebas adicionales -## Before you start +## Antes de comenzar -TIP: This guide assumes you've already read the [component harnesses overview guide](guide/testing/component-harnesses-overview). Read that first if you're new to using component harnesses. +CONSEJO: Esta guía asume que ya leíste la [guía de visión general de component harnesses](guide/testing/component-harnesses-overview). Lee eso primero si eres nuevo en el uso de component harnesses. -### When does adding support for a test environment make sense? +### ¿Cuándo tiene sentido agregar soporte para un entorno de prueba? -To use component harnesses in the following environments, you can use Angular CDK's two built-in environments: +Para usar component harnesses en los siguientes entornos, puedes usar los dos entornos integrados del CDK de Angular: -- Unit tests -- WebDriver end-to-end tests +- Pruebas unitarias +- Pruebas end-to-end de WebDriver -To use a supported testing environment, read the [Creating harnesses for your components guide](guide/testing/creating-component-harnesses). +Para usar un entorno de pruebas soportado, lee la [guía de Crear harnesses para tus componentes](guide/testing/creating-component-harnesses). -Otherwise, to add support for other environments, you need to define how to interact with a DOM element and how DOM interactions work in your environment. Continue reading to learn more. +De lo contrario, para agregar soporte para otros entornos, necesitas definir cómo interactuar con un elemento DOM y cómo funcionan las interacciones DOM en tu entorno. Continúa leyendo para aprender más. -### CDK Installation +### Instalación del CDK -The [Component Dev Kit (CDK)](https://material.angular.dev/cdk/categories) is a set of behavior primitives for building components. To use the component harnesses, first install `@angular/cdk` from npm. You can do this from your terminal using the Angular CLI: +El [Component Dev Kit (CDK)](https://material.angular.dev/cdk/categories) es un conjunto de primitivas de comportamiento para construir componentes. Para usar los component harnesses, primero instala `@angular/cdk` desde npm. Puedes hacer esto desde tu terminal usando Angular CLI: ng add @angular/cdk -## Creating a `TestElement` implementation +## Crear una implementación de `TestElement` -Every test environment must define a `TestElement` implementation. The `TestElement` interface serves as an environment-agnostic representation of a DOM element. It enables harnesses to interact with DOM elements regardless of the underlying environment. Because some environments don't support interacting with DOM elements synchronously (e.g. WebDriver), all `TestElement` methods are asynchronous, returning a `Promise` with the result of the operation. +Cada entorno de prueba debe definir una implementación de `TestElement`. La interfaz `TestElement` sirve como una representación independiente del entorno de un elemento DOM. Permite a los harnesses interactuar con elementos DOM independientemente del entorno subyacente. Porque algunos entornos no soportan interactuar con elementos DOM de forma síncrona (p. ej., WebDriver), todos los métodos `TestElement` son asíncronos, retornando una `Promise` con el resultado de la operación. -`TestElement` offers a number of methods to interact with the underlying DOM such as `blur()`, `click()`, `getAttribute()`, and more. See the [TestElement API reference page](/api/cdk/testing/TestElement) for the full list of methods. +`TestElement` ofrece una cantidad de métodos para interactuar con el DOM subyacente como `blur()`, `click()`, `getAttribute()` y más. Consulta la [página de referencia de la API de TestElement](/api/cdk/testing/TestElement) para la lista completa de métodos. -The `TestElement` interface consists largely of methods that resemble methods available on `HTMLElement`. Similar methods exist in most test environments, which makes implementing the methods fairly straightforward. However, one important difference to note when implementing the `sendKeys` method, is that the key codes in the `TestKey` enum likely differ from the key codes used in the test environment. Environment authors should maintain a mapping from `TestKey` codes to the codes used in the particular testing environment. +La interfaz `TestElement` consiste en gran medida de métodos que se asemejan a los métodos disponibles en `HTMLElement`. Métodos similares existen en la mayoría de los entornos de prueba, lo que hace que implementar los métodos sea bastante directo. Sin embargo, una diferencia importante a notar al implementar el método `sendKeys`, es que los códigos de tecla en el enum `TestKey` probablemente difieran de los códigos de tecla usados en el entorno de prueba. Los autores de entornos deberían mantener un mapeo de códigos `TestKey` a los códigos usados en el entorno de pruebas particular. -The [UnitTestElement](/api/cdk/testing/testbed/UnitTestElement) and [SeleniumWebDriverElement](/api/cdk/testing/selenium-webdriver/SeleniumWebDriverElement) implementations in Angular CDK serve as good examples of implementations of this interface. +Las implementaciones [UnitTestElement](/api/cdk/testing/testbed/UnitTestElement) y [SeleniumWebDriverElement](/api/cdk/testing/selenium-webdriver/SeleniumWebDriverElement) en el CDK de Angular sirven como buenos ejemplos de implementaciones de esta interfaz. -## Creating a `HarnessEnvironment` implementation +## Crear una implementación de `HarnessEnvironment` -Test authors use `HarnessEnvironment` to create component harness instances for use in tests. `HarnessEnvironment` is an abstract class that must be extended to create a concrete subclass for the new environment. When supporting a new test environment, create a `HarnessEnvironment` subclass that adds concrete implementations for all abstract members. +Los autores de pruebas usan `HarnessEnvironment` para crear instancias de component harness para usar en pruebas. `HarnessEnvironment` es una clase abstracta que debe extenderse para crear una subclase concreta para el nuevo entorno. Al soportar un nuevo entorno de prueba, crea una subclase `HarnessEnvironment` que agregue implementaciones concretas para todos los miembros abstractos. -`HarnessEnvironment` has a generic type parameter: `HarnessEnvironment`. This parameter, `E`, represents the raw element type of the environment. For example, this parameter is Element for unit test environments. +`HarnessEnvironment` tiene un parámetro de tipo genérico: `HarnessEnvironment`. Este parámetro, `E`, representa el tipo de elemento raw del entorno. Por ejemplo, este parámetro es Element para entornos de prueba unitaria. -The following are the abstract methods that must be implemented: +Los siguientes son los métodos abstractos que deben implementarse: -| Method | Description | +| Método | Descripción | | :----------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `abstract getDocumentRoot(): E` | Gets the root element for the environment (e.g. `document.body`). | -| `abstract createTestElement(element: E): TestElement` | Creates a `TestElement` for the given raw element. | -| `abstract createEnvironment(element: E): HarnessEnvironment` | Creates a `HarnessEnvironment` rooted at the given raw element. | -| `abstract getAllRawElements(selector: string): Promise` | Gets all of the raw elements under the root element of the environment matching the given selector. | -| `abstract forceStabilize(): Promise` | Gets a `Promise` that resolves when the `NgZone` is stable. Additionally, if applicable, tells `NgZone` to stabilize (e.g. calling `flush()` in a `fakeAsync` test). | -| `abstract waitForTasksOutsideAngular(): Promise` | Gets a `Promise` that resolves when the parent zone of `NgZone` is stable. | +| `abstract getDocumentRoot(): E` | Obtiene el elemento raíz para el entorno (p. ej., `document.body`). | +| `abstract createTestElement(element: E): TestElement` | Crea un `TestElement` para el elemento raw dado. | +| `abstract createEnvironment(element: E): HarnessEnvironment` | Crea un `HarnessEnvironment` enraizado en el elemento raw dado. | +| `abstract getAllRawElements(selector: string): Promise` | Obtiene todos los elementos raw bajo el elemento raíz del entorno que coinciden con el selector dado. | +| `abstract forceStabilize(): Promise` | Obtiene una `Promise` que se resuelve cuando el `NgZone` es estable. Además, si es aplicable, le dice a `NgZone` que se estabilice (p. ej., llamando `flush()` en una prueba `fakeAsync`). | +| `abstract waitForTasksOutsideAngular(): Promise` | Obtiene una `Promise` que se resuelve cuando la zona padre de `NgZone` es estable. | -In addition to implementing the missing methods, this class should provide a way for test authors to get `ComponentHarness` instances. You should define a protected constructor and provide a static method called `loader` that returns a `HarnessLoader` instance. This allows test authors to write code like: `SomeHarnessEnvironment.loader().getHarness(...)`. Depending on the needs of the particular environment, the class may provide several different static methods or require arguments to be passed. (e.g. the `loader` method on `TestbedHarnessEnvironment` takes a `ComponentFixture`, and the class provides additional static methods called `documentRootLoader` and `harnessForFixture`). +Además de implementar los métodos faltantes, esta clase debería proporcionar una forma para que los autores de pruebas obtengan instancias de `ComponentHarness`. Deberías definir un constructor protegido y proporcionar un método estático llamado `loader` que retorne una instancia de `HarnessLoader`. Esto permite a los autores de pruebas escribir código como: `SomeHarnessEnvironment.loader().getHarness(...)`. Dependiendo de las necesidades del entorno particular, la clase puede proporcionar varios métodos estáticos diferentes o requerir que se pasen argumentos. (p. ej., el método `loader` en `TestbedHarnessEnvironment` toma un `ComponentFixture`, y la clase proporciona métodos estáticos adicionales llamados `documentRootLoader` y `harnessForFixture`). -The [`TestbedHarnessEnvironment`](/api/cdk/testing/testbed/TestbedHarnessEnvironment) and [SeleniumWebDriverHarnessEnvironment](/api/cdk/testing/selenium-webdriver/SeleniumWebDriverHarnessEnvironment) implementations in Angular CDK serve as good examples of implementations of this interface. +Las implementaciones [`TestbedHarnessEnvironment`](/api/cdk/testing/testbed/TestbedHarnessEnvironment) y [SeleniumWebDriverHarnessEnvironment](/api/cdk/testing/selenium-webdriver/SeleniumWebDriverHarnessEnvironment) en el CDK de Angular sirven como buenos ejemplos de implementaciones de esta interfaz. -## Handling auto change detection +## Manejar la detección automática de cambios -In order to support the `manualChangeDetection` and parallel APIs, your environment should install a handler for the auto change detection status. +Para soportar las APIs `manualChangeDetection` y parallel, tu entorno debería instalar un manejador para el estado de detección automática de cambios. -When your environment wants to start handling the auto change detection status it can call `handleAutoChangeDetectionStatus(handler)`. The handler function will receive a `AutoChangeDetectionStatus` which has two properties `isDisabled` and `onDetectChangesNow()`. See the [AutoChangeDetectionStatus API reference page](/api/cdk/testing/AutoChangeDetectionStatus) for more information. -If your environment wants to stop handling auto change detection status it can call `stopHandlingAutoChangeDetectionStatus()`. +Cuando tu entorno quiera comenzar a manejar el estado de detección automática de cambios puede llamar a `handleAutoChangeDetectionStatus(handler)`. La función handler recibirá un `AutoChangeDetectionStatus` que tiene dos propiedades `isDisabled` y `onDetectChangesNow()`. Consulta la [página de referencia de la API de AutoChangeDetectionStatus](/api/cdk/testing/AutoChangeDetectionStatus) para más información. +Si tu entorno quiere dejar de manejar el estado de detección automática de cambios puede llamar a `stopHandlingAutoChangeDetectionStatus()`. diff --git a/adev-es/src/content/guide/testing/components-basics.en.md b/adev-es/src/content/guide/testing/components-basics.en.md new file mode 100644 index 0000000..e22f608 --- /dev/null +++ b/adev-es/src/content/guide/testing/components-basics.en.md @@ -0,0 +1,181 @@ +# Basics of testing components + +A component, unlike all other parts of an Angular application, combines an HTML template and a TypeScript class. +The component truly is the template and the class *working together*. +To adequately test a component, you should test that they work together as intended. + +Such tests require creating the component's host element in the browser DOM, as Angular does, and investigating the component class's interaction with the DOM as described by its template. + +The Angular `TestBed` facilitates this kind of testing as you'll see in the following sections. +But in many cases, *testing the component class alone*, without DOM involvement, can validate much of the component's behavior in a straightforward, more obvious way. + +## Component DOM testing + +A component is more than just its class. +A component interacts with the DOM and with other components. +Classes alone cannot tell you if the component is going to render properly, respond to user input and gestures, or integrate with its parent and child components. + +* Is `Lightswitch.clicked()` bound to anything such that the user can invoke it? +* Is the `Lightswitch.message` displayed? +* Can the user actually select the hero displayed by `DashboardHeroComponent`? +* Is the hero name displayed as expected \(such as uppercase\)? +* Is the welcome message displayed by the template of `WelcomeComponent`? + +These might not be troubling questions for the preceding simple components illustrated. +But many components have complex interactions with the DOM elements described in their templates, causing HTML to appear and disappear as the component state changes. + +To answer these kinds of questions, you have to create the DOM elements associated with the components, you must examine the DOM to confirm that component state displays properly at the appropriate times, and you must simulate user interaction with the screen to determine whether those interactions cause the component to behave as expected. + +To write these kinds of test, you'll use additional features of the `TestBed` as well as other testing helpers. + +### CLI-generated tests + +The CLI creates an initial test file for you by default when you ask it to generate a new component. + +For example, the following CLI command generates a `BannerComponent` in the `app/banner` folder \(with inline template and styles\): + + + +ng generate component banner --inline-template --inline-style --module app + + + +It also generates an initial test file for the component, `banner-external.component.spec.ts`, that looks like this: + + + +HELPFUL: Because `compileComponents` is asynchronous, it uses the [`waitForAsync`](api/core/testing/waitForAsync) utility function imported from `@angular/core/testing`. + +Refer to the [waitForAsync](guide/testing/components-scenarios#waitForAsync) section for more details. + +### Reduce the setup + +Only the last three lines of this file actually test the component and all they do is assert that Angular can create the component. + +The rest of the file is boilerplate setup code anticipating more advanced tests that *might* become necessary if the component evolves into something substantial. + +You'll learn about these advanced test features in the following sections. +For now, you can radically reduce this test file to a more manageable size: + + + +In this example, the metadata object passed to `TestBed.configureTestingModule` simply declares `BannerComponent`, the component to test. + + + +HELPFUL: There's no need to declare or import anything else. +The default test module is pre-configured with something like the `BrowserModule` from `@angular/platform-browser`. + +Later you'll call `TestBed.configureTestingModule()` with imports, providers, and more declarations to suit your testing needs. +Optional `override` methods can further fine-tune aspects of the configuration. + +### `createComponent()` + +After configuring `TestBed`, you call its `createComponent()` method. + + + +`TestBed.createComponent()` creates an instance of the `BannerComponent`, adds a corresponding element to the test-runner DOM, and returns a [`ComponentFixture`](#componentfixture). + +IMPORTANT: Do not re-configure `TestBed` after calling `createComponent`. + +The `createComponent` method freezes the current `TestBed` definition, closing it to further configuration. + +You cannot call any more `TestBed` configuration methods, not `configureTestingModule()`, nor `get()`, nor any of the `override...` methods. +If you try, `TestBed` throws an error. + +### `ComponentFixture` + +The [ComponentFixture](api/core/testing/ComponentFixture) is a test harness for interacting with the created component and its corresponding element. + +Access the component instance through the fixture and confirm it exists with a Jasmine expectation: + + + +### `beforeEach()` + +You will add more tests as this component evolves. +Rather than duplicate the `TestBed` configuration for each test, you refactor to pull the setup into a Jasmine `beforeEach()` and some supporting variables: + + + +Now add a test that gets the component's element from `fixture.nativeElement` and looks for the expected text. + + + +### `nativeElement` + +The value of `ComponentFixture.nativeElement` has the `any` type. +Later you'll encounter the `DebugElement.nativeElement` and it too has the `any` type. + +Angular can't know at compile time what kind of HTML element the `nativeElement` is or if it even is an HTML element. +The application might be running on a *non-browser platform*, such as the server or a [Web Worker](https://developer.mozilla.org/docs/Web/API/Web_Workers_API), where the element might have a diminished API or not exist at all. + +The tests in this guide are designed to run in a browser so a `nativeElement` value will always be an `HTMLElement` or one of its derived classes. + +Knowing that it is an `HTMLElement` of some sort, use the standard HTML `querySelector` to dive deeper into the element tree. + +Here's another test that calls `HTMLElement.querySelector` to get the paragraph element and look for the banner text: + + + +### `DebugElement` + +The Angular *fixture* provides the component's element directly through the `fixture.nativeElement`. + + + +This is actually a convenience method, implemented as `fixture.debugElement.nativeElement`. + + + +There's a good reason for this circuitous path to the element. + +The properties of the `nativeElement` depend upon the runtime environment. +You could be running these tests on a *non-browser* platform that doesn't have a DOM or whose DOM-emulation doesn't support the full `HTMLElement` API. + +Angular relies on the `DebugElement` abstraction to work safely across *all supported platforms*. +Instead of creating an HTML element tree, Angular creates a `DebugElement` tree that wraps the *native elements* for the runtime platform. +The `nativeElement` property unwraps the `DebugElement` and returns the platform-specific element object. + +Because the sample tests for this guide are designed to run only in a browser, a `nativeElement` in these tests is always an `HTMLElement` whose familiar methods and properties you can explore within a test. + +Here's the previous test, re-implemented with `fixture.debugElement.nativeElement`: + + + +The `DebugElement` has other methods and properties that are useful in tests, as you'll see elsewhere in this guide. + +You import the `DebugElement` symbol from the Angular core library. + + + +### `By.css()` + +Although the tests in this guide all run in the browser, some applications might run on a different platform at least some of the time. + +For example, the component might render first on the server as part of a strategy to make the application launch faster on poorly connected devices. +The server-side renderer might not support the full HTML element API. +If it doesn't support `querySelector`, the previous test could fail. + +The `DebugElement` offers query methods that work for all supported platforms. +These query methods take a *predicate* function that returns `true` when a node in the `DebugElement` tree matches the selection criteria. + +You create a *predicate* with the help of a `By` class imported from a library for the runtime platform. +Here's the `By` import for the browser platform: + + + +The following example re-implements the previous test with `DebugElement.query()` and the browser's `By.css` method. + + + +Some noteworthy observations: + +* The `By.css()` static method selects `DebugElement` nodes with a [standard CSS selector](https://developer.mozilla.org/docs/Learn/CSS/Building_blocks/Selectors 'CSS selectors'). +* The query returns a `DebugElement` for the paragraph. +* You must unwrap that result to get the paragraph element. + +When you're filtering by CSS selector and only testing properties of a browser's *native element*, the `By.css` approach might be overkill. + +It's often more straightforward and clear to filter with a standard `HTMLElement` method such as `querySelector()` or `querySelectorAll()`. diff --git a/adev-es/src/content/guide/testing/components-basics.md b/adev-es/src/content/guide/testing/components-basics.md index e22f608..561c1cc 100644 --- a/adev-es/src/content/guide/testing/components-basics.md +++ b/adev-es/src/content/guide/testing/components-basics.md @@ -1,38 +1,38 @@ -# Basics of testing components +# Fundamentos de probar componentes -A component, unlike all other parts of an Angular application, combines an HTML template and a TypeScript class. -The component truly is the template and the class *working together*. -To adequately test a component, you should test that they work together as intended. +Un componente, a diferencia de todas las otras partes de una aplicación Angular, combina una plantilla HTML y una clase TypeScript. +El componente verdaderamente es la plantilla y la clase *trabajando juntas*. +Para probar adecuadamente un componente, deberías probar que trabajen juntos como se pretende. -Such tests require creating the component's host element in the browser DOM, as Angular does, and investigating the component class's interaction with the DOM as described by its template. +Tales pruebas requieren crear el elemento host del componente en el DOM del navegador, como hace Angular, e investigar la interacción de la clase del componente con el DOM como se describe en su plantilla. -The Angular `TestBed` facilitates this kind of testing as you'll see in the following sections. -But in many cases, *testing the component class alone*, without DOM involvement, can validate much of the component's behavior in a straightforward, more obvious way. +El `TestBed` de Angular facilita este tipo de pruebas como verás en las siguientes secciones. +Pero en muchos casos, *probar la clase del componente sola*, sin involucramiento del DOM, puede validar mucho del comportamiento del componente de una manera más directa y obvia. -## Component DOM testing +## Pruebas del DOM de componentes -A component is more than just its class. -A component interacts with the DOM and with other components. -Classes alone cannot tell you if the component is going to render properly, respond to user input and gestures, or integrate with its parent and child components. +Un componente es más que solo su clase. +Un componente interactúa con el DOM y con otros componentes. +Las clases solas no pueden decirte si el componente va a renderizar correctamente, responder a la entrada y gestos del usuario, o integrarse con sus componentes padre e hijo. -* Is `Lightswitch.clicked()` bound to anything such that the user can invoke it? -* Is the `Lightswitch.message` displayed? -* Can the user actually select the hero displayed by `DashboardHeroComponent`? -* Is the hero name displayed as expected \(such as uppercase\)? -* Is the welcome message displayed by the template of `WelcomeComponent`? +* ¿Está `Lightswitch.clicked()` vinculado a algo de modo que el usuario pueda invocarlo? +* ¿Se muestra el `Lightswitch.message`? +* ¿Puede el usuario realmente seleccionar el héroe mostrado por `DashboardHeroComponent`? +* ¿Se muestra el nombre del héroe como se espera \(como mayúsculas\)? +* ¿Se muestra el mensaje de bienvenida por la plantilla de `WelcomeComponent`? -These might not be troubling questions for the preceding simple components illustrated. -But many components have complex interactions with the DOM elements described in their templates, causing HTML to appear and disappear as the component state changes. +Estas podrían no ser preguntas problemáticas para los componentes simples precedentes ilustrados. +Pero muchos componentes tienen interacciones complejas con los elementos DOM descritos en sus plantillas, causando que HTML aparezca y desaparezca a medida que el estado del componente cambia. -To answer these kinds of questions, you have to create the DOM elements associated with the components, you must examine the DOM to confirm that component state displays properly at the appropriate times, and you must simulate user interaction with the screen to determine whether those interactions cause the component to behave as expected. +Para responder estos tipos de preguntas, tienes que crear los elementos DOM asociados con los componentes, debes examinar el DOM para confirmar que el estado del componente se muestra correctamente en los momentos apropiados, y debes simular la interacción del usuario con la pantalla para determinar si esas interacciones hacen que el componente se comporte como se espera. -To write these kinds of test, you'll use additional features of the `TestBed` as well as other testing helpers. +Para escribir estos tipos de prueba, usarás características adicionales del `TestBed` así como otros helpers de pruebas. -### CLI-generated tests +### Pruebas generadas por el CLI -The CLI creates an initial test file for you by default when you ask it to generate a new component. +El CLI crea un archivo de prueba inicial para ti por defecto cuando le pides que genere un nuevo componente. -For example, the following CLI command generates a `BannerComponent` in the `app/banner` folder \(with inline template and styles\): +Por ejemplo, el siguiente comando del CLI genera un `BannerComponent` en la carpeta `app/banner` \(con plantilla y estilos inline\): @@ -40,142 +40,142 @@ ng generate component banner --inline-template --inline-style --module app -It also generates an initial test file for the component, `banner-external.component.spec.ts`, that looks like this: +También genera un archivo de prueba inicial para el componente, `banner-external.component.spec.ts`, que se ve así: -HELPFUL: Because `compileComponents` is asynchronous, it uses the [`waitForAsync`](api/core/testing/waitForAsync) utility function imported from `@angular/core/testing`. +ÚTIL: Porque `compileComponents` es asíncrono, usa la función utilitaria [`waitForAsync`](api/core/testing/waitForAsync) importada de `@angular/core/testing`. -Refer to the [waitForAsync](guide/testing/components-scenarios#waitForAsync) section for more details. +Consulta la sección [waitForAsync](guide/testing/components-scenarios#waitForAsync) para más detalles. -### Reduce the setup +### Reducir la configuración -Only the last three lines of this file actually test the component and all they do is assert that Angular can create the component. +Solo las últimas tres líneas de este archivo realmente prueban el componente y todo lo que hacen es afirmar que Angular puede crear el componente. -The rest of the file is boilerplate setup code anticipating more advanced tests that *might* become necessary if the component evolves into something substantial. +El resto del archivo es código de configuración boilerplate anticipando pruebas más avanzadas que *podrían* volverse necesarias si el componente evoluciona en algo sustancial. -You'll learn about these advanced test features in the following sections. -For now, you can radically reduce this test file to a more manageable size: +Aprenderás sobre estas características de prueba avanzadas en las siguientes secciones. +Por ahora, puedes reducir radicalmente este archivo de prueba a un tamaño más manejable: -In this example, the metadata object passed to `TestBed.configureTestingModule` simply declares `BannerComponent`, the component to test. +En este ejemplo, el objeto de metadata pasado a `TestBed.configureTestingModule` simplemente declara `BannerComponent`, el componente a probar. -HELPFUL: There's no need to declare or import anything else. -The default test module is pre-configured with something like the `BrowserModule` from `@angular/platform-browser`. +ÚTIL: No hay necesidad de declarar o importar nada más. +El módulo de prueba por defecto está pre-configurado con algo como el `BrowserModule` de `@angular/platform-browser`. -Later you'll call `TestBed.configureTestingModule()` with imports, providers, and more declarations to suit your testing needs. -Optional `override` methods can further fine-tune aspects of the configuration. +Más tarde llamarás a `TestBed.configureTestingModule()` con imports, providers y más declarations para adaptarse a tus necesidades de pruebas. +Métodos `override` opcionales pueden ajustar aún más aspectos de la configuración. ### `createComponent()` -After configuring `TestBed`, you call its `createComponent()` method. +Después de configurar `TestBed`, llamas a su método `createComponent()`. -`TestBed.createComponent()` creates an instance of the `BannerComponent`, adds a corresponding element to the test-runner DOM, and returns a [`ComponentFixture`](#componentfixture). +`TestBed.createComponent()` crea una instancia del `BannerComponent`, agrega un elemento correspondiente al DOM del test-runner, y retorna un [`ComponentFixture`](#componentfixture). -IMPORTANT: Do not re-configure `TestBed` after calling `createComponent`. +IMPORTANTE: No re-configures `TestBed` después de llamar a `createComponent`. -The `createComponent` method freezes the current `TestBed` definition, closing it to further configuration. +El método `createComponent` congela la definición actual del `TestBed`, cerrándola a más configuración. -You cannot call any more `TestBed` configuration methods, not `configureTestingModule()`, nor `get()`, nor any of the `override...` methods. -If you try, `TestBed` throws an error. +No puedes llamar más métodos de configuración del `TestBed`, ni `configureTestingModule()`, ni `get()`, ni ninguno de los métodos `override...`. +Si lo intentas, `TestBed` lanza un error. ### `ComponentFixture` -The [ComponentFixture](api/core/testing/ComponentFixture) is a test harness for interacting with the created component and its corresponding element. +El [ComponentFixture](api/core/testing/ComponentFixture) es un harness de prueba para interactuar con el componente creado y su elemento correspondiente. -Access the component instance through the fixture and confirm it exists with a Jasmine expectation: +Accede a la instancia del componente a través del fixture y confirma que existe con una expectativa de Jasmine: ### `beforeEach()` -You will add more tests as this component evolves. -Rather than duplicate the `TestBed` configuration for each test, you refactor to pull the setup into a Jasmine `beforeEach()` and some supporting variables: +Agregarás más pruebas a medida que este componente evolucione. +En lugar de duplicar la configuración del `TestBed` para cada prueba, refactoriza para sacar la configuración en un `beforeEach()` de Jasmine y algunas variables de soporte: -Now add a test that gets the component's element from `fixture.nativeElement` and looks for the expected text. +Ahora agrega una prueba que obtiene el elemento del componente de `fixture.nativeElement` y busca el texto esperado. ### `nativeElement` -The value of `ComponentFixture.nativeElement` has the `any` type. -Later you'll encounter the `DebugElement.nativeElement` and it too has the `any` type. +El valor de `ComponentFixture.nativeElement` tiene el tipo `any`. +Más tarde encontrarás el `DebugElement.nativeElement` y también tiene el tipo `any`. -Angular can't know at compile time what kind of HTML element the `nativeElement` is or if it even is an HTML element. -The application might be running on a *non-browser platform*, such as the server or a [Web Worker](https://developer.mozilla.org/docs/Web/API/Web_Workers_API), where the element might have a diminished API or not exist at all. +Angular no puede saber en tiempo de compilación qué tipo de elemento HTML es el `nativeElement` o si siquiera es un elemento HTML. +La aplicación podría estar ejecutándose en una *plataforma no-navegador*, como el servidor o un [Web Worker](https://developer.mozilla.org/docs/Web/API/Web_Workers_API), donde el elemento podría tener una API disminuida o no existir en absoluto. -The tests in this guide are designed to run in a browser so a `nativeElement` value will always be an `HTMLElement` or one of its derived classes. +Las pruebas en esta guía están diseñadas para ejecutarse en un navegador, por lo que un valor `nativeElement` siempre será un `HTMLElement` o una de sus clases derivadas. -Knowing that it is an `HTMLElement` of some sort, use the standard HTML `querySelector` to dive deeper into the element tree. +Sabiendo que es un `HTMLElement` de algún tipo, usa el `querySelector` HTML estándar para profundizar en el árbol de elementos. -Here's another test that calls `HTMLElement.querySelector` to get the paragraph element and look for the banner text: +Aquí hay otra prueba que llama a `HTMLElement.querySelector` para obtener el elemento párrafo y buscar el texto del banner: ### `DebugElement` -The Angular *fixture* provides the component's element directly through the `fixture.nativeElement`. +El *fixture* de Angular proporciona el elemento del componente directamente a través del `fixture.nativeElement`. -This is actually a convenience method, implemented as `fixture.debugElement.nativeElement`. +Esto es en realidad un método de conveniencia, implementado como `fixture.debugElement.nativeElement`. -There's a good reason for this circuitous path to the element. +Hay una buena razón para esta ruta indirecta al elemento. -The properties of the `nativeElement` depend upon the runtime environment. -You could be running these tests on a *non-browser* platform that doesn't have a DOM or whose DOM-emulation doesn't support the full `HTMLElement` API. +Las propiedades del `nativeElement` dependen del entorno de ejecución. +Podrías estar ejecutando estas pruebas en una plataforma *no-navegador* que no tiene un DOM o cuya emulación de DOM no soporta la API completa de `HTMLElement`. -Angular relies on the `DebugElement` abstraction to work safely across *all supported platforms*. -Instead of creating an HTML element tree, Angular creates a `DebugElement` tree that wraps the *native elements* for the runtime platform. -The `nativeElement` property unwraps the `DebugElement` and returns the platform-specific element object. +Angular depende de la abstracción `DebugElement` para trabajar de forma segura en *todas las plataformas soportadas*. +En lugar de crear un árbol de elementos HTML, Angular crea un árbol `DebugElement` que envuelve los *elementos nativos* para la plataforma de ejecución. +La propiedad `nativeElement` desenvuelve el `DebugElement` y retorna el objeto de elemento específico de la plataforma. -Because the sample tests for this guide are designed to run only in a browser, a `nativeElement` in these tests is always an `HTMLElement` whose familiar methods and properties you can explore within a test. +Porque las pruebas de muestra para esta guía están diseñadas para ejecutarse solo en un navegador, un `nativeElement` en estas pruebas es siempre un `HTMLElement` cuyos métodos y propiedades familiares puedes explorar dentro de una prueba. -Here's the previous test, re-implemented with `fixture.debugElement.nativeElement`: +Aquí está la prueba anterior, re-implementada con `fixture.debugElement.nativeElement`: -The `DebugElement` has other methods and properties that are useful in tests, as you'll see elsewhere in this guide. +El `DebugElement` tiene otros métodos y propiedades que son útiles en pruebas, como verás en otros lugares de esta guía. -You import the `DebugElement` symbol from the Angular core library. +Importas el símbolo `DebugElement` de la librería core de Angular. ### `By.css()` -Although the tests in this guide all run in the browser, some applications might run on a different platform at least some of the time. +Aunque las pruebas en esta guía todas se ejecutan en el navegador, algunas aplicaciones podrían ejecutarse en una plataforma diferente al menos parte del tiempo. -For example, the component might render first on the server as part of a strategy to make the application launch faster on poorly connected devices. -The server-side renderer might not support the full HTML element API. -If it doesn't support `querySelector`, the previous test could fail. +Por ejemplo, el componente podría renderizar primero en el servidor como parte de una estrategia para hacer que la aplicación se inicie más rápido en dispositivos pobremente conectados. +El renderizador del lado del servidor podría no soportar la API completa de elementos HTML. +Si no soporta `querySelector`, la prueba anterior podría fallar. -The `DebugElement` offers query methods that work for all supported platforms. -These query methods take a *predicate* function that returns `true` when a node in the `DebugElement` tree matches the selection criteria. +El `DebugElement` ofrece métodos de consulta que funcionan para todas las plataformas soportadas. +Estos métodos de consulta toman una función *predicate* que retorna `true` cuando un nodo en el árbol `DebugElement` coincide con los criterios de selección. -You create a *predicate* with the help of a `By` class imported from a library for the runtime platform. -Here's the `By` import for the browser platform: +Creas un *predicate* con la ayuda de una clase `By` importada de una librería para la plataforma de ejecución. +Aquí está el import `By` para la plataforma navegador: -The following example re-implements the previous test with `DebugElement.query()` and the browser's `By.css` method. +El siguiente ejemplo re-implementa la prueba anterior con `DebugElement.query()` y el método `By.css` del navegador. -Some noteworthy observations: +Algunas observaciones dignas de mención: -* The `By.css()` static method selects `DebugElement` nodes with a [standard CSS selector](https://developer.mozilla.org/docs/Learn/CSS/Building_blocks/Selectors 'CSS selectors'). -* The query returns a `DebugElement` for the paragraph. -* You must unwrap that result to get the paragraph element. +* El método estático `By.css()` selecciona nodos `DebugElement` con un [selector CSS estándar](https://developer.mozilla.org/docs/Learn/CSS/Building_blocks/Selectors 'CSS selectors'). +* La consulta retorna un `DebugElement` para el párrafo. +* Debes desenvolver ese resultado para obtener el elemento párrafo. -When you're filtering by CSS selector and only testing properties of a browser's *native element*, the `By.css` approach might be overkill. +Cuando estás filtrando por selector CSS y solo probando propiedades del *elemento nativo* de un navegador, el enfoque `By.css` podría ser excesivo. -It's often more straightforward and clear to filter with a standard `HTMLElement` method such as `querySelector()` or `querySelectorAll()`. +A menudo es más directo y claro filtrar con un método `HTMLElement` estándar como `querySelector()` o `querySelectorAll()`. diff --git a/adev-es/src/content/guide/testing/components-scenarios.en.md b/adev-es/src/content/guide/testing/components-scenarios.en.md new file mode 100644 index 0000000..7efc281 --- /dev/null +++ b/adev-es/src/content/guide/testing/components-scenarios.en.md @@ -0,0 +1,809 @@ +# Component testing scenarios + +This guide explores common component testing use cases. + +## Component binding + +In the example application, the `BannerComponent` presents static title text in the HTML template. + +After a few changes, the `BannerComponent` presents a dynamic title by binding to the component's `title` property like this. + + + +As minimal as this is, you decide to add a test to confirm that component actually displays the right content where you think it should. + +### Query for the `

` + +You'll write a sequence of tests that inspect the value of the `

` element that wraps the *title* property interpolation binding. + +You update the `beforeEach` to find that element with a standard HTML `querySelector` and assign it to the `h1` variable. + + + +### `createComponent()` does not bind data + +For your first test you'd like to see that the screen displays the default `title`. +Your instinct is to write a test that immediately inspects the `

` like this: + + + +*That test fails* with the message: + + + +expected '' to contain 'Test Tour of Heroes'. + + + +Binding happens when Angular performs **change detection**. + +In production, change detection kicks in automatically when Angular creates a component or the user enters a keystroke, for example. + +The `TestBed.createComponent` does not trigger change detection by default; a fact confirmed in the revised test: + + + +### `detectChanges()` + +You can tell the `TestBed` to perform data binding by calling `fixture.detectChanges()`. +Only then does the `

` have the expected title. + + + +Delayed change detection is intentional and useful. +It gives the tester an opportunity to inspect and change the state of the component *before Angular initiates data binding and calls [lifecycle hooks](guide/components/lifecycle)*. + +Here's another test that changes the component's `title` property *before* calling `fixture.detectChanges()`. + + + +### Automatic change detection + +The `BannerComponent` tests frequently call `detectChanges`. +Many testers prefer that the Angular test environment run change detection automatically like it does in production. + +That's possible by configuring the `TestBed` with the `ComponentFixtureAutoDetect` provider. +First import it from the testing utility library: + + + +Then add it to the `providers` array of the testing module configuration: + + + +HELPFUL: You can also use the `fixture.autoDetectChanges()` function instead if you only want to enable automatic change detection +after making updates to the state of the fixture's component. In addition, automatic change detection is on by default +when using `provideZonelessChangeDetection` and turning it off is not recommended. + +Here are three tests that illustrate how automatic change detection works. + + + +The first test shows the benefit of automatic change detection. + +The second and third test reveal an important limitation. +The Angular testing environment does not run change detection synchronously when updates happen inside the test case that changed the component's `title`. +The test must call `await fixture.whenStable` to wait for another round of change detection. + +HELPFUL: Angular does not know about direct updates to values that are not signals. The easiest way to ensure that +change detection will be scheduled is to use signals for values read in the template. + +### Change an input value with `dispatchEvent()` + +To simulate user input, find the input element and set its `value` property. + +But there is an essential, intermediate step. + +Angular doesn't know that you set the input element's `value` property. +It won't read that property until you raise the element's `input` event by calling `dispatchEvent()`. + +The following example demonstrates the proper sequence. + + + +## Component with external files + +The preceding `BannerComponent` is defined with an *inline template* and *inline css*, specified in the `@Component.template` and `@Component.styles` properties respectively. + +Many components specify *external templates* and *external css* with the `@Component.templateUrl` and `@Component.styleUrls` properties respectively, as the following variant of `BannerComponent` does. + + + +This syntax tells the Angular compiler to read the external files during component compilation. + +That's not a problem when you run the CLI `ng test` command because it *compiles the application before running the tests*. + +However, if you run the tests in a **non-CLI environment**, tests of this component might fail. +For example, if you run the `BannerComponent` tests in a web coding environment such as [plunker](https://plnkr.co), you'll see a message like this one: + + + +Error: This test module uses the component BannerComponent +which is using a "templateUrl" or "styleUrls", but they were never compiled. +Please call "TestBed.compileComponents" before your test. + + + +You get this test failure message when the runtime environment compiles the source code *during the tests themselves*. + +To correct the problem, call `compileComponents()` as explained in the following [Calling compileComponents](#calling-compilecomponents) section. + +## Component with a dependency + +Components often have service dependencies. + +The `WelcomeComponent` displays a welcome message to the logged-in user. +It knows who the user is based on a property of the injected `UserService`: + + + +The `WelcomeComponent` has decision logic that interacts with the service, logic that makes this component worth testing. + +### Provide service test doubles + +A *component-under-test* doesn't have to be provided with real services. + +Injecting the real `UserService` could be difficult. +The real service might ask the user for login credentials and attempt to reach an authentication server. +These behaviors can be hard to intercept. Be aware that using test doubles makes the test behave differently from production so use them sparingly. + +### Get injected services + +The tests need access to the `UserService` injected into the `WelcomeComponent`. + +Angular has a hierarchical injection system. +There can be injectors at multiple levels, from the root injector created by the `TestBed` down through the component tree. + +The safest way to get the injected service, the way that ***always works***, +is to **get it from the injector of the *component-under-test***. +The component injector is a property of the fixture's `DebugElement`. + + + +HELPFUL: This is _usually_ not necessary. Services are often provided in the root or the TestBed overrides and can be retrieved more easily with `TestBed.inject()` (see below). + +### `TestBed.inject()` + +This is easier to remember and less verbose than retrieving a service using the fixture's `DebugElement`. + +In this test suite, the *only* provider of `UserService` is the root testing module, so it is safe to call `TestBed.inject()` as follows: + + + +HELPFUL: For a use case in which `TestBed.inject()` does not work, see the [*Override component providers*](#override-component-providers) section that explains when and why you must get the service from the component's injector instead. + +### Final setup and tests + +Here's the complete `beforeEach()`, using `TestBed.inject()`: + + + +And here are some tests: + + + +The first is a sanity test; it confirms that the `UserService` is called and working. + +HELPFUL: The withContext function \(for example, `'expected name'`\) is an optional failure label. +If the expectation fails, Jasmine appends this label to the expectation failure message. +In a spec with multiple expectations, it can help clarify what went wrong and which expectation failed. + +The remaining tests confirm the logic of the component when the service returns different values. +The second test validates the effect of changing the user name. +The third test checks that the component displays the proper message when there is no logged-in user. + +## Component with async service + +In this sample, the `AboutComponent` template hosts a `TwainComponent`. +The `TwainComponent` displays Mark Twain quotes. + + + +HELPFUL: The value of the component's `quote` property passes through an `AsyncPipe`. +That means the property returns either a `Promise` or an `Observable`. + +In this example, the `TwainComponent.getQuote()` method tells you that the `quote` property returns an `Observable`. + + + +The `TwainComponent` gets quotes from an injected `TwainService`. +The component starts the returned `Observable` with a placeholder value \(`'...'`\), before the service can return its first quote. + +The `catchError` intercepts service errors, prepares an error message, and returns the placeholder value on the success channel. + +These are all features you'll want to test. + +### Testing with a spy + +When testing a component, only the service's public API should matter. +In general, tests themselves should not make calls to remote servers. +They should emulate such calls. +The setup in this `app/twain/twain.component.spec.ts` shows one way to do that: + + + +Focus on the spy. + + + +The spy is designed such that any call to `getQuote` receives an observable with a test quote. +Unlike the real `getQuote()` method, this spy bypasses the server and returns a synchronous observable whose value is available immediately. + +You can write many useful tests with this spy, even though its `Observable` is synchronous. + +HELPFUL: It is best to limit the usage of spies to only what is necessary for the test. Creating mocks or spies for more than what's necessary can be brittle. As the component and injectable evolves, the unrelated tests can fail because they no longer mock enough behaviors that would otherwise not affect the test. + + +### Async test with `fakeAsync()` + +To use `fakeAsync()` functionality, you must import `zone.js/testing` in your test setup file. +If you created your project with the Angular CLI, `zone-testing` is already imported in `src/test.ts`. + +The following test confirms the expected behavior when the service returns an `ErrorObservable`. + + + +HELPFUL: The `it()` function receives an argument of the following form. + + + +fakeAsync(() => { /*test body*/ }) + + + +The `fakeAsync()` function enables a linear coding style by running the test body in a special `fakeAsync test zone`. +The test body appears to be synchronous. +There is no nested syntax \(like a `Promise.then()`\) to disrupt the flow of control. + +HELPFUL: Limitation: The `fakeAsync()` function won't work if the test body makes an `XMLHttpRequest` \(XHR\) call. +XHR calls within a test are rare, but if you need to call XHR, see the [`waitForAsync()`](#waitForAsync) section. + +IMPORTANT: Be aware that asynchronous tasks that happen inside the `fakeAsync` zone need to be manually executed with `flush` or `tick`. If you attempt to +wait for them to complete (i.e. using `fixture.whenStable`) without using the +`fakeAsync` test helpers to advance time, your test will likely fail. See below for more information. + +### The `tick()` function + +You do have to call [tick()](api/core/testing/tick) to advance the virtual clock. + +Calling [tick()](api/core/testing/tick) simulates the passage of time until all pending asynchronous activities finish. +In this case, it waits for the observable's `setTimeout()`. + +The [tick()](api/core/testing/tick) function accepts `millis` and `tickOptions` as parameters. The `millis` parameter specifies how much the virtual clock advances and defaults to `0` if not provided. +For example, if you have a `setTimeout(fn, 100)` in a `fakeAsync()` test, you need to use `tick(100)` to trigger the fn callback. +The optional `tickOptions` parameter has a property named `processNewMacroTasksSynchronously`. The `processNewMacroTasksSynchronously` property represents whether to invoke new generated macro tasks when ticking and defaults to `true`. + + + +The [tick()](api/core/testing/tick) function is one of the Angular testing utilities that you import with `TestBed`. +It's a companion to `fakeAsync()` and you can only call it within a `fakeAsync()` body. + +### tickOptions + +In this example, you have a new macro task, the nested `setTimeout` function. By default, when the `tick` is setTimeout, `outside` and `nested` will both be triggered. + + + +In some case, you don't want to trigger the new macro task when ticking. You can use `tick(millis, {processNewMacroTasksSynchronously: false})` to not invoke a new macro task. + + + +### Comparing dates inside fakeAsync() + +`fakeAsync()` simulates passage of time, which lets you calculate the difference between dates inside `fakeAsync()`. + + + +### jasmine.clock with fakeAsync() + +Jasmine also provides a `clock` feature to mock dates. +Angular automatically runs tests that are run after `jasmine.clock().install()` is called inside a `fakeAsync()` method until `jasmine.clock().uninstall()` is called. +`fakeAsync()` is not needed and throws an error if nested. + +By default, this feature is disabled. +To enable it, set a global flag before importing `zone-testing`. + +If you use the Angular CLI, configure this flag in `src/test.ts`. + + + +[window as any]('__zone_symbol__fakeAsyncPatchLock') = true; +import 'zone.js/testing'; + + + + + +### Using the RxJS scheduler inside fakeAsync() + +You can also use RxJS scheduler in `fakeAsync()` just like using `setTimeout()` or `setInterval()`, but you need to import `zone.js/plugins/zone-patch-rxjs-fake-async` to patch RxJS scheduler. + + + +### Support more macroTasks + +By default, `fakeAsync()` supports the following macro tasks. + +* `setTimeout` +* `setInterval` +* `requestAnimationFrame` +* `webkitRequestAnimationFrame` +* `mozRequestAnimationFrame` + +If you run other macro tasks such as `HTMLCanvasElement.toBlob()`, an *"Unknown macroTask scheduled in fake async test"* error is thrown. + + + + + + +If you want to support such a case, you need to define the macro task you want to support in `beforeEach()`. +For example: + + + +HELPFUL: In order to make the `` element Zone.js-aware in your app, you need to import the `zone-patch-canvas` patch \(either in `polyfills.ts` or in the specific file that uses ``\): + + + +### Async observables + +You might be satisfied with the test coverage of these tests. + +However, you might be troubled by the fact that the real service doesn't quite behave this way. +The real service sends requests to a remote server. +A server takes time to respond and the response certainly won't be available immediately as in the previous two tests. + +Your tests will reflect the real world more faithfully if you return an *asynchronous* observable from the `getQuote()` spy like this. + + + +### Async observable helpers + +The async observable was produced by an `asyncData` helper. +The `asyncData` helper is a utility function that you'll have to write yourself, or copy this one from the sample code. + + + +This helper's observable emits the `data` value in the next turn of the JavaScript engine. + +The [RxJS `defer()` operator](http://reactivex.io/documentation/operators/defer.html) returns an observable. +It takes a factory function that returns either a promise or an observable. +When something subscribes to *defer*'s observable, it adds the subscriber to a new observable created with that factory. + +The `defer()` operator transforms the `Promise.resolve()` into a new observable that, like `HttpClient`, emits once and completes. +Subscribers are unsubscribed after they receive the data value. + +There's a similar helper for producing an async error. + + + +### More async tests + +Now that the `getQuote()` spy is returning async observables, most of your tests will have to be async as well. + +Here's a `fakeAsync()` test that demonstrates the data flow you'd expect in the real world. + + + +Notice that the quote element displays the placeholder value \(`'...'`\) after `ngOnInit()`. +The first quote hasn't arrived yet. + +To flush the first quote from the observable, you call [tick()](api/core/testing/tick). +Then call `detectChanges()` to tell Angular to update the screen. + +Then you can assert that the quote element displays the expected text. + +### Async test without `fakeAsync()` + +Here's the previous `fakeAsync()` test, re-written with the `async`. + + + +### `whenStable` + +The test must wait for the `getQuote()` observable to emit the next quote. +Instead of calling [tick()](api/core/testing/tick), it calls `fixture.whenStable()`. + +The `fixture.whenStable()` returns a promise that resolves when the JavaScript engine's task queue becomes empty. +In this example, the task queue becomes empty when the observable emits the first quote. + + +## Component with inputs and outputs + +A component with inputs and outputs typically appears inside the view template of a host component. +The host uses a property binding to set the input property and an event binding to listen to events raised by the output property. + +The testing goal is to verify that such bindings work as expected. +The tests should set input values and listen for output events. + +The `DashboardHeroComponent` is a tiny example of a component in this role. +It displays an individual hero provided by the `DashboardComponent`. +Clicking that hero tells the `DashboardComponent` that the user has selected the hero. + +The `DashboardHeroComponent` is embedded in the `DashboardComponent` template like this: + + + +The `DashboardHeroComponent` appears in an `@for` block, which sets each component's `hero` input property to the looping value and listens for the component's `selected` event. + +Here's the component's full definition: + + + +While testing a component this simple has little intrinsic value, it's worth knowing how. +Use one of these approaches: + +* Test it as used by `DashboardComponent` +* Test it as a standalone component +* Test it as used by a substitute for `DashboardComponent` + +The immediate goal is to test the `DashboardHeroComponent`, not the `DashboardComponent`, so, try the second and third options. + +### Test `DashboardHeroComponent` standalone + +Here's the meat of the spec file setup. + + + +Notice how the setup code assigns a test hero \(`expectedHero`\) to the component's `hero` property, emulating the way the `DashboardComponent` would set it using the property binding in its repeater. + +The following test verifies that the hero name is propagated to the template using a binding. + + + +Because the [template](#dashboard-hero-component) passes the hero name through the Angular `UpperCasePipe`, the test must match the element value with the upper-cased name. + +### Clicking + +Clicking the hero should raise a `selected` event that the host component \(`DashboardComponent` presumably\) can hear: + + + +The component's `selected` property returns an `EventEmitter`, which looks like an RxJS synchronous `Observable` to consumers. +The test subscribes to it *explicitly* just as the host component does *implicitly*. + +If the component behaves as expected, clicking the hero's element should tell the component's `selected` property to emit the `hero` object. + +The test detects that event through its subscription to `selected`. + +### `triggerEventHandler` + +The `heroDe` in the previous test is a `DebugElement` that represents the hero `
`. + +It has Angular properties and methods that abstract interaction with the native element. +This test calls the `DebugElement.triggerEventHandler` with the "click" event name. +The "click" event binding responds by calling `DashboardHeroComponent.click()`. + +The Angular `DebugElement.triggerEventHandler` can raise *any data-bound event* by its *event name*. +The second parameter is the event object passed to the handler. + +The test triggered a "click" event. + + + +In this case, the test correctly assumes that the runtime event handler, the component's `click()` method, doesn't care about the event object. + +HELPFUL: Other handlers are less forgiving. +For example, the `RouterLink` directive expects an object with a `button` property that identifies which mouse button, if any, was pressed during the click. +The `RouterLink` directive throws an error if the event object is missing. + +### Click the element + +The following test alternative calls the native element's own `click()` method, which is perfectly fine for *this component*. + + + +### `click()` helper + +Clicking a button, an anchor, or an arbitrary HTML element is a common test task. + +Make that consistent and straightforward by encapsulating the *click-triggering* process in a helper such as the following `click()` function: + + + +The first parameter is the *element-to-click*. +If you want, pass a custom event object as the second parameter. +The default is a partial [left-button mouse event object](https://developer.mozilla.org/docs/Web/API/MouseEvent/button) accepted by many handlers including the `RouterLink` directive. + +IMPORTANT: The `click()` helper function is **not** one of the Angular testing utilities. +It's a function defined in *this guide's sample code*. +All of the sample tests use it. +If you like it, add it to your own collection of helpers. + +Here's the previous test, rewritten using the click helper. + + + +## Component inside a test host + +The previous tests played the role of the host `DashboardComponent` themselves. +But does the `DashboardHeroComponent` work correctly when properly data-bound to a host component? + + + +The test host sets the component's `hero` input property with its test hero. +It binds the component's `selected` event with its `onSelected` handler, which records the emitted hero in its `selectedHero` property. + +Later, the tests will be able to check `selectedHero` to verify that the `DashboardHeroComponent.selected` event emitted the expected hero. + +The setup for the `test-host` tests is similar to the setup for the stand-alone tests: + + + +This testing module configuration shows two important differences: + +* It *creates* the `TestHostComponent` instead of the `DashboardHeroComponent` +* The `TestHostComponent` sets the `DashboardHeroComponent.hero` with a binding + +The `createComponent` returns a `fixture` that holds an instance of `TestHostComponent` instead of an instance of `DashboardHeroComponent`. + +Creating the `TestHostComponent` has the side effect of creating a `DashboardHeroComponent` because the latter appears within the template of the former. +The query for the hero element \(`heroEl`\) still finds it in the test DOM, albeit at greater depth in the element tree than before. + +The tests themselves are almost identical to the stand-alone version: + + + +Only the selected event test differs. +It confirms that the selected `DashboardHeroComponent` hero really does find its way up through the event binding to the host component. + +## Routing component + +A *routing component* is a component that tells the `Router` to navigate to another component. +The `DashboardComponent` is a *routing component* because the user can navigate to the `HeroDetailComponent` by clicking on one of the *hero buttons* on the dashboard. + +Angular provides test helpers to reduce boilerplate and more effectively test code which depends on `HttpClient`. The `provideRouter` function can be used directly in the test module as well. + + + +The following test clicks the displayed hero and confirms that we navigate to the expected URL. + + + +## Routed components + +A *routed component* is the destination of a `Router` navigation. +It can be trickier to test, especially when the route to the component *includes parameters*. +The `HeroDetailComponent` is a *routed component* that is the destination of such a route. + +When a user clicks a *Dashboard* hero, the `DashboardComponent` tells the `Router` to navigate to `heroes/:id`. +The `:id` is a route parameter whose value is the `id` of the hero to edit. + +The `Router` matches that URL to a route to the `HeroDetailComponent`. +It creates an `ActivatedRoute` object with the routing information and injects it into a new instance of the `HeroDetailComponent`. + +Here are the services injected into `HeroDetailComponent`: + + + +The `HeroDetail` component needs the `id` parameter so it can fetch the corresponding hero using the `HeroDetailService`. +The component has to get the `id` from the `ActivatedRoute.paramMap` property which is an `Observable`. + +It can't just reference the `id` property of the `ActivatedRoute.paramMap`. +The component has to *subscribe* to the `ActivatedRoute.paramMap` observable and be prepared for the `id` to change during its lifetime. + + + +Tests can explore how the `HeroDetailComponent` responds to different `id` parameter values by navigating to different routes. + +## Nested component tests + +Component templates often have nested components, whose templates might contain more components. + +The component tree can be very deep and sometimes the nested components play no role in testing the component at the top of the tree. + +The `AppComponent`, for example, displays a navigation bar with anchors and their `RouterLink` directives. + + + +To validate the links but not the navigation, you don't need the `Router` to navigate and you don't need the `` to mark where the `Router` inserts *routed components*. + +The `BannerComponent` and `WelcomeComponent` \(indicated by `` and ``\) are also irrelevant. + +Yet any test that creates the `AppComponent` in the DOM also creates instances of these three components and, if you let that happen, you'll have to configure the `TestBed` to create them. + +If you neglect to declare them, the Angular compiler won't recognize the ``, ``, and `` tags in the `AppComponent` template and will throw an error. + +If you declare the real components, you'll also have to declare *their* nested components and provide for *all* services injected in *any* component in the tree. + +This section describes two techniques for minimizing the setup. +Use them, alone or in combination, to stay focused on testing the primary component. + +### Stubbing unneeded components + +In the first technique, you create and declare stub versions of the components and directive that play little or no role in the tests. + + + +The stub selectors match the selectors for the corresponding real components. +But their templates and classes are empty. + +Then declare them by overriding the `imports` of your component using `TestBed.overrideComponent`. + + + +HELPFUL: The `set` key in this example replaces all the exisiting imports on your component, make sure to imports all dependencies, not only the stubs. Alternatively you can use the `remove`/`add` keys to selectively remove and add imports. + +### `NO_ERRORS_SCHEMA` + +In the second approach, add `NO_ERRORS_SCHEMA` to the metadata overrides of your component. + + + +The `NO_ERRORS_SCHEMA` tells the Angular compiler to ignore unrecognized elements and attributes. + +The compiler recognizes the `` element and the `routerLink` attribute because you declared a corresponding `AppComponent` and `RouterLink` in the `TestBed` configuration. + +But the compiler won't throw an error when it encounters ``, ``, or ``. +It simply renders them as empty tags and the browser ignores them. + +You no longer need the stub components. + +### Use both techniques together + +These are techniques for *Shallow Component Testing*, so-named because they reduce the visual surface of the component to just those elements in the component's template that matter for tests. + +The `NO_ERRORS_SCHEMA` approach is the easier of the two but don't overuse it. + +The `NO_ERRORS_SCHEMA` also prevents the compiler from telling you about the missing components and attributes that you omitted inadvertently or misspelled. +You could waste hours chasing phantom bugs that the compiler would have caught in an instant. + +The *stub component* approach has another advantage. +While the stubs in *this* example were empty, you could give them stripped-down templates and classes if your tests need to interact with them in some way. + +In practice you will combine the two techniques in the same setup, as seen in this example. + + + +The Angular compiler creates the `BannerStubComponent` for the `` element and applies the `RouterLink` to the anchors with the `routerLink` attribute, but it ignores the `` and `` tags. + +### `By.directive` and injected directives + +A little more setup triggers the initial data binding and gets references to the navigation links: + + + +Three points of special interest: + +* Locate the anchor elements with an attached directive using `By.directive` +* The query returns `DebugElement` wrappers around the matching elements +* Each `DebugElement` exposes a dependency injector with the specific instance of the directive attached to that element + +The `AppComponent` links to validate are as follows: + + + +Here are some tests that confirm those links are wired to the `routerLink` directives as expected: + + + +## Use a `page` object + +The `HeroDetailComponent` is a simple view with a title, two hero fields, and two buttons. + +But there's plenty of template complexity even in this simple form. + + + +Tests that exercise the component need … + +* To wait until a hero arrives before elements appear in the DOM +* A reference to the title text +* A reference to the name input box to inspect and set it +* References to the two buttons so they can click them + +Even a small form such as this one can produce a mess of tortured conditional setup and CSS element selection. + +Tame the complexity with a `Page` class that handles access to component properties and encapsulates the logic that sets them. + +Here is such a `Page` class for the `hero-detail.component.spec.ts` + + + +Now the important hooks for component manipulation and inspection are neatly organized and accessible from an instance of `Page`. + +A `createComponent` method creates a `page` object and fills in the blanks once the `hero` arrives. + + + +Here are a few more `HeroDetailComponent` tests to reinforce the point. + + + +## Override component providers + +The `HeroDetailComponent` provides its own `HeroDetailService`. + + + +It's not possible to stub the component's `HeroDetailService` in the `providers` of the `TestBed.configureTestingModule`. +Those are providers for the *testing module*, not the component. +They prepare the dependency injector at the *fixture level*. + +Angular creates the component with its *own* injector, which is a *child* of the fixture injector. +It registers the component's providers \(the `HeroDetailService` in this case\) with the child injector. + +A test cannot get to child injector services from the fixture injector. +And `TestBed.configureTestingModule` can't configure them either. + +Angular has created new instances of the real `HeroDetailService` all along! + +HELPFUL: These tests could fail or timeout if the `HeroDetailService` made its own XHR calls to a remote server. +There might not be a remote server to call. + +Fortunately, the `HeroDetailService` delegates responsibility for remote data access to an injected `HeroService`. + + + +The [previous test configuration](#import-a-feature-module) replaces the real `HeroService` with a `TestHeroService` that intercepts server requests and fakes their responses. + +What if you aren't so lucky. +What if faking the `HeroService` is hard? +What if `HeroDetailService` makes its own server requests? + +The `TestBed.overrideComponent` method can replace the component's `providers` with easy-to-manage *test doubles* as seen in the following setup variation: + + + +Notice that `TestBed.configureTestingModule` no longer provides a fake `HeroService` because it's [not needed](#spy-stub). + +### The `overrideComponent` method + +Focus on the `overrideComponent` method. + + + +It takes two arguments: the component type to override \(`HeroDetailComponent`\) and an override metadata object. +The [override metadata object](guide/testing/utility-apis#metadata-override-object) is a generic defined as follows: + + + +type MetadataOverride = { + add?: Partial; + remove?: Partial; + set?: Partial; +}; + + + +A metadata override object can either add-and-remove elements in metadata properties or completely reset those properties. +This example resets the component's `providers` metadata. + +The type parameter, `T`, is the kind of metadata you'd pass to the `@Component` decorator: + + + +selector?: string; +template?: string; +templateUrl?: string; +providers?: any[]; +… + + + +### Provide a *spy stub* (`HeroDetailServiceSpy`) + +This example completely replaces the component's `providers` array with a new array containing a `HeroDetailServiceSpy`. + +The `HeroDetailServiceSpy` is a stubbed version of the real `HeroDetailService` that fakes all necessary features of that service. +It neither injects nor delegates to the lower level `HeroService` so there's no need to provide a test double for that. + +The related `HeroDetailComponent` tests will assert that methods of the `HeroDetailService` were called by spying on the service methods. +Accordingly, the stub implements its methods as spies: + + + +### The override tests + +Now the tests can control the component's hero directly by manipulating the spy-stub's `testHero` and confirm that service methods were called. + + + +### More overrides + +The `TestBed.overrideComponent` method can be called multiple times for the same or different components. +The `TestBed` offers similar `overrideDirective`, `overrideModule`, and `overridePipe` methods for digging into and replacing parts of these other classes. + +Explore the options and combinations on your own. diff --git a/adev-es/src/content/guide/testing/components-scenarios.md b/adev-es/src/content/guide/testing/components-scenarios.md index 7efc281..976ef8e 100644 --- a/adev-es/src/content/guide/testing/components-scenarios.md +++ b/adev-es/src/content/guide/testing/components-scenarios.md @@ -1,33 +1,33 @@ -# Component testing scenarios +# Escenarios de prueba de componentes -This guide explores common component testing use cases. +Esta guía explora casos de uso comunes de prueba de componentes. -## Component binding +## Binding de componentes -In the example application, the `BannerComponent` presents static title text in the HTML template. +En la aplicación de ejemplo, el `BannerComponent` presenta texto de título estático en la plantilla HTML. -After a few changes, the `BannerComponent` presents a dynamic title by binding to the component's `title` property like this. +Después de algunos cambios, el `BannerComponent` presenta un título dinámico vinculándose a la propiedad `title` del componente como esto. -As minimal as this is, you decide to add a test to confirm that component actually displays the right content where you think it should. +Por mínimo que sea esto, decides agregar una prueba para confirmar que el componente realmente muestra el contenido correcto donde crees que debería. -### Query for the `

` +### Consultar por el `

` -You'll write a sequence of tests that inspect the value of the `

` element that wraps the *title* property interpolation binding. +Escribirás una secuencia de pruebas que inspeccionan el valor del elemento `

` que envuelve el binding de interpolación de la propiedad *title*. -You update the `beforeEach` to find that element with a standard HTML `querySelector` and assign it to the `h1` variable. +Actualizas el `beforeEach` para encontrar ese elemento con un `querySelector` HTML estándar y asignarlo a la variable `h1`. -### `createComponent()` does not bind data +### `createComponent()` no vincula datos -For your first test you'd like to see that the screen displays the default `title`. -Your instinct is to write a test that immediately inspects the `

` like this: +Para tu primera prueba te gustaría ver que la pantalla muestra el `title` predeterminado. +Tu instinto es escribir una prueba que inmediatamente inspecciona el `

` así: -*That test fails* with the message: +*Esa prueba falla* con el mensaje: @@ -35,86 +35,83 @@ expected '' to contain 'Test Tour of Heroes'. -Binding happens when Angular performs **change detection**. +El binding ocurre cuando Angular realiza **detección de cambios**. -In production, change detection kicks in automatically when Angular creates a component or the user enters a keystroke, for example. +En producción, la detección de cambios se activa automáticamente cuando Angular crea un componente o el usuario ingresa una pulsación de tecla, por ejemplo. -The `TestBed.createComponent` does not trigger change detection by default; a fact confirmed in the revised test: +El `TestBed.createComponent` no desencadena detección de cambios por defecto; un hecho confirmado en la prueba revisada: ### `detectChanges()` -You can tell the `TestBed` to perform data binding by calling `fixture.detectChanges()`. -Only then does the `

` have the expected title. +Puedes decirle al `TestBed` que realice binding de datos llamando a `fixture.detectChanges()`. +Solo entonces el `

` tiene el título esperado. -Delayed change detection is intentional and useful. -It gives the tester an opportunity to inspect and change the state of the component *before Angular initiates data binding and calls [lifecycle hooks](guide/components/lifecycle)*. +La detección de cambios retrasada es intencional y útil. +Le da al probador una oportunidad de inspeccionar y cambiar el estado del componente *antes de que Angular inicie el binding de datos y llame a [hooks de ciclo de vida](guide/components/lifecycle)*. -Here's another test that changes the component's `title` property *before* calling `fixture.detectChanges()`. +Aquí hay otra prueba que cambia la propiedad `title` del componente *antes* de llamar a `fixture.detectChanges()`. -### Automatic change detection +### Detección automática de cambios -The `BannerComponent` tests frequently call `detectChanges`. -Many testers prefer that the Angular test environment run change detection automatically like it does in production. +Las pruebas de `BannerComponent` llaman frecuentemente a `detectChanges`. +Muchos probadores prefieren que el entorno de prueba de Angular ejecute la detección de cambios automáticamente como lo hace en producción. -That's possible by configuring the `TestBed` with the `ComponentFixtureAutoDetect` provider. -First import it from the testing utility library: +Eso es posible configurando el `TestBed` con el provider `ComponentFixtureAutoDetect`. +Primero impórtalo de la librería utilitaria de testing: -Then add it to the `providers` array of the testing module configuration: +Luego agrégalo al array `providers` de la configuración del módulo de testing: -HELPFUL: You can also use the `fixture.autoDetectChanges()` function instead if you only want to enable automatic change detection -after making updates to the state of the fixture's component. In addition, automatic change detection is on by default -when using `provideZonelessChangeDetection` and turning it off is not recommended. +ÚTIL: También puedes usar la función `fixture.autoDetectChanges()` en su lugar si solo quieres habilitar la detección automática de cambios después de hacer actualizaciones al estado del componente del fixture. Además, la detección automática de cambios está activada por defecto cuando usas `provideZonelessChangeDetection` y desactivarla no es recomendado. -Here are three tests that illustrate how automatic change detection works. +Aquí hay tres pruebas que ilustran cómo funciona la detección automática de cambios. -The first test shows the benefit of automatic change detection. +La primera prueba muestra el beneficio de la detección automática de cambios. -The second and third test reveal an important limitation. -The Angular testing environment does not run change detection synchronously when updates happen inside the test case that changed the component's `title`. -The test must call `await fixture.whenStable` to wait for another round of change detection. +La segunda y tercera prueba revelan una limitación importante. +El entorno de testing de Angular no ejecuta detección de cambios síncronamente cuando las actualizaciones ocurren dentro del caso de prueba que cambió el `title` del componente. +La prueba debe llamar a `await fixture.whenStable` para esperar otra ronda de detección de cambios. -HELPFUL: Angular does not know about direct updates to values that are not signals. The easiest way to ensure that -change detection will be scheduled is to use signals for values read in the template. +ÚTIL: Angular no sabe sobre actualizaciones directas a valores que no son signals. La forma más fácil de asegurar que la detección de cambios se programe es usar signals para valores leídos en la plantilla. -### Change an input value with `dispatchEvent()` +### Cambiar un valor de input con `dispatchEvent()` -To simulate user input, find the input element and set its `value` property. +Para simular la entrada del usuario, encuentra el elemento input y establece su propiedad `value`. -But there is an essential, intermediate step. +Pero hay un paso esencial, intermedio. -Angular doesn't know that you set the input element's `value` property. -It won't read that property until you raise the element's `input` event by calling `dispatchEvent()`. +Angular no sabe que estableciste la propiedad `value` del elemento input. +No leerá esa propiedad hasta que generes el evento `input` del elemento llamando a `dispatchEvent()`. -The following example demonstrates the proper sequence. +El siguiente ejemplo demuestra la secuencia adecuada. -## Component with external files +## Componente con archivos externos -The preceding `BannerComponent` is defined with an *inline template* and *inline css*, specified in the `@Component.template` and `@Component.styles` properties respectively. +El `BannerComponent` precedente está definido con una *plantilla inline* y *css inline*, especificados en las propiedades `@Component.template` y `@Component.styles` respectivamente. -Many components specify *external templates* and *external css* with the `@Component.templateUrl` and `@Component.styleUrls` properties respectively, as the following variant of `BannerComponent` does. +Muchos componentes especifican *plantillas externas* y *css externo* con las propiedades `@Component.templateUrl` y `@Component.styleUrls` respectivamente, como lo hace la siguiente variante de `BannerComponent`. -This syntax tells the Angular compiler to read the external files during component compilation. +Esta sintaxis le dice al compilador de Angular que lea los archivos externos durante la compilación del componente. -That's not a problem when you run the CLI `ng test` command because it *compiles the application before running the tests*. +Eso no es un problema cuando ejecutas el comando CLI `ng test` porque *compila la aplicación antes de ejecutar las pruebas*. -However, if you run the tests in a **non-CLI environment**, tests of this component might fail. -For example, if you run the `BannerComponent` tests in a web coding environment such as [plunker](https://plnkr.co), you'll see a message like this one: +Sin embargo, si ejecutas las pruebas en un **entorno no-CLI**, las pruebas de este componente podrían fallar. +Por ejemplo, si ejecutas las pruebas de `BannerComponent` en un entorno de codificación web como [plunker](https://plnkr.co), verás un mensaje como este: @@ -124,126 +121,126 @@ Please call "TestBed.compileComponents" before your test. -You get this test failure message when the runtime environment compiles the source code *during the tests themselves*. +Obtienes este mensaje de fallo de prueba cuando el entorno de runtime compila el código fuente *durante las pruebas mismas*. -To correct the problem, call `compileComponents()` as explained in the following [Calling compileComponents](#calling-compilecomponents) section. +Para corregir el problema, llama a `compileComponents()` como se explica en la siguiente sección [Llamando compileComponents](#calling-compilecomponents). -## Component with a dependency +## Componente con una dependencia -Components often have service dependencies. +Los componentes a menudo tienen dependencias de servicio. -The `WelcomeComponent` displays a welcome message to the logged-in user. -It knows who the user is based on a property of the injected `UserService`: +El `WelcomeComponent` muestra un mensaje de bienvenida al usuario autenticado. +Sabe quién es el usuario basado en una propiedad del `UserService` inyectado: -The `WelcomeComponent` has decision logic that interacts with the service, logic that makes this component worth testing. +El `WelcomeComponent` tiene lógica de decisión que interactúa con el servicio, lógica que hace que este componente valga la pena probar. -### Provide service test doubles +### Proporcionar dobles de prueba de servicio -A *component-under-test* doesn't have to be provided with real services. +Un *componente-bajo-prueba* no tiene que ser proporcionado con servicios reales. -Injecting the real `UserService` could be difficult. -The real service might ask the user for login credentials and attempt to reach an authentication server. -These behaviors can be hard to intercept. Be aware that using test doubles makes the test behave differently from production so use them sparingly. +Inyectar el `UserService` real podría ser difícil. +El servicio real podría pedirle al usuario credenciales de inicio de sesión e intentar llegar a un servidor de autenticación. +Estos comportamientos pueden ser difíciles de interceptar. Ten en cuenta que usar dobles de prueba hace que la prueba se comporte diferente de la producción, así que úsalos con moderación. -### Get injected services +### Obtener servicios inyectados -The tests need access to the `UserService` injected into the `WelcomeComponent`. +Las pruebas necesitan acceso al `UserService` inyectado en el `WelcomeComponent`. -Angular has a hierarchical injection system. -There can be injectors at multiple levels, from the root injector created by the `TestBed` down through the component tree. +Angular tiene un sistema de inyección jerárquico. +Puede haber inyectores en múltiples niveles, desde el inyector raíz creado por el `TestBed` hacia abajo a través del árbol de componentes. -The safest way to get the injected service, the way that ***always works***, -is to **get it from the injector of the *component-under-test***. -The component injector is a property of the fixture's `DebugElement`. +La forma más segura de obtener el servicio inyectado, la forma que ***siempre funciona***, +es **obtenerlo del inyector del *componente-bajo-prueba***. +El inyector del componente es una propiedad del `DebugElement` del fixture. -HELPFUL: This is _usually_ not necessary. Services are often provided in the root or the TestBed overrides and can be retrieved more easily with `TestBed.inject()` (see below). +ÚTIL: Esto _usualmente_ no es necesario. Los servicios a menudo se proporcionan en la raíz o los overrides del TestBed y pueden recuperarse más fácilmente con `TestBed.inject()` (ver abajo). ### `TestBed.inject()` -This is easier to remember and less verbose than retrieving a service using the fixture's `DebugElement`. +Esto es más fácil de recordar y menos verboso que recuperar un servicio usando el `DebugElement` del fixture. -In this test suite, the *only* provider of `UserService` is the root testing module, so it is safe to call `TestBed.inject()` as follows: +En esta suite de pruebas, el *único* provider de `UserService` es el módulo de testing raíz, por lo que es seguro llamar a `TestBed.inject()` de la siguiente manera: -HELPFUL: For a use case in which `TestBed.inject()` does not work, see the [*Override component providers*](#override-component-providers) section that explains when and why you must get the service from the component's injector instead. +ÚTIL: Para un caso de uso en el que `TestBed.inject()` no funciona, consulta la sección [*Override component providers*](#override-component-providers) que explica cuándo y por qué debes obtener el servicio del inyector del componente en su lugar. -### Final setup and tests +### Configuración final y pruebas -Here's the complete `beforeEach()`, using `TestBed.inject()`: +Aquí está el `beforeEach()` completo, usando `TestBed.inject()`: -And here are some tests: +Y aquí hay algunas pruebas: -The first is a sanity test; it confirms that the `UserService` is called and working. +La primera es una prueba de cordura; confirma que el `UserService` es llamado y funciona. -HELPFUL: The withContext function \(for example, `'expected name'`\) is an optional failure label. -If the expectation fails, Jasmine appends this label to the expectation failure message. -In a spec with multiple expectations, it can help clarify what went wrong and which expectation failed. +ÚTIL: La función withContext \(por ejemplo, `'expected name'`\) es una etiqueta de fallo opcional. +Si la expectativa falla, Jasmine agrega esta etiqueta al mensaje de fallo de expectativa. +En una spec con múltiples expectativas, puede ayudar a aclarar qué salió mal y qué expectativa falló. -The remaining tests confirm the logic of the component when the service returns different values. -The second test validates the effect of changing the user name. -The third test checks that the component displays the proper message when there is no logged-in user. +Las pruebas restantes confirman la lógica del componente cuando el servicio retorna diferentes valores. +La segunda prueba valida el efecto de cambiar el nombre del usuario. +La tercera prueba verifica que el componente muestra el mensaje apropiado cuando no hay usuario autenticado. -## Component with async service +## Componente con servicio async -In this sample, the `AboutComponent` template hosts a `TwainComponent`. -The `TwainComponent` displays Mark Twain quotes. +En esta muestra, la plantilla `AboutComponent` aloja un `TwainComponent`. +El `TwainComponent` muestra citas de Mark Twain. -HELPFUL: The value of the component's `quote` property passes through an `AsyncPipe`. -That means the property returns either a `Promise` or an `Observable`. +ÚTIL: El valor de la propiedad `quote` del componente pasa a través de un `AsyncPipe`. +Eso significa que la propiedad retorna ya sea una `Promise` o un `Observable`. -In this example, the `TwainComponent.getQuote()` method tells you that the `quote` property returns an `Observable`. +En este ejemplo, el método `TwainComponent.getQuote()` te dice que la propiedad `quote` retorna un `Observable`. -The `TwainComponent` gets quotes from an injected `TwainService`. -The component starts the returned `Observable` with a placeholder value \(`'...'`\), before the service can return its first quote. +El `TwainComponent` obtiene citas de un `TwainService` inyectado. +El componente inicia el `Observable` retornado con un valor placeholder \(`'...'`\), antes de que el servicio pueda retornar su primera cita. -The `catchError` intercepts service errors, prepares an error message, and returns the placeholder value on the success channel. +El `catchError` intercepta errores de servicio, prepara un mensaje de error, y retorna el valor placeholder en el canal de éxito. -These are all features you'll want to test. +Estas son todas características que querrás probar. -### Testing with a spy +### Probar con un spy -When testing a component, only the service's public API should matter. -In general, tests themselves should not make calls to remote servers. -They should emulate such calls. -The setup in this `app/twain/twain.component.spec.ts` shows one way to do that: +Cuando se prueba un componente, solo la API pública del servicio debería importar. +En general, las pruebas mismas no deberían hacer llamadas a servidores remotos. +Deberían emular tales llamadas. +La configuración en este `app/twain/twain.component.spec.ts` muestra una forma de hacerlo: -Focus on the spy. +Enfócate en el spy. -The spy is designed such that any call to `getQuote` receives an observable with a test quote. -Unlike the real `getQuote()` method, this spy bypasses the server and returns a synchronous observable whose value is available immediately. +El spy está diseñado de tal manera que cualquier llamada a `getQuote` recibe un observable con una cita de prueba. +A diferencia del método `getQuote()` real, este spy evita el servidor y retorna un observable síncrono cuyo valor está disponible inmediatamente. -You can write many useful tests with this spy, even though its `Observable` is synchronous. +Puedes escribir muchas pruebas útiles con este spy, aunque su `Observable` sea síncrono. -HELPFUL: It is best to limit the usage of spies to only what is necessary for the test. Creating mocks or spies for more than what's necessary can be brittle. As the component and injectable evolves, the unrelated tests can fail because they no longer mock enough behaviors that would otherwise not affect the test. +ÚTIL: Es mejor limitar el uso de spies solo a lo que es necesario para la prueba. Crear mocks o spies para más de lo necesario puede ser frágil. A medida que el componente e injectable evolucionan, las pruebas no relacionadas pueden fallar porque ya no simulan suficientes comportamientos que de otro modo no afectarían la prueba. -### Async test with `fakeAsync()` +### Prueba async con `fakeAsync()` -To use `fakeAsync()` functionality, you must import `zone.js/testing` in your test setup file. -If you created your project with the Angular CLI, `zone-testing` is already imported in `src/test.ts`. +Para usar la funcionalidad `fakeAsync()`, debes importar `zone.js/testing` en tu archivo de configuración de pruebas. +Si creaste tu proyecto con Angular CLI, `zone-testing` ya está importado en `src/test.ts`. -The following test confirms the expected behavior when the service returns an `ErrorObservable`. +La siguiente prueba confirma el comportamiento esperado cuando el servicio retorna un `ErrorObservable`. -HELPFUL: The `it()` function receives an argument of the following form. +ÚTIL: La función `it()` recibe un argumento de la siguiente forma. @@ -251,59 +248,57 @@ fakeAsync(() => { /*test body*/ }) -The `fakeAsync()` function enables a linear coding style by running the test body in a special `fakeAsync test zone`. -The test body appears to be synchronous. -There is no nested syntax \(like a `Promise.then()`\) to disrupt the flow of control. +La función `fakeAsync()` habilita un estilo de codificación lineal ejecutando el cuerpo de la prueba en una `fakeAsync test zone` especial. +El cuerpo de la prueba aparece ser síncrono. +No hay sintaxis anidada \(como un `Promise.then()`\) para interrumpir el flujo de control. -HELPFUL: Limitation: The `fakeAsync()` function won't work if the test body makes an `XMLHttpRequest` \(XHR\) call. -XHR calls within a test are rare, but if you need to call XHR, see the [`waitForAsync()`](#waitForAsync) section. +ÚTIL: Limitación: La función `fakeAsync()` no funcionará si el cuerpo de la prueba hace una llamada `XMLHttpRequest` \(XHR\). +Las llamadas XHR dentro de una prueba son raras, pero si necesitas llamar XHR, consulta la sección [`waitForAsync()`](#waitForAsync). -IMPORTANT: Be aware that asynchronous tasks that happen inside the `fakeAsync` zone need to be manually executed with `flush` or `tick`. If you attempt to -wait for them to complete (i.e. using `fixture.whenStable`) without using the -`fakeAsync` test helpers to advance time, your test will likely fail. See below for more information. +IMPORTANTE: Ten en cuenta que las tareas asíncronas que ocurren dentro de la zona `fakeAsync` necesitan ejecutarse manualmente con `flush` o `tick`. Si intentas esperar a que se completen (es decir, usando `fixture.whenStable`) sin usar los helpers de prueba `fakeAsync` para avanzar el tiempo, tu prueba probablemente fallará. Ver abajo para más información. -### The `tick()` function +### La función `tick()` -You do have to call [tick()](api/core/testing/tick) to advance the virtual clock. +Tienes que llamar a [tick()](api/core/testing/tick) para avanzar el reloj virtual. -Calling [tick()](api/core/testing/tick) simulates the passage of time until all pending asynchronous activities finish. -In this case, it waits for the observable's `setTimeout()`. +Llamar a [tick()](api/core/testing/tick) simula el paso del tiempo hasta que todas las actividades asíncronas pendientes terminen. +En este caso, espera al `setTimeout()` del observable. -The [tick()](api/core/testing/tick) function accepts `millis` and `tickOptions` as parameters. The `millis` parameter specifies how much the virtual clock advances and defaults to `0` if not provided. -For example, if you have a `setTimeout(fn, 100)` in a `fakeAsync()` test, you need to use `tick(100)` to trigger the fn callback. -The optional `tickOptions` parameter has a property named `processNewMacroTasksSynchronously`. The `processNewMacroTasksSynchronously` property represents whether to invoke new generated macro tasks when ticking and defaults to `true`. +La función [tick()](api/core/testing/tick) acepta `millis` y `tickOptions` como parámetros. El parámetro `millis` especifica cuánto avanza el reloj virtual y por defecto es `0` si no se proporciona. +Por ejemplo, si tienes un `setTimeout(fn, 100)` en una prueba `fakeAsync()`, necesitas usar `tick(100)` para desencadenar el callback fn. +El parámetro opcional `tickOptions` tiene una propiedad llamada `processNewMacroTasksSynchronously`. La propiedad `processNewMacroTasksSynchronously` representa si invocar nuevas macro tasks generadas al hacer tick y por defecto es `true`. -The [tick()](api/core/testing/tick) function is one of the Angular testing utilities that you import with `TestBed`. -It's a companion to `fakeAsync()` and you can only call it within a `fakeAsync()` body. +La función [tick()](api/core/testing/tick) es una de las utilidades de testing de Angular que importas con `TestBed`. +Es una compañera de `fakeAsync()` y solo puedes llamarla dentro de un cuerpo `fakeAsync()`. ### tickOptions -In this example, you have a new macro task, the nested `setTimeout` function. By default, when the `tick` is setTimeout, `outside` and `nested` will both be triggered. +En este ejemplo, tienes una nueva macro task, la función `setTimeout` anidada. Por defecto, cuando el `tick` es setTimeout, tanto `outside` como `nested` se desencadenarán. -In some case, you don't want to trigger the new macro task when ticking. You can use `tick(millis, {processNewMacroTasksSynchronously: false})` to not invoke a new macro task. +En algunos casos, no quieres desencadenar la nueva macro task al hacer tick. Puedes usar `tick(millis, {processNewMacroTasksSynchronously: false})` para no invocar una nueva macro task. -### Comparing dates inside fakeAsync() +### Comparar fechas dentro de fakeAsync() -`fakeAsync()` simulates passage of time, which lets you calculate the difference between dates inside `fakeAsync()`. +`fakeAsync()` simula el paso del tiempo, lo que te permite calcular la diferencia entre fechas dentro de `fakeAsync()`. -### jasmine.clock with fakeAsync() +### jasmine.clock con fakeAsync() -Jasmine also provides a `clock` feature to mock dates. -Angular automatically runs tests that are run after `jasmine.clock().install()` is called inside a `fakeAsync()` method until `jasmine.clock().uninstall()` is called. -`fakeAsync()` is not needed and throws an error if nested. +Jasmine también proporciona una característica `clock` para simular fechas. +Angular ejecuta automáticamente pruebas que se ejecutan después de que se llame `jasmine.clock().install()` dentro de un método `fakeAsync()` hasta que se llame `jasmine.clock().uninstall()`. +`fakeAsync()` no es necesario y lanza un error si se anida. -By default, this feature is disabled. -To enable it, set a global flag before importing `zone-testing`. +Por defecto, esta característica está deshabilitada. +Para habilitarla, establece una bandera global antes de importar `zone-testing`. -If you use the Angular CLI, configure this flag in `src/test.ts`. +Si usas Angular CLI, configura esta bandera en `src/test.ts`. @@ -314,15 +309,15 @@ import 'zone.js/testing'; -### Using the RxJS scheduler inside fakeAsync() +### Usar el scheduler de RxJS dentro de fakeAsync() -You can also use RxJS scheduler in `fakeAsync()` just like using `setTimeout()` or `setInterval()`, but you need to import `zone.js/plugins/zone-patch-rxjs-fake-async` to patch RxJS scheduler. +También puedes usar el scheduler de RxJS en `fakeAsync()` igual que usando `setTimeout()` o `setInterval()`, pero necesitas importar `zone.js/plugins/zone-patch-rxjs-fake-async` para parchear el scheduler de RxJS. -### Support more macroTasks +### Soportar más macroTasks -By default, `fakeAsync()` supports the following macro tasks. +Por defecto, `fakeAsync()` soporta las siguientes macro tasks. * `setTimeout` * `setInterval` @@ -330,433 +325,433 @@ By default, `fakeAsync()` supports the following macro tasks. * `webkitRequestAnimationFrame` * `mozRequestAnimationFrame` -If you run other macro tasks such as `HTMLCanvasElement.toBlob()`, an *"Unknown macroTask scheduled in fake async test"* error is thrown. +Si ejecutas otras macro tasks como `HTMLCanvasElement.toBlob()`, se lanza un error *"Unknown macroTask scheduled in fake async test"*. -If you want to support such a case, you need to define the macro task you want to support in `beforeEach()`. -For example: +Si quieres soportar tal caso, necesitas definir la macro task que quieres soportar en `beforeEach()`. +Por ejemplo: -HELPFUL: In order to make the `` element Zone.js-aware in your app, you need to import the `zone-patch-canvas` patch \(either in `polyfills.ts` or in the specific file that uses ``\): +ÚTIL: Para hacer que el elemento `` sea Zone.js-aware en tu aplicación, necesitas importar el parche `zone-patch-canvas` \(ya sea en `polyfills.ts` o en el archivo específico que usa ``\): -### Async observables +### Observables async -You might be satisfied with the test coverage of these tests. +Podrías estar satisfecho con la cobertura de prueba de estas pruebas. -However, you might be troubled by the fact that the real service doesn't quite behave this way. -The real service sends requests to a remote server. -A server takes time to respond and the response certainly won't be available immediately as in the previous two tests. +Sin embargo, podrías estar preocupado por el hecho de que el servicio real no se comporta exactamente de esta manera. +El servicio real envía solicitudes a un servidor remoto. +Un servidor toma tiempo en responder y la respuesta ciertamente no estará disponible inmediatamente como en las dos pruebas anteriores. -Your tests will reflect the real world more faithfully if you return an *asynchronous* observable from the `getQuote()` spy like this. +Tus pruebas reflejarán el mundo real más fielmente si retornas un observable *asíncrono* del spy `getQuote()` así. -### Async observable helpers +### Helpers de observable async -The async observable was produced by an `asyncData` helper. -The `asyncData` helper is a utility function that you'll have to write yourself, or copy this one from the sample code. +El observable async fue producido por un helper `asyncData`. +El helper `asyncData` es una función utilitaria que tendrás que escribir tú mismo, o copiar esta de el código de muestra. -This helper's observable emits the `data` value in the next turn of the JavaScript engine. +El observable de este helper emite el valor `data` en el siguiente turno del motor de JavaScript. -The [RxJS `defer()` operator](http://reactivex.io/documentation/operators/defer.html) returns an observable. -It takes a factory function that returns either a promise or an observable. -When something subscribes to *defer*'s observable, it adds the subscriber to a new observable created with that factory. +El [operador `defer()` de RxJS](http://reactivex.io/documentation/operators/defer.html) retorna un observable. +Toma una función factory que retorna ya sea una promesa o un observable. +Cuando algo se suscribe al observable de *defer*, agrega el suscriptor a un nuevo observable creado con esa factory. -The `defer()` operator transforms the `Promise.resolve()` into a new observable that, like `HttpClient`, emits once and completes. -Subscribers are unsubscribed after they receive the data value. +El operador `defer()` transforma el `Promise.resolve()` en un nuevo observable que, como `HttpClient`, emite una vez y se completa. +Los suscriptores se desuscriben después de recibir el valor de datos. -There's a similar helper for producing an async error. +Hay un helper similar para producir un error async. -### More async tests +### Más pruebas async -Now that the `getQuote()` spy is returning async observables, most of your tests will have to be async as well. +Ahora que el spy `getQuote()` está retornando observables async, la mayoría de tus pruebas tendrán que ser async también. -Here's a `fakeAsync()` test that demonstrates the data flow you'd expect in the real world. +Aquí hay una prueba `fakeAsync()` que demuestra el flujo de datos que esperarías en el mundo real. -Notice that the quote element displays the placeholder value \(`'...'`\) after `ngOnInit()`. -The first quote hasn't arrived yet. +Nota que el elemento quote muestra el valor placeholder \(`'...'`\) después de `ngOnInit()`. +La primera cita aún no ha llegado. -To flush the first quote from the observable, you call [tick()](api/core/testing/tick). -Then call `detectChanges()` to tell Angular to update the screen. +Para vaciar la primera cita del observable, llamas a [tick()](api/core/testing/tick). +Luego llamas a `detectChanges()` para decirle a Angular que actualice la pantalla. -Then you can assert that the quote element displays the expected text. +Entonces puedes afirmar que el elemento quote muestra el texto esperado. -### Async test without `fakeAsync()` +### Prueba async sin `fakeAsync()` -Here's the previous `fakeAsync()` test, re-written with the `async`. +Aquí está la prueba `fakeAsync()` anterior, reescrita con el `async`. ### `whenStable` -The test must wait for the `getQuote()` observable to emit the next quote. -Instead of calling [tick()](api/core/testing/tick), it calls `fixture.whenStable()`. +La prueba debe esperar a que el observable `getQuote()` emita la siguiente cita. +En lugar de llamar a [tick()](api/core/testing/tick), llama a `fixture.whenStable()`. -The `fixture.whenStable()` returns a promise that resolves when the JavaScript engine's task queue becomes empty. -In this example, the task queue becomes empty when the observable emits the first quote. +El `fixture.whenStable()` retorna una promesa que se resuelve cuando la cola de tareas del motor de JavaScript se vuelve vacía. +En este ejemplo, la cola de tareas se vuelve vacía cuando el observable emite la primera cita. -## Component with inputs and outputs +## Componente con inputs y outputs -A component with inputs and outputs typically appears inside the view template of a host component. -The host uses a property binding to set the input property and an event binding to listen to events raised by the output property. +Un componente con inputs y outputs típicamente aparece dentro de la plantilla de vista de un componente host. +El host usa un property binding para establecer la propiedad input y un event binding para escuchar eventos generados por la propiedad output. -The testing goal is to verify that such bindings work as expected. -The tests should set input values and listen for output events. +El objetivo de testing es verificar que tales bindings funcionen como se espera. +Las pruebas deberían establecer valores de input y escuchar eventos de output. -The `DashboardHeroComponent` is a tiny example of a component in this role. -It displays an individual hero provided by the `DashboardComponent`. -Clicking that hero tells the `DashboardComponent` that the user has selected the hero. +El `DashboardHeroComponent` es un pequeño ejemplo de un componente en este rol. +Muestra un héroe individual proporcionado por el `DashboardComponent`. +Hacer clic en ese héroe le dice al `DashboardComponent` que el usuario ha seleccionado el héroe. -The `DashboardHeroComponent` is embedded in the `DashboardComponent` template like this: +El `DashboardHeroComponent` está incrustado en la plantilla `DashboardComponent` así: -The `DashboardHeroComponent` appears in an `@for` block, which sets each component's `hero` input property to the looping value and listens for the component's `selected` event. +El `DashboardHeroComponent` aparece en un bloque `@for`, que establece la propiedad input `hero` de cada componente al valor de bucle y escucha el evento `selected` del componente. -Here's the component's full definition: +Aquí está la definición completa del componente: -While testing a component this simple has little intrinsic value, it's worth knowing how. -Use one of these approaches: +Aunque probar un componente tan simple tiene poco valor intrínseco, vale la pena saber cómo. +Usa uno de estos enfoques: -* Test it as used by `DashboardComponent` -* Test it as a standalone component -* Test it as used by a substitute for `DashboardComponent` +* Probarlo como se usa por `DashboardComponent` +* Probarlo como un componente standalone +* Probarlo como se usa por un sustituto para `DashboardComponent` -The immediate goal is to test the `DashboardHeroComponent`, not the `DashboardComponent`, so, try the second and third options. +El objetivo inmediato es probar el `DashboardHeroComponent`, no el `DashboardComponent`, así que, prueba la segunda y tercera opciones. -### Test `DashboardHeroComponent` standalone +### Probar `DashboardHeroComponent` standalone -Here's the meat of the spec file setup. +Aquí está la parte principal de la configuración del archivo spec. -Notice how the setup code assigns a test hero \(`expectedHero`\) to the component's `hero` property, emulating the way the `DashboardComponent` would set it using the property binding in its repeater. +Nota cómo el código de configuración asigna un héroe de prueba \(`expectedHero`\) a la propiedad `hero` del componente, emulando la forma en que el `DashboardComponent` lo establecería usando el property binding en su repeater. -The following test verifies that the hero name is propagated to the template using a binding. +La siguiente prueba verifica que el nombre del héroe se propaga a la plantilla usando un binding. -Because the [template](#dashboard-hero-component) passes the hero name through the Angular `UpperCasePipe`, the test must match the element value with the upper-cased name. +Porque la [plantilla](#dashboard-hero-component) pasa el nombre del héroe a través del `UpperCasePipe` de Angular, la prueba debe coincidir el valor del elemento con el nombre en mayúsculas. -### Clicking +### Hacer clic -Clicking the hero should raise a `selected` event that the host component \(`DashboardComponent` presumably\) can hear: +Hacer clic en el héroe debería generar un evento `selected` que el componente host \(`DashboardComponent` presumiblemente\) puede escuchar: -The component's `selected` property returns an `EventEmitter`, which looks like an RxJS synchronous `Observable` to consumers. -The test subscribes to it *explicitly* just as the host component does *implicitly*. +La propiedad `selected` del componente retorna un `EventEmitter`, que se ve como un `Observable` síncrono de RxJS para los consumidores. +La prueba se suscribe a él *explícitamente* igual que el componente host lo hace *implícitamente*. -If the component behaves as expected, clicking the hero's element should tell the component's `selected` property to emit the `hero` object. +Si el componente se comporta como se espera, hacer clic en el elemento del héroe debería decirle a la propiedad `selected` del componente que emita el objeto `hero`. -The test detects that event through its subscription to `selected`. +La prueba detecta ese evento a través de su suscripción a `selected`. ### `triggerEventHandler` -The `heroDe` in the previous test is a `DebugElement` that represents the hero `
`. +El `heroDe` en la prueba anterior es un `DebugElement` que representa el `
` del héroe. -It has Angular properties and methods that abstract interaction with the native element. -This test calls the `DebugElement.triggerEventHandler` with the "click" event name. -The "click" event binding responds by calling `DashboardHeroComponent.click()`. +Tiene propiedades y métodos de Angular que abstraen la interacción con el elemento nativo. +Esta prueba llama al `DebugElement.triggerEventHandler` con el nombre de evento "click". +El binding de evento "click" responde llamando a `DashboardHeroComponent.click()`. -The Angular `DebugElement.triggerEventHandler` can raise *any data-bound event* by its *event name*. -The second parameter is the event object passed to the handler. +El `DebugElement.triggerEventHandler` de Angular puede generar *cualquier evento vinculado a datos* por su *nombre de evento*. +El segundo parámetro es el objeto de evento pasado al handler. -The test triggered a "click" event. +La prueba desencadenó un evento "click". -In this case, the test correctly assumes that the runtime event handler, the component's `click()` method, doesn't care about the event object. +En este caso, la prueba asume correctamente que el handler de evento de runtime, el método `click()` del componente, no se preocupa por el objeto de evento. -HELPFUL: Other handlers are less forgiving. -For example, the `RouterLink` directive expects an object with a `button` property that identifies which mouse button, if any, was pressed during the click. -The `RouterLink` directive throws an error if the event object is missing. +ÚTIL: Otros handlers son menos indulgentes. +Por ejemplo, la directiva `RouterLink` espera un objeto con una propiedad `button` que identifica qué botón del mouse, si alguno, fue presionado durante el clic. +La directiva `RouterLink` lanza un error si el objeto de evento falta. -### Click the element +### Hacer clic en el elemento -The following test alternative calls the native element's own `click()` method, which is perfectly fine for *this component*. +La siguiente alternativa de prueba llama al método `click()` propio del elemento nativo, que es perfectamente fino para *este componente*. -### `click()` helper +### Helper `click()` -Clicking a button, an anchor, or an arbitrary HTML element is a common test task. +Hacer clic en un botón, un anchor, o un elemento HTML arbitrario es una tarea de prueba común. -Make that consistent and straightforward by encapsulating the *click-triggering* process in a helper such as the following `click()` function: +Haz eso consistente y directo encapsulando el proceso *click-triggering* en un helper como la siguiente función `click()`: -The first parameter is the *element-to-click*. -If you want, pass a custom event object as the second parameter. -The default is a partial [left-button mouse event object](https://developer.mozilla.org/docs/Web/API/MouseEvent/button) accepted by many handlers including the `RouterLink` directive. +El primer parámetro es el *elemento-a-hacer-clic*. +Si quieres, pasa un objeto de evento personalizado como segundo parámetro. +El predeterminado es un [objeto de evento de mouse de botón izquierdo](https://developer.mozilla.org/docs/Web/API/MouseEvent/button) parcial aceptado por muchos handlers incluyendo la directiva `RouterLink`. -IMPORTANT: The `click()` helper function is **not** one of the Angular testing utilities. -It's a function defined in *this guide's sample code*. -All of the sample tests use it. -If you like it, add it to your own collection of helpers. +IMPORTANTE: La función helper `click()` **no** es una de las utilidades de testing de Angular. +Es una función definida en el *código de muestra de esta guía*. +Todas las pruebas de muestra la usan. +Si te gusta, agrégala a tu propia colección de helpers. -Here's the previous test, rewritten using the click helper. +Aquí está la prueba anterior, reescrita usando el helper click. -## Component inside a test host +## Componente dentro de un test host -The previous tests played the role of the host `DashboardComponent` themselves. -But does the `DashboardHeroComponent` work correctly when properly data-bound to a host component? +Las pruebas anteriores jugaron el rol del `DashboardComponent` host ellas mismas. +¿Pero funciona correctamente el `DashboardHeroComponent` cuando está correctamente vinculado a datos a un componente host? -The test host sets the component's `hero` input property with its test hero. -It binds the component's `selected` event with its `onSelected` handler, which records the emitted hero in its `selectedHero` property. +El test host establece la propiedad input `hero` del componente con su héroe de prueba. +Vincula el evento `selected` del componente con su handler `onSelected`, que registra el héroe emitido en su propiedad `selectedHero`. -Later, the tests will be able to check `selectedHero` to verify that the `DashboardHeroComponent.selected` event emitted the expected hero. +Más tarde, las pruebas podrán verificar `selectedHero` para verificar que el evento `DashboardHeroComponent.selected` emitió el héroe esperado. -The setup for the `test-host` tests is similar to the setup for the stand-alone tests: +La configuración para las pruebas `test-host` es similar a la configuración para las pruebas standalone: -This testing module configuration shows two important differences: +Esta configuración de módulo de testing muestra dos diferencias importantes: -* It *creates* the `TestHostComponent` instead of the `DashboardHeroComponent` -* The `TestHostComponent` sets the `DashboardHeroComponent.hero` with a binding +* *Crea* el `TestHostComponent` en lugar del `DashboardHeroComponent` +* El `TestHostComponent` establece el `DashboardHeroComponent.hero` con un binding -The `createComponent` returns a `fixture` that holds an instance of `TestHostComponent` instead of an instance of `DashboardHeroComponent`. +El `createComponent` retorna un `fixture` que contiene una instancia de `TestHostComponent` en lugar de una instancia de `DashboardHeroComponent`. -Creating the `TestHostComponent` has the side effect of creating a `DashboardHeroComponent` because the latter appears within the template of the former. -The query for the hero element \(`heroEl`\) still finds it in the test DOM, albeit at greater depth in the element tree than before. +Crear el `TestHostComponent` tiene el efecto secundario de crear un `DashboardHeroComponent` porque este último aparece dentro de la plantilla del primero. +La consulta para el elemento héroe \(`heroEl`\) aún lo encuentra en el DOM de prueba, aunque a mayor profundidad en el árbol de elementos que antes. -The tests themselves are almost identical to the stand-alone version: +Las pruebas mismas son casi idénticas a la versión standalone: -Only the selected event test differs. -It confirms that the selected `DashboardHeroComponent` hero really does find its way up through the event binding to the host component. +Solo la prueba de evento selected difiere. +Confirma que el héroe `DashboardHeroComponent` seleccionado realmente encuentra su camino hacia arriba a través del event binding al componente host. -## Routing component +## Componente de enrutamiento -A *routing component* is a component that tells the `Router` to navigate to another component. -The `DashboardComponent` is a *routing component* because the user can navigate to the `HeroDetailComponent` by clicking on one of the *hero buttons* on the dashboard. +Un *componente de enrutamiento* es un componente que le dice al `Router` que navegue a otro componente. +El `DashboardComponent` es un *componente de enrutamiento* porque el usuario puede navegar al `HeroDetailComponent` haciendo clic en uno de los *botones de héroe* en el dashboard. -Angular provides test helpers to reduce boilerplate and more effectively test code which depends on `HttpClient`. The `provideRouter` function can be used directly in the test module as well. +Angular proporciona helpers de prueba para reducir boilerplate y probar más efectivamente código que depende de `HttpClient`. La función `provideRouter` puede usarse directamente en el módulo de prueba también. -The following test clicks the displayed hero and confirms that we navigate to the expected URL. +La siguiente prueba hace clic en el héroe mostrado y confirma que navegamos a la URL esperada. -## Routed components +## Componentes enrutados -A *routed component* is the destination of a `Router` navigation. -It can be trickier to test, especially when the route to the component *includes parameters*. -The `HeroDetailComponent` is a *routed component* that is the destination of such a route. +Un *componente enrutado* es el destino de una navegación `Router`. +Puede ser más difícil de probar, especialmente cuando la ruta al componente *incluye parámetros*. +El `HeroDetailComponent` es un *componente enrutado* que es el destino de tal ruta. -When a user clicks a *Dashboard* hero, the `DashboardComponent` tells the `Router` to navigate to `heroes/:id`. -The `:id` is a route parameter whose value is the `id` of the hero to edit. +Cuando un usuario hace clic en un héroe de *Dashboard*, el `DashboardComponent` le dice al `Router` que navegue a `heroes/:id`. +El `:id` es un parámetro de ruta cuyo valor es el `id` del héroe a editar. -The `Router` matches that URL to a route to the `HeroDetailComponent`. -It creates an `ActivatedRoute` object with the routing information and injects it into a new instance of the `HeroDetailComponent`. +El `Router` coincide esa URL con una ruta al `HeroDetailComponent`. +Crea un objeto `ActivatedRoute` con la información de enrutamiento y lo inyecta en una nueva instancia del `HeroDetailComponent`. -Here are the services injected into `HeroDetailComponent`: +Aquí están los servicios inyectados en `HeroDetailComponent`: -The `HeroDetail` component needs the `id` parameter so it can fetch the corresponding hero using the `HeroDetailService`. -The component has to get the `id` from the `ActivatedRoute.paramMap` property which is an `Observable`. +El componente `HeroDetail` necesita el parámetro `id` para poder obtener el héroe correspondiente usando el `HeroDetailService`. +El componente tiene que obtener el `id` de la propiedad `ActivatedRoute.paramMap` que es un `Observable`. -It can't just reference the `id` property of the `ActivatedRoute.paramMap`. -The component has to *subscribe* to the `ActivatedRoute.paramMap` observable and be prepared for the `id` to change during its lifetime. +No puede simplemente referenciar la propiedad `id` del `ActivatedRoute.paramMap`. +El componente tiene que *suscribirse* al observable `ActivatedRoute.paramMap` y estar preparado para que el `id` cambie durante su vida útil. -Tests can explore how the `HeroDetailComponent` responds to different `id` parameter values by navigating to different routes. +Las pruebas pueden explorar cómo el `HeroDetailComponent` responde a diferentes valores de parámetro `id` navegando a diferentes rutas. -## Nested component tests +## Pruebas de componentes anidados -Component templates often have nested components, whose templates might contain more components. +Las plantillas de componentes a menudo tienen componentes anidados, cuyas plantillas podrían contener más componentes. -The component tree can be very deep and sometimes the nested components play no role in testing the component at the top of the tree. +El árbol de componentes puede ser muy profundo y a veces los componentes anidados no juegan ningún rol en probar el componente en la parte superior del árbol. -The `AppComponent`, for example, displays a navigation bar with anchors and their `RouterLink` directives. +El `AppComponent`, por ejemplo, muestra una barra de navegación con anchors y sus directivas `RouterLink`. -To validate the links but not the navigation, you don't need the `Router` to navigate and you don't need the `` to mark where the `Router` inserts *routed components*. +Para validar los enlaces pero no la navegación, no necesitas el `Router` para navegar y no necesitas el `` para marcar dónde el `Router` inserta *componentes enrutados*. -The `BannerComponent` and `WelcomeComponent` \(indicated by `` and ``\) are also irrelevant. +El `BannerComponent` y `WelcomeComponent` \(indicados por `` y ``\) también son irrelevantes. -Yet any test that creates the `AppComponent` in the DOM also creates instances of these three components and, if you let that happen, you'll have to configure the `TestBed` to create them. +Sin embargo, cualquier prueba que cree el `AppComponent` en el DOM también crea instancias de estos tres componentes y, si dejas que eso suceda, tendrás que configurar el `TestBed` para crearlos. -If you neglect to declare them, the Angular compiler won't recognize the ``, ``, and `` tags in the `AppComponent` template and will throw an error. +Si descuidas declararlos, el compilador de Angular no reconocerá las etiquetas ``, `` y `` en la plantilla `AppComponent` y lanzará un error. -If you declare the real components, you'll also have to declare *their* nested components and provide for *all* services injected in *any* component in the tree. +Si declaras los componentes reales, también tendrás que declarar *sus* componentes anidados y proporcionar *todos* los servicios inyectados en *cualquier* componente en el árbol. -This section describes two techniques for minimizing the setup. -Use them, alone or in combination, to stay focused on testing the primary component. +Esta sección describe dos técnicas para minimizar la configuración. +Úsalas, solas o en combinación, para mantener el foco en probar el componente primario. -### Stubbing unneeded components +### Hacer stub de componentes innecesarios -In the first technique, you create and declare stub versions of the components and directive that play little or no role in the tests. +En la primera técnica, creas y declaras versiones stub de los componentes y directiva que juegan poco o ningún rol en las pruebas. -The stub selectors match the selectors for the corresponding real components. -But their templates and classes are empty. +Los selectores stub coinciden con los selectores para los componentes reales correspondientes. +Pero sus plantillas y clases están vacías. -Then declare them by overriding the `imports` of your component using `TestBed.overrideComponent`. +Luego declár alos sobrescribiendo los `imports` de tu componente usando `TestBed.overrideComponent`. -HELPFUL: The `set` key in this example replaces all the exisiting imports on your component, make sure to imports all dependencies, not only the stubs. Alternatively you can use the `remove`/`add` keys to selectively remove and add imports. +ÚTIL: La clave `set` en este ejemplo reemplaza todos los imports existentes en tu componente, asegúrate de importar todas las dependencias, no solo los stubs. Alternativamente puedes usar las claves `remove`/`add` para remover y agregar imports selectivamente. ### `NO_ERRORS_SCHEMA` -In the second approach, add `NO_ERRORS_SCHEMA` to the metadata overrides of your component. +En el segundo enfoque, agrega `NO_ERRORS_SCHEMA` a los overrides de metadata de tu componente. -The `NO_ERRORS_SCHEMA` tells the Angular compiler to ignore unrecognized elements and attributes. +El `NO_ERRORS_SCHEMA` le dice al compilador de Angular que ignore elementos y atributos no reconocidos. -The compiler recognizes the `` element and the `routerLink` attribute because you declared a corresponding `AppComponent` and `RouterLink` in the `TestBed` configuration. +El compilador reconoce el elemento `` y el atributo `routerLink` porque declaraste un `AppComponent` y `RouterLink` correspondientes en la configuración del `TestBed`. -But the compiler won't throw an error when it encounters ``, ``, or ``. -It simply renders them as empty tags and the browser ignores them. +Pero el compilador no lanzará un error cuando encuentre ``, `` o ``. +Simplemente los renderiza como etiquetas vacías y el navegador los ignora. -You no longer need the stub components. +Ya no necesitas los componentes stub. -### Use both techniques together +### Usar ambas técnicas juntas -These are techniques for *Shallow Component Testing*, so-named because they reduce the visual surface of the component to just those elements in the component's template that matter for tests. +Estas son técnicas para *Shallow Component Testing*, llamadas así porque reducen la superficie visual del componente solo a aquellos elementos en la plantilla del componente que importan para las pruebas. -The `NO_ERRORS_SCHEMA` approach is the easier of the two but don't overuse it. +El enfoque `NO_ERRORS_SCHEMA` es el más fácil de los dos pero no lo uses en exceso. -The `NO_ERRORS_SCHEMA` also prevents the compiler from telling you about the missing components and attributes that you omitted inadvertently or misspelled. -You could waste hours chasing phantom bugs that the compiler would have caught in an instant. +El `NO_ERRORS_SCHEMA` también evita que el compilador te diga sobre los componentes y atributos faltantes que omitiste inadvertidamente o escribiste mal. +Podrías desperdiciar horas persiguiendo bugs fantasma que el compilador habría capturado en un instante. -The *stub component* approach has another advantage. -While the stubs in *this* example were empty, you could give them stripped-down templates and classes if your tests need to interact with them in some way. +El enfoque de *componente stub* tiene otra ventaja. +Aunque los stubs en *este* ejemplo están vacíos, podrías darles plantillas y clases reducidas si tus pruebas necesitan interactuar con ellos de alguna manera. -In practice you will combine the two techniques in the same setup, as seen in this example. +En la práctica combinarás las dos técnicas en la misma configuración, como se ve en este ejemplo. -The Angular compiler creates the `BannerStubComponent` for the `` element and applies the `RouterLink` to the anchors with the `routerLink` attribute, but it ignores the `` and `` tags. +El compilador de Angular crea el `BannerStubComponent` para el elemento `` y aplica el `RouterLink` a los anchors con el atributo `routerLink`, pero ignora las etiquetas `` y ``. -### `By.directive` and injected directives +### `By.directive` y directivas inyectadas -A little more setup triggers the initial data binding and gets references to the navigation links: +Un poco más de configuración desencadena el binding de datos inicial y obtiene referencias a los enlaces de navegación: -Three points of special interest: +Tres puntos de interés especial: -* Locate the anchor elements with an attached directive using `By.directive` -* The query returns `DebugElement` wrappers around the matching elements -* Each `DebugElement` exposes a dependency injector with the specific instance of the directive attached to that element +* Localizar los elementos anchor con una directiva adjunta usando `By.directive` +* La consulta retorna wrappers `DebugElement` alrededor de los elementos coincidentes +* Cada `DebugElement` expone un inyector de dependencias con la instancia específica de la directiva adjunta a ese elemento -The `AppComponent` links to validate are as follows: +Los enlaces del `AppComponent` a validar son los siguientes: -Here are some tests that confirm those links are wired to the `routerLink` directives as expected: +Aquí hay algunas pruebas que confirman que esos enlaces están conectados a las directivas `routerLink` como se espera: -## Use a `page` object +## Usar un objeto `page` -The `HeroDetailComponent` is a simple view with a title, two hero fields, and two buttons. +El `HeroDetailComponent` es una vista simple con un título, dos campos de héroe y dos botones. -But there's plenty of template complexity even in this simple form. +Pero hay bastante complejidad de plantilla incluso en este formulario simple. -Tests that exercise the component need … +Las pruebas que ejercitan el componente necesitan… -* To wait until a hero arrives before elements appear in the DOM -* A reference to the title text -* A reference to the name input box to inspect and set it -* References to the two buttons so they can click them +* Esperar hasta que un héroe llegue antes de que los elementos aparezcan en el DOM +* Una referencia al texto del título +* Una referencia al cuadro de entrada de nombre para inspeccionarlo y establecerlo +* Referencias a los dos botones para poder hacer clic en ellos -Even a small form such as this one can produce a mess of tortured conditional setup and CSS element selection. +Incluso un formulario pequeño como este puede producir un lío de configuración condicional tortuosa y selección de elementos CSS. -Tame the complexity with a `Page` class that handles access to component properties and encapsulates the logic that sets them. +Domestica la complejidad con una clase `Page` que maneja el acceso a las propiedades del componente y encapsula la lógica que las establece. -Here is such a `Page` class for the `hero-detail.component.spec.ts` +Aquí hay tal clase `Page` para el `hero-detail.component.spec.ts` -Now the important hooks for component manipulation and inspection are neatly organized and accessible from an instance of `Page`. +Ahora los hooks importantes para manipulación e inspección de componentes están organizados ordenadamente y son accesibles desde una instancia de `Page`. -A `createComponent` method creates a `page` object and fills in the blanks once the `hero` arrives. +Un método `createComponent` crea un objeto `page` y llena los espacios en blanco una vez que el `hero` llega. -Here are a few more `HeroDetailComponent` tests to reinforce the point. +Aquí hay algunas pruebas más de `HeroDetailComponent` para reforzar el punto. ## Override component providers -The `HeroDetailComponent` provides its own `HeroDetailService`. +El `HeroDetailComponent` proporciona su propio `HeroDetailService`. -It's not possible to stub the component's `HeroDetailService` in the `providers` of the `TestBed.configureTestingModule`. -Those are providers for the *testing module*, not the component. -They prepare the dependency injector at the *fixture level*. +No es posible hacer stub del `HeroDetailService` del componente en los `providers` del `TestBed.configureTestingModule`. +Esos son providers para el *módulo de testing*, no el componente. +Preparan el inyector de dependencias en el *nivel del fixture*. -Angular creates the component with its *own* injector, which is a *child* of the fixture injector. -It registers the component's providers \(the `HeroDetailService` in this case\) with the child injector. +Angular crea el componente con su *propio* inyector, que es un *hijo* del inyector del fixture. +Registra los providers del componente \(el `HeroDetailService` en este caso\) con el inyector hijo. -A test cannot get to child injector services from the fixture injector. -And `TestBed.configureTestingModule` can't configure them either. +Una prueba no puede llegar a servicios del inyector hijo desde el inyector del fixture. +Y `TestBed.configureTestingModule` tampoco puede configurarlos. -Angular has created new instances of the real `HeroDetailService` all along! +¡Angular ha creado nuevas instancias del `HeroDetailService` real todo el tiempo! -HELPFUL: These tests could fail or timeout if the `HeroDetailService` made its own XHR calls to a remote server. -There might not be a remote server to call. +ÚTIL: Estas pruebas podrían fallar o agotar el tiempo de espera si el `HeroDetailService` hiciera sus propias llamadas XHR a un servidor remoto. +Podría no haber un servidor remoto al cual llamar. -Fortunately, the `HeroDetailService` delegates responsibility for remote data access to an injected `HeroService`. +Afortunadamente, el `HeroDetailService` delega responsabilidad para acceso a datos remotos a un `HeroService` inyectado. -The [previous test configuration](#import-a-feature-module) replaces the real `HeroService` with a `TestHeroService` that intercepts server requests and fakes their responses. +La [configuración de prueba anterior](#import-a-feature-module) reemplaza el `HeroService` real con un `TestHeroService` que intercepta solicitudes de servidor y falsifica sus respuestas. -What if you aren't so lucky. -What if faking the `HeroService` is hard? -What if `HeroDetailService` makes its own server requests? +¿Qué pasa si no tienes tanta suerte? +¿Qué pasa si falsificar el `HeroService` es difícil? +¿Qué pasa si `HeroDetailService` hace sus propias solicitudes de servidor? -The `TestBed.overrideComponent` method can replace the component's `providers` with easy-to-manage *test doubles* as seen in the following setup variation: +El método `TestBed.overrideComponent` puede reemplazar los `providers` del componente con *test doubles* fáciles de manejar como se ve en la siguiente variación de configuración: -Notice that `TestBed.configureTestingModule` no longer provides a fake `HeroService` because it's [not needed](#spy-stub). +Nota que `TestBed.configureTestingModule` ya no proporciona un `HeroService` falso porque [no es necesario](#spy-stub). -### The `overrideComponent` method +### El método `overrideComponent` -Focus on the `overrideComponent` method. +Enfócate en el método `overrideComponent`. -It takes two arguments: the component type to override \(`HeroDetailComponent`\) and an override metadata object. -The [override metadata object](guide/testing/utility-apis#metadata-override-object) is a generic defined as follows: +Toma dos argumentos: el tipo de componente a sobrescribir \(`HeroDetailComponent`\) y un objeto de metadata de override. +El [objeto de metadata de override](guide/testing/utility-apis#metadata-override-object) es un genérico definido como sigue: @@ -768,10 +763,10 @@ type MetadataOverride = { -A metadata override object can either add-and-remove elements in metadata properties or completely reset those properties. -This example resets the component's `providers` metadata. +Un objeto de metadata override puede agregar-y-remover elementos en propiedades de metadata o restablecer completamente esas propiedades. +Este ejemplo restablece los metadata `providers` del componente. -The type parameter, `T`, is the kind of metadata you'd pass to the `@Component` decorator: +El parámetro de tipo, `T`, es el tipo de metadata que pasarías al decorador `@Component`: @@ -783,27 +778,27 @@ providers?: any[]; -### Provide a *spy stub* (`HeroDetailServiceSpy`) +### Proporcionar un *spy stub* (`HeroDetailServiceSpy`) -This example completely replaces the component's `providers` array with a new array containing a `HeroDetailServiceSpy`. +Este ejemplo reemplaza completamente el array `providers` del componente con un nuevo array que contiene un `HeroDetailServiceSpy`. -The `HeroDetailServiceSpy` is a stubbed version of the real `HeroDetailService` that fakes all necessary features of that service. -It neither injects nor delegates to the lower level `HeroService` so there's no need to provide a test double for that. +El `HeroDetailServiceSpy` es una versión stubbed del `HeroDetailService` real que falsifica todas las características necesarias de ese servicio. +No inyecta ni delega al `HeroService` de nivel inferior, por lo que no hay necesidad de proporcionar un test double para eso. -The related `HeroDetailComponent` tests will assert that methods of the `HeroDetailService` were called by spying on the service methods. -Accordingly, the stub implements its methods as spies: +Las pruebas relacionadas con `HeroDetailComponent` afirmarán que los métodos del `HeroDetailService` fueron llamados espiando en los métodos del servicio. +En consecuencia, el stub implementa sus métodos como spies: -### The override tests +### Las pruebas override -Now the tests can control the component's hero directly by manipulating the spy-stub's `testHero` and confirm that service methods were called. +Ahora las pruebas pueden controlar el héroe del componente directamente manipulando el `testHero` del spy-stub y confirmar que los métodos del servicio fueron llamados. -### More overrides +### Más overrides -The `TestBed.overrideComponent` method can be called multiple times for the same or different components. -The `TestBed` offers similar `overrideDirective`, `overrideModule`, and `overridePipe` methods for digging into and replacing parts of these other classes. +El método `TestBed.overrideComponent` puede llamarse múltiples veces para los mismos o diferentes componentes. +El `TestBed` ofrece métodos similares `overrideDirective`, `overrideModule` y `overridePipe` para profundizar y reemplazar partes de estas otras clases. -Explore the options and combinations on your own. +Explora las opciones y combinaciones por tu cuenta. diff --git a/adev-es/src/content/guide/testing/creating-component-harnesses.en.md b/adev-es/src/content/guide/testing/creating-component-harnesses.en.md new file mode 100644 index 0000000..622305a --- /dev/null +++ b/adev-es/src/content/guide/testing/creating-component-harnesses.en.md @@ -0,0 +1,277 @@ +# Creating harnesses for your components + +## Before you start + +TIP: This guide assumes you've already read the [component harnesses overview guide](guide/testing/component-harnesses-overview). Read that first if you're new to using component harnesses. + +### When does creating a test harness make sense? + +The Angular team recommends creating component test harnesses for shared components that are used in many places and have some user interactivity. This most commonly applies to widget libraries and similar reusable components. Harnesses are valuable for these cases because they provide the consumers of these shared components a well- supported API for interacting with a component. Tests that use harnesses can avoid depending on unreliable implementation details of these shared components, such as DOM structure and specific event listeners. + +For components that appear in only one place, such as a page in an application, harnesses don't provide as much benefit. In these situations, a component's tests can reasonably depend on the implementation details of this component, as the tests and components are updated at the same time. However, harnesses still provide some value if you would use the harness in both unit and end-to-end tests. + +### CDK Installation + +The [Component Dev Kit (CDK)](https://material.angular.dev/cdk/categories) is a set of behavior primitives for building components. To use the component harnesses, first install `@angular/cdk` from npm. You can do this from your terminal using the Angular CLI: + + + ng add @angular/cdk + + +## Extending `ComponentHarness` + +The abstract `ComponentHarness` class is the base class for all component harnesses. To create a custom component harness, extend `ComponentHarness` and implement the static property `hostSelector`. + +The `hostSelector` property identifies elements in the DOM that match this harness subclass. In most cases, the `hostSelector` should be the same as the selector of the corresponding `Component` or `Directive`. For example, consider a simple popup component: + + +@Component({ + selector: 'my-popup', + template: ` + + @if (isOpen()) { +
+ } + ` +}) +class MyPopup { + triggerText = input(''); + + isOpen = signal(false); + + toggle() { + this.isOpen.update((value) => !value); + } +} +
+ +In this case, a minimal harness for the component would look like the following: + + +class MyPopupHarness extends ComponentHarness { + static hostSelector = 'my-popup'; +} + + +While `ComponentHarness` subclasses require only the `hostSelector` property, most harnesses should also implement a static `with` method to generate `HarnessPredicate` instances. The [filtering harnesses section](guide/testing/using-component-harnesses#filtering-harnesses) covers this in more detail. + +## Finding elements in the component's DOM + +Each instance of a `ComponentHarness` subclass represents a particular instance of the corresponding component. You can access the component's host element via the `host() `method from the `ComponentHarness` base class. + +`ComponentHarness` also offers several methods for locating elements within the component's DOM. These methods are `locatorFor()`, `locatorForOptional()`, and `locatorForAll()`. These methods create functions that find elements, they do not directly find elements. This approach safeguards against caching references to out-of-date elements. For example, when an `@if` block hides and then shows an element, the result is a new DOM element; using functions ensures that tests always reference the current state of the DOM. + +See the [ComponentHarness API reference page](/api/cdk/testing/ComponentHarness) for the full list details of the different `locatorFor` methods. + +For example, the `MyPopupHarness` example discussed above could provide methods to get the trigger and content elements as follows: + + +class MyPopupHarness extends ComponentHarness { + static hostSelector = 'my-popup'; + + // Gets the trigger element + getTriggerElement = this.locatorFor('button'); + + // Gets the content element. + getContentElement = this.locatorForOptional('.my-popup-content'); +} + + +## Working with `TestElement` instances + +`TestElement` is an abstraction designed to work across different test environments (Unit tests, WebDriver, etc). When using harnesses, you should perform all DOM interaction via this interface. Other means of accessing DOM elements, such as `document.querySelector()`, do not work in all test environments. + +`TestElement` has a number of methods to interact with the underlying DOM, such as `blur()`, `click()`, `getAttribute()`, and more. See the [TestElement API reference page](/api/cdk/testing/TestElement) for the full list of methods. + +Do not expose `TestElement` instances to harness users unless it's an element the component consumer defines directly, such as the component's host element. Exposing `TestElement` instances for internal elements leads users to depend on a component's internal DOM structure. + +Instead, provide more narrow-focused methods for specific actions the end-user may take or particular state they may observe. For example, `MyPopupHarness` from previous sections could provide methods like `toggle` and `isOpen`: + + +class MyPopupHarness extends ComponentHarness { + static hostSelector = 'my-popup'; + + protected getTriggerElement = this.locatorFor('button'); + protected getContentElement = this.locatorForOptional('.my-popup-content'); + + /** Toggles the open state of the popup. */ + async toggle() { + const trigger = await this.getTriggerElement(); + return trigger.click(); + } + + /** Checks if the popup us open. */ + async isOpen() { + const content = await this.getContentElement(); + return !!content; + } +} + + +## Loading harnesses for subcomponents + +Larger components often compose sub-components. You can reflect this structure in a component's harness as well. Each of the `locatorFor` methods on `ComponentHarness` has an alternate signature that can be used for locating sub-harnesses rather than elements. + +See the [ComponentHarness API reference page](/api/cdk/testing/ComponentHarness) for the full list of the different locatorFor methods. + +For example, consider a menu build using the popup from above: + + +@Directive({ + selector: 'my-menu-item' +}) +class MyMenuItem {} + +@Component({ + selector: 'my-menu', + template: ` + + + + ` +}) +class MyMenu { + triggerText = input(''); + + @ContentChildren(MyMenuItem) items: QueryList; +} + + +The harness for `MyMenu` can then take advantage of other harnesses for `MyPopup` and `MyMenuItem`: + + +class MyMenuHarness extends ComponentHarness { + static hostSelector = 'my-menu'; + + protected getPopupHarness = this.locatorFor(MyPopupHarness); + + /** Gets the currently shown menu items (empty list if menu is closed). */ + getItems = this.locatorForAll(MyMenuItemHarness); + + /** Toggles open state of the menu. */ + async toggle() { + const popupHarness = await this.getPopupHarness(); + return popupHarness.toggle(); + } +} + +class MyMenuItemHarness extends ComponentHarness { + static hostSelector = 'my-menu-item'; +} + + +## Filtering harness instances with `HarnessPredicate` + +When a page contains multiple instances of a particular component, you may want to filter based on some property of the component to get a particular component instance. For example, you may want a button with some specific text, or a menu with a specific ID. The `HarnessPredicate` class can capture criteria like this for a `ComponentHarness` subclass. While the test author is able to construct `HarnessPredicate` instances manually, it's easier when the `ComponentHarness` subclass provides a helper method to construct predicates for common filters. + +You should create a static `with()` method on each `ComponentHarness` subclass that returns a `HarnessPredicate` for that class. This allows test authors to write easily understandable code, e.g. `loader.getHarness(MyMenuHarness.with({selector: '#menu1'}))`. In addition to the standard selector and ancestor options, the `with` method should add any other options that make sense for the particular subclass. + +Harnesses that need to add additional options should extend the `BaseHarnessFilters` interface and additional optional properties as needed. `HarnessPredicate` provides several convenience methods for adding options: `stringMatches()`, `addOption()`, and `add()`. See the [HarnessPredicate API page](/api/cdk/testing/HarnessPredicate) for the full description. + +For example, when working with a menu it is useful to filter based on trigger text and to filter menu items based on their text: + + +interface MyMenuHarnessFilters extends BaseHarnessFilters { + /** Filters based on the trigger text for the menu. */ + triggerText?: string | RegExp; +} + +interface MyMenuItemHarnessFilters extends BaseHarnessFilters { + /** Filters based on the text of the menu item. */ + text?: string | RegExp; +} + +class MyMenuHarness extends ComponentHarness { + static hostSelector = 'my-menu'; + + /** Creates a `HarnessPredicate` used to locate a particular `MyMenuHarness`. */ + static with(options: MyMenuHarnessFilters): HarnessPredicate { + return new HarnessPredicate(MyMenuHarness, options) + .addOption('trigger text', options.triggerText, + (harness, text) => HarnessPredicate.stringMatches(harness.getTriggerText(), text)); + } + + protected getPopupHarness = this.locatorFor(MyPopupHarness); + + /** Gets the text of the menu trigger. */ + async getTriggerText(): Promise { + const popupHarness = await this.getPopupHarness(); + return popupHarness.getTriggerText(); + } + ... +} + +class MyMenuItemHarness extends ComponentHarness { + static hostSelector = 'my-menu-item'; + + /** Creates a `HarnessPredicate` used to locate a particular `MyMenuItemHarness`. */ + static with(options: MyMenuItemHarnessFilters): HarnessPredicate { + return new HarnessPredicate(MyMenuItemHarness, options) + .addOption('text', options.text, + (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text)); + } + + /** Gets the text of the menu item. */ + async getText(): Promise { + const host = await this.host(); + return host.text(); + } +} + + +You can pass a `HarnessPredicate` instead of a `ComponentHarness` class to any of the APIs on `HarnessLoader`, `LocatorFactory`, or `ComponentHarness`. This allows test authors to easily target a particular component instance when creating a harness instance. It also allows the harness author to leverage the same `HarnessPredicate` to enable more powerful APIs on their harness class. For example, consider the `getItems` method on the `MyMenuHarness` shown above. Adding a filtering API allows users of the harness to search for particular menu items: + + +class MyMenuHarness extends ComponentHarness { + static hostSelector = 'my-menu'; + + /** Gets a list of items in the menu, optionally filtered based on the given criteria. */ + async getItems(filters: MyMenuItemHarnessFilters = {}): Promise { + const getFilteredItems = this.locatorForAll(MyMenuItemHarness.with(filters)); + return getFilteredItems(); + } + ... +} + + +## Creating `HarnessLoader` for elements that use content projection + +Some components project additional content into the component's template. See the [content projection guide](guide/components/content-projection) for more information. + +Add a `HarnessLoader` instance scoped to the element containing the `` when you create a harness for a component that uses content projection. This allows the user of the harness to load additional harnesses for whatever components were passed in as content. `ComponentHarness` has several methods that can be used to create HarnessLoader instances for cases like this: `harnessLoaderFor()`, `harnessLoaderForOptional()`, `harnessLoaderForAll()`. See the [HarnessLoader interface API reference page](/api/cdk/testing/HarnessLoader) for more details. + +For example, the `MyPopupHarness` example from above can extend `ContentContainerComponentHarness` to add support to load harnesses within the `` of the component. + + +class MyPopupHarness extends ContentContainerComponentHarness { + static hostSelector = 'my-popup'; +} + + +## Accessing elements outside of the component's host element + +There are times when a component harness might need to access elements outside of its corresponding component's host element. For example, code that displays a floating element or pop-up often attaches DOM elements directly to the document body, such as the `Overlay` service in Angular CDK. + +In this case, `ComponentHarness` provides a method that can be used to get a `LocatorFactory` for the root element of the document. The `LocatorFactory` supports most of the same APIs as the `ComponentHarness` base class, and can then be used to query relative to the document's root element. + +Consider if the `MyPopup` component above used the CDK overlay for the popup content, rather than an element in its own template. In this case, `MyPopupHarness` would have to access the content element via `documentRootLocatorFactory()` method that gets a locator factory rooted at the document root. + + +class MyPopupHarness extends ComponentHarness { + static hostSelector = 'my-popup'; + + /** Gets a `HarnessLoader` whose root element is the popup's content element. */ + async getHarnessLoaderForContent(): Promise { + const rootLocator = this.documentRootLocatorFactory(); + return rootLocator.harnessLoaderFor('my-popup-content'); + } +} + + +## Waiting for asynchronous tasks + +The methods on `TestElement` automatically trigger Angular's change detection and wait for tasks inside the `NgZone`. In most cases no special effort is required for harness authors to wait on asynchronous tasks. However, there are some edge cases where this may not be sufficient. + +Under some circumstances, Angular animations may require a second cycle of change detection and subsequent `NgZone` stabilization before animation events are fully flushed. In cases where this is needed, the `ComponentHarness` offers a `forceStabilize()` method that can be called to do the second round. + +You can use `NgZone.runOutsideAngular()` to schedule tasks outside of NgZone. Call the `waitForTasksOutsideAngular()` method on the corresponding harness if you need to explicitly wait for tasks outside `NgZone` since this does not happen automatically. diff --git a/adev-es/src/content/guide/testing/creating-component-harnesses.md b/adev-es/src/content/guide/testing/creating-component-harnesses.md index 622305a..338fd28 100644 --- a/adev-es/src/content/guide/testing/creating-component-harnesses.md +++ b/adev-es/src/content/guide/testing/creating-component-harnesses.md @@ -1,28 +1,28 @@ -# Creating harnesses for your components +# Crear harnesses para tus componentes -## Before you start +## Antes de comenzar -TIP: This guide assumes you've already read the [component harnesses overview guide](guide/testing/component-harnesses-overview). Read that first if you're new to using component harnesses. +CONSEJO: Esta guía asume que ya leíste la [guía de visión general de component harnesses](guide/testing/component-harnesses-overview). Lee eso primero si eres nuevo en el uso de component harnesses. -### When does creating a test harness make sense? +### ¿Cuándo tiene sentido crear un test harness? -The Angular team recommends creating component test harnesses for shared components that are used in many places and have some user interactivity. This most commonly applies to widget libraries and similar reusable components. Harnesses are valuable for these cases because they provide the consumers of these shared components a well- supported API for interacting with a component. Tests that use harnesses can avoid depending on unreliable implementation details of these shared components, such as DOM structure and specific event listeners. +El equipo de Angular recomienda crear component test harnesses para componentes compartidos que se usan en muchos lugares y tienen algo de interactividad de usuario. Esto comúnmente aplica a librerías de widgets y componentes reutilizables similares. Los harnesses son valiosos para estos casos porque proporcionan a los consumidores de estos componentes compartidos una API bien soportada para interactuar con un componente. Las pruebas que usan harnesses pueden evitar depender de detalles de implementación poco confiables de estos componentes compartidos, como estructura DOM y event listeners específicos. -For components that appear in only one place, such as a page in an application, harnesses don't provide as much benefit. In these situations, a component's tests can reasonably depend on the implementation details of this component, as the tests and components are updated at the same time. However, harnesses still provide some value if you would use the harness in both unit and end-to-end tests. +Para componentes que aparecen en solo un lugar, como una página en una aplicación, los harnesses no proporcionan tanto beneficio. En estas situaciones, las pruebas de un componente pueden razonablemente depender de los detalles de implementación de este componente, ya que las pruebas y componentes se actualizan al mismo tiempo. Sin embargo, los harnesses aún proporcionan algo de valor si usarías el harness en pruebas tanto unitarias como end-to-end. -### CDK Installation +### Instalación del CDK -The [Component Dev Kit (CDK)](https://material.angular.dev/cdk/categories) is a set of behavior primitives for building components. To use the component harnesses, first install `@angular/cdk` from npm. You can do this from your terminal using the Angular CLI: +El [Component Dev Kit (CDK)](https://material.angular.dev/cdk/categories) es un conjunto de primitivas de comportamiento para construir componentes. Para usar los component harnesses, primero instala `@angular/cdk` desde npm. Puedes hacer esto desde tu terminal usando Angular CLI: ng add @angular/cdk -## Extending `ComponentHarness` +## Extender `ComponentHarness` -The abstract `ComponentHarness` class is the base class for all component harnesses. To create a custom component harness, extend `ComponentHarness` and implement the static property `hostSelector`. +La clase abstracta `ComponentHarness` es la clase base para todos los component harnesses. Para crear un component harness personalizado, extiende `ComponentHarness` e implementa la propiedad estática `hostSelector`. -The `hostSelector` property identifies elements in the DOM that match this harness subclass. In most cases, the `hostSelector` should be the same as the selector of the corresponding `Component` or `Directive`. For example, consider a simple popup component: +La propiedad `hostSelector` identifica elementos en el DOM que coinciden con esta subclase harness. En la mayoría de los casos, el `hostSelector` debería ser el mismo que el selector del `Component` o `Directive` correspondiente. Por ejemplo, considera un componente popup simple: @Component({ @@ -45,7 +45,7 @@ class MyPopup { } -In this case, a minimal harness for the component would look like the following: +En este caso, un harness mínimo para el componente se vería como lo siguiente: class MyPopupHarness extends ComponentHarness { @@ -53,39 +53,39 @@ class MyPopupHarness extends ComponentHarness { } -While `ComponentHarness` subclasses require only the `hostSelector` property, most harnesses should also implement a static `with` method to generate `HarnessPredicate` instances. The [filtering harnesses section](guide/testing/using-component-harnesses#filtering-harnesses) covers this in more detail. +Aunque las subclases de `ComponentHarness` requieren solo la propiedad `hostSelector`, la mayoría de los harnesses también deberían implementar un método estático `with` para generar instancias de `HarnessPredicate`. La [sección de filtrar harnesses](guide/testing/using-component-harnesses#filtering-harnesses) cubre esto con más detalle. -## Finding elements in the component's DOM +## Encontrar elementos en el DOM del componente -Each instance of a `ComponentHarness` subclass represents a particular instance of the corresponding component. You can access the component's host element via the `host() `method from the `ComponentHarness` base class. +Cada instancia de una subclase de `ComponentHarness` representa una instancia particular del componente correspondiente. Puedes acceder al elemento host del componente a través del método `host()` de la clase base `ComponentHarness`. -`ComponentHarness` also offers several methods for locating elements within the component's DOM. These methods are `locatorFor()`, `locatorForOptional()`, and `locatorForAll()`. These methods create functions that find elements, they do not directly find elements. This approach safeguards against caching references to out-of-date elements. For example, when an `@if` block hides and then shows an element, the result is a new DOM element; using functions ensures that tests always reference the current state of the DOM. +`ComponentHarness` también ofrece varios métodos para localizar elementos dentro del DOM del componente. Estos métodos son `locatorFor()`, `locatorForOptional()` y `locatorForAll()`. Estos métodos crean funciones que encuentran elementos, no encuentran elementos directamente. Este enfoque protege contra el almacenamiento en caché de referencias a elementos desactualizados. Por ejemplo, cuando un bloque `@if` oculta y luego muestra un elemento, el resultado es un nuevo elemento DOM; usar funciones asegura que las pruebas siempre referencien el estado actual del DOM. -See the [ComponentHarness API reference page](/api/cdk/testing/ComponentHarness) for the full list details of the different `locatorFor` methods. +Consulta la [página de referencia de la API de ComponentHarness](/api/cdk/testing/ComponentHarness) para la lista completa de detalles de los diferentes métodos `locatorFor`. -For example, the `MyPopupHarness` example discussed above could provide methods to get the trigger and content elements as follows: +Por ejemplo, el ejemplo `MyPopupHarness` discutido arriba podría proporcionar métodos para obtener los elementos trigger y content como sigue: class MyPopupHarness extends ComponentHarness { static hostSelector = 'my-popup'; - // Gets the trigger element + // Obtiene el elemento trigger getTriggerElement = this.locatorFor('button'); - // Gets the content element. + // Obtiene el elemento content. getContentElement = this.locatorForOptional('.my-popup-content'); } -## Working with `TestElement` instances +## Trabajar con instancias de `TestElement` -`TestElement` is an abstraction designed to work across different test environments (Unit tests, WebDriver, etc). When using harnesses, you should perform all DOM interaction via this interface. Other means of accessing DOM elements, such as `document.querySelector()`, do not work in all test environments. +`TestElement` es una abstracción diseñada para trabajar en diferentes entornos de prueba (Pruebas unitarias, WebDriver, etc). Al usar harnesses, deberías realizar toda interacción DOM a través de esta interfaz. Otros medios de acceder a elementos DOM, como `document.querySelector()`, no funcionan en todos los entornos de prueba. -`TestElement` has a number of methods to interact with the underlying DOM, such as `blur()`, `click()`, `getAttribute()`, and more. See the [TestElement API reference page](/api/cdk/testing/TestElement) for the full list of methods. +`TestElement` tiene una cantidad de métodos para interactuar con el DOM subyacente, como `blur()`, `click()`, `getAttribute()` y más. Consulta la [página de referencia de la API de TestElement](/api/cdk/testing/TestElement) para la lista completa de métodos. -Do not expose `TestElement` instances to harness users unless it's an element the component consumer defines directly, such as the component's host element. Exposing `TestElement` instances for internal elements leads users to depend on a component's internal DOM structure. +No expongas instancias de `TestElement` a usuarios de harness a menos que sea un elemento que el consumidor del componente define directamente, como el elemento host del componente. Exponer instancias de `TestElement` para elementos internos lleva a los usuarios a depender de la estructura DOM interna de un componente. -Instead, provide more narrow-focused methods for specific actions the end-user may take or particular state they may observe. For example, `MyPopupHarness` from previous sections could provide methods like `toggle` and `isOpen`: +En su lugar, proporciona métodos más enfocados para acciones específicas que el usuario final puede tomar o estado particular que pueden observar. Por ejemplo, `MyPopupHarness` de secciones anteriores podría proporcionar métodos como `toggle` e `isOpen`: class MyPopupHarness extends ComponentHarness { @@ -94,13 +94,13 @@ class MyPopupHarness extends ComponentHarness { protected getTriggerElement = this.locatorFor('button'); protected getContentElement = this.locatorForOptional('.my-popup-content'); - /** Toggles the open state of the popup. */ + /** Alterna el estado abierto del popup. */ async toggle() { const trigger = await this.getTriggerElement(); return trigger.click(); } - /** Checks if the popup us open. */ + /** Verifica si el popup está abierto. */ async isOpen() { const content = await this.getContentElement(); return !!content; @@ -108,13 +108,13 @@ class MyPopupHarness extends ComponentHarness { } -## Loading harnesses for subcomponents +## Cargar harnesses para subcomponentes -Larger components often compose sub-components. You can reflect this structure in a component's harness as well. Each of the `locatorFor` methods on `ComponentHarness` has an alternate signature that can be used for locating sub-harnesses rather than elements. +Los componentes más grandes a menudo componen subcomponentes. Puedes reflejar esta estructura en el harness de un componente también. Cada uno de los métodos `locatorFor` en `ComponentHarness` tiene una firma alternativa que puede usarse para localizar sub-harnesses en lugar de elementos. -See the [ComponentHarness API reference page](/api/cdk/testing/ComponentHarness) for the full list of the different locatorFor methods. +Consulta la [página de referencia de la API de ComponentHarness](/api/cdk/testing/ComponentHarness) para la lista completa de los diferentes métodos locatorFor. -For example, consider a menu build using the popup from above: +Por ejemplo, considera un menú construido usando el popup de arriba: @Directive({ @@ -137,7 +137,7 @@ class MyMenu { } -The harness for `MyMenu` can then take advantage of other harnesses for `MyPopup` and `MyMenuItem`: +El harness para `MyMenu` puede entonces aprovechar otros harnesses para `MyPopup` y `MyMenuItem`: class MyMenuHarness extends ComponentHarness { @@ -145,10 +145,10 @@ class MyMenuHarness extends ComponentHarness { protected getPopupHarness = this.locatorFor(MyPopupHarness); - /** Gets the currently shown menu items (empty list if menu is closed). */ + /** Obtiene los items de menú actualmente mostrados (lista vacía si el menú está cerrado). */ getItems = this.locatorForAll(MyMenuItemHarness); - /** Toggles open state of the menu. */ + /** Alterna el estado abierto del menú. */ async toggle() { const popupHarness = await this.getPopupHarness(); return popupHarness.toggle(); @@ -160,31 +160,31 @@ class MyMenuItemHarness extends ComponentHarness { } -## Filtering harness instances with `HarnessPredicate` +## Filtrar instancias de harness con `HarnessPredicate` -When a page contains multiple instances of a particular component, you may want to filter based on some property of the component to get a particular component instance. For example, you may want a button with some specific text, or a menu with a specific ID. The `HarnessPredicate` class can capture criteria like this for a `ComponentHarness` subclass. While the test author is able to construct `HarnessPredicate` instances manually, it's easier when the `ComponentHarness` subclass provides a helper method to construct predicates for common filters. +Cuando una página contiene múltiples instancias de un componente particular, es posible que quieras filtrar basado en alguna propiedad del componente para obtener una instancia de componente particular. Por ejemplo, es posible que quieras un botón con algún texto específico, o un menú con un ID específico. La clase `HarnessPredicate` puede capturar criterios como este para una subclase de `ComponentHarness`. Aunque el autor de la prueba puede construir instancias de `HarnessPredicate` manualmente, es más fácil cuando la subclase de `ComponentHarness` proporciona un método helper para construir predicates para filtros comunes. -You should create a static `with()` method on each `ComponentHarness` subclass that returns a `HarnessPredicate` for that class. This allows test authors to write easily understandable code, e.g. `loader.getHarness(MyMenuHarness.with({selector: '#menu1'}))`. In addition to the standard selector and ancestor options, the `with` method should add any other options that make sense for the particular subclass. +Deberías crear un método estático `with()` en cada subclase de `ComponentHarness` que retorne un `HarnessPredicate` para esa clase. Esto permite a los autores de pruebas escribir código fácilmente comprensible, p. ej., `loader.getHarness(MyMenuHarness.with({selector: '#menu1'}))`. Además de las opciones estándar de selector y ancestor, el método `with` debería agregar cualquier otra opción que tenga sentido para la subclase particular. -Harnesses that need to add additional options should extend the `BaseHarnessFilters` interface and additional optional properties as needed. `HarnessPredicate` provides several convenience methods for adding options: `stringMatches()`, `addOption()`, and `add()`. See the [HarnessPredicate API page](/api/cdk/testing/HarnessPredicate) for the full description. +Los harnesses que necesitan agregar opciones adicionales deberían extender la interfaz `BaseHarnessFilters` y propiedades opcionales adicionales según sea necesario. `HarnessPredicate` proporciona varios métodos de conveniencia para agregar opciones: `stringMatches()`, `addOption()` y `add()`. Consulta la [página de API de HarnessPredicate](/api/cdk/testing/HarnessPredicate) para la descripción completa. -For example, when working with a menu it is useful to filter based on trigger text and to filter menu items based on their text: +Por ejemplo, cuando se trabaja con un menú es útil filtrar basado en el texto del trigger y filtrar items de menú basado en su texto: interface MyMenuHarnessFilters extends BaseHarnessFilters { - /** Filters based on the trigger text for the menu. */ + /** Filtra basado en el texto del trigger para el menú. */ triggerText?: string | RegExp; } interface MyMenuItemHarnessFilters extends BaseHarnessFilters { - /** Filters based on the text of the menu item. */ + /** Filtra basado en el texto del item de menú. */ text?: string | RegExp; } class MyMenuHarness extends ComponentHarness { static hostSelector = 'my-menu'; - /** Creates a `HarnessPredicate` used to locate a particular `MyMenuHarness`. */ + /** Crea un `HarnessPredicate` usado para localizar un `MyMenuHarness` particular. */ static with(options: MyMenuHarnessFilters): HarnessPredicate { return new HarnessPredicate(MyMenuHarness, options) .addOption('trigger text', options.triggerText, @@ -193,7 +193,7 @@ class MyMenuHarness extends ComponentHarness { protected getPopupHarness = this.locatorFor(MyPopupHarness); - /** Gets the text of the menu trigger. */ + /** Obtiene el texto del trigger del menú. */ async getTriggerText(): Promise { const popupHarness = await this.getPopupHarness(); return popupHarness.getTriggerText(); @@ -204,14 +204,14 @@ class MyMenuHarness extends ComponentHarness { class MyMenuItemHarness extends ComponentHarness { static hostSelector = 'my-menu-item'; - /** Creates a `HarnessPredicate` used to locate a particular `MyMenuItemHarness`. */ + /** Crea un `HarnessPredicate` usado para localizar un `MyMenuItemHarness` particular. */ static with(options: MyMenuItemHarnessFilters): HarnessPredicate { return new HarnessPredicate(MyMenuItemHarness, options) .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text)); } - /** Gets the text of the menu item. */ + /** Obtiene el texto del item de menú. */ async getText(): Promise { const host = await this.host(); return host.text(); @@ -219,13 +219,13 @@ class MyMenuItemHarness extends ComponentHarness { } -You can pass a `HarnessPredicate` instead of a `ComponentHarness` class to any of the APIs on `HarnessLoader`, `LocatorFactory`, or `ComponentHarness`. This allows test authors to easily target a particular component instance when creating a harness instance. It also allows the harness author to leverage the same `HarnessPredicate` to enable more powerful APIs on their harness class. For example, consider the `getItems` method on the `MyMenuHarness` shown above. Adding a filtering API allows users of the harness to search for particular menu items: +Puedes pasar un `HarnessPredicate` en lugar de una clase `ComponentHarness` a cualquiera de las APIs en `HarnessLoader`, `LocatorFactory` o `ComponentHarness`. Esto permite a los autores de pruebas fácilmente dirigirse a una instancia de componente particular al crear una instancia de harness. También permite al autor del harness aprovechar el mismo `HarnessPredicate` para habilitar APIs más poderosas en su clase harness. Por ejemplo, considera el método `getItems` en el `MyMenuHarness` mostrado arriba. Agregar una API de filtrado permite a los usuarios del harness buscar items de menú particulares: class MyMenuHarness extends ComponentHarness { static hostSelector = 'my-menu'; - /** Gets a list of items in the menu, optionally filtered based on the given criteria. */ + /** Obtiene una lista de items en el menú, opcionalmente filtrados basados en el criterio dado. */ async getItems(filters: MyMenuItemHarnessFilters = {}): Promise { const getFilteredItems = this.locatorForAll(MyMenuItemHarness.with(filters)); return getFilteredItems(); @@ -234,13 +234,13 @@ class MyMenuHarness extends ComponentHarness { } -## Creating `HarnessLoader` for elements that use content projection +## Crear `HarnessLoader` para elementos que usan proyección de contenido -Some components project additional content into the component's template. See the [content projection guide](guide/components/content-projection) for more information. +Algunos componentes proyectan contenido adicional en la plantilla del componente. Consulta la [guía de proyección de contenido](guide/components/content-projection) para más información. -Add a `HarnessLoader` instance scoped to the element containing the `` when you create a harness for a component that uses content projection. This allows the user of the harness to load additional harnesses for whatever components were passed in as content. `ComponentHarness` has several methods that can be used to create HarnessLoader instances for cases like this: `harnessLoaderFor()`, `harnessLoaderForOptional()`, `harnessLoaderForAll()`. See the [HarnessLoader interface API reference page](/api/cdk/testing/HarnessLoader) for more details. +Agrega una instancia de `HarnessLoader` con alcance al elemento que contiene el `` cuando crees un harness para un componente que usa proyección de contenido. Esto permite al usuario del harness cargar harnesses adicionales para cualquier componente que fue pasado como contenido. `ComponentHarness` tiene varios métodos que pueden usarse para crear instancias de HarnessLoader para casos como este: `harnessLoaderFor()`, `harnessLoaderForOptional()`, `harnessLoaderForAll()`. Consulta la [página de referencia de la API de la interfaz HarnessLoader](/api/cdk/testing/HarnessLoader) para más detalles. -For example, the `MyPopupHarness` example from above can extend `ContentContainerComponentHarness` to add support to load harnesses within the `` of the component. +Por ejemplo, el ejemplo `MyPopupHarness` de arriba puede extender `ContentContainerComponentHarness` para agregar soporte para cargar harnesses dentro del `` del componente. class MyPopupHarness extends ContentContainerComponentHarness { @@ -248,19 +248,19 @@ class MyPopupHarness extends ContentContainerComponentHarness { } -## Accessing elements outside of the component's host element +## Acceder a elementos fuera del elemento host del componente -There are times when a component harness might need to access elements outside of its corresponding component's host element. For example, code that displays a floating element or pop-up often attaches DOM elements directly to the document body, such as the `Overlay` service in Angular CDK. +Hay momentos cuando un component harness podría necesitar acceder a elementos fuera del elemento host de su componente correspondiente. Por ejemplo, código que muestra un elemento flotante o pop-up a menudo adjunta elementos DOM directamente al body del documento, como el servicio `Overlay` en el CDK de Angular. -In this case, `ComponentHarness` provides a method that can be used to get a `LocatorFactory` for the root element of the document. The `LocatorFactory` supports most of the same APIs as the `ComponentHarness` base class, and can then be used to query relative to the document's root element. +En este caso, `ComponentHarness` proporciona un método que puede usarse para obtener un `LocatorFactory` para el elemento raíz del documento. El `LocatorFactory` soporta la mayoría de las mismas APIs que la clase base `ComponentHarness`, y puede luego usarse para consultar relativo al elemento raíz del documento. -Consider if the `MyPopup` component above used the CDK overlay for the popup content, rather than an element in its own template. In this case, `MyPopupHarness` would have to access the content element via `documentRootLocatorFactory()` method that gets a locator factory rooted at the document root. +Considera si el componente `MyPopup` arriba usara el overlay del CDK para el contenido del popup, en lugar de un elemento en su propia plantilla. En este caso, `MyPopupHarness` tendría que acceder al elemento content a través del método `documentRootLocatorFactory()` que obtiene una factory locator enraizada en la raíz del documento. class MyPopupHarness extends ComponentHarness { static hostSelector = 'my-popup'; - /** Gets a `HarnessLoader` whose root element is the popup's content element. */ + /** Obtiene un `HarnessLoader` cuyo elemento raíz es el elemento content del popup. */ async getHarnessLoaderForContent(): Promise { const rootLocator = this.documentRootLocatorFactory(); return rootLocator.harnessLoaderFor('my-popup-content'); @@ -268,10 +268,10 @@ class MyPopupHarness extends ComponentHarness { } -## Waiting for asynchronous tasks +## Esperar tareas asíncronas -The methods on `TestElement` automatically trigger Angular's change detection and wait for tasks inside the `NgZone`. In most cases no special effort is required for harness authors to wait on asynchronous tasks. However, there are some edge cases where this may not be sufficient. +Los métodos en `TestElement` automáticamente desencadenan la detección de cambios de Angular y esperan tareas dentro del `NgZone`. En la mayoría de los casos no se requiere esfuerzo especial para que los autores de harness esperen tareas asíncronas. Sin embargo, hay algunos casos extremos donde esto puede no ser suficiente. -Under some circumstances, Angular animations may require a second cycle of change detection and subsequent `NgZone` stabilization before animation events are fully flushed. In cases where this is needed, the `ComponentHarness` offers a `forceStabilize()` method that can be called to do the second round. +Bajo algunas circunstancias, las animaciones de Angular pueden requerir un segundo ciclo de detección de cambios y la subsiguiente estabilización de `NgZone` antes de que los eventos de animación se vacíen completamente. En casos donde esto se necesita, el `ComponentHarness` ofrece un método `forceStabilize()` que puede llamarse para hacer la segunda ronda. -You can use `NgZone.runOutsideAngular()` to schedule tasks outside of NgZone. Call the `waitForTasksOutsideAngular()` method on the corresponding harness if you need to explicitly wait for tasks outside `NgZone` since this does not happen automatically. +Puedes usar `NgZone.runOutsideAngular()` para programar tareas fuera de NgZone. Llama al método `waitForTasksOutsideAngular()` en el harness correspondiente si necesitas esperar explícitamente tareas fuera de `NgZone` ya que esto no sucede automáticamente. diff --git a/adev-es/src/content/guide/testing/debugging.en.md b/adev-es/src/content/guide/testing/debugging.en.md new file mode 100644 index 0000000..c5822b4 --- /dev/null +++ b/adev-es/src/content/guide/testing/debugging.en.md @@ -0,0 +1,17 @@ +# Debugging tests + +If your tests aren't working as you expect them to, you can inspect and debug them in the browser. + +Debug specs in the browser in the same way that you debug an application. + +1. Reveal the Karma browser window. + See [Set up testing](guide/testing#set-up-testing) if you need help with this step. + +1. Click the **DEBUG** button to open a new browser tab and re-run the tests. +1. Open the browser's **Developer Tools**. On Windows, press `Ctrl-Shift-I`. On macOS, press `Command-Option-I`. +1. Pick the **Sources** section. +1. Press `Control/Command-P`, and then start typing the name of your test file to open it. +1. Set a breakpoint in the test. +1. Refresh the browser, and notice how it stops at the breakpoint. + +Karma debugging diff --git a/adev-es/src/content/guide/testing/debugging.md b/adev-es/src/content/guide/testing/debugging.md index c5822b4..2b9abc0 100644 --- a/adev-es/src/content/guide/testing/debugging.md +++ b/adev-es/src/content/guide/testing/debugging.md @@ -1,17 +1,17 @@ -# Debugging tests +# Depurar pruebas -If your tests aren't working as you expect them to, you can inspect and debug them in the browser. +Si tus pruebas no están funcionando como esperas, puedes inspeccionarlas y depurarlas en el navegador. -Debug specs in the browser in the same way that you debug an application. +Depura specs en el navegador de la misma manera que depuras una aplicación. -1. Reveal the Karma browser window. - See [Set up testing](guide/testing#set-up-testing) if you need help with this step. +1. Revela la ventana del navegador de Karma. + Consulta [Configurar testing](guide/testing#set-up-testing) si necesitas ayuda con este paso. -1. Click the **DEBUG** button to open a new browser tab and re-run the tests. -1. Open the browser's **Developer Tools**. On Windows, press `Ctrl-Shift-I`. On macOS, press `Command-Option-I`. -1. Pick the **Sources** section. -1. Press `Control/Command-P`, and then start typing the name of your test file to open it. -1. Set a breakpoint in the test. -1. Refresh the browser, and notice how it stops at the breakpoint. +1. Haz clic en el botón **DEBUG** para abrir una nueva pestaña del navegador y re-ejecutar las pruebas. +1. Abre las **Herramientas de Desarrollador** del navegador. En Windows, presiona `Ctrl-Shift-I`. En macOS, presiona `Command-Option-I`. +1. Selecciona la sección **Sources**. +1. Presiona `Control/Command-P`, y luego comienza a escribir el nombre de tu archivo de prueba para abrirlo. +1. Establece un breakpoint en la prueba. +1. Actualiza el navegador, y nota cómo se detiene en el breakpoint. -Karma debugging +Depuración de Karma diff --git a/adev-es/src/content/guide/testing/experimental-unit-test.en.md b/adev-es/src/content/guide/testing/experimental-unit-test.en.md new file mode 100644 index 0000000..ccca5dc --- /dev/null +++ b/adev-es/src/content/guide/testing/experimental-unit-test.en.md @@ -0,0 +1,83 @@ +# Experimental unit testing system + +The Angular CLI provides an experimental unit test system that can use [Vitest](https://vitest.dev/) as a test runner. + +IMPORTANT: This experimental unit testing system requires the use of the `application` build system. +The `application` build system is the default for all newly created projects. + +## Installing dependencies + +Some packages are required for the new builder to work. In order to install the new packages, run the following command : + + + +npm install vitest jsdom --save-dev + + + +If no other projects in your workspace use Karma, run the following command to uninstall the corresponding packages : + + + +npm uninstall karma karma-chrome-launcher karma-coverage karma-jasmine karma-jasmine-html-reporter --save-dev + + + +## Set up testing + +The Angular CLI includes the test system within a new project but must be configured before it can be used. + +The project you create with the CLI is setup to use the `karma` test system by default. +To change to the experimental unit test system, update the `test` target as follows: + + +"test": { + "builder": "@angular/build:unit-test", + "options": { + "tsConfig": "tsconfig.spec.json", + "runner": "vitest", + "buildTarget": "::development" + } +} + + +The `buildTarget` operates similarly to the option available to the development server. +The `build` target configures build options for the tests. +If the `development` build configuration is missing for a project or you need +different options for testing, you can create and use a `testing` or similarly named build configuration. + +To execute the application's testing, just run the [`ng test`](cli/test) CLI command as before: + + + +ng test + + + +The `ng test` command builds the application in *watch mode*, and launches the configured runner. + +The console output looks like below: + + + ✓ spec-app-app.spec.js (2 tests) 31ms + ✓ App > should create the app 22ms + ✓ App > should render title 8ms + + Test Files 1 passed (1) + Tests 2 passed (2) + Start at 14:24:15 + Duration 1.16s (transform 628ms, setup 703ms, collect 64ms, tests 31ms, environment 188ms, prepare 33ms) + + +Watch mode is enabled by default when using an interactive terminal and not running on CI. + +## Configuration + +The Angular CLI takes care of the Vitest configuration for you. It constructs the full configuration in memory, based on options specified in the `angular.json` file. +Directly customizing the underlying test runner configuration is currently not supported. + +## Bug reports + +Report issues and feature requests on [GitHub](https://github.com/angular/angular-cli/issues). + +Please provide a minimal reproduction where possible to aid the team in addressing issues. diff --git a/adev-es/src/content/guide/testing/experimental-unit-test.md b/adev-es/src/content/guide/testing/experimental-unit-test.md index ccca5dc..3a0baec 100644 --- a/adev-es/src/content/guide/testing/experimental-unit-test.md +++ b/adev-es/src/content/guide/testing/experimental-unit-test.md @@ -1,13 +1,13 @@ -# Experimental unit testing system +# Sistema experimental de pruebas unitarias -The Angular CLI provides an experimental unit test system that can use [Vitest](https://vitest.dev/) as a test runner. +Angular CLI proporciona un sistema experimental de pruebas unitarias que puede usar [Vitest](https://vitest.dev/) como test runner. -IMPORTANT: This experimental unit testing system requires the use of the `application` build system. -The `application` build system is the default for all newly created projects. +IMPORTANTE: Este sistema experimental de pruebas unitarias requiere el uso del sistema de build `application`. +El sistema de build `application` es el predeterminado para todos los proyectos creados recientemente. -## Installing dependencies +## Instalar dependencias -Some packages are required for the new builder to work. In order to install the new packages, run the following command : +Algunos paquetes son requeridos para que el nuevo builder funcione. Para instalar los nuevos paquetes, ejecuta el siguiente comando: @@ -15,7 +15,7 @@ npm install vitest jsdom --save-dev -If no other projects in your workspace use Karma, run the following command to uninstall the corresponding packages : +Si ningún otro proyecto en tu workspace usa Karma, ejecuta el siguiente comando para desinstalar los paquetes correspondientes: @@ -23,12 +23,12 @@ npm uninstall karma karma-chrome-launcher karma-coverage karma-jasmine karma-jas -## Set up testing +## Configurar testing -The Angular CLI includes the test system within a new project but must be configured before it can be used. +Angular CLI incluye el sistema de pruebas dentro de un nuevo proyecto pero debe configurarse antes de que pueda usarse. -The project you create with the CLI is setup to use the `karma` test system by default. -To change to the experimental unit test system, update the `test` target as follows: +El proyecto que creas con el CLI está configurado para usar el sistema de pruebas `karma` por defecto. +Para cambiar al sistema experimental de pruebas unitarias, actualiza el target `test` como sigue: "test": { @@ -41,12 +41,12 @@ To change to the experimental unit test system, update the `test` target as foll } -The `buildTarget` operates similarly to the option available to the development server. -The `build` target configures build options for the tests. -If the `development` build configuration is missing for a project or you need -different options for testing, you can create and use a `testing` or similarly named build configuration. +El `buildTarget` opera de manera similar a la opción disponible para el servidor de desarrollo. +El target `build` configura opciones de build para las pruebas. +Si la configuración de build `development` falta para un proyecto o necesitas +opciones diferentes para testing, puedes crear y usar una configuración de build `testing` o con nombre similar. -To execute the application's testing, just run the [`ng test`](cli/test) CLI command as before: +Para ejecutar el testing de la aplicación, solo ejecuta el comando CLI [`ng test`](cli/test) como antes: @@ -54,9 +54,9 @@ ng test -The `ng test` command builds the application in *watch mode*, and launches the configured runner. +El comando `ng test` construye la aplicación en modo *watch*, y lanza el runner configurado. -The console output looks like below: +La salida de consola se ve como a continuación: ✓ spec-app-app.spec.js (2 tests) 31ms @@ -69,15 +69,15 @@ The console output looks like below: Duration 1.16s (transform 628ms, setup 703ms, collect 64ms, tests 31ms, environment 188ms, prepare 33ms) -Watch mode is enabled by default when using an interactive terminal and not running on CI. +El modo watch está habilitado por defecto cuando se usa una terminal interactiva y no se está ejecutando en CI. -## Configuration +## Configuración -The Angular CLI takes care of the Vitest configuration for you. It constructs the full configuration in memory, based on options specified in the `angular.json` file. -Directly customizing the underlying test runner configuration is currently not supported. +Angular CLI se encarga de la configuración de Vitest por ti. Construye la configuración completa en memoria, basándose en opciones especificadas en el archivo `angular.json`. +Personalizar directamente la configuración del test runner subyacente actualmente no está soportado. -## Bug reports +## Reportes de bugs -Report issues and feature requests on [GitHub](https://github.com/angular/angular-cli/issues). +Reporta problemas y solicitudes de características en [GitHub](https://github.com/angular/angular-cli/issues). -Please provide a minimal reproduction where possible to aid the team in addressing issues. +Por favor proporciona una reproducción mínima cuando sea posible para ayudar al equipo a abordar problemas. diff --git a/adev-es/src/content/guide/testing/overview.en.md b/adev-es/src/content/guide/testing/overview.en.md new file mode 100644 index 0000000..661b3f1 --- /dev/null +++ b/adev-es/src/content/guide/testing/overview.en.md @@ -0,0 +1,125 @@ +# Testing + +Testing your Angular application helps you check that your application is working as you expect. + +## Set up testing + +The Angular CLI downloads and installs everything you need to test an Angular application with [Jasmine testing framework](https://jasmine.github.io). + +The project you create with the CLI is immediately ready to test. +Just run the [`ng test`](cli/test) CLI command: + + + +ng test + + + +The `ng test` command builds the application in *watch mode*, +and launches the [Karma test runner](https://karma-runner.github.io). + +The console output looks like below: + + + +02 11 2022 09:08:28.605:INFO [karma-server]: Karma v6.4.1 server started at http://localhost:9876/ +02 11 2022 09:08:28.607:INFO [launcher]: Launching browsers Chrome with concurrency unlimited +02 11 2022 09:08:28.620:INFO [launcher]: Starting browser Chrome +02 11 2022 09:08:31.312:INFO [Chrome]: Connected on socket -LaEYvD2R7MdcS0-AAAB with id 31534482 +Chrome: Executed 3 of 3 SUCCESS (0.193 secs / 0.172 secs) +TOTAL: 3 SUCCESS + + + +The last line of the log shows that Karma ran three tests that all passed. + +The test output is displayed in the browser using [Karma Jasmine HTML Reporter](https://github.com/dfederm/karma-jasmine-html-reporter). + +Jasmine HTML Reporter in the browser + +Click on a test row to re-run just that test or click on a description to re-run the tests in the selected test group \("test suite"\). + +Meanwhile, the `ng test` command is watching for changes. + +To see this in action, make a small change to `app.component.ts` and save. +The tests run again, the browser refreshes, and the new test results appear. + +## Configuration + +The Angular CLI takes care of Jasmine and Karma configuration for you. It constructs the full configuration in memory, based on options specified in the `angular.json` file. + +If you want to customize Karma, you can create a `karma.conf.js` by running the following command: + + + +ng generate config karma + + + +HELPFUL: Read more about Karma configuration in the [Karma configuration guide](http://karma-runner.github.io/6.4/config/configuration-file.html). + +### Other test frameworks + +You can also unit test an Angular application with other testing libraries and test runners. +Each library and runner has its own distinctive installation procedures, configuration, and syntax. + +### Test file name and location + +Inside the `src/app` folder the Angular CLI generated a test file for the `AppComponent` named `app.component.spec.ts`. + +IMPORTANT: The test file extension **must be `.spec.ts`** so that tooling can identify it as a file with tests \(also known as a *spec* file\). + +The `app.component.ts` and `app.component.spec.ts` files are siblings in the same folder. +The root file names \(`app.component`\) are the same for both files. + +Adopt these two conventions in your own projects for *every kind* of test file. + +#### Place your spec file next to the file it tests + +It's a good idea to put unit test spec files in the same folder +as the application source code files that they test: + +* Such tests are painless to find +* You see at a glance if a part of your application lacks tests +* Nearby tests can reveal how a part works in context +* When you move the source \(inevitable\), you remember to move the test +* When you rename the source file \(inevitable\), you remember to rename the test file + +#### Place your spec files in a test folder + +Application integration specs can test the interactions of multiple parts +spread across folders and modules. +They don't really belong to any part in particular, so they don't have a +natural home next to any one file. + +It's often better to create an appropriate folder for them in the `tests` directory. + +Of course specs that test the test helpers belong in the `test` folder, +next to their corresponding helper files. + +## Testing in continuous integration + +One of the best ways to keep your project bug-free is through a test suite, but you might forget to run tests all the time. + +Continuous integration \(CI\) servers let you set up your project repository so that your tests run on every commit and pull request. + +To test your Angular CLI application in Continuous integration \(CI\) run the following command: + + +ng test --no-watch --no-progress --browsers=ChromeHeadless + + +## More information on testing + +After you've set up your application for testing, you might find the following testing guides useful. + +| | Details | +|:--- |:--- | +| [Code coverage](guide/testing/code-coverage) | How much of your app your tests are covering and how to specify required amounts. | +| [Testing services](guide/testing/services) | How to test the services your application uses. | +| [Basics of testing components](guide/testing/components-basics) | Basics of testing Angular components. | +| [Component testing scenarios](guide/testing/components-scenarios) | Various kinds of component testing scenarios and use cases. | +| [Testing attribute directives](guide/testing/attribute-directives) | How to test your attribute directives. | +| [Testing pipes](guide/testing/pipes) | How to test pipes. | +| [Debugging tests](guide/testing/debugging) | Common testing bugs. | +| [Testing utility APIs](guide/testing/utility-apis) | Angular testing features. | diff --git a/adev-es/src/content/guide/testing/overview.md b/adev-es/src/content/guide/testing/overview.md index 661b3f1..410e674 100644 --- a/adev-es/src/content/guide/testing/overview.md +++ b/adev-es/src/content/guide/testing/overview.md @@ -1,13 +1,13 @@ -# Testing +# Pruebas -Testing your Angular application helps you check that your application is working as you expect. +Probar tu aplicación Angular te ayuda a verificar que tu aplicación está funcionando como esperas. -## Set up testing +## Configurar pruebas -The Angular CLI downloads and installs everything you need to test an Angular application with [Jasmine testing framework](https://jasmine.github.io). +Angular CLI descarga e instala todo lo que necesitas para probar una aplicación Angular con [Jasmine testing framework](https://jasmine.github.io). -The project you create with the CLI is immediately ready to test. -Just run the [`ng test`](cli/test) CLI command: +El proyecto que creas con el CLI está inmediatamente listo para probar. +Solo ejecuta el comando CLI [`ng test`](cli/test): @@ -15,10 +15,10 @@ ng test -The `ng test` command builds the application in *watch mode*, -and launches the [Karma test runner](https://karma-runner.github.io). +El comando `ng test` construye la aplicación en modo *watch*, +y lanza el [Karma test runner](https://karma-runner.github.io). -The console output looks like below: +La salida de consola se ve como a continuación: @@ -31,24 +31,24 @@ TOTAL: 3 SUCCESS -The last line of the log shows that Karma ran three tests that all passed. +La última línea del log muestra que Karma ejecutó tres pruebas que todas pasaron. -The test output is displayed in the browser using [Karma Jasmine HTML Reporter](https://github.com/dfederm/karma-jasmine-html-reporter). +La salida de pruebas se muestra en el navegador usando [Karma Jasmine HTML Reporter](https://github.com/dfederm/karma-jasmine-html-reporter). -Jasmine HTML Reporter in the browser +Jasmine HTML Reporter en el navegador -Click on a test row to re-run just that test or click on a description to re-run the tests in the selected test group \("test suite"\). +Haz clic en una fila de prueba para re-ejecutar solo esa prueba o haz clic en una descripción para re-ejecutar las pruebas en el grupo de pruebas seleccionado \("test suite"\). -Meanwhile, the `ng test` command is watching for changes. +Mientras tanto, el comando `ng test` está observando cambios. -To see this in action, make a small change to `app.component.ts` and save. -The tests run again, the browser refreshes, and the new test results appear. +Para ver esto en acción, haz un pequeño cambio a `app.component.ts` y guarda. +Las pruebas se ejecutan nuevamente, el navegador se actualiza y los nuevos resultados de prueba aparecen. -## Configuration +## Configuración -The Angular CLI takes care of Jasmine and Karma configuration for you. It constructs the full configuration in memory, based on options specified in the `angular.json` file. +Angular CLI se encarga de la configuración de Jasmine y Karma por ti. Construye la configuración completa en memoria, basándose en opciones especificadas en el archivo `angular.json`. -If you want to customize Karma, you can create a `karma.conf.js` by running the following command: +Si quieres personalizar Karma, puedes crear un `karma.conf.js` ejecutando el siguiente comando: @@ -56,70 +56,70 @@ ng generate config karma -HELPFUL: Read more about Karma configuration in the [Karma configuration guide](http://karma-runner.github.io/6.4/config/configuration-file.html). +ÚTIL: Lee más sobre la configuración de Karma en la [guía de configuración de Karma](http://karma-runner.github.io/6.4/config/configuration-file.html). -### Other test frameworks +### Otros frameworks de prueba -You can also unit test an Angular application with other testing libraries and test runners. -Each library and runner has its own distinctive installation procedures, configuration, and syntax. +También puedes hacer pruebas unitarias de una aplicación Angular con otras librerías de prueba y test runners. +Cada librería y runner tiene sus propios procedimientos de instalación, configuración y sintaxis distintivos. -### Test file name and location +### Nombre y ubicación del archivo de prueba -Inside the `src/app` folder the Angular CLI generated a test file for the `AppComponent` named `app.component.spec.ts`. +Dentro de la carpeta `src/app` el Angular CLI generó un archivo de prueba para el `AppComponent` llamado `app.component.spec.ts`. -IMPORTANT: The test file extension **must be `.spec.ts`** so that tooling can identify it as a file with tests \(also known as a *spec* file\). +IMPORTANTE: La extensión del archivo de prueba **debe ser `.spec.ts`** para que las herramientas puedan identificarlo como un archivo con pruebas \(también conocido como un archivo *spec*\). -The `app.component.ts` and `app.component.spec.ts` files are siblings in the same folder. -The root file names \(`app.component`\) are the same for both files. +Los archivos `app.component.ts` y `app.component.spec.ts` son hermanos en la misma carpeta. +Los nombres raíz de los archivos \(`app.component`\) son los mismos para ambos archivos. -Adopt these two conventions in your own projects for *every kind* of test file. +Adopta estas dos convenciones en tus propios proyectos para *cada tipo* de archivo de prueba. -#### Place your spec file next to the file it tests +#### Coloca tu archivo spec junto al archivo que prueba -It's a good idea to put unit test spec files in the same folder -as the application source code files that they test: +Es una buena idea colocar los archivos spec de prueba unitaria en la misma carpeta +que los archivos de código fuente de la aplicación que prueban: -* Such tests are painless to find -* You see at a glance if a part of your application lacks tests -* Nearby tests can reveal how a part works in context -* When you move the source \(inevitable\), you remember to move the test -* When you rename the source file \(inevitable\), you remember to rename the test file +* Tales pruebas son fáciles de encontrar +* Ves de un vistazo si una parte de tu aplicación carece de pruebas +* Las pruebas cercanas pueden revelar cómo funciona una parte en contexto +* Cuando mueves el código fuente \(inevitable\), recuerdas mover la prueba +* Cuando renombras el archivo fuente \(inevitable\), recuerdas renombrar el archivo de prueba -#### Place your spec files in a test folder +#### Coloca tus archivos spec en una carpeta de prueba -Application integration specs can test the interactions of multiple parts -spread across folders and modules. -They don't really belong to any part in particular, so they don't have a -natural home next to any one file. +Las specs de integración de aplicación pueden probar las interacciones de múltiples partes +distribuidas en carpetas y módulos. +Realmente no pertenecen a ninguna parte en particular, por lo que no tienen un +hogar natural junto a ningún archivo. -It's often better to create an appropriate folder for them in the `tests` directory. +A menudo es mejor crear una carpeta apropiada para ellas en el directorio `tests`. -Of course specs that test the test helpers belong in the `test` folder, -next to their corresponding helper files. +Por supuesto, las specs que prueban los helpers de prueba pertenecen en la carpeta `test`, +junto a sus archivos helper correspondientes. -## Testing in continuous integration +## Pruebas en integración continua -One of the best ways to keep your project bug-free is through a test suite, but you might forget to run tests all the time. +Una de las mejores maneras de mantener tu proyecto libre de errores es a través de un conjunto de pruebas, pero podrías olvidar ejecutar las pruebas todo el tiempo. -Continuous integration \(CI\) servers let you set up your project repository so that your tests run on every commit and pull request. +Los servidores de integración continua \(CI\) te permiten configurar el repositorio de tu proyecto para que tus pruebas se ejecuten en cada commit y pull request. -To test your Angular CLI application in Continuous integration \(CI\) run the following command: +Para probar tu aplicación Angular CLI en integración continua \(CI\) ejecuta el siguiente comando: ng test --no-watch --no-progress --browsers=ChromeHeadless -## More information on testing +## Más información sobre pruebas -After you've set up your application for testing, you might find the following testing guides useful. +Después de que hayas configurado tu aplicación para pruebas, podrías encontrar útiles las siguientes guías de pruebas. -| | Details | +| | Detalles | |:--- |:--- | -| [Code coverage](guide/testing/code-coverage) | How much of your app your tests are covering and how to specify required amounts. | -| [Testing services](guide/testing/services) | How to test the services your application uses. | -| [Basics of testing components](guide/testing/components-basics) | Basics of testing Angular components. | -| [Component testing scenarios](guide/testing/components-scenarios) | Various kinds of component testing scenarios and use cases. | -| [Testing attribute directives](guide/testing/attribute-directives) | How to test your attribute directives. | -| [Testing pipes](guide/testing/pipes) | How to test pipes. | -| [Debugging tests](guide/testing/debugging) | Common testing bugs. | -| [Testing utility APIs](guide/testing/utility-apis) | Angular testing features. | +| [Cobertura de código](guide/testing/code-coverage) | Cuánto de tu aplicación cubren tus pruebas y cómo especificar cantidades requeridas. | +| [Probar servicios](guide/testing/services) | Cómo probar los servicios que usa tu aplicación. | +| [Fundamentos de probar componentes](guide/testing/components-basics) | Fundamentos de probar componentes en Angular. | +| [Escenarios de prueba de componentes](guide/testing/components-scenarios) | Varios tipos de escenarios de prueba de componentes y casos de uso. | +| [Probar directivas de atributo](guide/testing/attribute-directives) | Cómo probar tus directivas de atributo. | +| [Probar pipes](guide/testing/pipes) | Cómo probar pipes. | +| [Depurar pruebas](guide/testing/debugging) | Bugs comunes de pruebas. | +| [APIs utilitarias de pruebas](guide/testing/utility-apis) | Características de pruebas en Angular. | diff --git a/adev-es/src/content/guide/testing/pipes.en.md b/adev-es/src/content/guide/testing/pipes.en.md new file mode 100644 index 0000000..260f73a --- /dev/null +++ b/adev-es/src/content/guide/testing/pipes.en.md @@ -0,0 +1,28 @@ +# Testing Pipes + +You can test [pipes](guide/templates/pipes) without the Angular testing utilities. + +## Testing the `TitleCasePipe` + +A pipe class has one method, `transform`, that manipulates the input value into a transformed output value. +The `transform` implementation rarely interacts with the DOM. +Most pipes have no dependence on Angular other than the `@Pipe` metadata and an interface. + +Consider a `TitleCasePipe` that capitalizes the first letter of each word. +Here's an implementation with a regular expression. + + + +Anything that uses a regular expression is worth testing thoroughly. +Use simple Jasmine to explore the expected cases and the edge cases. + + + +## Writing DOM tests to support a pipe test + +These are tests of the pipe *in isolation*. +They can't tell if the `TitleCasePipe` is working properly as applied in the application components. + +Consider adding component tests such as this one: + + diff --git a/adev-es/src/content/guide/testing/pipes.md b/adev-es/src/content/guide/testing/pipes.md index 260f73a..24081d4 100644 --- a/adev-es/src/content/guide/testing/pipes.md +++ b/adev-es/src/content/guide/testing/pipes.md @@ -1,28 +1,28 @@ -# Testing Pipes +# Probar Pipes -You can test [pipes](guide/templates/pipes) without the Angular testing utilities. +Puedes probar [pipes](guide/templates/pipes) sin las utilidades de pruebas de Angular. -## Testing the `TitleCasePipe` +## Probar el `TitleCasePipe` -A pipe class has one method, `transform`, that manipulates the input value into a transformed output value. -The `transform` implementation rarely interacts with the DOM. -Most pipes have no dependence on Angular other than the `@Pipe` metadata and an interface. +Una clase pipe tiene un método, `transform`, que manipula el valor de entrada en un valor de salida transformado. +La implementación de `transform` rara vez interactúa con el DOM. +La mayoría de pipes no tienen dependencia de Angular aparte de los metadata `@Pipe` y una interfaz. -Consider a `TitleCasePipe` that capitalizes the first letter of each word. -Here's an implementation with a regular expression. +Considera un `TitleCasePipe` que capitaliza la primera letra de cada palabra. +Aquí hay una implementación con una expresión regular. -Anything that uses a regular expression is worth testing thoroughly. -Use simple Jasmine to explore the expected cases and the edge cases. +Cualquier cosa que use una expresión regular vale la pena probar exhaustivamente. +Usa Jasmine simple para explorar los casos esperados y los casos extremos. -## Writing DOM tests to support a pipe test +## Escribir pruebas DOM para soportar una prueba de pipe -These are tests of the pipe *in isolation*. -They can't tell if the `TitleCasePipe` is working properly as applied in the application components. +Estas son pruebas del pipe *de forma aislada*. +No pueden decir si el `TitleCasePipe` está funcionando correctamente como se aplica en los componentes de la aplicación. -Consider adding component tests such as this one: +Considera agregar pruebas de componente como esta: diff --git a/adev-es/src/content/guide/testing/services.en.md b/adev-es/src/content/guide/testing/services.en.md new file mode 100644 index 0000000..4a7ed5f --- /dev/null +++ b/adev-es/src/content/guide/testing/services.en.md @@ -0,0 +1,129 @@ +# Testing services + +To check that your services are working as you intend, you can write tests specifically for them. + +Services are often the smoothest files to unit test. +Here are some synchronous and asynchronous unit tests of the `ValueService` written without assistance from Angular testing utilities. + + + +## Services with dependencies + +Services often depend on other services that Angular injects into the constructor. +In many cases, you can create and *inject* these dependencies by hand while calling the service's constructor. + +The `MasterService` is a simple example: + + + +`MasterService` delegates its only method, `getValue`, to the injected `ValueService`. + +Here are several ways to test it. + + + +The first test creates a `ValueService` with `new` and passes it to the `MasterService` constructor. + +However, injecting the real service rarely works well as most dependent services are difficult to create and control. + +Instead, mock the dependency, use a dummy value, or create a [spy](https://jasmine.github.io/tutorials/your_first_suite#section-Spies) on the pertinent service method. + +HELPFUL: Prefer spies as they are usually the best way to mock services. + +These standard testing techniques are great for unit testing services in isolation. + +However, you almost always inject services into application classes using Angular dependency injection and you should have tests that reflect that usage pattern. +Angular testing utilities make it straightforward to investigate how injected services behave. + +## Testing services with the `TestBed` + +Your application relies on Angular [dependency injection (DI)](guide/di) to create services. +When a service has a dependent service, DI finds or creates that dependent service. +And if that dependent service has its own dependencies, DI finds-or-creates them as well. + +As a service *consumer*, you don't worry about any of this. +You don't worry about the order of constructor arguments or how they're created. + +As a service *tester*, you must at least think about the first level of service dependencies but you *can* let Angular DI do the service creation and deal with constructor argument order when you use the `TestBed` testing utility to provide and create services. + +## Angular `TestBed` + +The `TestBed` is the most important of the Angular testing utilities. +The `TestBed` creates a dynamically-constructed Angular *test* module that emulates an Angular [@NgModule](guide/ngmodules). + +The `TestBed.configureTestingModule()` method takes a metadata object that can have most of the properties of an [@NgModule](guide/ngmodules). + +To test a service, you set the `providers` metadata property with an array of the services that you'll test or mock. + + + +Then inject it inside a test by calling `TestBed.inject()` with the service class as the argument. + +HELPFUL: `TestBed.get()` was deprecated as of Angular version 9. +To help minimize breaking changes, Angular introduces a new function called `TestBed.inject()`, which you should use instead. + + + +Or inside the `beforeEach()` if you prefer to inject the service as part of your setup. + + + +When testing a service with a dependency, provide the mock in the `providers` array. + +In the following example, the mock is a spy object. + + + +The test consumes that spy in the same way it did earlier. + + + +## Testing without `beforeEach()` + +Most test suites in this guide call `beforeEach()` to set the preconditions for each `it()` test and rely on the `TestBed` to create classes and inject services. + +There's another school of testing that never calls `beforeEach()` and prefers to create classes explicitly rather than use the `TestBed`. + +Here's how you might rewrite one of the `MasterService` tests in that style. + +Begin by putting re-usable, preparatory code in a *setup* function instead of `beforeEach()`. + + + +The `setup()` function returns an object literal with the variables, such as `masterService`, that a test might reference. +You don't define *semi-global* variables \(for example, `let masterService: MasterService`\) in the body of the `describe()`. + +Then each test invokes `setup()` in its first line, before continuing with steps that manipulate the test subject and assert expectations. + + + +Notice how the test uses [*destructuring assignment*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) to extract the setup variables that it needs. + + + +Many developers feel this approach is cleaner and more explicit than the traditional `beforeEach()` style. + +Although this testing guide follows the traditional style and the default [CLI schematics](https://github.com/angular/angular-cli) generate test files with `beforeEach()` and `TestBed`, feel free to adopt *this alternative approach* in your own projects. + +## Testing HTTP services + +Data services that make HTTP calls to remote servers typically inject and delegate to the Angular [`HttpClient`](guide/http/testing) service for XHR calls. + +You can test a data service with an injected `HttpClient` spy as you would test any service with a dependency. + + + +IMPORTANT: The `HeroService` methods return `Observables`. +You must *subscribe* to an observable to \(a\) cause it to execute and \(b\) assert that the method succeeds or fails. + +The `subscribe()` method takes a success \(`next`\) and fail \(`error`\) callback. +Make sure you provide *both* callbacks so that you capture errors. +Neglecting to do so produces an asynchronous uncaught observable error that the test runner will likely attribute to a completely different test. + +## `HttpClientTestingModule` + +Extended interactions between a data service and the `HttpClient` can be complex and difficult to mock with spies. + +The `HttpClientTestingModule` can make these testing scenarios more manageable. + +While the *code sample* accompanying this guide demonstrates `HttpClientTestingModule`, this page defers to the [Http guide](guide/http/testing), which covers testing with the `HttpClientTestingModule` in detail. diff --git a/adev-es/src/content/guide/testing/services.md b/adev-es/src/content/guide/testing/services.md index 4a7ed5f..a901a4c 100644 --- a/adev-es/src/content/guide/testing/services.md +++ b/adev-es/src/content/guide/testing/services.md @@ -1,129 +1,129 @@ -# Testing services +# Probar servicios -To check that your services are working as you intend, you can write tests specifically for them. +Para verificar que tus servicios están funcionando como pretendes, puedes escribir pruebas específicamente para ellos. -Services are often the smoothest files to unit test. -Here are some synchronous and asynchronous unit tests of the `ValueService` written without assistance from Angular testing utilities. +Los servicios son a menudo los archivos más sencillos de probar unitariamente. +Aquí hay algunas pruebas unitarias síncronas y asíncronas del `ValueService` escritas sin ayuda de las utilidades de pruebas de Angular. -## Services with dependencies +## Servicios con dependencias -Services often depend on other services that Angular injects into the constructor. -In many cases, you can create and *inject* these dependencies by hand while calling the service's constructor. +Los servicios a menudo dependen de otros servicios que Angular inyecta en el constructor. +En muchos casos, puedes crear e *inyectar* estas dependencias manualmente mientras llamas al constructor del servicio. -The `MasterService` is a simple example: +El `MasterService` es un ejemplo simple: -`MasterService` delegates its only method, `getValue`, to the injected `ValueService`. +`MasterService` delega su único método, `getValue`, al `ValueService` inyectado. -Here are several ways to test it. +Aquí hay varias formas de probarlo. -The first test creates a `ValueService` with `new` and passes it to the `MasterService` constructor. +La primera prueba crea un `ValueService` con `new` y lo pasa al constructor de `MasterService`. -However, injecting the real service rarely works well as most dependent services are difficult to create and control. +Sin embargo, inyectar el servicio real rara vez funciona bien ya que la mayoría de los servicios dependientes son difíciles de crear y controlar. -Instead, mock the dependency, use a dummy value, or create a [spy](https://jasmine.github.io/tutorials/your_first_suite#section-Spies) on the pertinent service method. +En su lugar, simula la dependencia, usa un valor dummy, o crea un [spy](https://jasmine.github.io/tutorials/your_first_suite#section-Spies) en el método pertinente del servicio. -HELPFUL: Prefer spies as they are usually the best way to mock services. +ÚTIL: Prefiere los spies ya que usualmente son la mejor forma de simular servicios. -These standard testing techniques are great for unit testing services in isolation. +Estas técnicas estándar de pruebas son geniales para probar servicios de forma aislada unitariamente. -However, you almost always inject services into application classes using Angular dependency injection and you should have tests that reflect that usage pattern. -Angular testing utilities make it straightforward to investigate how injected services behave. +Sin embargo, casi siempre inyectas servicios en clases de aplicación usando inyección de dependencias de Angular y deberías tener pruebas que reflejen ese patrón de uso. +Las utilidades de pruebas de Angular hacen que sea sencillo investigar cómo se comportan los servicios inyectados. -## Testing services with the `TestBed` +## Probar servicios con el `TestBed` -Your application relies on Angular [dependency injection (DI)](guide/di) to create services. -When a service has a dependent service, DI finds or creates that dependent service. -And if that dependent service has its own dependencies, DI finds-or-creates them as well. +Tu aplicación depende de la [inyección de dependencias (DI)](guide/di) de Angular para crear servicios. +Cuando un servicio tiene un servicio dependiente, DI encuentra o crea ese servicio dependiente. +Y si ese servicio dependiente tiene sus propias dependencias, DI las encuentra-o-crea también. -As a service *consumer*, you don't worry about any of this. -You don't worry about the order of constructor arguments or how they're created. +Como *consumidor* del servicio, no te preocupas por nada de esto. +No te preocupas por el orden de los argumentos del constructor o cómo se crean. -As a service *tester*, you must at least think about the first level of service dependencies but you *can* let Angular DI do the service creation and deal with constructor argument order when you use the `TestBed` testing utility to provide and create services. +Como *probador* del servicio, debes al menos pensar sobre el primer nivel de dependencias del servicio pero *puedes* dejar que Angular DI haga la creación del servicio y se ocupe del orden de los argumentos del constructor cuando usas la utilidad de pruebas `TestBed` para proporcionar y crear servicios. ## Angular `TestBed` -The `TestBed` is the most important of the Angular testing utilities. -The `TestBed` creates a dynamically-constructed Angular *test* module that emulates an Angular [@NgModule](guide/ngmodules). +El `TestBed` es la más importante de las utilidades de pruebas de Angular. +El `TestBed` crea un módulo *test* de Angular construido dinámicamente que emula un [@NgModule](guide/ngmodules) de Angular. -The `TestBed.configureTestingModule()` method takes a metadata object that can have most of the properties of an [@NgModule](guide/ngmodules). +El método `TestBed.configureTestingModule()` toma un objeto de metadata que puede tener la mayoría de las propiedades de un [@NgModule](guide/ngmodules). -To test a service, you set the `providers` metadata property with an array of the services that you'll test or mock. +Para probar un servicio, estableces la propiedad de metadata `providers` con un array de los servicios que probarás o simularás. -Then inject it inside a test by calling `TestBed.inject()` with the service class as the argument. +Luego inyéctalo dentro de una prueba llamando a `TestBed.inject()` con la clase del servicio como argumento. -HELPFUL: `TestBed.get()` was deprecated as of Angular version 9. -To help minimize breaking changes, Angular introduces a new function called `TestBed.inject()`, which you should use instead. +ÚTIL: `TestBed.get()` fue deprecado a partir de la versión 9 de Angular. +Para ayudar a minimizar cambios disruptivos, Angular introduce una nueva función llamada `TestBed.inject()`, que deberías usar en su lugar. -Or inside the `beforeEach()` if you prefer to inject the service as part of your setup. +O dentro del `beforeEach()` si prefieres inyectar el servicio como parte de tu configuración. -When testing a service with a dependency, provide the mock in the `providers` array. +Cuando pruebes un servicio con una dependencia, proporciona el mock en el array `providers`. -In the following example, the mock is a spy object. +En el siguiente ejemplo, el mock es un objeto spy. -The test consumes that spy in the same way it did earlier. +La prueba consume ese spy de la misma manera que lo hizo antes. -## Testing without `beforeEach()` +## Probar sin `beforeEach()` -Most test suites in this guide call `beforeEach()` to set the preconditions for each `it()` test and rely on the `TestBed` to create classes and inject services. +La mayoría de suites de prueba en esta guía llaman a `beforeEach()` para establecer las precondiciones para cada prueba `it()` y dependen del `TestBed` para crear clases e inyectar servicios. -There's another school of testing that never calls `beforeEach()` and prefers to create classes explicitly rather than use the `TestBed`. +Hay otra escuela de pruebas que nunca llama a `beforeEach()` y prefiere crear clases explícitamente en lugar de usar el `TestBed`. -Here's how you might rewrite one of the `MasterService` tests in that style. +Aquí está cómo podrías reescribir una de las pruebas de `MasterService` en ese estilo. -Begin by putting re-usable, preparatory code in a *setup* function instead of `beforeEach()`. +Comienza poniendo código preparatorio reutilizable en una función *setup* en lugar de `beforeEach()`. -The `setup()` function returns an object literal with the variables, such as `masterService`, that a test might reference. -You don't define *semi-global* variables \(for example, `let masterService: MasterService`\) in the body of the `describe()`. +La función `setup()` retorna un objeto literal con las variables, como `masterService`, que una prueba podría referenciar. +No defines variables *semi-globales* \(por ejemplo, `let masterService: MasterService`\) en el cuerpo del `describe()`. -Then each test invokes `setup()` in its first line, before continuing with steps that manipulate the test subject and assert expectations. +Luego cada prueba invoca `setup()` en su primera línea, antes de continuar con pasos que manipulan el sujeto de prueba y afirman expectativas. -Notice how the test uses [*destructuring assignment*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) to extract the setup variables that it needs. +Nota cómo la prueba usa [*asignación por desestructuración*](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) para extraer las variables de setup que necesita. -Many developers feel this approach is cleaner and more explicit than the traditional `beforeEach()` style. +Muchos desarrolladores sienten que este enfoque es más limpio y más explícito que el estilo tradicional de `beforeEach()`. -Although this testing guide follows the traditional style and the default [CLI schematics](https://github.com/angular/angular-cli) generate test files with `beforeEach()` and `TestBed`, feel free to adopt *this alternative approach* in your own projects. +Aunque esta guía de pruebas sigue el estilo tradicional y los [schematics por defecto del CLI](https://github.com/angular/angular-cli) generan archivos de prueba con `beforeEach()` y `TestBed`, siéntete libre de adoptar *este enfoque alternativo* en tus propios proyectos. -## Testing HTTP services +## Probar servicios HTTP -Data services that make HTTP calls to remote servers typically inject and delegate to the Angular [`HttpClient`](guide/http/testing) service for XHR calls. +Los servicios de datos que hacen llamadas HTTP a servidores remotos típicamente inyectan y delegan al servicio [`HttpClient`](guide/http/testing) de Angular para llamadas XHR. -You can test a data service with an injected `HttpClient` spy as you would test any service with a dependency. +Puedes probar un servicio de datos con un spy de `HttpClient` inyectado como probarías cualquier servicio con una dependencia. -IMPORTANT: The `HeroService` methods return `Observables`. -You must *subscribe* to an observable to \(a\) cause it to execute and \(b\) assert that the method succeeds or fails. +IMPORTANTE: Los métodos de `HeroService` retornan `Observables`. +Debes *suscribirte* a un observable para \(a\) hacer que se ejecute y \(b\) afirmar que el método tiene éxito o falla. -The `subscribe()` method takes a success \(`next`\) and fail \(`error`\) callback. -Make sure you provide *both* callbacks so that you capture errors. -Neglecting to do so produces an asynchronous uncaught observable error that the test runner will likely attribute to a completely different test. +El método `subscribe()` toma un callback de éxito \(`next`\) y uno de fallo \(`error`\). +Asegúrate de proporcionar *ambos* callbacks para que captures errores. +Descuidar hacerlo produce un error asíncrono no capturado de observable que el test runner probablemente atribuirá a una prueba completamente diferente. ## `HttpClientTestingModule` -Extended interactions between a data service and the `HttpClient` can be complex and difficult to mock with spies. +Las interacciones extendidas entre un servicio de datos y el `HttpClient` pueden ser complejas y difíciles de simular con spies. -The `HttpClientTestingModule` can make these testing scenarios more manageable. +El `HttpClientTestingModule` puede hacer que estos escenarios de pruebas sean más manejables. -While the *code sample* accompanying this guide demonstrates `HttpClientTestingModule`, this page defers to the [Http guide](guide/http/testing), which covers testing with the `HttpClientTestingModule` in detail. +Mientras que la *muestra de código* que acompaña esta guía demuestra `HttpClientTestingModule`, esta página difiere a la [guía de Http](guide/http/testing), que cubre pruebas con el `HttpClientTestingModule` en detalle. diff --git a/adev-es/src/content/guide/testing/using-component-harnesses.en.md b/adev-es/src/content/guide/testing/using-component-harnesses.en.md new file mode 100644 index 0000000..03cbe63 --- /dev/null +++ b/adev-es/src/content/guide/testing/using-component-harnesses.en.md @@ -0,0 +1,220 @@ +# Using component harnesses in tests + +## Before you start + +TIP: This guide assumes you've already read the [component harnesses overview guide](guide/testing/component-harnesses-overview). Read that first if you're new to using component harnesses. + +### CDK Installation + +The [Component Dev Kit (CDK)](https://material.angular.dev/cdk/categories) is a set of behavior primitives for building components. To use the component harnesses, first install `@angular/cdk` from npm. You can do this from your terminal using the Angular CLI: + + + ng add @angular/cdk + + +## Test harness environments and loaders + +You can use component test harnesses in different test environments. Angular CDK supports two built-in environments: + +- Unit tests with Angular's `TestBed` +- End-to-end tests with [WebDriver](https://developer.mozilla.org/en-US/docs/Web/WebDriver) + +Each environment provides a harness loader. The loader creates the harness instances you use throughout your tests. See below for more specific guidance on supported testing environments. + +Additional testing environments require custom bindings. See the [adding harness support for additional testing environments guide](guide/testing/component-harnesses-testing-environments) for more information. + +### Using the loader from `TestbedHarnessEnvironment` for unit tests + +For unit tests you can create a harness loader from [TestbedHarnessEnvironment](/api/cdk/testing/TestbedHarnessEnvironment). This environment uses a [component fixture](api/core/testing/ComponentFixture) created by Angular's `TestBed`. + +To create a harness loader rooted at the fixture's root element, use the `loader()` method: + + +const fixture = TestBed.createComponent(MyComponent); + +// Create a harness loader from the fixture +const loader = TestbedHarnessEnvironment.loader(fixture); +... + +// Use the loader to get harness instances +const myComponentHarness = await loader.getHarness(MyComponent); + + +To create a harness loader for harnesses for elements that fall outside the fixture, use the `documentRootLoader()` method. For example, code that displays a floating element or pop-up often attaches DOM elements directly to the document body, such as the `Overlay` service in Angular CDK. + +You can also create a harness loader directly with `harnessForFixture()` for a harness at that fixture's root element directly. + +### Using the loader from `SeleniumWebDriverHarnessEnvironment` for end-to-end tests + +For WebDriver-based end-to-end tests you can create a harness loader with `SeleniumWebDriverHarnessEnvironment`. + +Use the `loader()` method to get the harness loader instance for the current HTML document, rooted at the document's root element. This environment uses a WebDriver client. + + +let wd: webdriver.WebDriver = getMyWebDriverClient(); +const loader = SeleniumWebDriverHarnessEnvironment.loader(wd); +... +const myComponentHarness = await loader.getHarness(MyComponent); + + +## Using a harness loader + +Harness loader instances correspond to a specific DOM element and are used to create component harness instances for elements under that specific element. + +To get `ComponentHarness` for the first instance of the element, use the `getHarness()` method. To get all `ComponentHarness` instances, use the `getAllHarnesses()` method. + + +// Get harness for first instance of the element +const myComponentHarness = await loader.getHarness(MyComponent); + +// Get harnesses for all instances of the element +const myComponentHarnesses = await loader.getHarnesses(MyComponent); + + +In addition to `getHarness` and `getAllHarnesses`, `HarnessLoader` has several other useful methods for querying for harnesses: + +- `getHarnessAtIndex(...)`: Gets the harness for a component that matches the given criteria at a specific index. +- `countHarnesses(...)`: Counts the number of component instances that match the given criteria. +- `hasHarness(...)`: Checks if at least one component instance matches the given criteria. + +As an example, consider a reusable dialog-button component that opens a dialog on click. It contains the following components, each with a corresponding harness: + +- `MyDialogButton` (composes the `MyButton` and `MyDialog` with a convenient API) +- `MyButton` (a standard button component) +- `MyDialog` (a dialog appended to `document.body` by `MyDialogButton` upon click) + +The following test loads harnesses for each of these components: + + +let fixture: ComponentFixture; +let loader: HarnessLoader; +let rootLoader: HarnessLoader; + +beforeEach(() => { + fixture = TestBed.createComponent(MyDialogButton); + loader = TestbedHarnessEnvironment.loader(fixture); + rootLoader = TestbedHarnessEnvironment.documentRootLoader(fixture); +}); + +it('loads harnesses', async () => { + // Load a harness for the bootstrapped component with `harnessForFixture` + dialogButtonHarness = + await TestbedHarnessEnvironment.harnessForFixture(fixture, MyDialogButtonHarness); + + // The button element is inside the fixture's root element, so we use `loader`. + const buttonHarness = await loader.getHarness(MyButtonHarness); + + // Click the button to open the dialog + await buttonHarness.click(); + + // The dialog is appended to `document.body`, outside of the fixture's root element, + // so we use `rootLoader` in this case. + const dialogHarness = await rootLoader.getHarness(MyDialogHarness); + + // ... make some assertions +}); + + +### Harness behavior in different environments + +Harnesses may not behave exactly the same in all environments. Some differences are unavoidable between the real user interaction versus the simulated events generated in unit tests. Angular CDK makes a best effort to normalize the behavior to the extent possible. + +### Interacting with child elements + +To interact with elements below the root element of this harness loader, use the `HarnessLoader` instance of a child element. For the first instance of the child element, use the `getChildLoader()` method. For all instances of the child element, use the `getAllChildLoaders()` method. + + +const myComponentHarness = await loader.getHarness(MyComponent); + +// Get loader for first instance of child element with '.child' selector +const childLoader = await myComponentHarness.getLoader('.child'); + +// Get loaders for all instances of child elements with '.child' selector +const allChildLoaders = await myComponentHarness.getAllChildLoaders('.child'); + + +### Filtering harnesses + +When a page contains multiple instances of a particular component, you may want to filter based on some property of the component to get a particular component instance. You can use a harness predicate, a class used to associate a `ComponentHarness` class with predicates functions that can be used to filter component instances, to do so. + +When you ask a `HarnessLoader` for a harness, you're actually providing a HarnessQuery. A query can be one of two things: + +- A harness constructor. This just gets that harness +- A `HarnessPredicate`, which gets harnesses that are filtered based on one or more conditions + +`HarnessPredicate` does support some base filters (selector, ancestor) that work on anything that extends `ComponentHarness`. + + +// Example of loading a MyButtonComponentHarness with a harness predicate +const disabledButtonPredicate = new HarnessPredicate(MyButtonComponentHarness, {selector: '[disabled]'}); +const disabledButton = await loader.getHarness(disabledButtonPredicate); + + +However it's common for harnesses to implement a static `with()` method that accepts component-specific filtering options and returns a `HarnessPredicate`. + + +// Example of loading a MyButtonComponentHarness with a specific selector +const button = await loader.getHarness(MyButtonComponentHarness.with({selector: 'btn'})) + + +For more details refer to the specific harness documentation since additional filtering options are specific to each harness implementation. + +## Using test harness APIs + +While every harness defines an API specific to its corresponding component, they all share a common base class, [ComponentHarness](/api/cdk/testing/ComponentHarness). This base class defines a static property, `hostSelector`, that matches the harness class to instances of the component in the DOM. + +Beyond that, the API of any given harness is specific to its corresponding component; refer to the component's documentation to learn how to use a specific harness. + +As an example, the following is a test for a component that uses the [Angular Material slider component harness](https://material.angular.dev/components/slider/api#MatSliderHarness): + + +it('should get value of slider thumb', async () => { + const slider = await loader.getHarness(MatSliderHarness); + const thumb = await slider.getEndThumb(); + expect(await thumb.getValue()).toBe(50); +}); + + +## Interop with Angular change detection + +By default, test harnesses runs Angular's [change detection](https://angular.dev/best-practices/runtime-performance) before reading the state of a DOM element and after interacting with a DOM element. + +There may be times that you need finer-grained control over change detection in your tests. such as checking the state of a component while an async operation is pending. In these cases use the `manualChangeDetection` function to disable automatic handling of change detection for a block of code. + + +it('checks state while async action is in progress', async () => { + const buttonHarness = loader.getHarness(MyButtonHarness); + await manualChangeDetection(async () => { + await buttonHarness.click(); + fixture.detectChanges(); + // Check expectations while async click operation is in progress. + expect(isProgressSpinnerVisible()).toBe(true); + await fixture.whenStable(); + // Check expectations after async click operation complete. + expect(isProgressSpinnerVisible()).toBe(false); + }); +}); + + +Almost all harness methods are asynchronous and return a `Promise` to support the following: + +- Support for unit tests +- Support for end-to-end tests +- Insulate tests against changes in asynchronous behavior + +The Angular team recommends using [await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) to improve the test readability. Calling `await` blocks the execution of your test until the associated `Promise` resolves. + +Occasionally, you may want to perform multiple actions simultaneously and wait until they're all done rather than performing each action sequentially. For example, read multiple properties of a single component. In these situations use the `parallel` function to parallelize the operations. The parallel function works similarly to `Promise.all`, while also optimizing change detection checks. + + +it('reads properties in parallel', async () => { + const checkboxHarness = loader.getHarness(MyCheckboxHarness); + // Read the checked and intermediate properties simultaneously. + const [checked, indeterminate] = await parallel(() => [ + checkboxHarness.isChecked(), + checkboxHarness.isIndeterminate() + ]); + expect(checked).toBe(false); + expect(indeterminate).toBe(true); +}); + diff --git a/adev-es/src/content/guide/testing/using-component-harnesses.md b/adev-es/src/content/guide/testing/using-component-harnesses.md index 03cbe63..6272684 100644 --- a/adev-es/src/content/guide/testing/using-component-harnesses.md +++ b/adev-es/src/content/guide/testing/using-component-harnesses.md @@ -1,54 +1,54 @@ -# Using component harnesses in tests +# Usar component harnesses en pruebas -## Before you start +## Antes de comenzar -TIP: This guide assumes you've already read the [component harnesses overview guide](guide/testing/component-harnesses-overview). Read that first if you're new to using component harnesses. +CONSEJO: Esta guía asume que ya leíste la [guía de visión general de component harnesses](guide/testing/component-harnesses-overview). Lee eso primero si eres nuevo en el uso de component harnesses. -### CDK Installation +### Instalación del CDK -The [Component Dev Kit (CDK)](https://material.angular.dev/cdk/categories) is a set of behavior primitives for building components. To use the component harnesses, first install `@angular/cdk` from npm. You can do this from your terminal using the Angular CLI: +El [Component Dev Kit (CDK)](https://material.angular.dev/cdk/categories) es un conjunto de primitivas de comportamiento para construir componentes. Para usar los component harnesses, primero instala `@angular/cdk` desde npm. Puedes hacer esto desde tu terminal usando Angular CLI: ng add @angular/cdk -## Test harness environments and loaders +## Entornos de test harness y loaders -You can use component test harnesses in different test environments. Angular CDK supports two built-in environments: +Puedes usar component test harnesses en diferentes entornos de prueba. El CDK de Angular soporta dos entornos integrados: -- Unit tests with Angular's `TestBed` -- End-to-end tests with [WebDriver](https://developer.mozilla.org/en-US/docs/Web/WebDriver) +- Pruebas unitarias con el `TestBed` de Angular +- Pruebas end-to-end con [WebDriver](https://developer.mozilla.org/en-US/docs/Web/WebDriver) -Each environment provides a harness loader. The loader creates the harness instances you use throughout your tests. See below for more specific guidance on supported testing environments. +Cada entorno proporciona un harness loader. El loader crea las instancias de harness que usas a lo largo de tus pruebas. Consulta abajo para una guía más específica sobre entornos de testing soportados. -Additional testing environments require custom bindings. See the [adding harness support for additional testing environments guide](guide/testing/component-harnesses-testing-environments) for more information. +Los entornos de testing adicionales requieren bindings personalizados. Consulta la [guía de agregar soporte de harness para entornos de testing adicionales](guide/testing/component-harnesses-testing-environments) para más información. -### Using the loader from `TestbedHarnessEnvironment` for unit tests +### Usar el loader de `TestbedHarnessEnvironment` para pruebas unitarias -For unit tests you can create a harness loader from [TestbedHarnessEnvironment](/api/cdk/testing/TestbedHarnessEnvironment). This environment uses a [component fixture](api/core/testing/ComponentFixture) created by Angular's `TestBed`. +Para pruebas unitarias puedes crear un harness loader desde [TestbedHarnessEnvironment](/api/cdk/testing/TestbedHarnessEnvironment). Este entorno usa un [component fixture](api/core/testing/ComponentFixture) creado por el `TestBed` de Angular. -To create a harness loader rooted at the fixture's root element, use the `loader()` method: +Para crear un harness loader enraizado en el elemento raíz del fixture, usa el método `loader()`: const fixture = TestBed.createComponent(MyComponent); -// Create a harness loader from the fixture +// Crear un harness loader desde el fixture const loader = TestbedHarnessEnvironment.loader(fixture); ... -// Use the loader to get harness instances +// Usar el loader para obtener instancias de harness const myComponentHarness = await loader.getHarness(MyComponent); -To create a harness loader for harnesses for elements that fall outside the fixture, use the `documentRootLoader()` method. For example, code that displays a floating element or pop-up often attaches DOM elements directly to the document body, such as the `Overlay` service in Angular CDK. +Para crear un harness loader para harnesses para elementos que caen fuera del fixture, usa el método `documentRootLoader()`. Por ejemplo, código que muestra un elemento flotante o pop-up a menudo adjunta elementos DOM directamente al body del documento, como el servicio `Overlay` en el CDK de Angular. -You can also create a harness loader directly with `harnessForFixture()` for a harness at that fixture's root element directly. +También puedes crear un harness loader directamente con `harnessForFixture()` para un harness en el elemento raíz de ese fixture directamente. -### Using the loader from `SeleniumWebDriverHarnessEnvironment` for end-to-end tests +### Usar el loader de `SeleniumWebDriverHarnessEnvironment` para pruebas end-to-end -For WebDriver-based end-to-end tests you can create a harness loader with `SeleniumWebDriverHarnessEnvironment`. +Para pruebas end-to-end basadas en WebDriver puedes crear un harness loader con `SeleniumWebDriverHarnessEnvironment`. -Use the `loader()` method to get the harness loader instance for the current HTML document, rooted at the document's root element. This environment uses a WebDriver client. +Usa el método `loader()` para obtener la instancia de harness loader para el documento HTML actual, enraizado en el elemento raíz del documento. Este entorno usa un cliente WebDriver. let wd: webdriver.WebDriver = getMyWebDriverClient(); @@ -57,33 +57,33 @@ const loader = SeleniumWebDriverHarnessEnvironment.loader(wd); const myComponentHarness = await loader.getHarness(MyComponent); -## Using a harness loader +## Usar un harness loader -Harness loader instances correspond to a specific DOM element and are used to create component harness instances for elements under that specific element. +Las instancias de harness loader corresponden a un elemento DOM específico y se usan para crear instancias de component harness para elementos bajo ese elemento específico. -To get `ComponentHarness` for the first instance of the element, use the `getHarness()` method. To get all `ComponentHarness` instances, use the `getAllHarnesses()` method. +Para obtener `ComponentHarness` para la primera instancia del elemento, usa el método `getHarness()`. Para obtener todas las instancias de `ComponentHarness`, usa el método `getAllHarnesses()`. -// Get harness for first instance of the element +// Obtener harness para la primera instancia del elemento const myComponentHarness = await loader.getHarness(MyComponent); -// Get harnesses for all instances of the element +// Obtener harnesses para todas las instancias del elemento const myComponentHarnesses = await loader.getHarnesses(MyComponent); -In addition to `getHarness` and `getAllHarnesses`, `HarnessLoader` has several other useful methods for querying for harnesses: +Además de `getHarness` y `getAllHarnesses`, `HarnessLoader` tiene varios otros métodos útiles para consultar harnesses: -- `getHarnessAtIndex(...)`: Gets the harness for a component that matches the given criteria at a specific index. -- `countHarnesses(...)`: Counts the number of component instances that match the given criteria. -- `hasHarness(...)`: Checks if at least one component instance matches the given criteria. +- `getHarnessAtIndex(...)`: Obtiene el harness para un componente que coincide con el criterio dado en un índice específico. +- `countHarnesses(...)`: Cuenta el número de instancias de componente que coinciden con el criterio dado. +- `hasHarness(...)`: Verifica si al menos una instancia de componente coincide con el criterio dado. -As an example, consider a reusable dialog-button component that opens a dialog on click. It contains the following components, each with a corresponding harness: +Como ejemplo, considera un componente dialog-button reutilizable que abre un diálogo al hacer clic. Contiene los siguientes componentes, cada uno con un harness correspondiente: -- `MyDialogButton` (composes the `MyButton` and `MyDialog` with a convenient API) -- `MyButton` (a standard button component) -- `MyDialog` (a dialog appended to `document.body` by `MyDialogButton` upon click) +- `MyDialogButton` (compone el `MyButton` y `MyDialog` con una API conveniente) +- `MyButton` (un componente button estándar) +- `MyDialog` (un diálogo adjuntado a `document.body` por `MyDialogButton` al hacer clic) -The following test loads harnesses for each of these components: +La siguiente prueba carga harnesses para cada uno de estos componentes: let fixture: ComponentFixture; @@ -97,75 +97,75 @@ beforeEach(() => { }); it('loads harnesses', async () => { - // Load a harness for the bootstrapped component with `harnessForFixture` + // Cargar un harness para el componente bootstrap con `harnessForFixture` dialogButtonHarness = await TestbedHarnessEnvironment.harnessForFixture(fixture, MyDialogButtonHarness); - // The button element is inside the fixture's root element, so we use `loader`. + // El elemento button está dentro del elemento raíz del fixture, así que usamos `loader`. const buttonHarness = await loader.getHarness(MyButtonHarness); - // Click the button to open the dialog + // Hacer clic en el botón para abrir el diálogo await buttonHarness.click(); - // The dialog is appended to `document.body`, outside of the fixture's root element, - // so we use `rootLoader` in this case. + // El diálogo se adjunta a `document.body`, fuera del elemento raíz del fixture, + // así que usamos `rootLoader` en este caso. const dialogHarness = await rootLoader.getHarness(MyDialogHarness); - // ... make some assertions + // ... hacer algunas afirmaciones }); -### Harness behavior in different environments +### Comportamiento de harness en diferentes entornos -Harnesses may not behave exactly the same in all environments. Some differences are unavoidable between the real user interaction versus the simulated events generated in unit tests. Angular CDK makes a best effort to normalize the behavior to the extent possible. +Los harnesses pueden no comportarse exactamente igual en todos los entornos. Algunas diferencias son inevitables entre la interacción real del usuario versus los eventos simulados generados en pruebas unitarias. El CDK de Angular hace un mejor esfuerzo para normalizar el comportamiento en la medida posible. -### Interacting with child elements +### Interactuar con elementos hijos -To interact with elements below the root element of this harness loader, use the `HarnessLoader` instance of a child element. For the first instance of the child element, use the `getChildLoader()` method. For all instances of the child element, use the `getAllChildLoaders()` method. +Para interactuar con elementos debajo del elemento raíz de este harness loader, usa la instancia `HarnessLoader` de un elemento hijo. Para la primera instancia del elemento hijo, usa el método `getChildLoader()`. Para todas las instancias del elemento hijo, usa el método `getAllChildLoaders()`. const myComponentHarness = await loader.getHarness(MyComponent); -// Get loader for first instance of child element with '.child' selector +// Obtener loader para la primera instancia del elemento hijo con selector '.child' const childLoader = await myComponentHarness.getLoader('.child'); -// Get loaders for all instances of child elements with '.child' selector +// Obtener loaders para todas las instancias de elementos hijos con selector '.child' const allChildLoaders = await myComponentHarness.getAllChildLoaders('.child'); -### Filtering harnesses +### Filtrar harnesses -When a page contains multiple instances of a particular component, you may want to filter based on some property of the component to get a particular component instance. You can use a harness predicate, a class used to associate a `ComponentHarness` class with predicates functions that can be used to filter component instances, to do so. +Cuando una página contiene múltiples instancias de un componente particular, es posible que quieras filtrar basado en alguna propiedad del componente para obtener una instancia de componente particular. Puedes usar un harness predicate, una clase usada para asociar una clase `ComponentHarness` con funciones predicates que pueden usarse para filtrar instancias de componentes, para hacerlo. -When you ask a `HarnessLoader` for a harness, you're actually providing a HarnessQuery. A query can be one of two things: +Cuando le pides a un `HarnessLoader` un harness, en realidad estás proporcionando una HarnessQuery. Una consulta puede ser una de dos cosas: -- A harness constructor. This just gets that harness -- A `HarnessPredicate`, which gets harnesses that are filtered based on one or more conditions +- Un constructor de harness. Esto solo obtiene ese harness +- Un `HarnessPredicate`, que obtiene harnesses que están filtrados basados en una o más condiciones -`HarnessPredicate` does support some base filters (selector, ancestor) that work on anything that extends `ComponentHarness`. +`HarnessPredicate` soporta algunos filtros base (selector, ancestor) que funcionan en cualquier cosa que extienda `ComponentHarness`. -// Example of loading a MyButtonComponentHarness with a harness predicate +// Ejemplo de cargar un MyButtonComponentHarness con un harness predicate const disabledButtonPredicate = new HarnessPredicate(MyButtonComponentHarness, {selector: '[disabled]'}); const disabledButton = await loader.getHarness(disabledButtonPredicate); -However it's common for harnesses to implement a static `with()` method that accepts component-specific filtering options and returns a `HarnessPredicate`. +Sin embargo, es común que los harnesses implementen un método estático `with()` que acepta opciones de filtrado específicas del componente y retorna un `HarnessPredicate`. -// Example of loading a MyButtonComponentHarness with a specific selector +// Ejemplo de cargar un MyButtonComponentHarness con un selector específico const button = await loader.getHarness(MyButtonComponentHarness.with({selector: 'btn'})) -For more details refer to the specific harness documentation since additional filtering options are specific to each harness implementation. +Para más detalles consulta la documentación específica del harness ya que las opciones de filtrado adicionales son específicas de cada implementación de harness. -## Using test harness APIs +## Usar APIs de test harness -While every harness defines an API specific to its corresponding component, they all share a common base class, [ComponentHarness](/api/cdk/testing/ComponentHarness). This base class defines a static property, `hostSelector`, that matches the harness class to instances of the component in the DOM. +Aunque cada harness define una API específica para su componente correspondiente, todos comparten una clase base común, [ComponentHarness](/api/cdk/testing/ComponentHarness). Esta clase base define una propiedad estática, `hostSelector`, que coincide la clase harness con instancias del componente en el DOM. -Beyond that, the API of any given harness is specific to its corresponding component; refer to the component's documentation to learn how to use a specific harness. +Más allá de eso, la API de cualquier harness dado es específica de su componente correspondiente; consulta la documentación del componente para aprender cómo usar un harness específico. -As an example, the following is a test for a component that uses the [Angular Material slider component harness](https://material.angular.dev/components/slider/api#MatSliderHarness): +Como ejemplo, lo siguiente es una prueba para un componente que usa el [harness del componente slider de Angular Material](https://material.angular.dev/components/slider/api#MatSliderHarness): it('should get value of slider thumb', async () => { @@ -175,11 +175,11 @@ it('should get value of slider thumb', async () => { }); -## Interop with Angular change detection +## Interoperabilidad con la detección de cambios de Angular -By default, test harnesses runs Angular's [change detection](https://angular.dev/best-practices/runtime-performance) before reading the state of a DOM element and after interacting with a DOM element. +Por defecto, los test harnesses ejecutan la [detección de cambios](https://angular.dev/best-practices/runtime-performance) de Angular antes de leer el estado de un elemento DOM y después de interactuar con un elemento DOM. -There may be times that you need finer-grained control over change detection in your tests. such as checking the state of a component while an async operation is pending. In these cases use the `manualChangeDetection` function to disable automatic handling of change detection for a block of code. +Puede haber momentos en que necesites un control más fino sobre la detección de cambios en tus pruebas, como verificar el estado de un componente mientras una operación async está pendiente. En estos casos usa la función `manualChangeDetection` para deshabilitar el manejo automático de detección de cambios para un bloque de código. it('checks state while async action is in progress', async () => { @@ -187,29 +187,29 @@ it('checks state while async action is in progress', async () => { await manualChangeDetection(async () => { await buttonHarness.click(); fixture.detectChanges(); - // Check expectations while async click operation is in progress. + // Verificar expectativas mientras la operación de clic async está en progreso. expect(isProgressSpinnerVisible()).toBe(true); await fixture.whenStable(); - // Check expectations after async click operation complete. + // Verificar expectativas después de que la operación de clic async se complete. expect(isProgressSpinnerVisible()).toBe(false); }); }); -Almost all harness methods are asynchronous and return a `Promise` to support the following: +Casi todos los métodos de harness son asíncronos y retornan una `Promise` para soportar lo siguiente: -- Support for unit tests -- Support for end-to-end tests -- Insulate tests against changes in asynchronous behavior +- Soporte para pruebas unitarias +- Soporte para pruebas end-to-end +- Aislar pruebas contra cambios en comportamiento asíncrono -The Angular team recommends using [await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) to improve the test readability. Calling `await` blocks the execution of your test until the associated `Promise` resolves. +El equipo de Angular recomienda usar [await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) para mejorar la legibilidad de la prueba. Llamar a `await` bloquea la ejecución de tu prueba hasta que la `Promise` asociada se resuelva. -Occasionally, you may want to perform multiple actions simultaneously and wait until they're all done rather than performing each action sequentially. For example, read multiple properties of a single component. In these situations use the `parallel` function to parallelize the operations. The parallel function works similarly to `Promise.all`, while also optimizing change detection checks. +Ocasionalmente, es posible que quieras realizar múltiples acciones simultáneamente y esperar hasta que todas estén hechas en lugar de realizar cada acción secuencialmente. Por ejemplo, leer múltiples propiedades de un solo componente. En estas situaciones usa la función `parallel` para paralelizar las operaciones. La función parallel funciona de manera similar a `Promise.all`, mientras también optimiza las verificaciones de detección de cambios. it('reads properties in parallel', async () => { const checkboxHarness = loader.getHarness(MyCheckboxHarness); - // Read the checked and intermediate properties simultaneously. + // Leer las propiedades checked e intermediate simultáneamente. const [checked, indeterminate] = await parallel(() => [ checkboxHarness.isChecked(), checkboxHarness.isIndeterminate() diff --git a/adev-es/src/content/guide/testing/utility-apis.en.md b/adev-es/src/content/guide/testing/utility-apis.en.md new file mode 100644 index 0000000..dd218d7 --- /dev/null +++ b/adev-es/src/content/guide/testing/utility-apis.en.md @@ -0,0 +1,151 @@ +# Testing Utility APIs + +This page describes the most useful Angular testing features. + +The Angular testing utilities include the `TestBed`, the `ComponentFixture`, and a handful of functions that control the test environment. +The [`TestBed`](#testbed-api-summary) and [`ComponentFixture`](#component-fixture-api-summary) classes are covered separately. + +Here's a summary of the stand-alone functions, in order of likely utility: + +| Function | Details | +|:--- |:--- | +| `waitForAsync` | Runs the body of a test \(`it`\) or setup \(`beforeEach`\) function within a special *async test zone*. See [waitForAsync](guide/testing/components-scenarios#waitForAsync). | +| `fakeAsync` | Runs the body of a test \(`it`\) within a special *fakeAsync test zone*, enabling a linear control flow coding style. See [fakeAsync](guide/testing/components-scenarios#fake-async). | +| `tick` | Simulates the passage of time and the completion of pending asynchronous activities by flushing both *timer* and *micro-task* queues within the *fakeAsync test zone*. The curious, dedicated reader might enjoy this lengthy blog post, ["*Tasks, microtasks, queues and schedules*"](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules). Accepts an optional argument that moves the virtual clock forward by the specified number of milliseconds, clearing asynchronous activities scheduled within that timeframe. See [tick](guide/testing/components-scenarios#tick). | +| `inject` | Injects one or more services from the current `TestBed` injector into a test function. It cannot inject a service provided by the component itself. See discussion of the [debugElement.injector](guide/testing/components-scenarios#get-injected-services). | +| `discardPeriodicTasks` | When a `fakeAsync()` test ends with pending timer event *tasks* \(queued `setTimeOut` and `setInterval` callbacks\), the test fails with a clear error message.
In general, a test should end with no queued tasks. When pending timer tasks are expected, call `discardPeriodicTasks` to flush the *task* queue and avoid the error. | +| `flushMicrotasks` | When a `fakeAsync()` test ends with pending *micro-tasks* such as unresolved promises, the test fails with a clear error message.
In general, a test should wait for micro-tasks to finish. When pending microtasks are expected, call `flushMicrotasks` to flush the *micro-task* queue and avoid the error. | +| `ComponentFixtureAutoDetect` | A provider token for a service that turns on [automatic change detection](guide/testing/components-scenarios#automatic-change-detection). | +| `getTestBed` | Gets the current instance of the `TestBed`. Usually unnecessary because the static class methods of the `TestBed` class are typically sufficient. The `TestBed` instance exposes a few rarely used members that are not available as static methods. | + +## `TestBed` class summary + +The `TestBed` class is one of the principal Angular testing utilities. +Its API is quite large and can be overwhelming until you've explored it, a little at a time. +Read the early part of this guide first to get the basics before trying to absorb the full API. + +The module definition passed to `configureTestingModule` is a subset of the `@NgModule` metadata properties. + + + +type TestModuleMetadata = { + providers?: any[]; + declarations?: any[]; + imports?: any[]; + schemas?: Array; +}; + + + +Each override method takes a `MetadataOverride` where `T` is the kind of metadata appropriate to the method, that is, the parameter of an `@NgModule`, `@Component`, `@Directive`, or `@Pipe`. + + + +type MetadataOverride = { + add?: Partial; + remove?: Partial; + set?: Partial; +}; + + + +The `TestBed` API consists of static class methods that either update or reference a *global* instance of the `TestBed`. + +Internally, all static methods cover methods of the current runtime `TestBed` instance, which is also returned by the `getTestBed()` function. + +Call `TestBed` methods *within* a `beforeEach()` to ensure a fresh start before each individual test. + +Here are the most important static methods, in order of likely utility. + +| Methods | Details | +|:--- |:--- | +| `configureTestingModule` | The testing shims \(`karma-test-shim`, `browser-test-shim`\) establish the [initial test environment](guide/testing) and a default testing module. The default testing module is configured with basic declaratives and some Angular service substitutes that every tester needs.
Call `configureTestingModule` to refine the testing module configuration for a particular set of tests by adding and removing imports, declarations \(of components, directives, and pipes\), and providers. | +| `compileComponents` | Compile the testing module asynchronously after you've finished configuring it. You **must** call this method if *any* of the testing module components have a `templateUrl` or `styleUrls` because fetching component template and style files is necessarily asynchronous. See [compileComponents](guide/testing/components-scenarios#calling-compilecomponents).
After calling `compileComponents`, the `TestBed` configuration is frozen for the duration of the current spec. | +| `createComponent` | Create an instance of a component of type `T` based on the current `TestBed` configuration. After calling `createComponent`, the `TestBed` configuration is frozen for the duration of the current spec. | +| `overrideModule` | Replace metadata for the given `NgModule`. Recall that modules can import other modules. The `overrideModule` method can reach deeply into the current testing module to modify one of these inner modules. | +| `overrideComponent` | Replace metadata for the given component class, which could be nested deeply within an inner module. | +| `overrideDirective` | Replace metadata for the given directive class, which could be nested deeply within an inner module. | +| `overridePipe` | Replace metadata for the given pipe class, which could be nested deeply within an inner module. | +| + `inject` | Retrieve a service from the current `TestBed` injector. The `inject` function is often adequate for this purpose. But `inject` throws an error if it can't provide the service.
What if the service is optional?
The `TestBed.inject()` method takes an optional second parameter, the object to return if Angular can't find the provider \(`null` in this example\): After calling `TestBed.inject`, the `TestBed` configuration is frozen for the duration of the current spec. | +| + `initTestEnvironment` | Initialize the testing environment for the entire test run.
The testing shims \(`karma-test-shim`, `browser-test-shim`\) call it for you so there is rarely a reason for you to call it yourself.
Call this method *exactly once*. To change this default in the middle of a test run, call `resetTestEnvironment` first.
Specify the Angular compiler factory, a `PlatformRef`, and a default Angular testing module. Alternatives for non-browser platforms are available in the general form `@angular/platform-/testing/`. | +| `resetTestEnvironment` | Reset the initial test environment, including the default testing module. | + +A few of the `TestBed` instance methods are not covered by static `TestBed` *class* methods. +These are rarely needed. + +## The `ComponentFixture` + +The `TestBed.createComponent` creates an instance of the component `T` and returns a strongly typed `ComponentFixture` for that component. + +The `ComponentFixture` properties and methods provide access to the component, its DOM representation, and aspects of its Angular environment. + +### `ComponentFixture` properties + +Here are the most important properties for testers, in order of likely utility. + +| Properties | Details | +|:--- |:--- | +| `componentInstance` | The instance of the component class created by `TestBed.createComponent`. | +| `debugElement` | The `DebugElement` associated with the root element of the component.
The `debugElement` provides insight into the component and its DOM element during test and debugging. It's a critical property for testers. The most interesting members are covered [below](#debug-element-details). | +| `nativeElement` | The native DOM element at the root of the component. | +| `changeDetectorRef` | The `ChangeDetectorRef` for the component.
The `ChangeDetectorRef` is most valuable when testing a component that has the `ChangeDetectionStrategy.OnPush` method or the component's change detection is under your programmatic control. | + +### `ComponentFixture` methods + +The *fixture* methods cause Angular to perform certain tasks on the component tree. +Call these method to trigger Angular behavior in response to simulated user action. + +Here are the most useful methods for testers. + +| Methods | Details | +|:--- |:--- | +| `detectChanges` | Trigger a change detection cycle for the component.
Call it to initialize the component \(it calls `ngOnInit`\) and after your test code, change the component's data bound property values. Angular can't see that you've changed `personComponent.name` and won't update the `name` binding until you call `detectChanges`.
Runs `checkNoChanges` afterwards to confirm that there are no circular updates unless called as `detectChanges(false)`; | +| `autoDetectChanges` | Set this to `true` when you want the fixture to detect changes automatically.
When autodetect is `true`, the test fixture calls `detectChanges` immediately after creating the component. Then it listens for pertinent zone events and calls `detectChanges` accordingly. When your test code modifies component property values directly, you probably still have to call `fixture.detectChanges` to trigger data binding updates.
The default is `false`. Testers who prefer fine control over test behavior tend to keep it `false`. | +| `checkNoChanges` | Do a change detection run to make sure there are no pending changes. Throws an exceptions if there are. | +| `isStable` | If the fixture is currently *stable*, returns `true`. If there are async tasks that have not completed, returns `false`. | +| `whenStable` | Returns a promise that resolves when the fixture is stable.
To resume testing after completion of asynchronous activity or asynchronous change detection, hook that promise. See [whenStable](guide/testing/components-scenarios#whenstable). | +| `destroy` | Trigger component destruction. | + +#### `DebugElement` + +The `DebugElement` provides crucial insights into the component's DOM representation. + +From the test root component's `DebugElement` returned by `fixture.debugElement`, you can walk \(and query\) the fixture's entire element and component subtrees. + +Here are the most useful `DebugElement` members for testers, in approximate order of utility: + +| Members | Details | +|:--- |:--- | +| `nativeElement` | The corresponding DOM element in the browser | +| `query` | Calling `query(predicate: Predicate)` returns the first `DebugElement` that matches the [predicate](#query-predicate) at any depth in the subtree. | +| `queryAll` | Calling `queryAll(predicate: Predicate)` returns all `DebugElements` that matches the [predicate](#query-predicate) at any depth in subtree. | +| `injector` | The host dependency injector. For example, the root element's component instance injector. | +| `componentInstance` | The element's own component instance, if it has one. | +| `context` | An object that provides parent context for this element. Often an ancestor component instance that governs this element.
When an element is repeated within `@for` block, the context is an `RepeaterContext` whose `$implicit` property is the value of the row instance value. For example, the `hero` in `@for(hero of heroes; ...)`. | +| `children` | The immediate `DebugElement` children. Walk the tree by descending through `children`. `DebugElement` also has `childNodes`, a list of `DebugNode` objects. `DebugElement` derives from `DebugNode` objects and there are often more nodes than elements. Testers can usually ignore plain nodes. | +| `parent` | The `DebugElement` parent. Null if this is the root element. | +| `name` | The element tag name, if it is an element. | +| `triggerEventHandler` | Triggers the event by its name if there is a corresponding listener in the element's `listeners` collection. The second parameter is the *event object* expected by the handler. See [triggerEventHandler](guide/testing/components-scenarios#trigger-event-handler).
If the event lacks a listener or there's some other problem, consider calling `nativeElement.dispatchEvent(eventObject)`. | +| `listeners` | The callbacks attached to the component's `@Output` properties and/or the element's event properties. | +| `providerTokens` | This component's injector lookup tokens. Includes the component itself plus the tokens that the component lists in its `providers` metadata. | +| `source` | Where to find this element in the source component template. | +| `references` | Dictionary of objects associated with template local variables \(for example, `#foo`\), keyed by the local variable name. | + +The `DebugElement.query(predicate)` and `DebugElement.queryAll(predicate)` methods take a predicate that filters the source element's subtree for matching `DebugElement`. + +The predicate is any method that takes a `DebugElement` and returns a *truthy* value. +The following example finds all `DebugElements` with a reference to a template local variable named "content": + + + +The Angular `By` class has three static methods for common predicates: + +| Static method | Details | +|:--- |:--- | +| `By.all` | Return all elements | +| `By.css(selector)` | Return elements with matching CSS selectors | +| `By.directive(directive)` | Return elements that Angular matched to an instance of the directive class | + + diff --git a/adev-es/src/content/guide/testing/utility-apis.md b/adev-es/src/content/guide/testing/utility-apis.md index dd218d7..fcdc31d 100644 --- a/adev-es/src/content/guide/testing/utility-apis.md +++ b/adev-es/src/content/guide/testing/utility-apis.md @@ -1,30 +1,30 @@ -# Testing Utility APIs +# APIs utilitarias de pruebas -This page describes the most useful Angular testing features. +Esta página describe las características de pruebas de Angular más útiles. -The Angular testing utilities include the `TestBed`, the `ComponentFixture`, and a handful of functions that control the test environment. -The [`TestBed`](#testbed-api-summary) and [`ComponentFixture`](#component-fixture-api-summary) classes are covered separately. +Las utilidades de pruebas de Angular incluyen el `TestBed`, el `ComponentFixture` y un puñado de funciones que controlan el entorno de prueba. +Las clases [`TestBed`](#testbed-api-summary) y [`ComponentFixture`](#component-fixture-api-summary) se cubren por separado. -Here's a summary of the stand-alone functions, in order of likely utility: +Aquí hay un resumen de las funciones independientes, en orden de utilidad probable: -| Function | Details | +| Función | Detalles | |:--- |:--- | -| `waitForAsync` | Runs the body of a test \(`it`\) or setup \(`beforeEach`\) function within a special *async test zone*. See [waitForAsync](guide/testing/components-scenarios#waitForAsync). | -| `fakeAsync` | Runs the body of a test \(`it`\) within a special *fakeAsync test zone*, enabling a linear control flow coding style. See [fakeAsync](guide/testing/components-scenarios#fake-async). | -| `tick` | Simulates the passage of time and the completion of pending asynchronous activities by flushing both *timer* and *micro-task* queues within the *fakeAsync test zone*. The curious, dedicated reader might enjoy this lengthy blog post, ["*Tasks, microtasks, queues and schedules*"](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules). Accepts an optional argument that moves the virtual clock forward by the specified number of milliseconds, clearing asynchronous activities scheduled within that timeframe. See [tick](guide/testing/components-scenarios#tick). | -| `inject` | Injects one or more services from the current `TestBed` injector into a test function. It cannot inject a service provided by the component itself. See discussion of the [debugElement.injector](guide/testing/components-scenarios#get-injected-services). | -| `discardPeriodicTasks` | When a `fakeAsync()` test ends with pending timer event *tasks* \(queued `setTimeOut` and `setInterval` callbacks\), the test fails with a clear error message.
In general, a test should end with no queued tasks. When pending timer tasks are expected, call `discardPeriodicTasks` to flush the *task* queue and avoid the error. | -| `flushMicrotasks` | When a `fakeAsync()` test ends with pending *micro-tasks* such as unresolved promises, the test fails with a clear error message.
In general, a test should wait for micro-tasks to finish. When pending microtasks are expected, call `flushMicrotasks` to flush the *micro-task* queue and avoid the error. | -| `ComponentFixtureAutoDetect` | A provider token for a service that turns on [automatic change detection](guide/testing/components-scenarios#automatic-change-detection). | -| `getTestBed` | Gets the current instance of the `TestBed`. Usually unnecessary because the static class methods of the `TestBed` class are typically sufficient. The `TestBed` instance exposes a few rarely used members that are not available as static methods. | +| `waitForAsync` | Ejecuta el cuerpo de una prueba \(`it`\) o función de configuración \(`beforeEach`\) dentro de una *zona de prueba async* especial. Ver [waitForAsync](guide/testing/components-scenarios#waitForAsync). | +| `fakeAsync` | Ejecuta el cuerpo de una prueba \(`it`\) dentro de una *zona de prueba fakeAsync* especial, habilitando un estilo de codificación de flujo de control lineal. Ver [fakeAsync](guide/testing/components-scenarios#fake-async). | +| `tick` | Simula el paso del tiempo y la finalización de actividades asíncronas pendientes vaciando tanto las colas de *timer* como de *micro-task* dentro de la *zona de prueba fakeAsync*. El lector curioso y dedicado podría disfrutar esta larga publicación de blog, ["*Tasks, microtasks, queues and schedules*"](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules). Acepta un argumento opcional que mueve el reloj virtual hacia adelante por el número especificado de milisegundos, limpiando actividades asíncronas programadas dentro de ese marco de tiempo. Ver [tick](guide/testing/components-scenarios#tick). | +| `inject` | Inyecta uno o más servicios del inyector `TestBed` actual en una función de prueba. No puede inyectar un servicio proporcionado por el componente mismo. Ver discusión de [debugElement.injector](guide/testing/components-scenarios#get-injected-services). | +| `discardPeriodicTasks` | Cuando una prueba `fakeAsync()` termina con *tasks* de evento de timer pendientes \(callbacks `setTimeOut` y `setInterval` en cola\), la prueba falla con un mensaje de error claro.
En general, una prueba debería terminar sin tareas en cola. Cuando se esperan tareas de timer pendientes, llama a `discardPeriodicTasks` para vaciar la cola de *task* y evitar el error. | +| `flushMicrotasks` | Cuando una prueba `fakeAsync()` termina con *micro-tasks* pendientes como promesas no resueltas, la prueba falla con un mensaje de error claro.
En general, una prueba debería esperar a que las micro-tasks finalicen. Cuando se esperan microtasks pendientes, llama a `flushMicrotasks` para vaciar la cola de *micro-task* y evitar el error. | +| `ComponentFixtureAutoDetect` | Un token de provider para un servicio que activa la [detección automática de cambios](guide/testing/components-scenarios#automatic-change-detection). | +| `getTestBed` | Obtiene la instancia actual del `TestBed`. Usualmente innecesario porque los métodos de clase estáticos de la clase `TestBed` son típicamente suficientes. La instancia `TestBed` expone algunos miembros raramente usados que no están disponibles como métodos estáticos. | -## `TestBed` class summary +## Resumen de la clase `TestBed` -The `TestBed` class is one of the principal Angular testing utilities. -Its API is quite large and can be overwhelming until you've explored it, a little at a time. -Read the early part of this guide first to get the basics before trying to absorb the full API. +La clase `TestBed` es una de las utilidades principales de pruebas de Angular. +Su API es bastante grande y puede ser abrumadora hasta que la hayas explorado, un poco a la vez. +Lee la parte temprana de esta guía primero para obtener lo básico antes de intentar absorber la API completa. -The module definition passed to `configureTestingModule` is a subset of the `@NgModule` metadata properties. +La definición de módulo pasada a `configureTestingModule` es un subconjunto de las propiedades de metadata `@NgModule`. @@ -37,7 +37,7 @@ type TestModuleMetadata = { -Each override method takes a `MetadataOverride` where `T` is the kind of metadata appropriate to the method, that is, the parameter of an `@NgModule`, `@Component`, `@Directive`, or `@Pipe`. +Cada método override toma un `MetadataOverride` donde `T` es el tipo de metadata apropiado para el método, es decir, el parámetro de un `@NgModule`, `@Component`, `@Directive` o `@Pipe`. @@ -49,103 +49,103 @@ type MetadataOverride = { -The `TestBed` API consists of static class methods that either update or reference a *global* instance of the `TestBed`. +La API del `TestBed` consiste en métodos de clase estáticos que actualizan o referencian una instancia *global* del `TestBed`. -Internally, all static methods cover methods of the current runtime `TestBed` instance, which is also returned by the `getTestBed()` function. +Internamente, todos los métodos estáticos cubren métodos de la instancia `TestBed` de runtime actual, que también es retornada por la función `getTestBed()`. -Call `TestBed` methods *within* a `beforeEach()` to ensure a fresh start before each individual test. +Llama a los métodos `TestBed` *dentro* de un `beforeEach()` para asegurar un comienzo fresco antes de cada prueba individual. -Here are the most important static methods, in order of likely utility. +Aquí están los métodos estáticos más importantes, en orden de utilidad probable. -| Methods | Details | +| Métodos | Detalles | |:--- |:--- | -| `configureTestingModule` | The testing shims \(`karma-test-shim`, `browser-test-shim`\) establish the [initial test environment](guide/testing) and a default testing module. The default testing module is configured with basic declaratives and some Angular service substitutes that every tester needs.
Call `configureTestingModule` to refine the testing module configuration for a particular set of tests by adding and removing imports, declarations \(of components, directives, and pipes\), and providers. | -| `compileComponents` | Compile the testing module asynchronously after you've finished configuring it. You **must** call this method if *any* of the testing module components have a `templateUrl` or `styleUrls` because fetching component template and style files is necessarily asynchronous. See [compileComponents](guide/testing/components-scenarios#calling-compilecomponents).
After calling `compileComponents`, the `TestBed` configuration is frozen for the duration of the current spec. | -| `createComponent` | Create an instance of a component of type `T` based on the current `TestBed` configuration. After calling `createComponent`, the `TestBed` configuration is frozen for the duration of the current spec. | -| `overrideModule` | Replace metadata for the given `NgModule`. Recall that modules can import other modules. The `overrideModule` method can reach deeply into the current testing module to modify one of these inner modules. | -| `overrideComponent` | Replace metadata for the given component class, which could be nested deeply within an inner module. | -| `overrideDirective` | Replace metadata for the given directive class, which could be nested deeply within an inner module. | -| `overridePipe` | Replace metadata for the given pipe class, which could be nested deeply within an inner module. | +| `configureTestingModule` | Los shims de testing \(`karma-test-shim`, `browser-test-shim`\) establecen el [entorno de prueba inicial](guide/testing) y un módulo de testing predeterminado. El módulo de testing predeterminado está configurado con declarativas básicas y algunos sustitutos de servicio de Angular que cada probador necesita.
Llama a `configureTestingModule` para refinar la configuración del módulo de testing para un conjunto particular de pruebas agregando y eliminando imports, declarations \(de componentes, directivas y pipes\), y providers. | +| `compileComponents` | Compila el módulo de testing de forma asíncrona después de que hayas terminado de configurarlo. **Debes** llamar a este método si *alguno* de los componentes del módulo de testing tiene un `templateUrl` o `styleUrls` porque obtener archivos de plantilla y estilo del componente es necesariamente asíncrono. Ver [compileComponents](guide/testing/components-scenarios#calling-compilecomponents).
Después de llamar a `compileComponents`, la configuración del `TestBed` se congela durante la duración del spec actual. | +| `createComponent` | Crea una instancia de un componente de tipo `T` basado en la configuración actual del `TestBed`. Después de llamar a `createComponent`, la configuración del `TestBed` se congela durante la duración del spec actual. | +| `overrideModule` | Reemplaza metadata para el `NgModule` dado. Recuerda que los módulos pueden importar otros módulos. El método `overrideModule` puede llegar profundamente al módulo de testing actual para modificar uno de estos módulos internos. | +| `overrideComponent` | Reemplaza metadata para la clase de componente dada, que podría estar anidada profundamente dentro de un módulo interno. | +| `overrideDirective` | Reemplaza metadata para la clase de directiva dada, que podría estar anidada profundamente dentro de un módulo interno. | +| `overridePipe` | Reemplaza metadata para la clase de pipe dada, que podría estar anidada profundamente dentro de un módulo interno. | | - `inject` | Retrieve a service from the current `TestBed` injector. The `inject` function is often adequate for this purpose. But `inject` throws an error if it can't provide the service.
What if the service is optional?
The `TestBed.inject()` method takes an optional second parameter, the object to return if Angular can't find the provider \(`null` in this example\): After calling `TestBed.inject`, the `TestBed` configuration is frozen for the duration of the current spec. | +| `inject` | Recupera un servicio del inyector `TestBed` actual. La función `inject` es a menudo adecuada para este propósito. Pero `inject` lanza un error si no puede proporcionar el servicio.
¿Qué pasa si el servicio es opcional?
El método `TestBed.inject()` toma un segundo parámetro opcional, el objeto a retornar si Angular no puede encontrar el provider \(`null` en este ejemplo\): Después de llamar a `TestBed.inject`, la configuración del `TestBed` se congela durante la duración del spec actual. | | - `initTestEnvironment` | Initialize the testing environment for the entire test run.
The testing shims \(`karma-test-shim`, `browser-test-shim`\) call it for you so there is rarely a reason for you to call it yourself.
Call this method *exactly once*. To change this default in the middle of a test run, call `resetTestEnvironment` first.
Specify the Angular compiler factory, a `PlatformRef`, and a default Angular testing module. Alternatives for non-browser platforms are available in the general form `@angular/platform-/testing/`. | -| `resetTestEnvironment` | Reset the initial test environment, including the default testing module. | +| `initTestEnvironment` | Inicializa el entorno de testing para toda la ejecución de pruebas.
Los shims de testing \(`karma-test-shim`, `browser-test-shim`\) lo llaman por ti así que raramente hay una razón para que lo llames tú mismo.
Llama a este método *exactamente una vez*. Para cambiar este predeterminado en medio de una ejecución de pruebas, llama primero a `resetTestEnvironment`.
Especifica la factory del compilador de Angular, un `PlatformRef`, y un módulo de testing de Angular predeterminado. Alternativas para plataformas no-navegador están disponibles en la forma general `@angular/platform-/testing/`. | +| `resetTestEnvironment` | Reinicia el entorno de prueba inicial, incluyendo el módulo de testing predeterminado. | -A few of the `TestBed` instance methods are not covered by static `TestBed` *class* methods. -These are rarely needed. +Algunos de los métodos de instancia del `TestBed` no están cubiertos por métodos de *clase* `TestBed` estáticos. +Estos rara vez se necesitan. -## The `ComponentFixture` +## El `ComponentFixture` -The `TestBed.createComponent` creates an instance of the component `T` and returns a strongly typed `ComponentFixture` for that component. +El `TestBed.createComponent` crea una instancia del componente `T` y retorna un `ComponentFixture` fuertemente tipado para ese componente. -The `ComponentFixture` properties and methods provide access to the component, its DOM representation, and aspects of its Angular environment. +Las propiedades y métodos del `ComponentFixture` proporcionan acceso al componente, su representación DOM y aspectos de su entorno Angular. -### `ComponentFixture` properties +### Propiedades de `ComponentFixture` -Here are the most important properties for testers, in order of likely utility. +Aquí están las propiedades más importantes para los probadores, en orden de utilidad probable. -| Properties | Details | +| Propiedades | Detalles | |:--- |:--- | -| `componentInstance` | The instance of the component class created by `TestBed.createComponent`. | -| `debugElement` | The `DebugElement` associated with the root element of the component.
The `debugElement` provides insight into the component and its DOM element during test and debugging. It's a critical property for testers. The most interesting members are covered [below](#debug-element-details). | -| `nativeElement` | The native DOM element at the root of the component. | -| `changeDetectorRef` | The `ChangeDetectorRef` for the component.
The `ChangeDetectorRef` is most valuable when testing a component that has the `ChangeDetectionStrategy.OnPush` method or the component's change detection is under your programmatic control. | +| `componentInstance` | La instancia de la clase del componente creada por `TestBed.createComponent`. | +| `debugElement` | El `DebugElement` asociado con el elemento raíz del componente.
El `debugElement` proporciona información sobre el componente y su elemento DOM durante la prueba y depuración. Es una propiedad crítica para los probadores. Los miembros más interesantes se cubren [abajo](#debug-element-details). | +| `nativeElement` | El elemento DOM nativo en la raíz del componente. | +| `changeDetectorRef` | El `ChangeDetectorRef` para el componente.
El `ChangeDetectorRef` es más valioso cuando se prueba un componente que tiene el método `ChangeDetectionStrategy.OnPush` o la detección de cambios del componente está bajo tu control programático. | -### `ComponentFixture` methods +### Métodos de `ComponentFixture` -The *fixture* methods cause Angular to perform certain tasks on the component tree. -Call these method to trigger Angular behavior in response to simulated user action. +Los métodos *fixture* hacen que Angular realice ciertas tareas en el árbol de componentes. +Llama a estos métodos para desencadenar comportamiento de Angular en respuesta a una acción de usuario simulada. -Here are the most useful methods for testers. +Aquí están los métodos más útiles para los probadores. -| Methods | Details | +| Métodos | Detalles | |:--- |:--- | -| `detectChanges` | Trigger a change detection cycle for the component.
Call it to initialize the component \(it calls `ngOnInit`\) and after your test code, change the component's data bound property values. Angular can't see that you've changed `personComponent.name` and won't update the `name` binding until you call `detectChanges`.
Runs `checkNoChanges` afterwards to confirm that there are no circular updates unless called as `detectChanges(false)`; | -| `autoDetectChanges` | Set this to `true` when you want the fixture to detect changes automatically.
When autodetect is `true`, the test fixture calls `detectChanges` immediately after creating the component. Then it listens for pertinent zone events and calls `detectChanges` accordingly. When your test code modifies component property values directly, you probably still have to call `fixture.detectChanges` to trigger data binding updates.
The default is `false`. Testers who prefer fine control over test behavior tend to keep it `false`. | -| `checkNoChanges` | Do a change detection run to make sure there are no pending changes. Throws an exceptions if there are. | -| `isStable` | If the fixture is currently *stable*, returns `true`. If there are async tasks that have not completed, returns `false`. | -| `whenStable` | Returns a promise that resolves when the fixture is stable.
To resume testing after completion of asynchronous activity or asynchronous change detection, hook that promise. See [whenStable](guide/testing/components-scenarios#whenstable). | -| `destroy` | Trigger component destruction. | +| `detectChanges` | Desencadena un ciclo de detección de cambios para el componente.
Llámalo para inicializar el componente \(llama a `ngOnInit`\) y después de que tu código de prueba cambie los valores de propiedad vinculados a datos del componente. Angular no puede ver que has cambiado `personComponent.name` y no actualizará el binding `name` hasta que llames a `detectChanges`.
Ejecuta `checkNoChanges` después para confirmar que no hay actualizaciones circulares a menos que se llame como `detectChanges(false)`; | +| `autoDetectChanges` | Establece esto a `true` cuando quieras que el fixture detecte cambios automáticamente.
Cuando autodetect es `true`, el test fixture llama a `detectChanges` inmediatamente después de crear el componente. Luego escucha eventos de zona pertinentes y llama a `detectChanges` en consecuencia. Cuando tu código de prueba modifica valores de propiedad del componente directamente, probablemente aún tengas que llamar a `fixture.detectChanges` para desencadenar actualizaciones de binding de datos.
El predeterminado es `false`. Los probadores que prefieren control fino sobre el comportamiento de prueba tienden a mantenerlo en `false`. | +| `checkNoChanges` | Ejecuta una ejecución de detección de cambios para asegurarse de que no hay cambios pendientes. Lanza excepciones si los hay. | +| `isStable` | Si el fixture es actualmente *estable*, retorna `true`. Si hay tareas async que no se han completado, retorna `false`. | +| `whenStable` | Retorna una promesa que se resuelve cuando el fixture es estable.
Para reanudar las pruebas después de la finalización de actividad asíncrona o detección de cambios asíncrona, engancha esa promesa. Ver [whenStable](guide/testing/components-scenarios#whenstable). | +| `destroy` | Desencadena la destrucción del componente. | #### `DebugElement` -The `DebugElement` provides crucial insights into the component's DOM representation. +El `DebugElement` proporciona información crucial sobre la representación DOM del componente. -From the test root component's `DebugElement` returned by `fixture.debugElement`, you can walk \(and query\) the fixture's entire element and component subtrees. +Desde el `DebugElement` del componente raíz de prueba retornado por `fixture.debugElement`, puedes caminar \(y consultar\) todo el subárbol de elementos y componentes del fixture. -Here are the most useful `DebugElement` members for testers, in approximate order of utility: +Aquí están los miembros más útiles de `DebugElement` para los probadores, en orden aproximado de utilidad: -| Members | Details | +| Miembros | Detalles | |:--- |:--- | -| `nativeElement` | The corresponding DOM element in the browser | -| `query` | Calling `query(predicate: Predicate)` returns the first `DebugElement` that matches the [predicate](#query-predicate) at any depth in the subtree. | -| `queryAll` | Calling `queryAll(predicate: Predicate)` returns all `DebugElements` that matches the [predicate](#query-predicate) at any depth in subtree. | -| `injector` | The host dependency injector. For example, the root element's component instance injector. | -| `componentInstance` | The element's own component instance, if it has one. | -| `context` | An object that provides parent context for this element. Often an ancestor component instance that governs this element.
When an element is repeated within `@for` block, the context is an `RepeaterContext` whose `$implicit` property is the value of the row instance value. For example, the `hero` in `@for(hero of heroes; ...)`. | -| `children` | The immediate `DebugElement` children. Walk the tree by descending through `children`. `DebugElement` also has `childNodes`, a list of `DebugNode` objects. `DebugElement` derives from `DebugNode` objects and there are often more nodes than elements. Testers can usually ignore plain nodes. | -| `parent` | The `DebugElement` parent. Null if this is the root element. | -| `name` | The element tag name, if it is an element. | -| `triggerEventHandler` | Triggers the event by its name if there is a corresponding listener in the element's `listeners` collection. The second parameter is the *event object* expected by the handler. See [triggerEventHandler](guide/testing/components-scenarios#trigger-event-handler).
If the event lacks a listener or there's some other problem, consider calling `nativeElement.dispatchEvent(eventObject)`. | -| `listeners` | The callbacks attached to the component's `@Output` properties and/or the element's event properties. | -| `providerTokens` | This component's injector lookup tokens. Includes the component itself plus the tokens that the component lists in its `providers` metadata. | -| `source` | Where to find this element in the source component template. | -| `references` | Dictionary of objects associated with template local variables \(for example, `#foo`\), keyed by the local variable name. | - -The `DebugElement.query(predicate)` and `DebugElement.queryAll(predicate)` methods take a predicate that filters the source element's subtree for matching `DebugElement`. - -The predicate is any method that takes a `DebugElement` and returns a *truthy* value. -The following example finds all `DebugElements` with a reference to a template local variable named "content": +| `nativeElement` | El elemento DOM correspondiente en el navegador | +| `query` | Llamar a `query(predicate: Predicate)` retorna el primer `DebugElement` que coincide con el [predicate](#query-predicate) a cualquier profundidad en el subárbol. | +| `queryAll` | Llamar a `queryAll(predicate: Predicate)` retorna todos los `DebugElements` que coinciden con el [predicate](#query-predicate) a cualquier profundidad en el subárbol. | +| `injector` | El inyector de dependencias del host. Por ejemplo, el inyector de instancia del componente del elemento raíz. | +| `componentInstance` | La propia instancia del componente del elemento, si tiene una. | +| `context` | Un objeto que proporciona contexto padre para este elemento. A menudo una instancia de componente ancestro que gobierna este elemento.
Cuando un elemento se repite dentro de un bloque `@for`, el contexto es un `RepeaterContext` cuya propiedad `$implicit` es el valor de la instancia de la fila. Por ejemplo, el `hero` en `@for(hero of heroes; ...)`. | +| `children` | Los hijos `DebugElement` inmediatos. Camina el árbol descendiendo a través de `children`. `DebugElement` también tiene `childNodes`, una lista de objetos `DebugNode`. `DebugElement` deriva de objetos `DebugNode` y a menudo hay más nodos que elementos. Los probadores usualmente pueden ignorar nodos planos. | +| `parent` | El padre `DebugElement`. Null si este es el elemento raíz. | +| `name` | El nombre de tag del elemento, si es un elemento. | +| `triggerEventHandler` | Desencadena el evento por su nombre si hay un listener correspondiente en la colección `listeners` del elemento. El segundo parámetro es el *objeto evento* esperado por el handler. Ver [triggerEventHandler](guide/testing/components-scenarios#trigger-event-handler).
Si el evento carece de un listener o hay algún otro problema, considera llamar a `nativeElement.dispatchEvent(eventObject)`. | +| `listeners` | Los callbacks adjuntos a las propiedades `@Output` del componente y/o las propiedades de evento del elemento. | +| `providerTokens` | Los tokens de lookup del inyector de este componente. Incluye el componente mismo más los tokens que el componente lista en su metadata `providers`. | +| `source` | Dónde encontrar este elemento en la plantilla del componente fuente. | +| `references` | Diccionario de objetos asociados con variables locales de plantilla \(por ejemplo, `#foo`\), con clave del nombre de la variable local. | + +Los métodos `DebugElement.query(predicate)` y `DebugElement.queryAll(predicate)` toman un predicate que filtra el subárbol del elemento fuente para coincidencias `DebugElement`. + +El predicate es cualquier método que toma un `DebugElement` y retorna un valor *truthy*. +El siguiente ejemplo encuentra todos los `DebugElements` con una referencia a una variable local de plantilla llamada "content": -The Angular `By` class has three static methods for common predicates: +La clase `By` de Angular tiene tres métodos estáticos para predicates comunes: -| Static method | Details | +| Método estático | Detalles | |:--- |:--- | -| `By.all` | Return all elements | -| `By.css(selector)` | Return elements with matching CSS selectors | -| `By.directive(directive)` | Return elements that Angular matched to an instance of the directive class | +| `By.all` | Retorna todos los elementos | +| `By.css(selector)` | Retorna elementos con selectores CSS coincidentes | +| `By.directive(directive)` | Retorna elementos que Angular coincidió con una instancia de la clase de directiva |