Skip to content
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

656 autofill bug #1609

Merged
merged 3 commits into from
Jul 30, 2019
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
24 changes: 15 additions & 9 deletions terminus-ui/input/src/input.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import {
} from '@angular/core';
import {
ComponentFixture,
fakeAsync,
TestBed,
tick,
} from '@angular/core/testing';
import {
FormControl,
Expand Down Expand Up @@ -715,19 +717,23 @@ describe(`TsInputComponent`, function() {

describe(`AutofillMonitor`, () => {

test(`should monitor the input for autofill and cleanup after ngOnDestroy`, () => {
const fixture = createComponent(TestComponents.Autofill);
test(`should monitor the input for autofill and cleanup after ngOnDestroy`, fakeAsync(() => {
const fixture = createComponent<TestComponents.Autofill>(TestComponents.Autofill);
fixture.detectChanges();
fixture.componentInstance.inputComponent['autofillMonitor'].stopMonitoring = jest.fn();
const instance = getInputInstance(fixture);
instance['autofillMonitor'].stopMonitoring = jest.fn();

expect(fixture.componentInstance.inputComponent.autofilled).toEqual(false);
fixture.componentInstance.inputComponent['autofillMonitor']['fireMockFillEvent']();
expect(instance.autofilled).toEqual(false);
instance['autofillMonitor']['fireMockFillEvent']();
fixture.detectChanges();
tick(1000);
fixture.detectChanges();

expect(fixture.componentInstance.inputComponent.autofilled).toEqual(true);
expect(instance.autofilled).toEqual(true);

fixture.componentInstance.inputComponent.ngOnDestroy();
expect(fixture.componentInstance.inputComponent['autofillMonitor'].stopMonitoring).toHaveBeenCalled();
});
instance.ngOnDestroy();
expect(instance['autofillMonitor'].stopMonitoring).toHaveBeenCalled();
}));

});

Expand Down
47 changes: 20 additions & 27 deletions terminus-ui/input/src/input.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
NgZone,
OnChanges,
OnDestroy,
OnInit,
Optional,
Output,
Renderer2,
Expand Down Expand Up @@ -253,7 +252,6 @@ const DEFAULT_TEXTAREA_ROWS = 4;
export class TsInputComponent implements
// tslint:disable-next-line no-any
TsFormFieldControl<any>,
OnInit,
AfterViewInit,
AfterContentInit,
DoCheck,
Expand Down Expand Up @@ -882,13 +880,30 @@ export class TsInputComponent implements


/**
* Begin monitoring for the input autofill
* After the view is initialized, trigger any needed animations
*/
public ngOnInit(): void {
this.autofillMonitor.monitor(this.elementRef.nativeElement).subscribe(event => {
public ngAfterViewInit(): void {
// Begin monitoring for the input autofill
this.autofillMonitor.monitor(this.inputElement.nativeElement).subscribe(event => {
this.autofilled = event.isAutofilled;
this.stateChanges.next();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably the meat of this fix...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. Mainly we were passing a reference to our component rather than the actual <input> element. Moving the setup into ngAfterViewInit just makes sure all the ngIfs are settled before using that reference.

});

// istanbul ignore else
if (this.mask) {
this.setUpMask();
}

// Register this component as the associated input for the Material datepicker
// istanbul ignore else
// NOTE: Dangle naming controlled by Material
/* eslint-disable no-underscore-dangle */
if (this.picker && !this.picker._datepickerInput) {
// NOTE: Dangle naming controlled by Material
// tslint:disable-next-line no-any
this.picker._registerInput(this as any);
/* eslint-enable no-underscore-dangle */
}
}


Expand Down Expand Up @@ -922,28 +937,6 @@ export class TsInputComponent implements
}


/**
* After the view is initialized, trigger any needed animations
*/
public ngAfterViewInit(): void {
// istanbul ignore else
if (this.mask) {
this.setUpMask();
}

// Register this component as the associated input for the Material datepicker
// istanbul ignore else
// NOTE: Dangle naming controlled by Material
/* eslint-disable no-underscore-dangle */
if (this.picker && !this.picker._datepickerInput) {
// NOTE: Dangle naming controlled by Material
// tslint:disable-next-line no-any
this.picker._registerInput(this as any);
/* eslint-enable no-underscore-dangle */
}
}


// tslint:disable-next-line no-conflicting-lifecycle
public ngDoCheck(): void {
// We need to dirty-check the native element's value, because there are some cases where we won't be notified when it changes (e.g. the
Expand Down
1 change: 1 addition & 0 deletions terminus-ui/login-form/src/login-form.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
[isRequired]="true"
[spellcheck]="false"
[autocapitalize]="false"
autocomplete="email"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what difference does it make with or without this autocomplete input?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The autocomplete attribute tells the browser what data should be used when providing autocompletion.

In my quick tests it seems that both Chrome and FF can infer this if the input has a name or type that defines email. But since this is the 'correct' way to define it, I thought it should be added.

tabindex="-1"
tabIndex="1"
></ts-input>
Expand Down
30 changes: 30 additions & 0 deletions terminus-ui/utilities/src/type-coercion/is-mouse-event.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { createMouseEvent } from '@terminus/ngx-tools/testing';

import { isMouseEvent } from './is-mouse-event';


describe(`isMouseEvent`, function() {

test(`should return true for mouse events`, function() {
const fakeMouseEvent = createMouseEvent('click');
expect(isMouseEvent(fakeMouseEvent)).toEqual(true);
});


test(`should return false for anything that is not a mouse event`, function() {
const badValues = [
null,
void 0,
1,
0,
'foo',
{},
'',
];

for (const value of badValues) {
expect(isMouseEvent(value as any)).toEqual(false);
}
});

});
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ import { isSet } from '@terminus/ngx-tools';
*/
// tslint:disable-next-line no-any
export function isMouseEvent(x: any): x is MouseEvent {
return isSet(x.relatedTarget);
return !!x && isSet(x.relatedTarget);
}