ng-autosize
Version:
Angular Directive that automatically adjusts textarea height to fit content
146 lines (111 loc) • 4.85 kB
text/typescript
import { Component, DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { Autosize } from './autosize.directive';
({
standalone: true,
imports: [Autosize],
template: `<textarea autosize></textarea>`
})
class TestHostComponent {}
({
standalone: true,
imports: [Autosize],
template: `<textarea autosize [minHeight]="minHeight" [maxHeight]="maxHeight"></textarea>`
})
class TestHostWithInputsComponent {
minHeight = '100';
maxHeight = '300';
}
describe('Autosize', () => {
let fixture: ComponentFixture<TestHostComponent>;
let textarea: DebugElement;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TestHostComponent, TestHostWithInputsComponent]
});
fixture = TestBed.createComponent(TestHostComponent);
textarea = fixture.debugElement.query(By.css('textarea'));
fixture.detectChanges();
});
it('should create the directive', () => {
const directive = textarea.injector.get(Autosize);
expect(directive).toBeTruthy();
});
it('should adjust height on initialization', () => {
const element = textarea.nativeElement as HTMLTextAreaElement;
fixture.detectChanges();
expect(element.style.height).toBeTruthy();
});
it('should adjust height when input changes', () => {
const element = textarea.nativeElement as HTMLTextAreaElement;
const initialHeight = element.style.height;
element.value = 'Line 1\nLine 2\nLine 3\nLine 4\nLine 5';
element.dispatchEvent(new Event('input'));
fixture.detectChanges();
// Height should have changed due to more content
expect(element.style.height).not.toBe(initialHeight);
});
it('should set overflow to hidden', () => {
const element = textarea.nativeElement as HTMLTextAreaElement;
fixture.detectChanges();
expect(element.style.overflow).toBe('hidden');
});
it('should handle window resize', () => {
const directive = textarea.injector.get(Autosize);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
spyOn(directive as any, 'adjust');
window.dispatchEvent(new Event('resize'));
fixture.detectChanges();
// adjust should be called on resize
// eslint-disable-next-line @typescript-eslint/no-explicit-any
expect((directive as any).adjust).toHaveBeenCalled();
});
it('should set resize style for textareas with both resize', () => {
const element = textarea.nativeElement as HTMLTextAreaElement;
element.style.resize = 'both';
fixture.detectChanges();
const directive = textarea.injector.get(Autosize);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(directive as any).ngAfterViewInit();
expect(element.style.resize).toBe('horizontal');
});
it('should set resize to none for textareas with vertical resize', () => {
const element = textarea.nativeElement as HTMLTextAreaElement;
element.style.resize = 'vertical';
fixture.detectChanges();
const directive = textarea.injector.get(Autosize);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(directive as any).ngAfterViewInit();
expect(element.style.resize).toBe('none');
});
describe('with minHeight and maxHeight inputs', () => {
let fixtureWithInputs: ComponentFixture<TestHostWithInputsComponent>;
let textareaWithInputs: DebugElement;
beforeEach(() => {
fixtureWithInputs = TestBed.createComponent(TestHostWithInputsComponent);
textareaWithInputs = fixtureWithInputs.debugElement.query(By.css('textarea'));
fixtureWithInputs.detectChanges();
});
it('should set minHeight when provided', () => {
const element = textareaWithInputs.nativeElement as HTMLTextAreaElement;
expect(element.style.minHeight).toBe('100px');
});
it('should set maxHeight when provided', () => {
const element = textareaWithInputs.nativeElement as HTMLTextAreaElement;
expect(element.style.maxHeight).toBe('300px');
});
it('should update minHeight when input changes', () => {
const element = textareaWithInputs.nativeElement as HTMLTextAreaElement;
fixtureWithInputs.componentInstance.minHeight = '150';
fixtureWithInputs.detectChanges();
expect(element.style.minHeight).toBe('150px');
});
it('should update maxHeight when input changes', () => {
const element = textareaWithInputs.nativeElement as HTMLTextAreaElement;
fixtureWithInputs.componentInstance.maxHeight = '400';
fixtureWithInputs.detectChanges();
expect(element.style.maxHeight).toBe('400px');
});
});
});