test: test input masking

This commit is contained in:
Sean Perkins
2023-05-08 23:09:50 -04:00
parent 18c9ca141b
commit 2dc4ae57dc
4 changed files with 152 additions and 11 deletions

View File

@@ -374,6 +374,14 @@ export class Input implements ComponentInterface {
this.emitStyle();
}
@Watch('mask')
protected maskChanged() {
if (this.maskController) {
this.maskController.destroy();
}
this.initInputMask();
}
componentWillLoad() {
const { el } = this;
@@ -400,18 +408,9 @@ export class Input implements ComponentInterface {
}
componentDidLoad() {
const { mask, nativeInput } = this;
this.originalIonInput = this.ionInput;
if (mask !== undefined && nativeInput) {
const formattedMask = formatMask(mask);
if (formattedMask) {
this.maskController = new MaskController(nativeInput, {
mask: formattedMask,
});
}
}
this.initInputMask();
}
disconnectedCallback() {
@@ -484,6 +483,18 @@ export class Input implements ComponentInterface {
return clearOnEdit === undefined ? type === 'password' : clearOnEdit;
}
private initInputMask() {
const { mask, nativeInput } = this;
if (mask !== undefined && nativeInput) {
const formattedMask = formatMask(mask);
if (formattedMask) {
this.maskController = new MaskController(nativeInput, {
mask: formattedMask,
});
}
}
}
private getValue(): string {
return typeof this.value === 'number' ? this.value.toString() : (this.value || '').toString();
}

View File

@@ -19,6 +19,7 @@
grid-row-gap: 20px;
grid-column-gap: 20px;
}
h2 {
font-size: 12px;
font-weight: normal;
@@ -27,6 +28,7 @@
margin-top: 10px;
}
@media screen and (max-width: 800px) {
.grid {
grid-template-columns: 1fr;
@@ -40,7 +42,7 @@
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>Input - Item</ion-title>
<ion-title>Input - Mask</ion-title>
</ion-toolbar>
</ion-header>
@@ -51,6 +53,17 @@
<ion-input id="input-phone-us" label="Phone"></ion-input>
</div>
<div class="grid-item">
<ion-card>
<ion-card-header>
<ion-card-title>Dynamic Mask</ion-card-title>
</ion-card-header>
<ion-card-content>
<ion-input id="dynamicMaskInput" label="Enter a mask"></ion-input>
<ion-input id="dynamicExample" label="Example"></ion-input>
</ion-card-content>
</ion-card>
</div>
</div>
</ion-content>
</ion-app>
@@ -76,6 +89,22 @@
/\d/,
/\d/,
];
inputPhoneUS.addEventListener('ionInput', (ev) => {
console.log('** ionInput event **', ev.detail);
});
inputPhoneUS.addEventListener('ionChange', (ev) => {
console.log('** ionChange event **', ev.detail);
});
const dynamicMaskInput = document.querySelector('#dynamicMaskInput');
dynamicMaskInput.addEventListener('ionChange', (ev) => {
const mask = ev.detail.value;
const exampleInput = document.querySelector('#dynamicExample');
console.log('setting the mask to: ', mask);
exampleInput.mask = mask;
});
</script>
</body>
</html>

View File

@@ -0,0 +1,44 @@
import { configs } from '@utils/test/playwright';
import { test } from './mask-fixture';
configs({
modes: ['md'],
directions: ['ltr'],
}).forEach(({ title, config }) => {
test.describe(title('input: mask'), () => {
test('should mask the input', async ({ maskPage }) => {
// US Phone number
await maskPage.init(config, [
'+',
'1',
' ',
'(',
/\d/,
/\d/,
/\d/,
')',
' ',
/\d/,
/\d/,
/\d/,
'-',
/\d/,
/\d/,
/\d/,
/\d/,
]);
await maskPage.typeAndBlur('5555555555');
await maskPage.expectValue('+1 (555) 555-5555');
});
test('should mask the input with a string', async ({ maskPage }) => {
// Only allow lowercase letters
await maskPage.init(config, '[a-z]$');
await maskPage.typeAndBlur('5abc123d');
await maskPage.expectValue('abcd');
});
});
});

View File

@@ -0,0 +1,57 @@
import { expect } from '@playwright/test';
import type { E2ELocator, E2EPage, TestConfig } from '@utils/test/playwright';
import { test as base } from '@utils/test/playwright';
import type { MaskExpression } from 'src/interface';
const stringifyMask = (mask: MaskExpression | string): string => {
if (typeof mask === 'string') {
return `'${mask}'`;
}
if (Array.isArray(mask)) {
return `[${mask.map(stringifyMask).join(', ')}]`;
}
return mask.toString();
};
class MaskPage {
ionInput!: E2ELocator;
nativeInput!: E2ELocator;
constructor(private page: E2EPage) {}
async init(config: TestConfig, mask: MaskExpression | string) {
await this.page.setContent(
`<ion-input></ion-input>
<script>
const input = document.querySelector('ion-input');
input.mask = ${stringifyMask(mask)};
</script>
`,
config
);
this.ionInput = this.page.locator('ion-input');
this.nativeInput = this.page.locator('ion-input input');
}
async typeAndBlur(value: string) {
await this.ionInput.click();
await this.ionInput.type(value, { delay: 50 });
await this.ionInput.blur();
}
async expectValue(value: string) {
expect(await this.ionInput.evaluate((node: HTMLIonInputElement) => node.value)).toBe(value);
}
}
type MaskFixtures = {
maskPage: MaskPage;
};
export const test = base.extend<MaskFixtures>({
maskPage: async ({ page }, use) => {
await use(new MaskPage(page));
},
});