Skip to content

Commit

Permalink
feat: remove change and changeInput in favor of rerender (#378)
Browse files Browse the repository at this point in the history
BREAKING CHANGE:

Use `rerender` instead of `change`.
Use `rerender` instead of `changechangeInput`.

For more info see #365
  • Loading branch information
timdeschryver authored Apr 3, 2023
1 parent 71c623f commit ccfcecf
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 281 deletions.
13 changes: 0 additions & 13 deletions apps/example-app-karma/src/app/issues/issue-222.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,3 @@ it('https://github.com/testing-library/angular-testing-library/issues/222 with r

expect(screen.getByText('Hello Mark')).toBeTruthy();
});

it('https://github.com/testing-library/angular-testing-library/issues/222 with change', async () => {
const { change } = await render(`<div>Hello {{ name}}</div>`, {
componentProperties: {
name: 'Sarah',
},
});

expect(screen.getByText('Hello Sarah')).toBeTruthy();
await change({ name: 'Mark' });

expect(screen.getByText('Hello Mark')).toBeTruthy();
});
14 changes: 0 additions & 14 deletions apps/example-app/src/app/examples/16-input-getter-setter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,6 @@ test('should run logic in the input setter and getter', async () => {
expect(getterValueControl).toHaveTextContent('I am value from getter Angular');
});

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

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

await change({ value: 'React' });

expect(valueControl).toHaveTextContent('I am value from setter React');
expect(getterValueControl).toHaveTextContent('I am value from getter React');
});

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

Expand Down
16 changes: 0 additions & 16 deletions projects/testing-library/src/lib/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,6 @@ export interface RenderResult<ComponentType, WrapperType = ComponentType> extend
'componentProperties' | 'componentInputs' | 'componentOutputs' | 'detectChangesOnRender'
>,
) => Promise<void>;
/**
* @deprecated
* Use rerender instead. For more info see {@link https://github.com/testing-library/angular-testing-library/issues/365 GitHub Issue}
*
* @description
* Keeps the current fixture intact and invokes ngOnChanges with the updated properties.
*/
change: (changedProperties: Partial<ComponentType>) => void;
/**
* @deprecated
* Use rerender instead. For more info see {@link https://github.com/testing-library/angular-testing-library/issues/365 GitHub Issue}
*
* @description
* Keeps the current fixture intact, update the @Input properties and invoke ngOnChanges with the updated properties.
*/
changeInput: (changedInputProperties: Partial<ComponentType>) => void;
}

export interface RenderComponentOptions<ComponentType, Q extends Queries = typeof queries> {
Expand Down
64 changes: 20 additions & 44 deletions projects/testing-library/src/lib/testing-library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,7 @@ export async function render<SutType, WrapperType = SutType>(
>,
) => {
const newComponentInputs = properties?.componentInputs ?? {};
for (const inputKey of renderedInputKeys) {
if (!Object.prototype.hasOwnProperty.call(newComponentInputs, inputKey)) {
delete (fixture.componentInstance as any)[inputKey];
}
}
setComponentInputs(fixture, newComponentInputs);
const changesInComponentInput = update(fixture, renderedInputKeys, newComponentInputs, setComponentInputs);
renderedInputKeys = Object.keys(newComponentInputs);

const newComponentOutputs = properties?.componentOutputs ?? {};
Expand All @@ -151,43 +146,21 @@ export async function render<SutType, WrapperType = SutType>(
renderedOutputKeys = Object.keys(newComponentOutputs);

const newComponentProps = properties?.componentProperties ?? {};
const changes = updateProps(fixture, renderedPropKeys, newComponentProps);
const changesInComponentProps = update(fixture, renderedPropKeys, newComponentProps, setComponentProperties);
renderedPropKeys = Object.keys(newComponentProps);

if (hasOnChangesHook(fixture.componentInstance)) {
fixture.componentInstance.ngOnChanges(changes);
fixture.componentInstance.ngOnChanges({
...changesInComponentInput,
...changesInComponentProps,
});
}
renderedPropKeys = Object.keys(newComponentProps);

if (properties?.detectChangesOnRender !== false) {
fixture.componentRef.injector.get(ChangeDetectorRef).detectChanges();
}
};

const changeInput = (changedInputProperties: Partial<SutType>) => {
if (Object.keys(changedInputProperties).length === 0) {
return;
}

setComponentInputs(fixture, changedInputProperties);

fixture.detectChanges();
};

const change = (changedProperties: Partial<SutType>) => {
if (Object.keys(changedProperties).length === 0) {
return;
}

const changes = getChangesObj(fixture.componentInstance as Record<string, any>, changedProperties);

setComponentProperties(fixture, changedProperties);

if (hasOnChangesHook(fixture.componentInstance)) {
fixture.componentInstance.ngOnChanges(changes);
}

fixture.componentRef.injector.get(ChangeDetectorRef).detectChanges();
};

const navigate = async (elementOrPath: Element | string, basePath = ''): Promise<boolean> => {
const href = typeof elementOrPath === 'string' ? elementOrPath : elementOrPath.getAttribute('href');
const [path, params] = (basePath + href).split('?');
Expand Down Expand Up @@ -234,8 +207,6 @@ export async function render<SutType, WrapperType = SutType>(
detectChanges: () => detectChanges(),
navigate,
rerender,
change,
changeInput,
// @ts-ignore: fixture assigned
debugElement: fixture.debugElement,
// @ts-ignore: fixture assigned
Expand Down Expand Up @@ -389,27 +360,32 @@ function getChangesObj(oldProps: Record<string, any> | null, newProps: Record<st
);
}

function updateProps<SutType>(
function update<SutType>(
fixture: ComponentFixture<SutType>,
prevRenderedPropsKeys: string[],
newProps: Record<string, any>,
prevRenderedKeys: string[],
newValues: Record<string, any>,
updateFunction: (
fixture: ComponentFixture<SutType>,
values: RenderTemplateOptions<SutType>['componentInputs' | 'componentProperties'],
) => void,
) {
const componentInstance = fixture.componentInstance as Record<string, any>;
const simpleChanges: SimpleChanges = {};

for (const key of prevRenderedPropsKeys) {
if (!Object.prototype.hasOwnProperty.call(newProps, key)) {
for (const key of prevRenderedKeys) {
if (!Object.prototype.hasOwnProperty.call(newValues, key)) {
simpleChanges[key] = new SimpleChange(componentInstance[key], undefined, false);
delete componentInstance[key];
}
}

for (const [key, value] of Object.entries(newProps)) {
for (const [key, value] of Object.entries(newValues)) {
if (value !== componentInstance[key]) {
simpleChanges[key] = new SimpleChange(componentInstance[key], value, false);
}
}
setComponentProperties(fixture, newProps);

updateFunction(fixture, newValues);

return simpleChanges;
}
Expand Down
96 changes: 0 additions & 96 deletions projects/testing-library/tests/change.spec.ts

This file was deleted.

97 changes: 0 additions & 97 deletions projects/testing-library/tests/changeInputs.spec.ts

This file was deleted.

Loading

0 comments on commit ccfcecf

Please sign in to comment.