-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(textarea): ionChange will only emit from user committed changes (#…
- Loading branch information
1 parent
a03c8af
commit 68bae80
Showing
15 changed files
with
280 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
describe('Textarea', () => { | ||
beforeEach(() => cy.visit('/textarea')); | ||
|
||
it('should become valid', () => { | ||
cy.get('#status').should('have.text', 'INVALID'); | ||
|
||
cy.get('ion-textarea').type('hello'); | ||
|
||
cy.get('#status').should('have.text', 'VALID'); | ||
}); | ||
|
||
it('should update the form control value when typing', () => { | ||
cy.get('#value').contains(`"textarea": ""`); | ||
cy.get('ion-textarea').type('hello'); | ||
|
||
cy.get('#value').contains(`"textarea": "hello"`); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
angular/test/base/src/app/textarea/textarea-routing.module.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { NgModule } from "@angular/core"; | ||
import { RouterModule } from "@angular/router"; | ||
import { TextareaComponent } from "./textarea.component"; | ||
|
||
@NgModule({ | ||
imports: [ | ||
RouterModule.forChild([ | ||
{ | ||
path: '', | ||
component: TextareaComponent | ||
} | ||
]) | ||
], | ||
exports: [RouterModule] | ||
}) | ||
export class TextareaRoutingModule { } |
16 changes: 16 additions & 0 deletions
16
angular/test/base/src/app/textarea/textarea.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<ion-content> | ||
<form [formGroup]="form"> | ||
<ion-list> | ||
<ion-item> | ||
<ion-label>Textarea</ion-label> | ||
<ion-textarea formControlName="textarea"></ion-textarea> | ||
</ion-item> | ||
</ion-list> | ||
</form> | ||
<p> | ||
Form status: <span id="status">{{ form.status }}</span> | ||
</p> | ||
<p> | ||
Form value: <span id="value">{{ form.value | json }}</span> | ||
</p> | ||
</ion-content> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
|
||
import { Component } from '@angular/core'; | ||
import { FormBuilder, Validators } from '@angular/forms'; | ||
|
||
@Component({ | ||
selector: 'app-textarea', | ||
templateUrl: 'textarea.component.html', | ||
}) | ||
export class TextareaComponent { | ||
|
||
form = this.fb.group({ | ||
textarea: ['', Validators.required] | ||
}) | ||
|
||
constructor(private fb: FormBuilder) { } | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { CommonModule } from "@angular/common"; | ||
import { NgModule } from "@angular/core"; | ||
import { FormsModule, ReactiveFormsModule } from "@angular/forms"; | ||
import { IonicModule } from "@ionic/angular"; | ||
|
||
import { TextareaRoutingModule } from "./textarea-routing.module"; | ||
import { TextareaComponent } from "./textarea.component"; | ||
|
||
@NgModule({ | ||
imports: [ | ||
CommonModule, | ||
FormsModule, | ||
ReactiveFormsModule, | ||
IonicModule, | ||
TextareaRoutingModule | ||
], | ||
declarations: [ | ||
TextareaComponent | ||
] | ||
}) | ||
export class TextareaModule { } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { expect } from '@playwright/test'; | ||
import { test } from '@utils/test/playwright'; | ||
|
||
test.describe('textarea: events: ionChange', () => { | ||
test.beforeEach(({ skip }) => { | ||
skip.rtl(); | ||
}); | ||
|
||
test.describe('when the textarea is blurred', () => { | ||
test('should emit if the value has changed', async ({ page }) => { | ||
await page.setContent(`<ion-textarea></ion-textarea>`); | ||
|
||
const nativeTextarea = page.locator('ion-textarea textarea'); | ||
const ionChangeSpy = await page.spyOnEvent('ionChange'); | ||
|
||
await nativeTextarea.type('new value', { delay: 100 }); | ||
// Value change is not emitted until the control is blurred. | ||
await nativeTextarea.evaluate((e) => e.blur()); | ||
|
||
await ionChangeSpy.next(); | ||
|
||
expect(ionChangeSpy).toHaveReceivedEventDetail({ value: 'new value' }); | ||
expect(ionChangeSpy).toHaveReceivedEventTimes(1); | ||
}); | ||
|
||
test('should emit if the textarea is cleared with an initial value', async ({ page }) => { | ||
await page.setContent(`<ion-textarea clear-on-edit="true" value="123"></ion-textarea>`); | ||
|
||
const textarea = page.locator('ion-textarea'); | ||
const nativeTextarea = textarea.locator('textarea'); | ||
const ionChangeSpy = await page.spyOnEvent('ionChange'); | ||
|
||
await nativeTextarea.type('new value'); | ||
|
||
await nativeTextarea.evaluate((e) => e.blur()); | ||
|
||
await ionChangeSpy.next(); | ||
|
||
expect(ionChangeSpy).toHaveReceivedEventDetail({ value: 'new value' }); | ||
expect(ionChangeSpy).toHaveReceivedEventTimes(1); | ||
}); | ||
|
||
test('should not emit if the value is set programmatically', async ({ page }) => { | ||
await page.setContent(`<ion-textarea></ion-textarea>`); | ||
|
||
const textarea = page.locator('ion-textarea'); | ||
const ionChangeSpy = await page.spyOnEvent('ionChange'); | ||
|
||
await textarea.evaluate((el: HTMLIonTextareaElement) => { | ||
el.value = 'new value'; | ||
}); | ||
|
||
await page.waitForChanges(); | ||
|
||
expect(ionChangeSpy).toHaveReceivedEventTimes(0); | ||
|
||
// Update the value again to make sure it doesn't emit a second time | ||
await textarea.evaluate((el: HTMLIonTextareaElement) => { | ||
el.value = 'new value 2'; | ||
}); | ||
|
||
await page.waitForChanges(); | ||
|
||
expect(ionChangeSpy).toHaveReceivedEventTimes(0); | ||
}); | ||
}); | ||
}); | ||
|
||
test.describe('textarea: events: ionInput', () => { | ||
test('should emit when the user types', async ({ page }) => { | ||
await page.setContent(`<ion-textarea value="some value"></ion-textarea>`); | ||
|
||
const ionInputSpy = await page.spyOnEvent('ionInput'); | ||
|
||
const nativeTextarea = page.locator('ion-textarea textarea'); | ||
await nativeTextarea.type('new value', { delay: 100 }); | ||
|
||
expect(ionInputSpy).toHaveReceivedEventDetail({ isTrusted: true }); | ||
}); | ||
|
||
test('should emit when the textarea is cleared on edit', async ({ page }) => { | ||
await page.setContent(`<ion-textarea clear-on-edit="true" value="some value"></ion-textarea>`); | ||
|
||
const ionInputSpy = await page.spyOnEvent('ionInput'); | ||
const textarea = page.locator('ion-textarea'); | ||
|
||
await textarea.click(); | ||
await textarea.press('Backspace'); | ||
|
||
expect(ionInputSpy).toHaveReceivedEventTimes(1); | ||
expect(ionInputSpy).toHaveReceivedEventDetail(null); | ||
}); | ||
}); |
Oops, something went wrong.