From 9160da11d4870ea7d4a59e2912bdf75c4022ebe3 Mon Sep 17 00:00:00 2001
From: Mahdi Lazraq <94069699+mlz11@users.noreply.github.com>
Date: Tue, 13 Aug 2024 19:48:52 +0200
Subject: [PATCH 1/3] fix: add support for InputSignalWithTransform in inputs
 property (#484)

Closes #483
---
 .../22-signal-inputs.component.spec.ts        | 25 ++++++++++++-------
 .../examples/22-signal-inputs.component.ts    |  7 +++---
 projects/testing-library/src/lib/models.ts    |  8 ++++--
 3 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/apps/example-app/src/app/examples/22-signal-inputs.component.spec.ts b/apps/example-app/src/app/examples/22-signal-inputs.component.spec.ts
index cb22ba6..470e639 100644
--- a/apps/example-app/src/app/examples/22-signal-inputs.component.spec.ts
+++ b/apps/example-app/src/app/examples/22-signal-inputs.component.spec.ts
@@ -7,11 +7,12 @@ test('works with signal inputs', async () => {
     inputs: {
       ...aliasedInput('greeting', 'Hello'),
       name: 'world',
+      age: '45',
     },
   });
 
   const inputValue = within(screen.getByTestId('input-value'));
-  expect(inputValue.getByText(/hello world/i)).toBeInTheDocument();
+  expect(inputValue.getByText(/hello world of 45 years old/i)).toBeInTheDocument();
 });
 
 test('works with computed', async () => {
@@ -19,11 +20,12 @@ test('works with computed', async () => {
     inputs: {
       ...aliasedInput('greeting', 'Hello'),
       name: 'world',
+      age: '45',
     },
   });
 
   const computedValue = within(screen.getByTestId('computed-value'));
-  expect(computedValue.getByText(/hello world/i)).toBeInTheDocument();
+  expect(computedValue.getByText(/hello world of 45 years old/i)).toBeInTheDocument();
 });
 
 test('can update signal inputs', async () => {
@@ -31,18 +33,19 @@ test('can update signal inputs', async () => {
     inputs: {
       ...aliasedInput('greeting', 'Hello'),
       name: 'world',
+      age: '45',
     },
   });
 
   const inputValue = within(screen.getByTestId('input-value'));
   const computedValue = within(screen.getByTestId('computed-value'));
 
-  expect(inputValue.getByText(/hello world/i)).toBeInTheDocument();
+  expect(inputValue.getByText(/hello world of 45 years old/i)).toBeInTheDocument();
 
   fixture.componentInstance.name.set('updated');
   // set doesn't trigger change detection within the test, findBy is needed to update the template
-  expect(await inputValue.findByText(/hello updated/i)).toBeInTheDocument();
-  expect(await computedValue.findByText(/hello updated/i)).toBeInTheDocument();
+  expect(await inputValue.findByText(/hello updated of 45 years old/i)).toBeInTheDocument();
+  expect(await computedValue.findByText(/hello updated of 45 years old/i)).toBeInTheDocument();
 
   // it's not recommended to access the model directly, but it's possible
   expect(fixture.componentInstance.name()).toBe('updated');
@@ -54,6 +57,7 @@ test('output emits a value', async () => {
     inputs: {
       ...aliasedInput('greeting', 'Hello'),
       name: 'world',
+      age: '45',
     },
     on: {
       submit: submitFn,
@@ -70,6 +74,7 @@ test('model update also updates the template', async () => {
     inputs: {
       ...aliasedInput('greeting', 'Hello'),
       name: 'initial',
+      age: '45',
     },
   });
 
@@ -100,22 +105,24 @@ test('works with signal inputs, computed values, and rerenders', async () => {
     inputs: {
       ...aliasedInput('greeting', 'Hello'),
       name: 'world',
+      age: '45',
     },
   });
 
   const inputValue = within(screen.getByTestId('input-value'));
   const computedValue = within(screen.getByTestId('computed-value'));
 
-  expect(inputValue.getByText(/hello world/i)).toBeInTheDocument();
-  expect(computedValue.getByText(/hello world/i)).toBeInTheDocument();
+  expect(inputValue.getByText(/hello world of 45 years old/i)).toBeInTheDocument();
+  expect(computedValue.getByText(/hello world of 45 years old/i)).toBeInTheDocument();
 
   await view.rerender({
     inputs: {
       ...aliasedInput('greeting', 'bye'),
       name: 'test',
+      age: '0',
     },
   });
 
-  expect(inputValue.getByText(/bye test/i)).toBeInTheDocument();
-  expect(computedValue.getByText(/bye test/i)).toBeInTheDocument();
+  expect(inputValue.getByText(/bye test of 0 years old/i)).toBeInTheDocument();
+  expect(computedValue.getByText(/bye test of 0 years old/i)).toBeInTheDocument();
 });
diff --git a/apps/example-app/src/app/examples/22-signal-inputs.component.ts b/apps/example-app/src/app/examples/22-signal-inputs.component.ts
index ddc0c90..dfe6bd0 100644
--- a/apps/example-app/src/app/examples/22-signal-inputs.component.ts
+++ b/apps/example-app/src/app/examples/22-signal-inputs.component.ts
@@ -1,10 +1,10 @@
-import { Component, computed, input, model, output } from '@angular/core';
+import { Component, computed, input, model, numberAttribute, output } from '@angular/core';
 import { FormsModule } from '@angular/forms';
 
 @Component({
   selector: 'app-signal-input',
   template: `
-    <div data-testid="input-value">{{ greetings() }} {{ name() }}</div>
+    <div data-testid="input-value">{{ greetings() }} {{ name() }} of {{ age() }} years old</div>
     <div data-testid="computed-value">{{ greetingMessage() }}</div>
     <button (click)="submitName()">Submit</button>
     <input type="text" [(ngModel)]="name" />
@@ -16,10 +16,11 @@ export class SignalInputComponent {
   greetings = input<string>('', {
     alias: 'greeting',
   });
+  age = input.required<number, string>({ transform: numberAttribute });
   name = model.required<string>();
   submit = output<string>();
 
-  greetingMessage = computed(() => `${this.greetings()} ${this.name()}`);
+  greetingMessage = computed(() => `${this.greetings()} ${this.name()} of ${this.age()} years old`);
 
   submitName() {
     this.submit.emit(this.name());
diff --git a/projects/testing-library/src/lib/models.ts b/projects/testing-library/src/lib/models.ts
index f7697c5..1956728 100644
--- a/projects/testing-library/src/lib/models.ts
+++ b/projects/testing-library/src/lib/models.ts
@@ -1,4 +1,4 @@
-import { Type, DebugElement, EventEmitter, Signal } from '@angular/core';
+import { Type, DebugElement, EventEmitter, Signal, InputSignalWithTransform } from '@angular/core';
 import { ComponentFixture, DeferBlockBehavior, DeferBlockState, TestBed } from '@angular/core/testing';
 import { Routes } from '@angular/router';
 import { BoundFunction, Queries, queries, Config as dtlConfig, PrettyDOMOptions } from '@testing-library/dom';
@@ -94,7 +94,11 @@ export type AliasedInputs = Record<string, AliasedInput<unknown>>;
 
 export type ComponentInput<T> =
   | {
-      [P in keyof T]?: T[P] extends Signal<infer U> ? U : T[P];
+      [P in keyof T]?: T[P] extends InputSignalWithTransform<any, infer U>
+        ? U
+        : T[P] extends Signal<infer U>
+        ? U
+        : T[P];
     }
   | AliasedInputs;
 

From b11b6c3c60a02172ad5bf02e7d3b1d8bb5196f8f Mon Sep 17 00:00:00 2001
From: "allcontributors[bot]"
 <46447321+allcontributors[bot]@users.noreply.github.com>
Date: Tue, 13 Aug 2024 19:50:36 +0200
Subject: [PATCH 2/3] docs: add mlz11 as a contributor for code, and test
 (#485)

* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
---
 .all-contributorsrc | 10 ++++++++++
 README.md           |  1 +
 2 files changed, 11 insertions(+)

diff --git a/.all-contributorsrc b/.all-contributorsrc
index a919fb6..198cd09 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -400,6 +400,16 @@
       "contributions": [
         "code"
       ]
+    },
+    {
+      "login": "mlz11",
+      "name": "Mahdi Lazraq",
+      "avatar_url": "https://avatars.githubusercontent.com/u/94069699?v=4",
+      "profile": "https://github.com/mlz11",
+      "contributions": [
+        "code",
+        "test"
+      ]
     }
   ],
   "contributorsPerLine": 7,
diff --git a/README.md b/README.md
index f542b69..17bffce 100644
--- a/README.md
+++ b/README.md
@@ -268,6 +268,7 @@ Thanks goes to these people ([emoji key][emojis]):
       <td align="center" valign="top" width="14.28%"><a href="https://github.com/mumenthalers"><img src="https://avatars.githubusercontent.com/u/3604424?v=4?s=100" width="100px;" alt="S. Mumenthaler"/><br /><sub><b>S. Mumenthaler</b></sub></a><br /><a href="https://github.com/testing-library/angular-testing-library/commits?author=mumenthalers" title="Code">💻</a> <a href="https://github.com/testing-library/angular-testing-library/commits?author=mumenthalers" title="Tests">⚠️</a></td>
       <td align="center" valign="top" width="14.28%"><a href="https://lets.poker/"><img src="https://avatars.githubusercontent.com/u/697707?v=4?s=100" width="100px;" alt="Andrei Alecu"/><br /><sub><b>Andrei Alecu</b></sub></a><br /><a href="https://github.com/testing-library/angular-testing-library/commits?author=andreialecu" title="Code">💻</a> <a href="#ideas-andreialecu" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/testing-library/angular-testing-library/commits?author=andreialecu" title="Documentation">📖</a></td>
       <td align="center" valign="top" width="14.28%"><a href="https://github.com/Hyperxq"><img src="https://avatars.githubusercontent.com/u/22332354?v=4?s=100" width="100px;" alt="Daniel Ramírez Barrientos"/><br /><sub><b>Daniel Ramírez Barrientos</b></sub></a><br /><a href="https://github.com/testing-library/angular-testing-library/commits?author=Hyperxq" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/mlz11"><img src="https://avatars.githubusercontent.com/u/94069699?v=4?s=100" width="100px;" alt="Mahdi Lazraq"/><br /><sub><b>Mahdi Lazraq</b></sub></a><br /><a href="https://github.com/testing-library/angular-testing-library/commits?author=mlz11" title="Code">💻</a> <a href="https://github.com/testing-library/angular-testing-library/commits?author=mlz11" title="Tests">⚠️</a></td>
     </tr>
   </tbody>
 </table>

From 460fb32da1158dc8adc26ca6acd052078cb747d4 Mon Sep 17 00:00:00 2001
From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com>
Date: Tue, 13 Aug 2024 20:04:07 +0200
Subject: [PATCH 3/3]