Skip to content

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Sep 24, 2025

Overview

This PR implements support for Angular's native bindings API in Angular Testing Library, addressing the suggestion in #526 that ATL's current input/output interfaces may be unnecessary with Angular's new approach.

What's New

Angular introduced a native bindings API that allows direct binding of inputs and outputs when creating components with TestBed.createComponent():

// Angular native approach
TestBed.createComponent(MyComponent, {
  bindings: [
    inputBinding('value', () => 'test-value'),
    outputBinding('click', (event) => console.log(event)),
    twoWayBinding('name', signal('initial'))
  ]
});

This PR adds seamless support for this pattern in ATL while maintaining full backward compatibility.

Usage Examples

New Bindings API

import { render, screen } from '@testing-library/angular';
import { inputBinding, outputBinding, twoWayBinding, signal } from '@angular/core';

await render(MyComponent, {
  bindings: [
    inputBinding('value', () => 'test-value'),
    inputBinding('greeting', () => 'hello'),  // supports aliases
    outputBinding('clicked', clickHandler),
    twoWayBinding('name', signal('initial'))  // two-way binding with signals
  ],
});

Traditional API (Still Supported)

await render(MyComponent, {
  inputs: { value: 'test-value', greeting: 'hello' },
  on: { clicked: clickHandler },
});

Mixed Usage

// Both approaches can coexist with intelligent warnings
await render(MyComponent, {
  bindings: [inputBinding('value', () => 'test-value')],
  inputs: { greeting: 'hello' }, // Warning: ignored due to Angular limitations
  on: { clicked: clickHandler }, // Works alongside bindings
});

Benefits

  1. Native Angular Integration - Uses Angular's official bindings API
  2. Better Performance - Bindings are handled natively by Angular, avoiding manual setup overhead
  3. Improved Type Safety - Leverages Angular's built-in type checking for bindings
  4. Future-Proof - Aligns with Angular's recommended testing patterns
  5. Zero Breaking Changes - Existing code continues to work unchanged
  6. Two-Way Data Binding - Full support for bidirectional data flow with signals

Implementation Details

  • Added bindings?: Binding[] option to RenderComponentOptions
  • Modified createComponent() to use TestBed.createComponent(component, { bindings }) when bindings are provided
  • Smart logic handles mixed usage scenarios with helpful warnings
  • Users import binding functions directly from @angular/core
  • Added comprehensive tests validating input binding, output binding, two-way binding, and mixed usage scenarios
  • Support for writable signals with re-rendering scenarios

Binding Types Supported

  • inputBinding() - Bind input values, including with writable signals for dynamic updates
  • outputBinding() - Listen to component outputs
  • twoWayBinding() - Bidirectional data binding with writable signals

Mixed Usage Behavior

Due to Angular's limitations, inputs and outputs behave differently when mixing approaches:

  • Inputs: Angular prevents mixing setInput() with inputBinding(), so bindings take complete precedence (with warning)
  • Outputs: Both outputBinding() and traditional on listeners work together
  • Warnings: Helpful messages guide users toward consistent usage patterns

Migration Path

Users can gradually adopt the new bindings API:

  • Immediate: Continue using existing inputs/on APIs - no changes required
  • Gradual: Start using bindings for new tests while keeping existing tests unchanged
  • Future: Eventually migrate to bindings API for consistency with Angular's patterns

This provides a smooth transition path while giving users access to Angular's modern testing capabilities.

Fixes #546

Fixes #546


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copilot AI and others added 2 commits September 24, 2025 16:55
Co-authored-by: timdeschryver <28659384+timdeschryver@users.noreply.github.com>
Co-authored-by: timdeschryver <28659384+timdeschryver@users.noreply.github.com>
@Copilot Copilot AI changed the title [WIP] Bindings API Add support for Angular v20 bindings API Sep 24, 2025
@Copilot Copilot AI requested a review from timdeschryver September 24, 2025 16:57
Copilot finished work on behalf of timdeschryver September 24, 2025 16:57
@timdeschryver
Copy link
Member

@copilot please look at my review comments

…arnings, remove v20 references

Co-authored-by: timdeschryver <28659384+timdeschryver@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Sep 24, 2025

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • cloud.nx.app
    • Triggering command: node ./bin/post-install (dns block)
    • Triggering command: node /home/REDACTED/work/angular-testing-library/angular-testing-library/node_modules/.bin/nx test testing-library (dns block)
    • Triggering command: node /home/REDACTED/work/angular-testing-library/angular-testing-library/node_modules/.bin/nx run-many --target=build --projects=testing-library (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@Copilot Copilot AI changed the title Add support for Angular v20 bindings API Add support for Angular bindings API Sep 24, 2025
@Copilot Copilot AI requested a review from timdeschryver September 24, 2025 18:35
Copilot finished work on behalf of timdeschryver September 24, 2025 18:35
@timdeschryver
Copy link
Member

@lacolaco is this what you had in mind?

@lacolaco
Copy link
Contributor

@timdeschryver Thanks. I'm gonna review in this week.

Copy link
Contributor

@lacolaco lacolaco left a comment

Choose a reason for hiding this comment

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

Basically, this is definitely what I wanted! I left some comments and suggestions on the implementation.

@timdeschryver
Copy link
Member

@copilot also add the functionality for twoWayBinding

Example:

const checkboxValue = signal('');
createComponent(MyCheckbox, {
bindings: [
twoWayBinding('value', checkboxValue),
],
});

And resolve this comment:

It would be better to add a case for a re-rendering scenario which uses inputBinding with a writable signal.

const valueSignal = signal('test-value');

await render(BindingsTestComponent, {
      bindings: [inputBinding('value', valueSignal), inputBinding('greet', () => 'hi there')],
    });

// <= assert 'test-value' is rendered.

valueSignal.set('updated-value');

// <= assert 'updated-value' is rendered

Co-authored-by: timdeschryver <28659384+timdeschryver@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Sep 27, 2025

@copilot also add the functionality for twoWayBinding

Example:
...

Added twoWayBinding functionality with comprehensive test coverage and documentation. Also added the requested test case using inputBinding with a writable signal that demonstrates re-rendering scenarios. The implementation supports signal-based two-way data binding where external signal changes update the component and component changes update the external signal. Commit 39fe933

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • cloud.nx.app
    • Triggering command: node ./bin/post-install (dns block)
    • Triggering command: node /home/REDACTED/work/angular-testing-library/angular-testing-library/node_modules/.bin/nx test testing-library (dns block)
    • Triggering command: node /home/REDACTED/work/angular-testing-library/angular-testing-library/node_modules/.bin/nx run-many --target=build --projects=testing-library (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@Copilot Copilot AI changed the title Add support for Angular bindings API Add support for Angular bindings API with twoWayBinding Sep 27, 2025
Copilot finished work on behalf of timdeschryver September 27, 2025 12:39
@timdeschryver timdeschryver marked this pull request as ready for review September 27, 2025 12:46
@timdeschryver timdeschryver force-pushed the copilot/fix-e93f4325-fc7e-4d7a-b6a8-9ff4df8eb8d9 branch from 46c5b80 to 04e96a2 Compare September 29, 2025 15:37
Copy link
Member

@timdeschryver timdeschryver left a comment

Choose a reason for hiding this comment

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

Thanks @lacolaco !

@timdeschryver timdeschryver merged commit f6d107d into main Sep 29, 2025
6 checks passed
@timdeschryver timdeschryver deleted the copilot/fix-e93f4325-fc7e-4d7a-b6a8-9ff4df8eb8d9 branch September 29, 2025 17:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bindings API
3 participants