Skip to content

Conversation

@crisbeto
Copy link
Member

@crisbeto crisbeto commented Jun 13, 2025

Adds support for passing in Binding objects into TestBed.createComponent. This makes it easier to test components by avoiding the need to create a wrapper component. Furthermore, it keeps the behavior consistent between tests and the actual app. For example, given a custom checkbox that looks like this:

@Component({
  selector: 'my-checkbox',
  template: '...',
  host: {'[class.checked]': 'isChecked()'}
})
export class MyCheckbox {
  isChecked = input(false);
}

A test for the isChecked input would look something like this:

it('should toggle the checked class', () => {
  @Component({
    imports: [MyCheckbox],
    template: '<my-checkbox [isChecked]="isChecked"/>',
  })
  class Wrapper {
    isChecked = false;
  }

  const fixture = TestBed.createComponent(Wrapper);
  const checkbox = fixture.nativeElement.querySelector('my-checkbox');
  fixture.detectChanges();
  expect(checkbox.classList).not.toContain('checked');

  fixture.componentInstance.isChecked = true;
  fixture.detectChanges();
  expect(checkbox.classList).toContain('checked');
});

Whereas with the new API, the test would look like this:

it('should toggle the checked class', () => {
  const isChecked = signal(false);
  const fixture = TestBed.createComponent(MyCheckbox, {
    bindings: [inputBinding('isChecked', isChecked)]
  });
  const checkbox = fixture.nativeElement.querySelector('my-checkbox');
  fixture.detectChanges();
  expect(checkbox.classList).not.toContain('checked');

  isChecked.set(true);
  fixture.detectChanges();
  expect(checkbox.classList).toContain('checked');
});

@crisbeto crisbeto added action: review The PR is still awaiting reviews from at least one requested reviewer target: minor This PR is targeted for the next minor release labels Jun 13, 2025
@angular-robot angular-robot bot added detected: feature PR contains a feature commit area: core Issues related to the framework runtime labels Jun 13, 2025
@ngbot ngbot bot added this to the Backlog milestone Jun 13, 2025
@crisbeto crisbeto force-pushed the test-component-bindings branch from 274b4a4 to 9611870 Compare June 13, 2025 07:12
@crisbeto crisbeto marked this pull request as ready for review June 13, 2025 07:22
@pullapprove pullapprove bot requested review from atscott and thePunderWoman June 13, 2025 07:22
@crisbeto crisbeto changed the title feat(core): support bindings TestBed feat(core): support bindings in TestBed Jun 14, 2025
Adds support for passing in `Binding` objects into `TestBed.createComponent`. This makes it easier to test components by avoiding the need to create a wrapper component. Furthermore, it keeps the behavior consistent between tests and the actual app. For example, given a custom checkbox that looks like this:

```typescript
@component({
  selector: 'my-checkbox',
  template: '...',
  host: {'[class.checked]': 'isChecked()'}
})
export class MyCheckbox {
  isChecked = input(false);
}
```

A test for the `isChecked` input would look something like this:

```typescript
it('should toggle the checked class', () => {
  @component({
    imports: [MyCheckbox],
    template: '<my-checkbox [isChecked]="isChecked"/>',
  })
  class Wrapper {
    isChecked = false;
  }

  const fixture = TestBed.createComponent(Wrapper);
  const checkbox = fixture.nativeElement.querySelector('my-checkbox');
  fixture.detectChanges();
  expect(checkbox.classList).not.toContain('checked');

  fixture.componentInstance.isChecked = true;
  fixture.detectChanges();
  expect(checkbox.classList).toContain('checked');
});
```

Whereas with the new API, the test would look like this:

```typescript
it('should toggle the checked class', () => {
  const isChecked = signal(false);
  const fixture = TestBed.createComponent(MyCheckbox, {
    bindings: [inputBinding('isChecked', isChecked)]
  });
  const checkbox = fixture.nativeElement.querySelector('my-checkbox');
  fixture.detectChanges();
  expect(checkbox.classList).not.toContain('checked');

  isChecked.set(true);
  fixture.detectChanges();
  expect(checkbox.classList).toContain('checked');
});
```
@crisbeto crisbeto force-pushed the test-component-bindings branch from 9611870 to 49a1f83 Compare June 14, 2025 05:00
Copy link
Contributor

@thePunderWoman thePunderWoman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

reviewed-for: fw-general, public-api

@pullapprove pullapprove bot requested a review from mmalerba June 16, 2025 08:44
Copy link
Contributor

@atscott atscott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reviewed-for: public-api

@crisbeto crisbeto added action: merge The PR is ready for merge by the caretaker and removed action: review The PR is still awaiting reviews from at least one requested reviewer labels Jun 16, 2025
@pkozlowski-opensource
Copy link
Member

This PR was merged into the repository by commit 2e0c98b.

The changes were merged into the following branches: main

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Jul 18, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

action: merge The PR is ready for merge by the caretaker area: core Issues related to the framework runtime detected: feature PR contains a feature commit target: minor This PR is targeted for the next minor release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants