У меня есть директива, которая изменяет высоту текста внутри элемента при изменении размера окна:
import {Directive, ElementRef, Renderer2, HostListener} from '@angular/core';
@Directive({selector: '[fittext]'})
export class FittextDirective {
constructor(private element: ElementRef, private renderer: Renderer2) { }
public changeFontSize(): void {
const htmlElement: HTMLElement = this.element.nativeElement;
const elemDims = htmlElement.getBoundingClientRect();
const height = elemDims.height;
// Set new font size on element
this.renderer.setStyle(htmlElement, 'font-size', `${height / 2}px`);
}
@HostListener('window:resize')
public onResize(): void {
this.changeFontSize();
}
}
И я пытаюсь протестировать его, используя пользовательский компонент-оболочку и отправляя событие изменения размера в окно.
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FittextDirective } from './fittext.directive';
import { Component, ViewChild, ElementRef } from '@angular/core';
import { By } from '@angular/platform-browser';
@Component({
template: `
<div #div fittext>{{ text }}</div>
<style>
div {
height: 100vh;
width: 100vw;
font-size: 100%;
}
</style>
`
})
class TestComponent {
@ViewChild('div') div: ElementRef;
public text: string = 'This is test string';
}
describe('FittextDirective', () => {
let component: TestComponent;
let fixture: ComponentFixture<TestComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
TestComponent,
FittextDirective
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
fit('should trigger on resize', () => {
const {height, width} = component.div.nativeElement.getBoundingClientRect();
const fontSize = component.div.nativeElement.style.fontSize;
window.dispatchEvent(new Event('resize'));
fixture.detectChanges()
const resizedElement = fixture.debugElement.query(By.directive(FittextDirective));
const {newHeight, newWidth} = resizedElement.nativeElement.getBoundingClientRect();
const newFontSize = resizedElement.nativeElement.style.fontSize;
expect(newHeight).not.toEqual(height);
expect(newWidth).not.toEqual(width);
expect(newFontSize).not.toEqual(fontSize);
});
});
Однако тесты сообщают, что размеры шрифта равны ''
, а высота и ширина после изменения размера (т. е. newHeight
и newWidth
) равны undefined
. Почему размер шрифта представляет собой пустую строку, хотя размер шрифта должен соответствовать размеру div? И почему высота и ширина после изменения размера окна не определены? Я использую безголовый хром для тестирования, поэтому я не могу использовать метод window.resizeTo(width, height)
.
Изменить 1: по предложению Alex K
я изменил newHeight
и newWidth
на:
const newHeight = resizedElement.nativeElement.getBoundingClientRect().height;
const newWidth = resizedElement.nativeElement.getBoundingClientRect().width;
Однако кажется, что после события изменения размера размер окна не изменяется (я получаю ошибку Expected 600 not to equal 600.
и Expected 785 not to equal 785.
). Я также изменил стиль между тегами на стиль в атрибуте компонента, то есть на атрибут styles
, но, тем не менее, fontSize
сообщается как ''
(или любой стиль в этом отношении).
Изменить 2: по какой-то странной причине стили можно получить только с помощью window.getComputedStyle()
(см. это). Теперь я получаю размер шрифта, но он не меняется после изменения размера.
const styles = window.getComputedStyle(element.nativeElement);
const fontSize = styles.fontSize;
...
const newStyles = window.getComputedStyle(resizedElement.nativeElement);
const newFontSize = newStyles.fontSize;
Редактировать 3: Как и предполагалось, я подделал размеры с помощью spyOn
, однако это не изменяет размер шрифтов.
spyOn(component.div.nativeElement, 'getBoundingClientRect')
.and.returnValue({height: height / 2, width: width / 2});
window.dispatchEvent(new Event('resize'));
fixture.detectChanges()
const {newHeight, newWidth} = resizedElement.nativeElement.getBoundingClientRect();
даетundefined
, потому что он пытается прочитать свойства с именамиnewHeight
иnewWidth
, которые не существуют в объекте. Вам нужно прочитать свойстваheight
иwidth
. - person Alex K   schedule 20.02.2019getBoundingClientRect()
. Но вы можете использоватьjasmine.spyOn
, чтобы метод возвращал любые размеры, которые вы хотите. Таким образом, вы можете вернуть 1000 для высоты, а затем проверить, например, что размер шрифта составляет 500 пикселей. - person Alex K   schedule 20.02.2019spyOn(component.div.nativeElement, 'getBoundingClientRect').and.returnValue({height: 100, width: 200})
- person Alex K   schedule 20.02.2019