ipsos-components
Version:
Material Design components for Angular
344 lines (278 loc) • 12.5 kB
text/typescript
import {Component, ViewChild} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {ComponentFixture, TestBed, async, fakeAsync, flushMicrotasks} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
import {MatInputModule} from './index';
import {MatTextareaAutosize} from './autosize';
import {MatStepperModule} from '@angular/material/stepper';
import {MatTabsModule} from '@angular/material/tabs';
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
describe('MatTextareaAutosize', () => {
let fixture: ComponentFixture<AutosizeTextAreaWithContent>;
let textarea: HTMLTextAreaElement;
let autosize: MatTextareaAutosize;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
FormsModule,
MatInputModule,
MatStepperModule,
MatTabsModule,
NoopAnimationsModule,
],
declarations: [
AutosizeTextareaInAStep,
AutosizeTextareaInATab,
AutosizeTextAreaWithContent,
AutosizeTextAreaWithValue,
AutosizeTextareaWithNgModel,
AutosizeTextareaWithLongPlaceholder
],
});
TestBed.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AutosizeTextAreaWithContent);
fixture.detectChanges();
textarea = fixture.nativeElement.querySelector('textarea');
autosize = fixture.debugElement.query(
By.directive(MatTextareaAutosize)).injector.get<MatTextareaAutosize>(MatTextareaAutosize);
});
it('should resize the textarea based on its content', () => {
let previousHeight = textarea.clientHeight;
fixture.componentInstance.content = `
Once upon a midnight dreary, while I pondered, weak and weary,
Over many a quaint and curious volume of forgotten lore—
While I nodded, nearly napping, suddenly there came a tapping,
As of some one gently rapping, rapping at my chamber door.
“’Tis some visitor,” I muttered, “tapping at my chamber door—
Only this and nothing more.”`;
// Manually call resizeToFitContent instead of faking an `input` event.
fixture.detectChanges();
autosize.resizeToFitContent();
expect(textarea.clientHeight)
.toBeGreaterThan(previousHeight, 'Expected textarea to have grown with added content.');
expect(textarea.clientHeight)
.toBe(textarea.scrollHeight, 'Expected textarea height to match its scrollHeight');
previousHeight = textarea.clientHeight;
fixture.componentInstance.content += `
Ah, distinctly I remember it was in the bleak December;
And each separate dying ember wrought its ghost upon the floor.
Eagerly I wished the morrow;—vainly I had sought to borrow
From my books surcease of sorrow—sorrow for the lost Lenore—
For the rare and radiant maiden whom the angels name Lenore—
Nameless here for evermore.`;
fixture.detectChanges();
autosize.resizeToFitContent();
expect(textarea.clientHeight)
.toBeGreaterThan(previousHeight, 'Expected textarea to have grown with added content.');
expect(textarea.clientHeight)
.toBe(textarea.scrollHeight, 'Expected textarea height to match its scrollHeight');
});
it('should set a min-width based on minRows', () => {
expect(textarea.style.minHeight).toBeFalsy();
fixture.componentInstance.minRows = 4;
fixture.detectChanges();
expect(textarea.style.minHeight).toBeDefined('Expected a min-height to be set via minRows.');
let previousMinHeight = parseInt(textarea.style.minHeight as string);
fixture.componentInstance.minRows = 6;
fixture.detectChanges();
expect(parseInt(textarea.style.minHeight as string))
.toBeGreaterThan(previousMinHeight, 'Expected increased min-height with minRows increase.');
});
it('should set a max-width based on maxRows', () => {
expect(textarea.style.maxHeight).toBeFalsy();
fixture.componentInstance.maxRows = 4;
fixture.detectChanges();
expect(textarea.style.maxHeight).toBeDefined('Expected a max-height to be set via maxRows.');
let previousMaxHeight = parseInt(textarea.style.maxHeight as string);
fixture.componentInstance.maxRows = 6;
fixture.detectChanges();
expect(parseInt(textarea.style.maxHeight as string))
.toBeGreaterThan(previousMaxHeight, 'Expected increased max-height with maxRows increase.');
});
it('should export the matAutosize reference', () => {
expect(fixture.componentInstance.autosize).toBeTruthy();
expect(fixture.componentInstance.autosize.resizeToFitContent).toBeTruthy();
});
it('should initially set the rows of a textarea to one', () => {
expect(textarea.rows)
.toBe(1, 'Expected the directive to initially set the rows property to one.');
fixture.componentInstance.minRows = 1;
fixture.detectChanges();
expect(textarea.rows)
.toBe(1, 'Expected the textarea to have the rows property set to one.');
const previousMinHeight = parseInt(textarea.style.minHeight as string);
fixture.componentInstance.minRows = 2;
fixture.detectChanges();
expect(textarea.rows).toBe(1, 'Expected the rows property to be set to one. ' +
'The amount of rows will be specified using CSS.');
expect(parseInt(textarea.style.minHeight as string))
.toBeGreaterThan(previousMinHeight, 'Expected the textarea to grow to two rows.');
});
it('should calculate the proper height based on the specified amount of max rows', () => {
fixture.componentInstance.content = [1, 2, 3, 4, 5, 6, 7, 8].join('\n');
fixture.detectChanges();
autosize.resizeToFitContent();
expect(textarea.clientHeight)
.toBe(textarea.scrollHeight, 'Expected textarea to not have a vertical scrollbar.');
fixture.componentInstance.maxRows = 5;
fixture.detectChanges();
expect(textarea.clientHeight)
.toBeLessThan(textarea.scrollHeight, 'Expected textarea to have a vertical scrollbar.');
});
it('should properly resize to content on init', () => {
// Manually create the test component in this test, because in this test the first change
// detection should be triggered after a multiline content is set.
fixture = TestBed.createComponent(AutosizeTextAreaWithContent);
textarea = fixture.nativeElement.querySelector('textarea');
autosize = fixture.debugElement.query(By.css('textarea')).injector.get(MatTextareaAutosize);
fixture.componentInstance.content = `
Line
Line
Line
Line
Line`;
fixture.detectChanges();
expect(textarea.clientHeight)
.toBe(textarea.scrollHeight, 'Expected textarea height to match its scrollHeight');
});
it('should not calculate wrong content height due to long placeholders', () => {
const fixtureWithPlaceholder = TestBed.createComponent(AutosizeTextareaWithLongPlaceholder);
fixtureWithPlaceholder.detectChanges();
textarea = fixtureWithPlaceholder.nativeElement.querySelector('textarea');
autosize = fixtureWithPlaceholder.debugElement.query(
By.directive(MatTextareaAutosize)).injector.get<MatTextareaAutosize>(MatTextareaAutosize);
triggerTextareaResize();
const heightWithLongPlaceholder = textarea.clientHeight;
fixtureWithPlaceholder.componentInstance.placeholder = 'Short';
fixtureWithPlaceholder.detectChanges();
triggerTextareaResize();
expect(textarea.clientHeight).toBe(heightWithLongPlaceholder,
'Expected the textarea height to be the same with a long placeholder.');
});
it('should resize when an associated form control value changes', fakeAsync(() => {
const fixtureWithForms = TestBed.createComponent(AutosizeTextareaWithNgModel);
textarea = fixtureWithForms.nativeElement.querySelector('textarea');
fixtureWithForms.detectChanges();
const previousHeight = textarea.clientHeight;
fixtureWithForms.componentInstance.model = `
And the silken, sad, uncertain rustling of each purple curtain
Thrilled me—filled me with fantastic terrors never felt before;
So that now, to still the beating of my heart, I stood repeating
“’Tis some visitor entreating entrance at my chamber door—
Some late visitor entreating entrance at my chamber door;—
This it is and nothing more.” `;
fixtureWithForms.detectChanges();
flushMicrotasks();
fixtureWithForms.detectChanges();
expect(textarea.clientHeight)
.toBeGreaterThan(previousHeight, 'Expected increased height when ngModel is updated.');
}));
it('should resize when the textarea value is changed programmatically', fakeAsync(() => {
const previousHeight = textarea.clientHeight;
textarea.value = `
How much wood would a woodchuck chuck
if a woodchuck could chuck wood?
`;
fixture.detectChanges();
flushMicrotasks();
fixture.detectChanges();
expect(textarea.clientHeight)
.toBeGreaterThan(previousHeight, 'Expected the textarea height to have increased.');
}));
it('should work in a tab', () => {
const fixtureWithForms = TestBed.createComponent(AutosizeTextareaInATab);
fixtureWithForms.detectChanges();
textarea = fixtureWithForms.nativeElement.querySelector('textarea');
expect(textarea.getBoundingClientRect().height).toBeGreaterThan(1);
});
it('should work in a step', () => {
const fixtureWithForms = TestBed.createComponent(AutosizeTextareaInAStep);
fixtureWithForms.detectChanges();
textarea = fixtureWithForms.nativeElement.querySelector('textarea');
expect(textarea.getBoundingClientRect().height).toBeGreaterThan(1);
});
/** Triggers a textarea resize to fit the content. */
function triggerTextareaResize() {
// To be able to trigger a new calculation of the height with a short placeholder, the
// textarea value needs to be changed.
textarea.value = '1';
autosize.resizeToFitContent();
textarea.value = '';
autosize.resizeToFitContent();
}
});
// Styles to reset padding and border to make measurement comparisons easier.
const textareaStyleReset = `
textarea {
padding: 0;
border: none;
overflow: auto;
}`;
({
template: `
<textarea matTextareaAutosize [matAutosizeMinRows]="minRows" [matAutosizeMaxRows]="maxRows"
#autosize="matTextareaAutosize">
{{content}}
</textarea>`,
styles: [textareaStyleReset],
})
class AutosizeTextAreaWithContent {
('autosize') autosize: MatTextareaAutosize;
minRows: number | null = null;
maxRows: number | null = null;
content: string = '';
}
({
template: `<textarea matTextareaAutosize [value]="value"></textarea>`,
styles: [textareaStyleReset],
})
class AutosizeTextAreaWithValue {
value: string = '';
}
({
template: `<textarea matTextareaAutosize [(ngModel)]="model"></textarea>`,
styles: [textareaStyleReset],
})
class AutosizeTextareaWithNgModel {
model = '';
}
({
template: `
<mat-form-field style="width: 100px">
<textarea matInput matTextareaAutosize [placeholder]="placeholder"></textarea>
</mat-form-field>`,
styles: [textareaStyleReset],
})
class AutosizeTextareaWithLongPlaceholder {
placeholder = 'Long Long Long Long Long Long Long Long Placeholder';
}
({
template: `
<mat-tab-group>
<mat-tab label="Tab 1">
<mat-form-field>
<textarea matInput matTextareaAutosize>
Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah
</textarea>
</mat-form-field>
</mat-tab>
</mat-tab-group>
`
})
class AutosizeTextareaInATab {}
({
template: `
<mat-horizontal-stepper>
<mat-step label="Step 1">
<mat-form-field>
<textarea matInput matTextareaAautosize>
Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah
</textarea>
</mat-form-field>
</mat-step>
</mat-horizontal-stepper>
`
})
class AutosizeTextareaInAStep {}