@@ -325,4 +543,6 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
-This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
+This project follows the
+[all-contributors](https://github.com/all-contributors/all-contributors)
+specification. Contributions of any kind welcome!
diff --git a/blog/2019-03-17-code-blocks.mdx b/blog/2019-03-17-code-blocks.mdx
index a9e4f2d2f..b17d70ea2 100755
--- a/blog/2019-03-17-code-blocks.mdx
+++ b/blog/2019-03-17-code-blocks.mdx
@@ -1,7 +1,7 @@
---
title: Multi-Framework Code Blocks
author: Alex Krolick
-authorURL: "http://github.com/alexkrolick"
+authorURL: 'http://github.com/alexkrolick'
---
Many of the code samples have been updated to include tabs to switch between
diff --git a/blog/2019-04-25-new-org.mdx b/blog/2019-04-25-new-org.mdx
index 6325f8ba2..b0e09c200 100644
--- a/blog/2019-04-25-new-org.mdx
+++ b/blog/2019-04-25-new-org.mdx
@@ -1,10 +1,12 @@
---
# prettier doesn't like how long this line is.: ""
# prettier-ignore: ""
-title: "Testing Library Updates: new release, github org, open collective, and twitter account"
+title:
+ 'Testing Library Updates: new release, github org, open collective, and
+ twitter account'
author: Kent C. Dodds
-authorURL: "https://kentcdodds.com/"
-authorImageURL: "https://avatars0.githubusercontent.com/u/1500684?s=120&v=4"
+authorURL: 'https://kentcdodds.com/'
+authorImageURL: 'https://avatars0.githubusercontent.com/u/1500684?s=120&v=4'
---
Hello friends! I'm pleased to announce the recent updates to the testing-library
@@ -121,33 +123,27 @@ there.) Please join us!
> [Join us on Spectrum](https://spectrum.chat/testing-library)
-## [Testing Library on React Native](https://www.native-testing-library.com/)
+## [Testing Library on React Native](https://callstack.github.io/react-native-testing-library/)
I'm really happy to announce a super solution to the React Native testing space.
The DOM is quite different from native, as I mentioned before, it's not the code
but the concepts that really make the Testing Library great. I'm happy to say
-that [Brandon Carroll](https://twitter.com/bcarroll22) has successfully ported
+that [Brandon Carroll](https://github.com/bcarroll22) has successfully ported
those concepts to a solution for React Native and I'm really happy with it. Give
it a look if you're building React Native applications and want confidence that
they continue to work as you make changes!
-(Note, there is already `react-native-testing-library`, but it doesn't quite
-follow the guiding principles of Testing Library, so we recommend you use
-`native-testing-library`.
-[Learn More](https://medium.com/@brandoncarroll/why-native-testing-library-exists-629ffb85cae2)).
+> [Checkout native-testing-library](https://callstack.github.io/react-native-testing-library/)
-> [Checkout native-testing-library](https://www.native-testing-library.com/)
-
-## [Learn Testing Library](https://testing-library.com/docs/learning)
+## [Learn Testing Library](/docs/learning)
There's been a LOT of activity around the Testing Library principles and tools
in the content space. We do have
-[a page that lists learning materials](https://testing-library.com/docs/learning),
-and more gets added to it daily. If you know of blog posts, YouTube videos,
-courses, or anything else about the Testing Library family of tools, please
-contribute to the list!
+[a page that lists learning materials](/docs/learning), and more gets added to
+it daily. If you know of blog posts, YouTube videos, courses, or anything else
+about the Testing Library family of tools, please contribute to the list!
-> [Contribute to the learning materials page](https://github.com/testing-library/testing-library-docs/edit/master/docs/learning.mdx)
+> [Contribute to the learning materials page](https://github.com/testing-library/testing-library-docs/edit/main/docs/learning.mdx)
## Other Exciting news
@@ -177,7 +173,7 @@ an especially significant impact on the Testing Library family of tools and
community.
[Myself 👋](https://kentcdodds.com), [Alex Krolick](https://alexkrolick.com/),
-[Brandon Carroll](https://twitter.com/bcarroll22),
+[Brandon Carroll](https://github.com/bcarroll22),
[Giorgio](https://twitter.com/Gpx),
[Ernesto García](https://twitter.com/gnapse), and
[Daniel Cook](https://github.com/dfcook).
diff --git a/docs/angular-testing-library/api.mdx b/docs/angular-testing-library/api.mdx
index 4ddb32ede..08daa3359 100644
--- a/docs/angular-testing-library/api.mdx
+++ b/docs/angular-testing-library/api.mdx
@@ -1,16 +1,12 @@
---
id: api
title: API
-sidebar_label: API
---
`Angular Testing Library` re-exports everything from `DOM Testing Library` as
-well as these methods:
+well as the `render` method.
-- [`render`](#render)
-
-Some of the `DOM Testing Library` re-exports are patched to work easier with
-Angular:
+The following re-exports are patched to make them easier to use with Angular:
- The events on `fireEvent` automatically invoke a change detection cycle after
the event has been fired
@@ -21,42 +17,116 @@ Angular:
## `render`
+With Angular Testing Library, the component can be rendered in two ways, via the
+component's type or with a template.
+
+> By default, `render` also imports the `NoopAnimationsModule`.
+
+## `Type`
+
+To render a component, you need to pass component's type to the `render` method.
+For components that don't use other parts of your application (for example
+design modules or services), rendering a component can be as simple as the
+following example.
+
+```typescript
+await render(AppComponent)
+```
+
+## `template`
+
+Instead of passing the component's type as first argument, you can also provide
+a template. This practice is required to render directives but can also be
+applied to components, it might even be more useful. The directive's (or
+component's) type must then be added to the `imports` (or `declarations` in case
+of non-standalone components).
+
+**example with directive**:
+
```typescript
-async function render(
+await render('', {
+ declarations: [SpoilerDirective],
+})
+```
+
+**example with component**:
+
+```typescript
+await render(
+ '',
+ {
+ declarations: [AppComponent],
+ componentProperties: {
+ anotherValue: 'valueOfAnotherProperty',
+ sendValue: jest.fn(),
+ },
+ },
+)
+```
+
+```typescript
+export async function render(
component: Type,
- renderOptions?: RenderComponentOptions
+ renderOptions?: RenderComponentOptions,
): Promise>
-async function render(
- component: Type,
- renderOptions?: RenderDirectiveOptions
-): Promise>
+export async function render(
+ template: string,
+ renderOptions?: RenderTemplateOptions,
+): Promise>
```
## Component RenderOptions
-### `componentProperties`
-An object to set `@Input` and `@Output` properties of the component.
+### `inputs`
-**default** : `{}`
+An object to set `@Input` or `input()` properties of the component.
-**example**:
+**default** : `{}`
```typescript
await render(AppComponent, {
- componentProperties: {
+ inputs: {
counterValue: 10,
- send: (value) => { ... }
+ // explicitly define aliases using `aliasedInput`
+ ...aliasedInput('someAlias', 'someValue'),
+ },
+})
+```
+
+### `on`
+
+An object with callbacks to subscribe to `EventEmitters` and `Observables` of
+the component.
+
+**default** : `{}`
+
+```ts
+// using a manual callback
+const sendValue = (value) => { ... }
+await render(AppComponent, {
+ on: {
+ send: (value) => sendValue(value),
+ }
+})
+
+// using a (jest) spy
+const sendValueSpy = jest.fn()
+
+await render(AppComponent, {
+ on: {
+ send: sendValueSpy
}
})
```
-### `componentProviders`
+### `declarations`
-A collection of providers to inject dependencies of the component.
+A collection of components, directives and pipes needed to render the component.
+For example, nested components of the component.
For more info see the
-[Angular docs](https://angular.io/api/core/Directive#providers).
+[Angular docs](https://angular.dev/guide/ngmodules/overview#declarations).
**default** : `[]`
@@ -64,17 +134,56 @@ For more info see the
```typescript
await render(AppComponent, {
- componentProviders: [AppComponentService],
+ declarations: [CustomerDetailComponent, ButtonComponent],
})
```
-### `declarations`
+### `deferBlockBehavior`
+
+Set the defer blocks behavior.
+
+For more info see the
+[Angular docs](https://angular.dev/api/core/testing/DeferBlockBehavior)
+
+**default** : `undefined` (uses `DeferBlockBehavior.Manual`, which is different
+from the Angular default of `DeferBlockBehavior.Playthrough`)
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+ deferBlockBehavior: DeferBlockBehavior.Playthrough,
+})
+```
+
+### `deferBlockStates`
+
+Set the initial state of a deferrable blocks in a component.
+
+For more info see the
+[Angular docs](https://angular.dev/api/core/testing/DeferBlockState)
+
+**default** : `undefined` (uses the Angular default, which is
+`DeferBlockState.Placeholder`)
+
+**example**:
+
+```typescript
+await render(FixtureComponent, {
+ deferBlockStates: DeferBlockState.Loading,
+})
+```
+
+### `componentProviders`
A collection of providers needed to render the component via Dependency
-Injection, for example, injectable services or tokens.
+Injection.
+
+These will be provided at the component level. To inject dependencies at the
+module level, use [`providers`](#providers).
For more info see the
-[Angular docs](https://angular.io/api/core/NgModule#providers).
+[Angular docs](https://angular.dev/guide/di/hierarchical-dependency-injection#example-providing-services-in-component).
**default** : `[]`
@@ -82,32 +191,75 @@ For more info see the
```typescript
await render(AppComponent, {
- providers: [
- CustomersService,
+ componentProviders: [AppComponentService],
+})
+```
+
+### `componentImports`
+
+A collection of imports to override a standalone component's imports with.
+
+**default** : `undefined`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+ componentImports: [MockChildComponent],
+})
+```
+
+### `childComponentOverrides`
+
+Collection of child component specified providers to override with.
+
+**default** : `undefined`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+ childComponentOverrides: [
{
- provide: MAX_CUSTOMERS_TOKEN,
- useValue: 10,
+ component: ChildOfAppComponent,
+ providers: [{provide: ChildService, useValue: {hello: 'world'}}],
},
],
})
```
-### `detectChanges`
+### `detectChangesOnRender`
+
+Invokes `detectChanges` after the component is rendered.
+
+**default** : `true`
+
+**example**:
+
+```typescript
+await render(AppComponent, {detectChangesOnRender: false})
+```
-Will call `detectChanges` when the component is compiled
+### `autoDetectChanges`
+
+Automatically detect changes as a "real" running component would do. For
+example, runs a change detection cycle when an event has occured.
**default** : `true`
**example**:
```typescript
-await render(AppComponent, { detectChanges: false })
+await render(AppComponent, {
+ autoDetectChanges: false,
+})
```
### `excludeComponentDeclaration`
Exclude the component to be automatically be added as a declaration. This is
-needed when the component is declared in an imported module.
+needed when the component is declared in an imported module, for example with
+SCAMs.
**default** : `false`
@@ -127,7 +279,7 @@ modules. Adds `NoopAnimationsModule` by default if `BrowserAnimationsModule`
isn't added to the collection
For more info see the
-[Angular docs](https://angular.io/api/core/NgModule#imports).
+[Angular docs](https://angular.dev/guide/components#imports-in-the-component-decorator).
**default** : `[NoopAnimationsModule]`
@@ -139,6 +291,33 @@ await render(AppComponent, {
})
```
+### `providers`
+
+A collection of providers needed to render the component via Dependency
+Injection.
+
+These will be provided at the module level. To inject dependencies at the
+component level, use [`componentProviders`](#componentProviders).
+
+For more info see the
+[Angular docs](https://angular.dev/guide/di/dependency-injection-providers#).
+
+**default** : `[]`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+ providers: [
+ CustomersService,
+ {
+ provide: MAX_CUSTOMERS_TOKEN,
+ useValue: 10,
+ },
+ ],
+})
+```
+
### `queries`
Queries to bind. Overrides the default set from DOM Testing Library unless
@@ -150,7 +329,7 @@ merged.
```typescript
await render(AppComponent, {
- queries: { ...queries, ...customQueries },
+ queries: {...queries, ...customQueries},
})
```
@@ -158,7 +337,7 @@ await render(AppComponent, {
The route configuration to set up the router service via
`RouterTestingModule.withRoutes`. For more info see the
-[Angular Routes docs](https://angular.io/api/router/Routes).
+[Angular Routes docs](https://angular.dev/api/router/Routes).
**default** : `[]`
@@ -187,7 +366,7 @@ A collection of schemas needed to render the component. Allowed values are
`NO_ERRORS_SCHEMA` and `CUSTOM_ELEMENTS_SCHEMA`.
For more info see the
-[Angular docs](https://angular.io/api/core/NgModule#schemas).
+[Angular docs](https://angular.dev/guide/components/advanced-configuration#custom-element-schemas).
**default** : `[]`
@@ -213,39 +392,64 @@ await render(AppComponent, {
})
```
-## Directive RenderOptions
-To test a directive, the render API is a bit different. The API has the same
-options as the Component RenderOptions, but has more options:
+### ~~`componentInputs`~~ (deprecated)
+
+An object to set `@Input` properties of the component. Uses `setInput` to set
+the input property. Throws if the component property is not annotated with the
+`@Input` attribute.
-### `template`
+**default** : `{}`
+
+**example**:
+
+```typescript
+await render(AppComponent, {
+ componentInputs: {
+ counterValue: 10,
+ },
+})
+```
+
+### ~~`componentOutputs`~~ (deprecated)
+
+An object to set `@Output` properties of the component.
-The template to render the directive.
+**default** : `{}`
**example**:
```typescript
-await render(SpoilerDirective, {
- template: ``,
+await render(AppComponent, {
+ componentOutputs: {
+ clicked: (value) => { ... }
+ }
})
```
-### `wrapper`
+### ~~`componentProperties`~~ (deprecated)
-An Angular component to wrap the directive in.
+An object to set `@Input` and `@Output` properties of the component. Doesn't
+have a fine-grained control as `inputs` and `on`.
-**default**: `WrapperComponent` , an empty component that strips the
-`ng-version` attribute.
+**default** : `{}`
**example**:
```typescript
-await render(SpoilerDirective, {
- template: ``
- wrapper: CustomWrapperComponent
+await render(AppComponent, {
+ componentProperties: {
+ // an input
+ counterValue: 10,
+ // an output
+ send: (value) => { ... }
+ // a public property
+ name: 'Tim'
+ }
})
```
+
## `RenderResult`
### `container`
@@ -260,49 +464,79 @@ Prints out the component's DOM with syntax highlighting. Accepts an optional
parameter, to print out a specific DOM node.
```typescript
-const { debug } = await render(AppComponent)
+const {debug} = await render(AppComponent)
debug()
```
### `rerender`
-Re-render the same component with different props. Will call `detectChanges`
-after props has been updated.
+Changes the input properties of the existing component instance by following
+Angular component lifecycle events (i.e. `ngOnChanges` is called). Input
+properties that are not defined are cleared.
```typescript
-const { rerender } = await render(Counter, { componentProperties: { count: 4 } })
+const {rerender} = await render(Counter, {
+ inputs: {count: 4, name: 'Sarah'},
+})
expect(screen.getByTestId('count-value').textContent).toBe('4')
+expect(screen.getByTestId('name-value').textContent).toBe('Sarah')
-rerender({ count: 7 })
+await rerender({
+ inputs: {count: 7}
+})
+
+// count is updated to 7
+expect(screen.getByTestId('count-value').textContent).toBe('7')
+// name is undefined because it's not provided in rerender
+expect(screen.getByTestId('name-value').textContent).toBeUndefined()
+```
+
+Using `partialUpdate`, only the newly provided properties will be updated. Other
+input properties that aren't provided won't be cleared.
+
+```typescript
+const {rerender} = await render(Counter, {
+ inputs: {count: 4, name: 'Sarah'},
+})
+
+expect(screen.getByTestId('count-value').textContent).toBe('4')
+expect(screen.getByTestId('name-value').textContent).toBe('Sarah')
+
+await rerender({inputs: {count: 7}, partialUpdate: true})
+// count is updated to 7
expect(screen.getByTestId('count-value').textContent).toBe('7')
+// name is still rendered as "Sarah" because of the partial update
+expect(screen.getByTestId('name-value').textContent).toBe('Sarah')
```
### `detectChanges`
Trigger a change detection cycle for the component.
-For more info see the [Angular docs](https://angular.io/api/core/testing/ComponentFixture#detectChanges).
+For more info see the
+[Angular docs](https://angular.dev/api/core/testing/ComponentFixture#detectChanges).
### `debugElement`
The Angular `DebugElement` of the component.
-For more info see the [Angular docs](https://angular.io/api/core/DebugElement).
+For more info see the [Angular docs](https://angular.dev/api/core/DebugElement).
### `fixture`
The Angular `ComponentFixture` of the component.
For more info see the
-[Angular docs](https://angular.io/api/core/testing/ComponentFixture).
+[Angular docs](https://angular.dev/api/core/testing/ComponentFixture).
```typescript
-const { fixture } = await render(AppComponent)
+const {fixture} = await render(AppComponent)
-const componentInstance = fixture.componentInstance as AppComponent
+// componentInstance is typed as AppComponent
+const componentInstance = fixture.componentInstance
```
> 🚨 If you find yourself using `fixture` to access the component's internal
@@ -327,18 +561,37 @@ await navigate('details/3')
### `...queries`
The most important feature of `render` is that the queries from
-[DOM Testing Library](https://testing-library.com/docs/dom-testing-library) are
-automatically returned with their first argument bound to the component under
-test.
+[DOM Testing Library](/docs/dom-testing-library/intro) are automatically
+returned with their first argument bound to the component under test.
-See [Queries](https://testing-library.com/docs/dom-testing-library/api-queries)
-for a complete list.
+See [Queries](queries/about.mdx) for a complete list.
**example**:
```typescript
-const { getByText, queryByLabelText} = await render(AppComponent)
+const {getByText, queryByLabelText} = await render(AppComponent)
+
+screen.getByRole('heading', {
+ name: /api/i,
+})
+queryByLabelText(/First name/i')
+```
+
+### `renderDeferBlock`
+
+To test [Deferrable views](https://angular.dev/guide/defer#defer), you can make
+use of `renderDeferBlock`. `renderDeferBlock` will set the desired defer state
+for a specific deferrable block. The default value of a deferrable view is
+`Placeholder`, but you can also set the initial state while rendering the
+component.
+
+```typescript
+const {renderDeferBlock} = await render(FixtureComponent, {
+ deferBlockStates: DeferBlockState.Loading,
+})
+
+expect(screen.getByText(/loading/i)).toBeInTheDocument()
-getByText('Hello world')
-queryByLabelText('First name:')
+await renderDeferBlock(DeferBlockState.Complete)
+expect(screen.getByText(/completed/i)).toBeInTheDocument()
```
diff --git a/docs/angular-testing-library/examples.mdx b/docs/angular-testing-library/examples.mdx
index c4eee4601..2e44b893c 100644
--- a/docs/angular-testing-library/examples.mdx
+++ b/docs/angular-testing-library/examples.mdx
@@ -1,72 +1,81 @@
---
id: examples
-title: Examples
-sidebar_label: Examples
+title: Example
---
-> Read
-> [Good testing practices with 🦔 Angular Testing Library](https://timdeschryver.dev/posts/good-testing-practices-with-angular-testing-library)
-> for a guided example
+> Read about
+> [best practices](https://timdeschryver.dev/blog/good-testing-practices-with-angular-testing-library),
+> or follow the
+> [guided example](https://timdeschryver.dev/blog/getting-the-most-value-out-of-your-angular-component-tests)
-counter.component.ts
+Angular Testing Library can be used with standalone components and also with Angular components that uses Modules.
+The example below shows how to test a standalone component, but the same principles apply to Angular components that uses Modules.
+In fact, there should be no difference in how you test both types of components, only the setup might be different.
-```typescript
+```ts title="counter.component.ts"
@Component({
- selector: 'counter',
+ selector: 'app-counter',
template: `
+ {{ hello() }}
- Current Count: {{ counter }}
+ Current Count: {{ counter() }}
`,
})
export class CounterComponent {
- @Input() counter = 0
+ counter = model(0);
+ hello = input('Hi', { alias: 'greeting' });
increment() {
- this.counter += 1
+ this.counter.set(this.counter() + 1);
}
decrement() {
- this.counter -= 1
+ this.counter.set(this.counter() - 1);
}
}
```
-counter.component.spec.ts
-
-```typescript
-import { render, screen, fireEvent } from '@testing-library/angular'
-import { CounterComponent } from './counter.component.ts'
+```typescript title="counter.component.spec.ts"
+import { render, screen, fireEvent, aliasedInput } from '@testing-library/angular';
+import { CounterComponent } from './counter.component';
describe('Counter', () => {
- test('should render counter', async () => {
+ it('should render counter', async () => {
await render(CounterComponent, {
- componentProperties: { counter: 5 },
- })
+ inputs: {
+ counter: 5,
+ // aliases need to be specified using aliasedInput
+ ...aliasedInput('greeting', 'Hello Alias!'),
+ },
+ });
- expect(screen.getByText('Current Count: 5'))
- })
+ expect(screen.getByText('Current Count: 5')).toBeVisible();
+ expect(screen.getByText('Hello Alias!')).toBeVisible();
+ });
- test('should increment the counter on click', async () => {
- await render(CounterComponent, {
- componentProperties: { counter: 5 },
- })
+ it('should increment the counter on click', async () => {
+ await render(CounterComponent, { inputs: { counter: 5 } });
- fireEvent.click(screen.getByText('+'))
+ const incrementButton = screen.getByRole('button', { name: '+' });
+ fireEvent.click(incrementButton);
- expect(screen.getByText('Current Count: 6'))
- })
-})
+ expect(screen.getByText('Current Count: 6')).toBeVisible();
+ });
+});
```
+## More examples
+
More examples can be found in the
-[GitHub project](https://github.com/testing-library/angular-testing-library/tree/master/apps/example-app/app/examples).
+[GitHub project](https://github.com/testing-library/angular-testing-library/tree/master/apps/example-app/src/app/examples).
These examples include:
-- `@Input` and `@Output` properties
-- (Reactive) Forms
-- Integration with NgRx (mock) Store
-- And more
+- `input` and `output` properties
+- Forms
+- Integration injected services
+- And
+ [more](https://github.com/testing-library/angular-testing-library/tree/master/apps/example-app/src/app/examples)
If you're looking for an example that isn't on the list, please feel free to
create a
diff --git a/docs/angular-testing-library/faq.mdx b/docs/angular-testing-library/faq.mdx
new file mode 100644
index 000000000..e333db4b3
--- /dev/null
+++ b/docs/angular-testing-library/faq.mdx
@@ -0,0 +1,109 @@
+---
+id: faq
+title: FAQ
+---
+
+See also the [main FAQ](dom-testing-library/faq.mdx) for questions not specific
+to Angular testing.
+
+
+
+Can I write unit tests with this library?
+
+Definitely yes! You can write unit and integration tests with this library. See
+below for more on how to mock dependencies (because this library intentionally
+does NOT support shallow rendering) if you want to unit test a high level
+component. The tests in this project show several examples of unit testing with
+this library.
+
+As you write your tests, keep in mind:
+
+> The more your tests resemble the way your software is used, the more
+> confidence they can give you. - [17 Feb 2018][guiding-principle]
+
+
+
+
+
+
+ If I can't use shallow rendering, how do I mock out components in tests?
+
+
+In general, you should avoid mocking out components (see
+[the Guiding Principles section](guiding-principles.mdx)). However, if you need
+to, then try to use [ng-mocks](https://ng-mocks.sudo.eu/) and its
+[`MockBuilder`](https://ng-mocks.sudo.eu/extra/with-3rd-party#testing-libraryangular-and-mockbuilder).
+
+```typescript
+import {Component, NgModule} from '@angular/core'
+import {render, screen} from '@testing-library/angular'
+import {MockBuilder} from 'ng-mocks'
+
+@Component({
+ selector: 'app-parent-component',
+ template: '',
+})
+class ParentComponent {}
+
+@Component({
+ selector: 'app-child-component',
+ template: '
Child component
',
+})
+class ChildComponent {}
+
+@NgModule({
+ declarations: [ParentComponent, ChildComponent],
+})
+export class AppModule {}
+
+describe('ParentComponent', () => {
+ it('should not render ChildComponent when shallow rendering', async () => {
+ // all imports, declarations and exports of AppModule will be mocked.
+ const dependencies = MockBuilder(ParentComponent, AppModule).build()
+
+ await render(ParentComponent, dependencies)
+
+ expect(screen.queryByText('Child component')).toBeNull()
+ })
+})
+```
+
+
+
+
+
+
+ What level of a component tree should I test? Children, parents, or both?
+
+
+Following the guiding principle of this library, it is useful to break down how
+tests are organized around how the user experiences and interacts with
+application functionality rather than around specific components themselves. In
+some cases, for example for reusable component libraries, it might be useful to
+include developers in the list of users to test for and test each of the
+reusable components individually. Other times, the specific break down of a
+component tree is just an implementation detail and testing every component
+within that tree individually can cause issues (see
+https://kentcdodds.com/blog/avoid-the-test-user).
+
+In practice this means that it is often preferable to test high enough up the
+component tree to simulate realistic user interactions. The question of whether
+it is worth additionally testing at a higher or lower level on top of this comes
+down to a question of tradeoffs and what will provide enough value for the cost
+(see https://kentcdodds.com/blog/unit-vs-integration-vs-e2e-tests on more info
+on different levels of testing).
+
+For a more in-depth discussion of this topic see
+[this video](https://youtu.be/0qmPdcV-rN8).
+
+
+
+
+
+
+
+[guiding-principle]: https://twitter.com/kentcdodds/status/977018512689455106
+
+
diff --git a/docs/angular-testing-library/intro.mdx b/docs/angular-testing-library/intro.mdx
index 7fb31f31a..a7820b7f0 100644
--- a/docs/angular-testing-library/intro.mdx
+++ b/docs/angular-testing-library/intro.mdx
@@ -8,9 +8,17 @@ sidebar_label: Introduction
builds on top of
[`DOM Testing Library`](https://github.com/testing-library/dom-testing-library)
by adding APIs for working with Angular components.
+Starting from ATL version 17, you also need to install `@testing-library/dom`:
+
+```bash npm2yarn
+npm install --save-dev @testing-library/angular @testing-library/dom
+```
+
+Or, you can use the `ng add` command.
+This sets up your project to use Angular Testing Library, which also includes the installation of `@testing-library/dom`.
```bash
-npm install --save-dev @testing-library/angular
+ng add @testing-library/angular
```
- [`@testing-library/angular-testing-library` on GitHub](https://github.com/testing-library/angular-testing-library)
diff --git a/docs/angular-testing-library/version-compatibility.mdx b/docs/angular-testing-library/version-compatibility.mdx
new file mode 100644
index 000000000..3b64dd5d2
--- /dev/null
+++ b/docs/angular-testing-library/version-compatibility.mdx
@@ -0,0 +1,18 @@
+---
+id: version-compatibility
+title: Version compatibility
+---
+
+An overview of the compatibility between different versions of Angular Testing
+Library and Angular.
+
+| Angular | Angular Testing Library |
+| ------- | ---------------------------------- |
+| 20.x | 18.x |
+| 19.x | 18.x, 17.x, 16.x, 15.x, 14.x, 13.x |
+| 18.x | 17.x, 16.x, 15.x, 14.x, 13.x |
+| 17.x | 17.x, 16.x, 15.x, 14.x, 13.x |
+| 16.x | 14.x, 13.x |
+| >= 15.1 | 14.x, 13.x |
+| < 15.1 | 12.x, 11.x |
+| 14.x | 12.x, 11.x |
diff --git a/docs/bs-react-testing-library/examples.mdx b/docs/bs-react-testing-library/examples.mdx
index ce8d544a7..08e96a7c9 100644
--- a/docs/bs-react-testing-library/examples.mdx
+++ b/docs/bs-react-testing-library/examples.mdx
@@ -1,6 +1,6 @@
---
id: examples
-title: Examples
+title: Example
---
You can find more bs-dom-testing-library examples at
@@ -11,9 +11,7 @@ You can find more bs-react-testing-library examples at
## React Testing Library
-```reason
-/* Component_test.re */
-
+```reason title="Component_test.re"
open Jest;
open Expect;
open ReactTestingLibrary;
@@ -37,8 +35,7 @@ with typings and creating events.
### getByText
-```reason
-/* __tests__/example_test.re */
+```reason title="__tests__/example_test.re"
open Jest;
open DomTestingLibrary;
open Expect;
diff --git a/docs/bs-react-testing-library/intro.mdx b/docs/bs-react-testing-library/intro.mdx
index 8e2545423..316ccc9b2 100644
--- a/docs/bs-react-testing-library/intro.mdx
+++ b/docs/bs-react-testing-library/intro.mdx
@@ -13,8 +13,11 @@ Bindings for several testing libraries have been ported to [ReasonML][re].
[`bs-dom-testing-library`][gh-dom] contains [BuckleScript][bs] bindings for
`DOM Testing Library`.
-```
+```bash npm2yarn
npm install --save-dev bs-dom-testing-library
+```
+
+```bash npm2yarn
npm install --save-dev bs-react-testing-library
```
@@ -49,7 +52,7 @@ _or_
This is what [BuckleScript][bs] uses to compile the [Reason][re] code to JS. If
it is not in your project you can install it like so:
-```
+```bash npm2yarn
npm install --save-dev bs-platform
```
@@ -60,7 +63,7 @@ examples here will be using it.
- [bs-jest on GitHub](https://github.com/glennsl/bs-jest)
-```
+```bash npm2yarn
npm install --save-dev @glennsl/bs-jest
```
diff --git a/docs/cypress-testing-library/intro.mdx b/docs/cypress-testing-library/intro.mdx
index cb6dacf7b..3c88d4d2b 100644
--- a/docs/cypress-testing-library/intro.mdx
+++ b/docs/cypress-testing-library/intro.mdx
@@ -6,7 +6,7 @@ title: Cypress Testing Library
[`Cypress Testing Library`][gh] allows the use of dom-testing queries within
[Cypress](https://cypress.io) end-to-end browser tests.
-```
+```bash npm2yarn
npm install --save-dev cypress @testing-library/cypress
```
@@ -18,13 +18,12 @@ npm install --save-dev cypress @testing-library/cypress
Add this line to your project's `cypress/support/commands.js`:
-```
-import '@testing-library/cypress/add-commands';
+```js
+import '@testing-library/cypress/add-commands'
```
-You can now use all of `DOM Testing Library`'s `findBy`, `findAllBy`, `queryBy`
-and `queryAllBy` commands off the global `cy` object.
-[See the `DOM Testing Library` docs for reference](https://testing-library.com/docs/dom-testing-library/api-queries).
+You can now use some of `DOM Testing Library`'s `findBy`, and `findAllBy` commands off the global `cy` object.
+[See the `About queries` docs for reference](/docs/queries/about).
> Note: the `get*` queries are not supported because for reasonable Cypress
> tests you need retryability and `find*` queries already support that. `query*`
@@ -53,19 +52,17 @@ To show some simple examples (from
[cypress/integration/find.spec.js](https://github.com/testing-library/cypress-testing-library/blob/97939da7d4707a71049884c0324c0eda56e26fc2/cypress/integration/find.spec.js)):
```javascript
-cy.findByRole('button', { name: /Jackie Chan/i }).click()
-cy.findByRole('button', { name: /Button Text/i }).should('exist')
-cy.findByRole('button', { name: /Non-existing Button Text/i }).should(
- 'not.exist'
-)
-cy.findByLabelText(/Label text/i, { timeout: 7000 }).should('exist')
-
-// findAllByText _inside_ a form element
+cy.findByRole('button', {name: /Jackie Chan/i}).click()
+cy.findByRole('button', {name: /Button Text/i}).should('exist')
+cy.findByRole('button', {name: /Non-existing Button Text/i}).should('not.exist')
+cy.findByLabelText(/Label text/i, {timeout: 7000}).should('exist')
+
+// findByRole _inside_ a form element
cy.get('form')
- .findByText('button', { name: /Button Text/i })
+ .findByRole('button', {name: /Button Text/i})
.should('exist')
cy.findByRole('dialog').within(() => {
- cy.findByRole('button', { name: /confirm/i })
+ cy.findByRole('button', {name: /confirm/i})
})
```
diff --git a/docs/dom-testing-library/api-accessibility.mdx b/docs/dom-testing-library/api-accessibility.mdx
index 11e2f2ccd..9b5e4e761 100644
--- a/docs/dom-testing-library/api-accessibility.mdx
+++ b/docs/dom-testing-library/api-accessibility.mdx
@@ -26,7 +26,7 @@ See
for more information about implicit ARIA roles.
```javascript
-import { getRoles } from '@testing-library/dom'
+import {getRoles} from '@testing-library/dom'
const nav = document.createElement('nav')
nav.innerHTML = `
@@ -64,7 +64,7 @@ nodes which match that role. This can be helpful for finding ways to query the
DOM under test with [getByRole](queries/byrole.mdx).
```javascript
-import { logRoles } from '@testing-library/dom'
+import {logRoles} from '@testing-library/dom'
const nav = document.createElement('nav')
nav.innerHTML = `
diff --git a/docs/dom-testing-library/api-async.mdx b/docs/dom-testing-library/api-async.mdx
index d9eafdabc..700fbe81d 100644
--- a/docs/dom-testing-library/api-async.mdx
+++ b/docs/dom-testing-library/api-async.mdx
@@ -22,7 +22,7 @@ accept the waitFor options as the last argument (e.g.
DOM might not happen immediately.
```js
-const button = screen.getByRole('button', { name: 'Click Me' })
+const button = screen.getByRole('button', {name: 'Click Me'})
fireEvent.click(button)
await screen.findByText('Clicked once')
fireEvent.click(button)
@@ -40,12 +40,14 @@ function waitFor(
interval?: number
onTimeout?: (error: Error) => Error
mutationObserverOptions?: MutationObserverInit
- }
+ },
): Promise
```
When in need to wait for any period of time you can use `waitFor`, to wait for
-your expectations to pass. Here's a simple example:
+your expectations to pass. Returning _a falsy condition is not sufficient_ to
+trigger a retry, the callback must throw an error in order to retry the
+condition. Here's a simple example:
```javascript
// ...
@@ -55,24 +57,25 @@ await waitFor(() => expect(mockAPI).toHaveBeenCalledTimes(1))
// ...
```
-`waitFor` may run the callback a variable number of times.
+`waitFor` may run the callback a number of times until the timeout is reached.
+Note that the number of calls is constrained by the `timeout` and `interval`
+options.
This can be useful if you have a unit test that mocks API calls and you need to
wait for your mock promises to all resolve.
If you return a promise in the `waitFor` callback (either explicitly or
-implicitly with `async` syntax), then the `waitFor` utility will not call your
-callback again until that promise rejects. This allows you to `waitFor` things
-that must be checked asynchronously.
+implicitly with the `async` syntax), then the `waitFor` utility does not call
+your callback again until that promise rejects. This allows you to `waitFor`
+things that must be checked asynchronously.
The default `container` is the global `document`. Make sure the elements you
wait for are descendants of `container`.
-The default `interval` is `50ms`. However it will run your callback immediately
+The default `interval` is `50ms`. However it runs your callback immediately
before starting the intervals.
-The default `timeout` is `1000ms` which will keep you under
-[Jest's default timeout of `5000ms`](https://jestjs.io/docs/en/jest-object.html#jestsettimeouttimeout).
+The default `timeout` is `1000ms`.
The default `onTimeout` takes the error and appends the `container`'s printed
state to the error message which should hopefully make it easier to track down
@@ -80,9 +83,9 @@ what caused the timeout.
The default `mutationObserverOptions` is
`{subtree: true, childList: true, attributes: true, characterData: true}` which
-will detect additions and removals of child elements (including text nodes) in
-the `container` and any of its descendants. It will also detect attribute
-changes. When any of those changes occur, it will re-run the callback.
+detects additions and removals of child elements (including text nodes) in the
+`container` and any of its descendants. It also detects attribute changes. When
+any of those changes occur, it re-runs the callback.
## `waitForElementToBeRemoved`
@@ -95,7 +98,7 @@ function waitForElementToBeRemoved(
interval?: number
onTimeout?: (error: Error) => Error
mutationObserverOptions?: MutationObserverInit
- }
+ },
): Promise
```
@@ -112,7 +115,7 @@ Here is an example where the promise resolves because the element is removed:
const el = document.querySelector('div.getOuttaHere')
waitForElementToBeRemoved(document.querySelector('div.getOuttaHere')).then(() =>
- console.log('Element no longer in DOM')
+ console.log('Element no longer in DOM'),
)
el.setAttribute('data-neat', true)
@@ -122,183 +125,22 @@ el.parentElement.removeChild(el)
// logs 'Element no longer in DOM'
```
-`waitForElementToBeRemoved` will throw an error if the first argument is `null`
-or an empty array:
+`waitForElementToBeRemoved` throws an error if the first argument is `null` or
+an empty array:
```javascript
-waitForElementToBeRemoved(null).catch((err) => console.log(err))
-waitForElementToBeRemoved(queryByText(/not here/i)).catch((err) =>
- console.log(err)
+waitForElementToBeRemoved(null).catch(err => console.log(err))
+waitForElementToBeRemoved(queryByText(/not here/i)).catch(err =>
+ console.log(err),
)
-waitForElementToBeRemoved(queryAllByText(/not here/i)).catch((err) =>
- console.log(err)
+waitForElementToBeRemoved(queryAllByText(/not here/i)).catch(err =>
+ console.log(err),
)
-waitForElementToBeRemoved(() => getByText(/not here/i)).catch((err) =>
- console.log(err)
+waitForElementToBeRemoved(() => getByText(/not here/i)).catch(err =>
+ console.log(err),
)
// Error: The element(s) given to waitForElementToBeRemoved are already removed. waitForElementToBeRemoved requires that the element(s) exist(s) before waiting for removal.
```
The options object is forwarded to `waitFor`.
-
-## Deprecated Methods
-
-`wait`, `waitForDomChange`, and `waitForElement` have been combined into the
-`waitFor` method.
-
-
-
-
-
-Deprecated Methods
-
-### `wait`
-
-> (DEPRECATED, use waitFor instead)
-
-```typescript
-function wait(
- callback: () => void,
- options?: {
- container?: HTMLElement
- timeout?: number
- interval?: number
- mutationObserverOptions?: MutationObserverInit
- }
-): Promise
-```
-
-Previously, wait was a wrapper around wait-for-expect and used polling instead
-of a MutationObserver to look for changes. It is now an alias to waitFor and
-will be removed in a future release.
-
-Unlike wait, the callback parameter is mandatory in waitFor. Although you can
-migrate an existing `wait()` call to `waitFor( () => {} )`, it is considered bad
-practice to use an empty callback because it will make the tests more fragile.
-
-### `waitForDomChange`
-
-> (DEPRECATED, use `waitFor` instead)
-
-```typescript
-function waitForDomChange(options?: {
- container?: HTMLElement
- timeout?: number
- mutationObserverOptions?: MutationObserverInit
-}): Promise
-```
-
-When in need to wait for the DOM to change you can use `waitForDomChange`. The
-`waitForDomChange` function is a small wrapper around the
-[`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).
-
-Here is an example where the promise will be resolved because the container is
-changed:
-
-```javascript
-const container = document.createElement('div')
-waitForDomChange({ container })
- .then(() => console.log('DOM changed!'))
- .catch((err) => console.log(`Error you need to deal with: ${err}`))
-container.append(document.createElement('p'))
-// if 👆 was the only code affecting the container and it was not run,
-// waitForDomChange would throw an error
-```
-
-The promise will resolve with a
-[`mutationsList`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/MutationObserver)
-which you can use to determine what kind of a change (or changes) affected the
-container
-
-```javascript
-const container = document.createElement('div')
-container.setAttribute('data-cool', 'true')
-waitForDomChange({ container }).then((mutationsList) => {
- const mutation = mutationsList[0]
- console.log(
- `was cool: ${mutation.oldValue}\ncurrently cool: ${mutation.target.dataset.cool}`
- )
-})
-container.setAttribute('data-cool', 'false')
-/*
- logs:
- was cool: true
- currently cool: false
-*/
-```
-
-The default `container` is the global `document`. Make sure the elements you
-wait for are descendants of `container`.
-
-The default `timeout` is `1000ms` which will keep you under
-[Jest's default timeout of `5000ms`](https://jestjs.io/docs/en/jest-object.html#jestsettimeouttimeout).
-
-The default `mutationObserverOptions` is
-`{subtree: true, childList: true, attributes: true, characterData: true}` which
-will detect additions and removals of child elements (including text nodes) in
-the `container` and any of its descendants. It will also detect attribute
-changes.
-
-### `waitForElement`
-
-> (DEPRECATED, use `find*` queries or `waitFor`)
-
-```typescript
-function waitForElement(
- callback: () => T,
- options?: {
- container?: HTMLElement
- timeout?: number
- mutationObserverOptions?: MutationObserverInit
- }
-): Promise
-```
-
-When in need to wait for DOM elements to appear, disappear, or change you can
-use `waitForElement`. The `waitForElement` function is a small wrapper around
-the
-[`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver).
-
-Here's a simple example:
-
-```javascript
-// ...
-// Wait until the callback does not throw an error and returns a truthy value. In this case, that means
-// it'll wait until we can get a form control with a label that matches "username".
-// Previously, the difference from `wait` is that rather than running your callback on
-// an interval, it's run as soon as there are DOM changes in the container
-// and returns the value returned by the callback.
-const usernameElement = await waitForElement(
- () => getByLabelText(container, 'username'),
- { container }
-)
-usernameElement.value = 'chucknorris'
-// ...
-```
-
-You can also wait for multiple elements at once:
-
-```javascript
-const [usernameElement, passwordElement] = await waitForElement(
- () => [
- getByLabelText(container, 'username'),
- getByLabelText(container, 'password'),
- ],
- { container }
-)
-```
-
-The default `container` is the global `document`. Make sure the elements you
-wait for will be attached to it, or set a different `container`.
-
-The default `timeout` is `4500ms` which will keep you under
-[Jest's default timeout of `5000ms`](https://facebook.github.io/jest/docs/en/jest-object.html#jestsettimeouttimeout).
-
-The default `mutationObserverOptions` is
-`{subtree: true, childList: true, attributes: true, characterData: true}` which
-will detect additions and removals of child elements (including text nodes) in
-the `container` and any of its descendants. It will also detect attribute
-changes.
-
-
diff --git a/docs/dom-testing-library/api-configuration.mdx b/docs/dom-testing-library/api-configuration.mdx
index 7d772dff2..72dd2e196 100644
--- a/docs/dom-testing-library/api-configuration.mdx
+++ b/docs/dom-testing-library/api-configuration.mdx
@@ -21,19 +21,26 @@ The library can be configured via the `configure` function, which accepts:
> Framework-specific wrappers like React Testing Library may add more options to
> the ones shown below.
-
+
```js title="setup-tests.js"
-import { configure } from '@testing-library/dom'
+import {configure} from '@testing-library/dom'
import serialize from 'my-custom-dom-serializer'
configure({
testIdAttribute: 'data-my-test-id',
getElementError: (message, container) => {
const customMessage = [message, serialize(container.firstChild)].join(
- '\n\n'
+ '\n\n',
)
return new Error(customMessage)
},
@@ -44,18 +51,31 @@ configure({
```js title="setup-tests.js"
-import { configure } from '@testing-library/react'
+import {configure} from '@testing-library/react'
-configure({ testIdAttribute: 'data-my-test-id' })
+configure({testIdAttribute: 'data-my-test-id'})
+```
+
+
+
+
+```ts title="setup-tests.ts"
+import {configure} from '@testing-library/angular'
+
+configure({
+ dom: {
+ testIdAttribute: 'data-my-test-id',
+ },
+})
```
```js title="setup-tests.js"
-import { configure } from '@testing-library/cypress'
+import {configure} from '@testing-library/cypress'
-configure({ testIdAttribute: 'data-my-test-id' })
+configure({testIdAttribute: 'data-my-test-id'})
```
@@ -70,37 +90,76 @@ second argument. If you're using testing-library in a browser you almost always
want to set this to `true`. Only very old browser don't support this property
(such as IE 8 and earlier). However, `jsdom` does not support the second
argument currently. This includes versions of `jsdom` prior to `16.4.0` and any
-version that logs a `not implemented` warning when calling `getComputedStyle`
+version that logs a `not implemented` warning when calling
+[`getComputedStyle`](https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle)
with a second argument e.g.
`window.getComputedStyle(document.createElement('div'), '::after')`. Defaults to
`false`
### `defaultHidden`
-The default value for the `hidden` option used by
+The default value for the [`hidden` option](queries/byrole#hidden) used by
[`getByRole`](queries/byrole.mdx). Defaults to `false`.
+### `defaultIgnore`
+
+The default value for the [`ignore` option](queries/bytext.mdx#ignore) used by
+[`getByText`](queries/bytext.mdx). Also determines the nodes that are being
+ignored when errors are printed.
+
+Defaults to `script, style`.
+
### `showOriginalStackTrace`
-By default, `waitFor` will ensure that the stack trace for errors thrown by
-Testing Library is cleaned up and shortened so it's easier for you to identify
-the part of your code that resulted in the error (async stack traces are hard to
-debug). If you want to disable this, then set`showOriginalStackTrace` to
-`false`. You can also disable this for a specific call in the options you pass
-to `waitFor`.
+By default, [`waitFor`](api-async#waitfor) will ensure that the stack trace for
+errors thrown by Testing Library is cleaned up and shortened so it's easier for
+you to identify the part of your code that resulted in the error (async stack
+traces are hard to debug). If you want to disable this, then
+set`showOriginalStackTrace` to `false`. You can also disable this for a specific
+call in the options you pass to `waitFor`.
### `throwSuggestions` (experimental)
-When enabled, if [better queries](queries/about.mdx#priority) are available the
-test will fail and provide a suggested query to use instead. Default to `false`.
+When enabled, if [better queries](queries/about.mdx#priority) are available, the
+test will fail and provide a suggested query to use instead. Defaults to
+`false`.
To disable a suggestion for a single query just add `{suggest:false}` as an
option.
```js
-screen.getByTestId('foo', { suggest: false }) // will not throw a suggestion
+screen.getByTestId('foo', {suggest: false}) // will not throw a suggestion
```
+:::note
+
+When this option is enabled, it may provide suggestions that lack an intuitive
+implementation. Typically this happens for
+[roles which cannot be named](https://w3c.github.io/aria/#namefromprohibited),
+most notably paragraphs. For instance, if you attempt to use
+[`getByText`](queries/bytext.mdx), you may encounter the following error:
+
+```
+TestingLibraryElementError: A better query is available, try this:
+ getByRole('paragraph')
+```
+
+However, there is no direct way to query paragraphs using the config object
+parameter, such as in `getByRole('paragraph', { name: 'Hello World' })`.
+
+To address this issue, you can leverage a custom function to validate the
+element's structure, as shown in the example below. More information can be
+found in the
+[GitHub issue](https://github.com/testing-library/dom-testing-library/issues/1306)
+
+```js
+getByRole('paragraph', {
+ name: (_, element) => element.textContent === 'Hello world',
+})
+```
+
+:::
+
### `testIdAttribute`
The attribute used by [`getByTestId`](queries/bytestid.mdx) and related queries.
@@ -114,5 +173,5 @@ message and container object as arguments.
### `asyncUtilTimeout`
-The global timeout value in milliseconds used by `waitFor` utilities. Defaults
-to 1000ms.
+The global timeout value in milliseconds used by [`waitFor`](api-async#waitfor)
+utilities. Defaults to 1000ms.
diff --git a/docs/dom-testing-library/api-custom-queries.mdx b/docs/dom-testing-library/api-custom-queries.mdx
index 0fdad0b6f..8147ead50 100644
--- a/docs/dom-testing-library/api-custom-queries.mdx
+++ b/docs/dom-testing-library/api-custom-queries.mdx
@@ -3,9 +3,6 @@ id: api-custom-queries
title: Custom Queries
---
-import Tabs from '@theme/Tabs'
-import TabItem from '@theme/TabItem'
-
`DOM Testing Library` exposes many of the helper functions that are used to
implement the default queries. You can use the helpers to build custom queries.
For example, the code below shows a way to override the default `testId` queries
@@ -21,18 +18,17 @@ to use a different data-attribute. (Note: test files would import
> Custom queries are different than
> [custom render](react-testing-library/setup.mdx#custom-render) methods.
-```js
-// test-utils.js
+```js title="test-utils.js"
const domTestingLib = require('@testing-library/dom')
-const { queryHelpers } = domTestingLib
+const {queryHelpers} = domTestingLib
export const queryByTestId = queryHelpers.queryByAttribute.bind(
null,
- 'data-test-id'
+ 'data-test-id',
)
export const queryAllByTestId = queryHelpers.queryAllByAttribute.bind(
null,
- 'data-test-id'
+ 'data-test-id',
)
export function getAllByTestId(container, id, ...rest) {
@@ -40,18 +36,22 @@ export function getAllByTestId(container, id, ...rest) {
if (!els.length) {
throw queryHelpers.getElementError(
`Unable to find an element by: [data-test-id="${id}"]`,
- container
+ container,
)
}
return els
}
-export function getByTestId(...args) {
- const result = getAllByTestId(...args)
- if (result.length > 0) {
- return result[0]
+export function getByTestId(container, id, ...rest) {
+ // result >= 1
+ const result = getAllByTestId(container, id, ...rest)
+ if (result.length > 1) {
+ throw queryHelpers.getElementError(
+ `Found multiple elements with the [data-test-id="${id}"]`,
+ container,
+ )
}
- return null
+ return result[0]
}
// re-export with overrides
diff --git a/docs/dom-testing-library/api-debugging.mdx b/docs/dom-testing-library/api-debugging.mdx
index b68e5c1bb..492542440 100644
--- a/docs/dom-testing-library/api-debugging.mdx
+++ b/docs/dom-testing-library/api-debugging.mdx
@@ -5,8 +5,8 @@ title: Debugging
## Automatic Logging
-When you use any `get` calls in your test cases, the current state of the
-`container` (DOM) gets printed on the console. For example:
+When any `get` or `find` calls you use in your test cases fail, the current
+state of the `container` (DOM) gets printed on the console. For example:
```javascript
//
Hello world
@@ -26,13 +26,13 @@ Here is the state of your container:
```
-Note: Since the DOM size can get really large, you can set the limit of DOM
+**Note**: Since the DOM size can get really large, you can set the limit of DOM
content to be printed via environment variable `DEBUG_PRINT_LIMIT`. The default
value is `7000`. You will see `...` in the console, when the DOM content is
stripped off, because of the length you have set or due to default size limit.
Here's how you might increase this limit when running tests:
-```
+```bash npm2yarn
DEBUG_PRINT_LIMIT=10000 npm test
```
@@ -40,33 +40,58 @@ This works on macOS/Linux, you'll need to do something else for Windows. If
you'd like a solution that works for both, see
[`cross-env`](https://www.npmjs.com/package/cross-env).
+**Note**: The output of the DOM is colorized by default if your tests are
+running in a node environment. However, you may sometimes want to turn off
+colors, such as in cases where the output is written to a log file for debugging
+purposes. You can use the environment variable `COLORS` to explicitly force the
+colorization off or on. For example:
+
+```bash npm2yarn
+COLORS=false npm test
+```
+
+This works on macOS/Linux, you'll need to do something else for Windows. If
+you'd like a solution that works for both, see
+[`cross-env`](https://www.npmjs.com/package/cross-env).
+
## `prettyDOM`
Built on top of
-[`pretty-format`](https://github.com/facebook/jest/tree/master/packages/pretty-format),
+[`pretty-format`](https://github.com/jestjs/jest/tree/main/packages/pretty-format),
this helper function can be used to print out readable representation of the DOM
tree of a node. This can be helpful for instance when debugging tests.
It is defined as:
```typescript
+interface Options extends prettyFormat.OptionsReceived {
+ filterNode?: (node: Node) => boolean
+}
+
function prettyDOM(
node: HTMLElement,
maxLength?: number,
- options?: Options
+ options?: Options,
): string
```
It receives the root node to print out, an optional extra parameter to limit the
size of the resulting string, for cases when it becomes too large. It has a last
-parameter which allows you to configure your formatting as defined in the
-[options](https://github.com/facebook/jest/tree/master/packages/pretty-format#usage-with-options)
+parameter which allows you to configure your formatting. In addition to the
+options listed you can also pass the
+[options](https://github.com/jestjs/jest/tree/main/packages/pretty-format#usage-with-options)
of `pretty-format`.
+By default, ``, `` and comment nodes are ignored. You can
+configure this behavior by passing a custom `filterNode` function that should
+return `true` for every node that you wish to include in the output.
+
This function is usually used alongside `console.log` to temporarily print out
DOM trees during tests for debugging purposes:
```javascript
+import {prettyDOM} from '@testing-library/dom'
+
const div = document.createElement('div')
div.innerHTML = '
Hello World
'
console.log(prettyDOM(div))
@@ -76,7 +101,51 @@ console.log(prettyDOM(div))
```
This function is what also powers
-[the automatic debugging output described above](#debugging).
+[the automatic debugging output described above](#automatic-logging).
+
+## `screen.debug()`
+
+For convenience `screen` also exposes a `debug` method. This method is
+essentially a shortcut for `console.log(prettyDOM())`. It supports debugging the
+document, a single element, or an array of elements.
+
+```javascript
+import {screen} from '@testing-library/dom'
+
+document.body.innerHTML = `
+
+ multi-test
+
multi-test
+`
+
+// debug document
+screen.debug()
+// debug single element
+screen.debug(screen.getByText('test'))
+// debug multiple elements
+screen.debug(screen.getAllByText('multi-test'))
+```
+
+## `screen.logTestingPlaygroundURL()`
+
+For debugging using [testing-playground](https://testing-playground.com), screen
+exposes this convenient method which logs and returns a URL that can be opened
+in a browser.
+
+```javascript
+import {screen} from '@testing-library/dom'
+
+document.body.innerHTML = `
+
+ multi-test
+
multi-test
+`
+
+// log entire document to testing-playground
+screen.logTestingPlaygroundURL()
+// log a single element
+screen.logTestingPlaygroundURL(screen.getByText('test'))
+```
## `logRoles`
@@ -86,7 +155,7 @@ nodes which match that role. This can be helpful for finding ways to query the
DOM under test with [getByRole](queries/byrole.mdx).
```javascript
-import { logRoles } from '@testing-library/dom'
+import {logRoles} from '@testing-library/dom'
const nav = document.createElement('nav')
nav.innerHTML = `
diff --git a/docs/dom-testing-library/api-events.mdx b/docs/dom-testing-library/api-events.mdx
index 9bc3910bf..614ff1689 100644
--- a/docs/dom-testing-library/api-events.mdx
+++ b/docs/dom-testing-library/api-events.mdx
@@ -10,7 +10,7 @@ import TabItem from '@theme/TabItem'
>
> Most projects have a few use cases for `fireEvent`, but the majority of the
> time you should probably use
-> [`@testing-library/user-event`](ecosystem-user-event.mdx).
+> [`@testing-library/user-event`](user-event/intro.mdx).
## `fireEvent`
@@ -27,7 +27,7 @@ fireEvent(
new MouseEvent('click', {
bubbles: true,
cancelable: true,
- })
+ }),
)
```
@@ -41,13 +41,6 @@ Convenience methods for firing DOM events. Check out
[src/event-map.js](https://github.com/testing-library/dom-testing-library/blob/master/src/event-map.js)
for a full list as well as default `eventProperties`.
-```javascript
-//
-const rightClick = { button: 2 }
-fireEvent.click(getByText('Submit'), rightClick)
-// default `button` property for click events is set to `0` which is a left click.
-```
-
**target**: When an event is dispatched on an element, the event has the
subjected element on a property called `target`. As a convenience, if you
provide a `target` property in the `eventProperties` (second argument), then
@@ -56,14 +49,14 @@ those properties will be assigned to the node which is receiving the event.
This is particularly useful for a change event:
```javascript
-fireEvent.change(getByLabelText(/username/i), { target: { value: 'a' } })
+fireEvent.change(getByLabelText(/username/i), {target: {value: 'a'}})
// note: attempting to manually set the files property of an HTMLInputElement
// results in an error as the files property is read-only.
// this feature works around that by using Object.defineProperty.
fireEvent.change(getByLabelText(/picture/i), {
target: {
- files: [new File(['(⌐□_□)'], 'chucknorris.png', { type: 'image/png' })],
+ files: [new File(['(⌐□_□)'], 'chucknorris.png', {type: 'image/png'})],
},
})
@@ -72,10 +65,10 @@ fireEvent.change(getByLabelText(/picture/i), {
// reflect the changed value.
// Invalid:
-fireEvent.change(input, { target: { value: '24/05/2020' } })
+fireEvent.change(input, {target: {value: '24/05/2020'}})
// Valid:
-fireEvent.change(input, { target: { value: '2020-05-24' } })
+fireEvent.change(input, {target: {value: '2020-05-24'}})
```
**dataTransfer**: Drag events have a `dataTransfer` property that contains data
@@ -88,7 +81,7 @@ This should predominantly be used for testing drag and drop interactions.
```javascript
fireEvent.drop(getByLabelText(/drop files here/i), {
dataTransfer: {
- files: [new File(['(⌐□_□)'], 'chucknorris.png', { type: 'image/png' })],
+ files: [new File(['(⌐□_□)'], 'chucknorris.png', {type: 'image/png'})],
},
})
```
@@ -98,13 +91,13 @@ fireEvent.drop(getByLabelText(/drop files here/i), {
element in the DOM and the key you want to fire.
```javascript
-fireEvent.keyDown(domNode, { key: 'Enter', code: 'Enter' })
+fireEvent.keyDown(domNode, {key: 'Enter', code: 'Enter', charCode: 13})
-fireEvent.keyDown(domNode, { key: 'A', code: 'KeyA' })
+fireEvent.keyDown(domNode, {key: 'A', code: 'KeyA'})
```
You can find out which key code to use at
-[https://keycode.info/](https://keycode.info/).
+[https://www.toptal.com/developers/keycode](https://www.toptal.com/developers/keycode).
## `createEvent[eventName]`
@@ -118,9 +111,12 @@ be useful if you need to access event properties that cannot be initiated
programmatically (such as `timeStamp`).
```javascript
-const myEvent = createEvent.click(node, { button: 2 })
+const myEvent = createEvent.click(node, {button: 2})
fireEvent(node, myEvent)
// myEvent.timeStamp can be accessed just like any other properties from myEvent
+// note: The access to the events created by `createEvent` is based on the native event API,
+// Therefore, native properties of HTMLEvent object (e.g. `timeStamp`, `cancelable`, `type`) should be set using Object.defineProperty
+// For more info see: https://developer.mozilla.org/en-US/docs/Web/API/Event
```
You can also create generic events:
@@ -130,31 +126,31 @@ You can also create generic events:
fireEvent(
input,
createEvent('input', input, {
- target: { files: inputFiles },
+ target: {files: inputFiles},
...init,
- })
+ }),
)
```
## Using Jest Function Mocks
[Jest's Mock functions](https://jestjs.io/docs/en/mock-functions) can be used to
-test that a callback passed to the function was called, or what it was called
-when the event that **should** trigger the callback function does trigger the
-bound callback.
+test that a component will call its bound callback in response to a particular
+event.
```jsx
-import { render, screen, fireEvent } from '@testing-library/react'
+import {render, screen, fireEvent} from '@testing-library/react'
-const Button = ({ onClick, children }) => (
+const Button = ({onClick, children}) => (
)
@@ -164,6 +160,31 @@ test('calls onClick prop when clicked', () => {
fireEvent.click(screen.getByText(/click me/i))
expect(handleClick).toHaveBeenCalledTimes(1)
})
+```
+
+
+
+
+```ts
+import {render, screen, fireEvent} from '@testing-library/angular'
+
+@Component({
+ template: ``,
+})
+class ButtonComponent {
+ @Output() handleClick = new EventEmitter()
+}
+
+test('calls onClick prop when clicked', async () => {
+ const handleClick = jest.fn()
+ await render(ButtonComponent, {
+ componentOutputs: {
+ handleClick: {emit: handleClick} as any,
+ },
+ })
+ await fireEvent.click(screen.getByText(/click me/i))
+ expect(handleClick).toHaveBeenCalledTimes(1)
+})
```
diff --git a/docs/dom-testing-library/api-within.mdx b/docs/dom-testing-library/api-within.mdx
index e1a78b54f..eda32b9a4 100644
--- a/docs/dom-testing-library/api-within.mdx
+++ b/docs/dom-testing-library/api-within.mdx
@@ -19,13 +19,14 @@ could do:
values={[
{ label: 'Native', value: 'native', },
{ label: 'React', value: 'react', },
+ { label: 'Angular', value: 'angular', },
{ label: 'Cypress', value: 'cypress', },
]
}>
```js
-import { within } from '@testing-library/dom'
+import {within} from '@testing-library/dom'
const messages = document.getElementById('messages')
const helloMessage = within(messages).getByText('hello')
@@ -35,19 +36,30 @@ const helloMessage = within(messages).getByText('hello')
```jsx
-import { render, within } from '@testing-library/react'
+import {render, within} from '@testing-library/react'
-const { getByLabelText } = render()
-const signinModal = getByLabelText('Sign In')
-within(signinModal).getByPlaceholderText('Username')
+const {getByText} = render()
+const messages = getByText('messages')
+const helloMessage = within(messages).getByText('hello')
+```
+
+
+
+
+```ts
+import {render, within} from '@testing-library/angular'
+
+const {getByText} = await render(MyComponent)
+const messages = getByText('messages')
+const helloMessage = within(messages).getByText('hello')
```
```js
-cy.get('form').within(() => {
- cy.findByText('Button Text').should('be.disabled')
+cy.findByText('messages').within(() => {
+ cy.findByText('hello')
})
```
diff --git a/docs/dom-testing-library/cheatsheet.mdx b/docs/dom-testing-library/cheatsheet.mdx
index 6a5614bfb..d5625d104 100644
--- a/docs/dom-testing-library/cheatsheet.mdx
+++ b/docs/dom-testing-library/cheatsheet.mdx
@@ -90,9 +90,9 @@ See [Async API](dom-testing-library/api-async.mdx). Remember to `await` or
> - **wait** (Promise) retry the function within until it stops throwing or
> times
> - **waitForElement** (Promise) retry the function until it returns an element
-> or an array of elements
-> - `findBy` and `findAllBy` queries are async and retry until either a timeout
-> or if the query returns successfully; they wrap `waitForElement`
+> or an array of elements. The `findBy` and `findAllBy` queries are async and
+> retry until the query returns successfully, or when the query times out;
+> they wrap `waitForElement`
> - **waitForDomChange** (Promise) retry the function each time the DOM is
> changed
@@ -130,8 +130,8 @@ Given the following HTML:
```javascript
// Matching a string:
getByText(container, 'Hello World') // full string match
-getByText(container, 'llo Worl', { exact: false }) // substring match
-getByText(container, 'hello world', { exact: false }) // ignore case
+getByText(container, 'llo Worl', {exact: false}) // substring match
+getByText(container, 'hello world', {exact: false}) // ignore case
// Matching a regex:
getByText(container, /World/) // substring match
@@ -151,7 +151,7 @@ test('loads items eventually', async () => {
fireEvent.click(getByText(node, 'Load'))
// Wait for page to update with query text
- const items = await findByText(node, /Item #[0-9]: /)
+ const items = await findAllByText(node, /Item #[0-9]: /)
expect(items).toHaveLength(10)
})
```
diff --git a/docs/dom-testing-library/example-intro.mdx b/docs/dom-testing-library/example-intro.mdx
index 4d2aca746..d169dc915 100644
--- a/docs/dom-testing-library/example-intro.mdx
+++ b/docs/dom-testing-library/example-intro.mdx
@@ -4,8 +4,7 @@ title: Example
sidebar_label: Example
---
-```javascript
-// src/__tests__/example.js
+```js title="src/__tests__/example.js"
// query utilities:
import {
getByLabelText,
@@ -17,7 +16,7 @@ import {
waitFor,
} from '@testing-library/dom'
// adds special assertions like toHaveTextContent
-import '@testing-library/jest-dom/extend-expect'
+import '@testing-library/jest-dom'
function getExampleDOM() {
// This is just a raw example of setting up some DOM
@@ -58,13 +57,13 @@ test('examples of some things', async () => {
getByText(container, 'Print Username').click()
await waitFor(() =>
- expect(queryByTestId(container, 'printed-username')).toBeTruthy()
+ expect(queryByTestId(container, 'printed-username')).toBeTruthy(),
)
// getByTestId and queryByTestId are an escape hatch to get elements
// by a test id (could also attempt to get this element by its text)
expect(getByTestId(container, 'printed-username')).toHaveTextContent(
- famousProgrammerInHistory
+ famousProgrammerInHistory,
)
// jest snapshots work great with regular DOM nodes!
expect(container).toMatchSnapshot()
diff --git a/docs/dom-testing-library/faq.mdx b/docs/dom-testing-library/faq.mdx
index 7afbb8172..39e8de991 100644
--- a/docs/dom-testing-library/faq.mdx
+++ b/docs/dom-testing-library/faq.mdx
@@ -91,7 +91,7 @@ index in question:
const items = [
/* your items */
]
-const container = render(/* however you render this stuff */)
+const {container} = render(/* however you render this stuff */)
const thirdItem = getAllByRole(container, 'listitem')[2]
```
diff --git a/docs/dom-testing-library/install.mdx b/docs/dom-testing-library/install.mdx
index a9a875266..903a0325f 100644
--- a/docs/dom-testing-library/install.mdx
+++ b/docs/dom-testing-library/install.mdx
@@ -7,7 +7,7 @@ sidebar_label: Install
This module is distributed via [npm][npm] which is bundled with [node][node] and
should be installed as one of your project's `devDependencies`:
-```
+```bash npm2yarn
npm install --save-dev @testing-library/dom
```
@@ -28,12 +28,13 @@ install the wrapper:
- [Puppeteer Testing Library](pptr-testing-library/intro.mdx)
- [Testcafe Testing Library](testcafe-testing-library/intro.mdx)
- [Nightwatch Testing Library](nightwatch-testing-library/intro.mdx)
+- [Solid Testing Library](solid-testing-library/intro.mdx)
## Ecosystem
`DOM Testing Library` works well with these companion libraries:
-- [user-event](ecosystem-user-event.mdx) browser event simulation
+- [user-event](user-event/intro.mdx) browser event simulation
- [jest-dom](ecosystem-jest-dom.mdx) custom Jest matchers
- [bs-jest-dom](ecosystem-bs-jest-dom.mdx) companion library for
`bs-react-testing-library`
@@ -61,7 +62,7 @@ right file when you require/import `@testing-library/dom` or you can import the
file you need more explicitly. For example:
```js
-import { within } from '@testing-library/dom/dist/@testing-library/dom.umd.js'
+import {within} from '@testing-library/dom/dist/@testing-library/dom.umd.js'
```
You can
diff --git a/docs/dom-testing-library/setup.mdx b/docs/dom-testing-library/setup.mdx
index 060e024a5..b3be51807 100644
--- a/docs/dom-testing-library/setup.mdx
+++ b/docs/dom-testing-library/setup.mdx
@@ -10,7 +10,6 @@ people using `DOM Testing Library` are using it with
[the Jest testing framework](https://jestjs.io/) with the `testEnvironment` set
to
[`jest-environment-jsdom`](https://www.npmjs.com/package/jest-environment-jsdom)
-(which is the default configuration with Jest).
## Using Without Jest
@@ -19,11 +18,14 @@ the DOM and browser APIs that runs in node. If you're not using Jest and you
would like to run your tests in Node, then you must install jsdom yourself.
There's also a package called
[global-jsdom](https://github.com/modosc/global-jsdom) which can be used to
-setup the global environment to simulate the browser APIs.
+setup the global environment to simulate the browser APIs. Note that if you're
+using Vitest you only need to configure
+[`environment`](https://vitest.dev/config/#environment) to `jsdom` to achieve
+the same effect, you don't need global-jsdom.
First, install jsdom and global-jsdom.
-```
+```bash npm2yarn
npm install --save-dev jsdom global-jsdom
```
diff --git a/docs/ecosystem-bs-jest-dom.mdx b/docs/ecosystem-bs-jest-dom.mdx
index 157e8c81a..0f75bb463 100644
--- a/docs/ecosystem-bs-jest-dom.mdx
+++ b/docs/ecosystem-bs-jest-dom.mdx
@@ -8,7 +8,7 @@ title: bs-jest-dom
custom DOM element matchers for Jest in [ReasonML][re] via
[BuckleScript][bucklescript].
-```
+```bash npm2yarn
npm install --save-dev bs-jest-dom
```
@@ -30,9 +30,7 @@ full list of available matchers.
## Example
-```reason
-/* A_test.re */
-
+```reason title="A_test.re"
open Jest;
open JestDom;
open ReactTestingLibrary;
diff --git a/docs/ecosystem-cli-testing-library.mdx b/docs/ecosystem-cli-testing-library.mdx
new file mode 100644
index 000000000..8b5a4074d
--- /dev/null
+++ b/docs/ecosystem-cli-testing-library.mdx
@@ -0,0 +1,48 @@
+---
+id: ecosystem-cli-testing-library
+title: cli-testing-library
+---
+
+[`CLI Testing Library`](https://github.com/crutchcorn/cli-testing-library) is a
+companion library to `Testing Library` that aims to mimic the API of
+`Testing Library` for testing CLI applications.
+
+```bash npm2yarn
+npm install --save-dev cli-testing-library
+```
+
+```js
+import {resolve} from 'path'
+import {render} from 'cli-testing-library'
+
+test('Is able to make terminal input and view in-progress stdout', async () => {
+ const {clear, findByText, queryByText, userEvent} = await render('node', [
+ resolve(__dirname, './execute-scripts/stdio-inquirer.js'),
+ ])
+
+ const instance = await findByText('First option')
+
+ expect(instance).toBeInTheConsole()
+
+ expect(await findByText('❯ One')).toBeInTheConsole()
+
+ clear()
+
+ userEvent('[ArrowDown]')
+
+ expect(await findByText('❯ Two')).toBeInTheConsole()
+
+ clear()
+
+ userEvent.keyboard('[Enter]')
+
+ expect(await findByText('First option: Two')).toBeInTheConsole()
+ expect(await queryByText('First option: Three')).not.toBeInTheConsole()
+})
+```
+
+Check out
+[CLI Testing Library's documentation](https://github.com/crutchcorn/cli-testing-library)
+for a full list of its API.
+
+- [CLI Testing Library on GitHub](https://github.com/crutchcorn/cli-testing-library)
diff --git a/docs/ecosystem-eslint-plugin-testing-library.mdx b/docs/ecosystem-eslint-plugin-testing-library.mdx
index 63ca6d5de..0b69bd33b 100644
--- a/docs/ecosystem-eslint-plugin-testing-library.mdx
+++ b/docs/ecosystem-eslint-plugin-testing-library.mdx
@@ -20,4 +20,4 @@ Find more info about available rules and configs on GitHub.
- [eslint-plugin-testing-library on GitHub][gh]
-[gh]: https://github.com/Belco90/eslint-plugin-testing-library
+[gh]: https://github.com/testing-library/eslint-plugin-testing-library
diff --git a/docs/ecosystem-jasmine-dom.mdx b/docs/ecosystem-jasmine-dom.mdx
index 956fd154d..853baff10 100644
--- a/docs/ecosystem-jasmine-dom.mdx
+++ b/docs/ecosystem-jasmine-dom.mdx
@@ -6,7 +6,7 @@ title: jasmine-dom
[`jasmine-dom`][gh] is a companion library for Testing Library that provides
custom DOM element matchers for Jasmine
-```
+```bash npm2yarn
npm install --save-dev @testing-library/jasmine-dom
```
diff --git a/docs/ecosystem-jest-dom.mdx b/docs/ecosystem-jest-dom.mdx
index ce90a6d8a..33d473fe6 100644
--- a/docs/ecosystem-jest-dom.mdx
+++ b/docs/ecosystem-jest-dom.mdx
@@ -6,7 +6,7 @@ title: jest-dom
[`jest-dom`][gh] is a companion library for Testing Library that provides custom
DOM element matchers for Jest
-```
+```bash npm2yarn
npm install --save-dev @testing-library/jest-dom
```
@@ -14,7 +14,7 @@ Then follow [usage section][gh-usage] from jest-dom's documentation to add the
matchers to Jest.
```jsx
-import { screen } from '@testing-library/dom'
+import {screen} from '@testing-library/dom'
test('uses jest-dom', () => {
document.body.innerHTML = `
diff --git a/docs/ecosystem-jest-native.mdx b/docs/ecosystem-jest-native.mdx
index e98369fb8..b201e8a9f 100644
--- a/docs/ecosystem-jest-native.mdx
+++ b/docs/ecosystem-jest-native.mdx
@@ -4,23 +4,39 @@ title: jest-native
sidebar_label: jest-native
---
+:::warning
+
+**This package is deprecated and is no longer actively maintained.**
+
+We encourage you to migrate to React Native Testing Library, v12.4 or later,
+which includes modern
+[built-in Jest matchers](https://callstack.github.io/react-native-testing-library/docs/api/jest-matchers)
+based on the matchers for this repository. The migration process should be
+relatively straightforward, we have a
+[migration guide](https://callstack.github.io/react-native-testing-library/docs/migration/jest-matchers)
+available.
+
+:::
+
[`Jest Native`](https://github.com/testing-library/jest-native) is a companion
library for `React Native Testing Library` that provides custom element matchers
for Jest.
-```
+```bash npm2yarn
npm install --save-dev @testing-library/jest-native
```
-```javascript
-;
-
-
-
- Visible Example
-
+```jsx
+const {queryByTestId} = render(
+
+
+
+
+ Visible Example
+ ,
+)
-expect(queryByTestId(baseElement, 'not-empty')).not.toBeEmpty()
+expect(queryByTestId('not-empty')).not.toBeEmpty()
```
> Note: when using some of these matchers, you may need to make sure you use a
diff --git a/docs/ecosystem-query-extensions.mdx b/docs/ecosystem-query-extensions.mdx
index 19b4ac8a6..f69c706e0 100644
--- a/docs/ecosystem-query-extensions.mdx
+++ b/docs/ecosystem-query-extensions.mdx
@@ -7,7 +7,7 @@ title: query-extensions
Library that mixes a higher-level API into the standard `@testing-library` core
queries
-```
+```bash npm2yarn
npm install --save-dev query-extensions
```
diff --git a/docs/ecosystem-react-select-event.mdx b/docs/ecosystem-react-select-event.mdx
index c3cbe39a0..d9362d85f 100644
--- a/docs/ecosystem-react-select-event.mdx
+++ b/docs/ecosystem-react-select-event.mdx
@@ -7,27 +7,27 @@ title: react-select-event
that provides helper methods for interacting with [`react-select`][react-select]
elements.
-```
+```bash npm2yarn
npm install --save-dev react-select-event
```
```jsx
import React from 'react'
import Select from 'react-select'
-import { render } from '@testing-library/react'
+import {render} from '@testing-library/react'
import selectEvent from 'react-select-event'
-const { getByTestId, getByLabelText } = render(
+const {getByTestId, getByLabelText} = render(
+ ,
)
-expect(getByTestId('form')).toHaveFormValues({ food: '' }) // empty select
+expect(getByTestId('form')).toHaveFormValues({food: ''}) // empty select
// select two values...
await selectEvent.select(getByLabelText('Food'), ['Strawberry', 'Mango'])
-expect(getByTestId('form')).toHaveFormValues({ food: ['strawberry', 'mango'] })
+expect(getByTestId('form')).toHaveFormValues({food: ['strawberry', 'mango']})
// ...and add a third one
await selectEvent.select(getByLabelText('Food'), 'Chocolate')
diff --git a/docs/ecosystem-riot-testing-library.mdx b/docs/ecosystem-riot-testing-library.mdx
index 87dd922b2..d8fff54d9 100644
--- a/docs/ecosystem-riot-testing-library.mdx
+++ b/docs/ecosystem-riot-testing-library.mdx
@@ -7,21 +7,21 @@ title: riot-testing-library
[DOM Testing Library](https://github.com/testing-library/dom-testing-library) by
adding APIs for working with [Riot.js](https://riot.js.org/) components.
-```
+```bash npm2yarn
npm install --save-dev riot-testing-library
```
```javascript
-import render, { fireEvent } from 'riot-testing-library'
+import render, {fireEvent} from 'riot-testing-library'
import TestTag from './test.tag'
test('should show count text when rendered', () => {
- const { queryByTestId } = render(TestTag, { count: 10 })
+ const {queryByTestId} = render(TestTag, {count: 10})
expect(queryByTestId('count').textContent).toBe('10')
})
test('should add count when click add button text', () => {
- const { queryByTestId } = render(TestTag, { count: 1 })
+ const {queryByTestId} = render(TestTag, {count: 1})
expect(queryByTestId('count').textContent).toBe('1')
fireEvent.click(queryByTestId('button'))
expect(queryByTestId('count').textContent).toBe('2')
diff --git a/docs/ecosystem-rtl-simple-queries.md b/docs/ecosystem-rtl-simple-queries.md
index 35c2b3768..5cead58aa 100644
--- a/docs/ecosystem-rtl-simple-queries.md
+++ b/docs/ecosystem-rtl-simple-queries.md
@@ -6,19 +6,19 @@ title: rtl-simple-queries
[`rtl-simple-queries`][gh] is a companion library for `React Testing Library`
that provides an alternative query API.
-```
+```bash npm2yarn
npm install --save-dev rtl-simple-queries
```
```jsx
-import { screen } from 'rtl-simple-queries'
+import {screen} from 'rtl-simple-queries'
-screen.fetchByText(/text/, { allowEmpty: true, allowMultiple: false })
-screen.fetchByText(/text/, { allowMultiple: false })
+screen.fetchByText(/text/, {allowEmpty: true, allowMultiple: false})
+screen.fetchByText(/text/, {allowMultiple: false})
screen.fetchByText(/text/)
// async
-await screen.fetchByTextAsync(/text/, { allowMultiple: true })
+await screen.fetchByTextAsync(/text/, {allowMultiple: true})
```
- [rtl-simple-queries on GitHub][gh]
diff --git a/docs/ecosystem-testing-library-selector.md b/docs/ecosystem-testing-library-selector.md
index 5b9b33508..b2556949d 100644
--- a/docs/ecosystem-testing-library-selector.md
+++ b/docs/ecosystem-testing-library-selector.md
@@ -6,17 +6,17 @@ title: testing-library-selector
[`testing-library-selector`][gh] is a library for `@testing-library` that
provides reusable selectors. Written in typescript.
-```
+```bash npm2yarn
npm install --save-dev testing-library-selector
```
```typescript
-import { byLabelText, byRole, byTestId } from './selector'
+import {byLabelText, byRole, byTestId} from './selector'
// define reusable selectors
const ui = {
container: byTestId('my-container'),
- submitButton: byRole('button', { name: 'Submit' }),
+ submitButton: byRole('button', {name: 'Submit'}),
usernameInput: byLabelText('Username:'),
// can encode more specific html element type
diff --git a/docs/example-drag.mdx b/docs/example-drag.mdx
index 2d0fcecff..7203e6336 100644
--- a/docs/example-drag.mdx
+++ b/docs/example-drag.mdx
@@ -13,18 +13,18 @@ sidebar_label: Drag
```js
await drag(slider, {
- delta: { x: -100, y: 0 },
+ delta: {x: -100, y: 0},
})
```
-# Kapture
+# Capture

# Code
```js
-import { fireEvent } from '@testing-library/dom'
+import {fireEvent} from '@testing-library/dom'
// https://stackoverflow.com/a/53946549/1179377
function isElement(obj) {
@@ -50,24 +50,24 @@ function isElement(obj) {
}
function getElementClientCenter(element) {
- const { left, top, width, height } = element.getBoundingClientRect()
+ const {left, top, width, height} = element.getBoundingClientRect()
return {
x: left + width / 2,
y: top + height / 2,
}
}
-const getCoords = (charlie) =>
+const getCoords = charlie =>
isElement(charlie) ? getElementClientCenter(charlie) : charlie
-const sleep = (ms) =>
- new Promise((resolve) => {
+const sleep = ms =>
+ new Promise(resolve => {
setTimeout(resolve, ms)
})
export default async function drag(
element,
- { to: inTo, delta, steps = 20, duration = 500 }
+ {to: inTo, delta, steps = 20, duration = 500},
) {
const from = getElementClientCenter(element)
const to = delta
diff --git a/docs/example-external.mdx b/docs/example-external.mdx
index a5f54a59e..430e6b38f 100644
--- a/docs/example-external.mdx
+++ b/docs/example-external.mdx
@@ -4,11 +4,6 @@ title: External Examples
sidebar_label: External Examples
---
-## Code Samples
-
-- You can find more React Testing Library examples at
- [react-testing-examples.com](https://react-testing-examples.com/jest-rtl/).
-
## Playground
- An interactive sandbox with visual feedback on different queries
@@ -24,6 +19,6 @@ sidebar_label: External Examples
width="200px"
alt="what is react testing library"
src="https://img.youtube.com/vi/JKOwJUM4_RM/0.jpg"
- style={{ marginLeft: 36 }}
+ style={{marginLeft: 36}}
/>
diff --git a/docs/example-findByText.md b/docs/example-findByText.md
index 2228d76c2..f2b02b2d6 100644
--- a/docs/example-findByText.md
+++ b/docs/example-findByText.md
@@ -8,17 +8,14 @@ title: Using findByText
// This is an example of how to use findByText to query for text that
// is not visible right away
-import {
- getByRole,
- findByText,
- getByPlaceholderText,
-} from '@testing-library/dom'
+import {screen} from '@testing-library/dom'
import userEvent from '@testing-library/user-event'
// provides a set of custom jest matchers that you can use to extend jest
// i.e. `.toBeVisible`
import '@testing-library/jest-dom'
-const renderContent = (el) => {
+function renderApp() {
+ const el = document.body.appendChild(document.createElement('div'))
el.innerHTML = `