Skip to content

Commit 539d20b

Browse files
committed
refactor: introduce ...aliasedInput()
1 parent 058386d commit 539d20b

File tree

4 files changed

+82
-25
lines changed

4 files changed

+82
-25
lines changed

README.md

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,15 @@ counter.component.ts
100100
@Component({
101101
selector: 'app-counter',
102102
template: `
103+
<span>{{ hello() }}</span>
103104
<button (click)="decrement()">-</button>
104105
<span>Current Count: {{ counter() }}</span>
105106
<button (click)="increment()">+</button>
106107
`,
107108
})
108-
export class CounterComponent {
109+
class CounterComponent {
109110
counter = model(0);
111+
hello = input('Hi', { alias: 'greeting' });
110112

111113
increment() {
112114
this.counter.set(this.counter() + 1);
@@ -121,23 +123,30 @@ export class CounterComponent {
121123
counter.component.spec.ts
122124

123125
```typescript
124-
import { render, screen, fireEvent } from '@testing-library/angular';
126+
import { render, screen, fireEvent, aliasedInput } from '@testing-library/angular';
125127
import { CounterComponent } from './counter.component';
126128

127129
describe('Counter', () => {
128-
test('should render counter', async () => {
129-
await render(CounterComponent, { inputs: { counter: 5 } });
130-
131-
expect(screen.getByText('Current Count: 5'));
130+
it('should render counter', async () => {
131+
await render(CounterComponent, {
132+
inputs: {
133+
counter: 5,
134+
// aliases need to be specified this way
135+
...aliasedInput('greeting', 'Hello Alias!'),
136+
},
137+
});
138+
139+
expect(screen.getByText('Current Count: 5')).toBeVisible();
140+
expect(screen.getByText('Hello Alias!')).toBeVisible();
132141
});
133142

134-
test('should increment the counter on click', async () => {
143+
it('should increment the counter on click', async () => {
135144
await render(CounterComponent, { inputs: { counter: 5 } });
136145

137146
const incrementButton = screen.getByRole('button', { name: '+' });
138147
fireEvent.click(incrementButton);
139148

140-
expect(screen.getByText('Current Count: 6'));
149+
expect(screen.getByText('Current Count: 6')).toBeVisible();
141150
});
142151
});
143152
```

apps/example-app/src/app/examples/22-signal-inputs.component.spec.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { aliasedInputWithValue, render, screen, within } from '@testing-library/angular';
1+
import { aliasedInput, render, screen, within } from '@testing-library/angular';
22
import { SignalInputComponent } from './22-signal-inputs.component';
33
import userEvent from '@testing-library/user-event';
44

55
test('works with signal inputs', async () => {
66
await render(SignalInputComponent, {
77
inputs: {
8-
greeting: aliasedInputWithValue('Hello'),
8+
...aliasedInput('greeting', 'Hello'),
99
name: 'world',
1010
},
1111
});
@@ -17,7 +17,7 @@ test('works with signal inputs', async () => {
1717
test('works with computed', async () => {
1818
await render(SignalInputComponent, {
1919
inputs: {
20-
greeting: aliasedInputWithValue('Hello'),
20+
...aliasedInput('greeting', 'Hello'),
2121
name: 'world',
2222
},
2323
});
@@ -29,7 +29,7 @@ test('works with computed', async () => {
2929
test('can update signal inputs', async () => {
3030
const { fixture } = await render(SignalInputComponent, {
3131
inputs: {
32-
greeting: aliasedInputWithValue('Hello'),
32+
...aliasedInput('greeting', 'Hello'),
3333
name: 'world',
3434
},
3535
});
@@ -52,7 +52,7 @@ test('output emits a value', async () => {
5252
const submitFn = jest.fn();
5353
await render(SignalInputComponent, {
5454
inputs: {
55-
greeting: aliasedInputWithValue('Hello'),
55+
...aliasedInput('greeting', 'Hello'),
5656
name: 'world',
5757
},
5858
on: {
@@ -68,7 +68,7 @@ test('output emits a value', async () => {
6868
test('model update also updates the template', async () => {
6969
const { fixture } = await render(SignalInputComponent, {
7070
inputs: {
71-
greeting: aliasedInputWithValue('Hello'),
71+
...aliasedInput('greeting', 'Hello'),
7272
name: 'initial',
7373
},
7474
});
@@ -98,7 +98,7 @@ test('model update also updates the template', async () => {
9898
test('works with signal inputs, computed values, and rerenders', async () => {
9999
const view = await render(SignalInputComponent, {
100100
inputs: {
101-
greeting: aliasedInputWithValue('Hello'),
101+
...aliasedInput('greeting', 'Hello'),
102102
name: 'world',
103103
},
104104
});
@@ -111,7 +111,7 @@ test('works with signal inputs, computed values, and rerenders', async () => {
111111

112112
await view.rerender({
113113
inputs: {
114-
greeting: aliasedInputWithValue('bye'),
114+
...aliasedInput('greeting', 'bye'),
115115
name: 'test',
116116
},
117117
});

projects/testing-library/src/lib/models.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ export type ComponentInput<T> =
9595
* Creates an aliased input branded type with a value
9696
*
9797
*/
98-
export function aliasedInputWithValue<T>(value: T): AliasedInput<T> {
99-
return value as AliasedInput<T>;
98+
export function aliasedInput<TAlias extends string, T>(alias: TAlias, value: T): Record<TAlias, AliasedInput<T>> {
99+
return { [alias]: value } as Record<TAlias, AliasedInput<T>>;
100100
}
101101

102102
export interface RenderComponentOptions<ComponentType, Q extends Queries = typeof queries> {
@@ -220,7 +220,7 @@ export interface RenderComponentOptions<ComponentType, Q extends Queries = typeo
220220
* @description
221221
* An object to set `@Input` properties of the component
222222
*
223-
* @deprecated use the `inputs` option instead. When you need to use aliases, use the `aliasedInputWithValue(...)` helper function.
223+
* @deprecated use the `inputs` option instead. When you need to use aliases, use the `aliasedInput(...)` helper function.
224224
* @default
225225
* {}
226226
*
@@ -245,7 +245,7 @@ export interface RenderComponentOptions<ComponentType, Q extends Queries = typeo
245245
* inputs: {
246246
* counterValue: 10,
247247
* // explicitly define aliases this way:
248-
* someAlias: aliasedInputWithValue('value')
248+
* ...aliasedInput('someAlias', 'someValue')
249249
* })
250250
*/
251251
inputs?: ComponentInput<ComponentType>;

projects/testing-library/tests/render.spec.ts

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@ import {
1414
inject,
1515
output,
1616
input,
17+
model,
1718
} from '@angular/core';
1819
import { outputFromObservable } from '@angular/core/rxjs-interop';
1920
import { NoopAnimationsModule, BrowserAnimationsModule } from '@angular/platform-browser/animations';
2021
import { TestBed } from '@angular/core/testing';
21-
import { render, fireEvent, screen, OutputRefKeysWithCallback, aliasedInputWithValue } from '../src/public_api';
22+
import { render, fireEvent, screen, OutputRefKeysWithCallback, aliasedInput } from '../src/public_api';
2223
import { ActivatedRoute, Resolve, RouterModule } from '@angular/router';
2324
import { fromEvent, map } from 'rxjs';
2425
import { AsyncPipe, NgIf } from '@angular/common';
@@ -550,7 +551,7 @@ describe('inputs and signals', () => {
550551
await render(InputComponent, {
551552
inputs: {
552553
myName: 'Bob',
553-
job: aliasedInputWithValue('Builder'),
554+
...aliasedInput('job', 'Builder'),
554555
},
555556
});
556557

@@ -583,15 +584,15 @@ describe('inputs and signals', () => {
583584
// OK:
584585
await render(InputComponent, {
585586
inputs: {
586-
job: aliasedInputWithValue('OK'),
587+
...aliasedInput('job', 'OK'),
587588
},
588589
});
589590
},
590591
async () => {
591-
// @ts-expect-error - job is not using aliasedInputWithValue
592+
// @ts-expect-error - job is not using aliasedInput
592593
await render(InputComponent, {
593594
inputs: {
594-
job: 'not used with aliasedInputWithValue',
595+
job: 'not used with aliasedInput',
595596
},
596597
});
597598
},
@@ -601,3 +602,50 @@ describe('inputs and signals', () => {
601602
expect(typeTests).toBeTruthy();
602603
});
603604
});
605+
606+
describe('README examples', () => {
607+
describe('Counter', () => {
608+
@Component({
609+
selector: 'atl-counter',
610+
template: `
611+
<span>{{ hello() }}</span>
612+
<button (click)="decrement()">-</button>
613+
<span>Current Count: {{ counter() }}</span>
614+
<button (click)="increment()">+</button>
615+
`,
616+
})
617+
class CounterComponent {
618+
counter = model(0);
619+
hello = input('Hi', { alias: 'greeting' });
620+
621+
increment() {
622+
this.counter.set(this.counter() + 1);
623+
}
624+
625+
decrement() {
626+
this.counter.set(this.counter() + 1);
627+
}
628+
}
629+
630+
it('should render counter', async () => {
631+
await render(CounterComponent, {
632+
inputs: {
633+
counter: 5,
634+
...aliasedInput('greeting', 'Hello Alias!'),
635+
},
636+
});
637+
638+
expect(screen.getByText('Current Count: 5')).toBeVisible();
639+
expect(screen.getByText('Hello Alias!')).toBeVisible();
640+
});
641+
642+
it('should increment the counter on click', async () => {
643+
await render(CounterComponent, { inputs: { counter: 5 } });
644+
645+
const incrementButton = screen.getByRole('button', { name: '+' });
646+
fireEvent.click(incrementButton);
647+
648+
expect(screen.getByText('Current Count: 6')).toBeVisible();
649+
});
650+
});
651+
});

0 commit comments

Comments
 (0)