From 7d03c2dbe770bab188370fb96d0b4b6b5e18cbe5 Mon Sep 17 00:00:00 2001 From: MG Date: Sun, 21 Mar 2021 23:48:18 +0100 Subject: [PATCH] fix(#316): better support for typeIn and ngModel --- .../lib/mock-helper/cva/mock-helper.change.ts | 17 +++++- tests-angular/e2e/src/mat-input/test.spec.ts | 53 +++++++++++++++++++ tests/ng-mocks-change/reactive-forms.spec.ts | 15 +++++- 3 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 tests-angular/e2e/src/mat-input/test.spec.ts diff --git a/libs/ng-mocks/src/lib/mock-helper/cva/mock-helper.change.ts b/libs/ng-mocks/src/lib/mock-helper/cva/mock-helper.change.ts index 86a5397c8b..2a29aa4bcb 100644 --- a/libs/ng-mocks/src/lib/mock-helper/cva/mock-helper.change.ts +++ b/libs/ng-mocks/src/lib/mock-helper/cva/mock-helper.change.ts @@ -1,10 +1,22 @@ -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); @@ -12,6 +24,7 @@ export default (el: DebugNode, value: any): void => { return; } + triggerInput(el, value); for (const key of ['onChange', '_onChange', 'changeFn', '_onChangeCallback', 'onModelChange']) { if (typeof valueAccessor[key] === 'function') { valueAccessor[key](value); diff --git a/tests-angular/e2e/src/mat-input/test.spec.ts b/tests-angular/e2e/src/mat-input/test.spec.ts new file mode 100644 index 0000000000..dc2feb80ef --- /dev/null +++ b/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: ` + + + `, +}) +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'); + }); + }); +}); diff --git a/tests/ng-mocks-change/reactive-forms.spec.ts b/tests/ng-mocks-change/reactive-forms.spec.ts index 0653a6a873..91f00655e5 100644 --- a/tests/ng-mocks-change/reactive-forms.spec.ts +++ b/tests/ng-mocks-change/reactive-forms.spec.ts @@ -3,6 +3,7 @@ import { ControlValueAccessor, DefaultValueAccessor, FormControl, + FormsModule, NG_VALUE_ACCESSOR, ReactiveFormsModule, } from '@angular/forms'; @@ -29,17 +30,19 @@ class CustomDirective implements ControlValueAccessor { selector: 'my', template: ` + `, }) class MyComponent { public readonly myControl = new FormControl(); + public value: any = null; } @NgModule({ declarations: [MyComponent, CustomDirective], exports: [MyComponent], - imports: [ReactiveFormsModule], + imports: [ReactiveFormsModule, FormsModule], }) class MyModule {} @@ -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(