Skip to content

Commit

Permalink
fix(#316): better support for typeIn and ngModel
Browse files Browse the repository at this point in the history
  • Loading branch information
satanTime committed Mar 21, 2021
1 parent 22b21d3 commit 7d03c2d
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 3 deletions.
17 changes: 15 additions & 2 deletions libs/ng-mocks/src/lib/mock-helper/cva/mock-helper.change.ts
@@ -1,17 +1,30 @@
import { DebugNode } from '@angular/core';
import { DebugElement } from '@angular/core';

import { isMockControlValueAccessor } from '../../common/func.is-mock-control-value-accessor';

import funcGetVca from './func.get-vca';

export default (el: DebugNode, value: any): void => {
// default html behavior
const triggerInput = (el: DebugElement, value: any): void => {
el.triggerEventHandler('focus', {});
el.nativeElement.value = value;
el.triggerEventHandler('input', {
target: {
value,
},
});
el.triggerEventHandler('blur', {});
};

export default (el: DebugElement, value: any): void => {
const valueAccessor = funcGetVca(el);
if (isMockControlValueAccessor(valueAccessor.instance)) {
valueAccessor.instance.__simulateChange(value);

return;
}

triggerInput(el, value);
for (const key of ['onChange', '_onChange', 'changeFn', '_onChangeCallback', 'onModelChange']) {
if (typeof valueAccessor[key] === 'function') {
valueAccessor[key](value);
Expand Down
53 changes: 53 additions & 0 deletions tests-angular/e2e/src/mat-input/test.spec.ts
@@ -0,0 +1,53 @@
import { Component, NgModule } from '@angular/core';
import {
FormControl,
FormsModule,
ReactiveFormsModule,
} from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { MockBuilder, MockRender, ngMocks } from 'ng-mocks';

@Component({
selector: 'target',
template: `
<input
type="text"
matInput
[formControl]="control"
name="form-control"
/>
<input type="text" matInput [(ngModel)]="value" name="ng-model" />
`,
})
class TargetComponent {
public readonly control = new FormControl();
public value;
}

@NgModule({
declarations: [TargetComponent],
imports: [FormsModule, ReactiveFormsModule, MatInputModule],
})
class TargetModule {}

describe('mat-input', () => {
describe('real', () => {
beforeEach(() => MockBuilder(TargetComponent).keep(TargetModule));

it('changes values', () => {
const component = MockRender(TargetComponent).point
.componentInstance;
const input1 = ngMocks.find(['name', 'form-control']);
const input2 = ngMocks.find(['name', 'ng-model']);

ngMocks.change(input1, 'input1');
expect(component.control.value).toEqual('input1');

ngMocks.change(input2, 'input2');
expect(component.value).toEqual('input2');

ngMocks.output(input2, 'ngModelChange').emit('input3');
expect(component.value).toEqual('input3');
});
});
});
15 changes: 14 additions & 1 deletion tests/ng-mocks-change/reactive-forms.spec.ts
Expand Up @@ -3,6 +3,7 @@ import {
ControlValueAccessor,
DefaultValueAccessor,
FormControl,
FormsModule,
NG_VALUE_ACCESSOR,
ReactiveFormsModule,
} from '@angular/forms';
Expand All @@ -29,17 +30,19 @@ class CustomDirective implements ControlValueAccessor {
selector: 'my',
template: `
<input data-testid="inputControl" [formControl]="myControl" />
<input data-testid="ngModel" [(ngModel)]="value" />
<custom [formControl]="myControl"></custom>
`,
})
class MyComponent {
public readonly myControl = new FormControl();
public value: any = null;
}

@NgModule({
declarations: [MyComponent, CustomDirective],
exports: [MyComponent],
imports: [ReactiveFormsModule],
imports: [ReactiveFormsModule, FormsModule],
})
class MyModule {}

Expand Down Expand Up @@ -82,6 +85,16 @@ describe('ng-mocks-change:reactive-forms:mock', () => {
expect(component.myControl.value).toEqual(123);
});

it('correctly changes ngModel', () => {
const component = MockRender(MyComponent).point.componentInstance;
const valueAccessorEl = ngMocks.find(['data-testid', 'ngModel']);

// normal change
expect(component.value).toEqual(null);
ngMocks.change(valueAccessorEl, 123);
expect(component.value).toEqual(123);
});

it('throws on bad element', () => {
const element = MockRender(MyComponent).point;
expect(() => ngMocks.change(element, 123)).toThrowError(
Expand Down

0 comments on commit 7d03c2d

Please sign in to comment.