Skip to content

Fix: component setter is overwritten when component properties are set #192

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions apps/example-app/app/examples/16-input-getter-setter.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { render, screen } from '@testing-library/angular';
import { InputGetterSetter } from './16-input-getter-setter';

test('should run logic in the input setter and getter', async () => {
await render(InputGetterSetter, { componentProperties: { value: 'Angular' } });
const valueControl = screen.getByTestId('value');
const getterValueControl = screen.getByTestId('value-getter');

expect(valueControl.textContent).toBe('I am value from setter Angular');
expect(getterValueControl.textContent).toBe('I am value from getter Angular');
});

test('should run logic in the input setter and getter while re-rendering', async () => {
const component = await render(InputGetterSetter, { componentProperties: { value: 'Angular' } });
const valueControl = screen.getByTestId('value');
const getterValueControl = screen.getByTestId('value-getter');

expect(valueControl.textContent).toBe('I am value from setter Angular');
expect(getterValueControl.textContent).toBe('I am value from getter Angular');

await component.rerender({ value: 'React' });

expect(valueControl.textContent).toBe('I am value from setter React');
expect(getterValueControl.textContent).toBe('I am value from getter React');
});
22 changes: 22 additions & 0 deletions apps/example-app/app/examples/16-input-getter-setter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Component, Input } from '@angular/core';

@Component({
selector: 'app-fixture',
template: `
<span data-testid="value">{{ derivedValue }}</span>
<span data-testid="value-getter">{{ value }}</span>
`,
})
export class InputGetterSetter {
@Input() set value(value: string) {
this.originalValue = value;
this.derivedValue = 'I am value from setter ' + value;
}

get value() {
return 'I am value from getter ' + this.originalValue;
}

private originalValue: string;
derivedValue: string;
}
20 changes: 15 additions & 5 deletions projects/testing-library/src/lib/testing-library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,14 +205,24 @@ function setComponentProperties<SutType>(
{ componentProperties = {} }: Pick<RenderDirectiveOptions<SutType, any>, 'componentProperties'>,
) {
for (const key of Object.keys(componentProperties)) {
const descriptor: PropertyDescriptor = Object.getOwnPropertyDescriptor(
fixture.componentInstance.constructor.prototype,
key,
);
let _value = componentProperties[key];
const defaultGetter = () => _value;
const extendedSetter = (value) => {
_value = value;
descriptor?.set?.call(fixture.componentInstance, _value);
fixture.detectChanges();
};

Object.defineProperty(fixture.componentInstance, key, {
get: () => _value,
set: (value) => {
_value = value;
fixture.detectChanges();
},
get: descriptor?.get || defaultGetter,
set: extendedSetter,
});

descriptor?.set?.call(fixture.componentInstance, _value);
}
return fixture;
}
Expand Down