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]):
 S. Mumenthaler 💻 ⚠️ |
 Andrei Alecu 💻 🤔 📖 |
 Daniel Ramírez Barrientos 💻 |
+  Mahdi Lazraq 💻 ⚠️ |
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: `
- {{ greetings() }} {{ name() }}
+ {{ greetings() }} {{ name() }} of {{ age() }} years old
{{ greetingMessage() }}
@@ -16,10 +16,11 @@ export class SignalInputComponent {
greetings = input('', {
alias: 'greeting',
});
+ age = input.required({ transform: numberAttribute });
name = model.required();
submit = output();
- 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>;
export type ComponentInput =
| {
- [P in keyof T]?: T[P] extends Signal ? U : T[P];
+ [P in keyof T]?: T[P] extends InputSignalWithTransform
+ ? U
+ : T[P] extends Signal
+ ? U
+ : T[P];
}
| AliasedInputs;