带有 @HostLinener 的 Angular Jest 测试指令 ('window:scroll' )

标签 angular testing scroll jestjs directive

问题:我想测试一个指令,该指令应该在“window:scroll”事件后更改元素的样式,但不知道如何触发该事件

指令:

@Directive({
    selector: '[directiveSelector]',
})
export class Directive {
    private breakpointOffset: number;
    private fixed = false;

    constructor(
        private readonly elementRef: ElementRef,
    ) {}

    ngAfterViewInit() {
            //fix the element when scrollTop reaches past element's offsetTop
            this.breakpointOffset = this.elementRef.nativeElement.offsetTop;
    }

    @HostListener('window:scroll')
    addScrollTrigger() {
        if (!this.fixed && window.pageYOffset > this.breakpointOffset) {
            this.elementRef.nativeElement.setAttribute(
                'style',
                'position: fixed;
            );
            this.fixed = true;
        }

        if (this.fixed && window.pageYOffset <= this.breakpointOffset) {
            this.elementRef.nativeElement.setAttribute('style', '');
            this.fixed = false;
        }
    }
}

我尝试过的:

@Component({
    template: ` <div #container directive></div> `,
})
class TestComponent {
    @ViewChild('container') container: ElementRef;
}

describe('Directive', () => {
    let fixture: ComponentFixture<TestComponent>;
    let component: TestComponent;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [TestComponent, Directive],
        }).compileComponents();

        fixture = TestBed.createComponent(TestComponent);
        component = fixture.componentInstance;
    }));

    describe('addScrollTrigger', () => {
        it('sets fixed style', () => {
            //Trigger scroll event?

            expect(component.container.nativeElement.styles).toEqual(....);
        });
    });
});

在我的测试中,我尝试创建一个带有模板的组件,该模板的 div 带有该指令。我无法做的是触发滚动事件,因为我必须直接访问指令并且无法调用“addScrollTrigger”函数,可以吗?

最佳答案

解决方案如下:

@Component({
    template: ` <div #container directive></div> `,
})
class TestComponent {
    @ViewChild('container', { static: true }) container: ElementRef;
}

describe('Directive', () => {
    let fixture: ComponentFixture<TestComponent>;
    let component: TestComponent;

    beforeEach(waitForAsync(() => {
        TestBed.configureTestingModule({
            declarations: [TestComponent, Directive],
        }).compileComponents();

        fixture = TestBed.createComponent(TestComponent);
        component = fixture.componentInstance;

        // mocking the offsetParent
        Object.defineProperty(HTMLElement.prototype, 'offsetParent', {
            get: function () {
                return { offsetTop: 100 };
            },
        });

        // mocking the offsetTop
        Object.defineProperty(HTMLElement.prototype, 'offsetTop', {
            get: function () {
                return 50;
            },
        });

        fixture.detectChanges();
    }));

    describe('addScrollTrigger', () => {
        it('sets fixed style', () => {
            //Trigger window scroll event 
            window.dispatchEvent(new Event('scroll'));
            fixture.detectChanges();
            
            expect(component.container.nativeElement.styles).toEqual(....);
        });
    });
});

关于带有 @HostLinener 的 Angular Jest 测试指令 ('window:scroll' ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64595128/

相关文章:

Java 和 Espresso - 无法输入,需要支持输入法或可从类 : class SearchView 分配

javascript - Angular 2.0 CLI 项目中 div 元素上的自定义滚动条?

Angular2(最终版本)和 Firebase 身份验证不是持久的

Angular 4 : Component reference inside ng-template

css - Angular - 单击按钮后更改表中行的背景颜色

javascript - getElementsByClassName 时旋转滚动 javascript 不起作用

android - 有没有办法找出 ListView 中显示了多少项?

Angular 4 "Can' t 绑定(bind)到 'ngModel',因为它不是 'input' 的已知属性。”

java - WebDriver 无法使用 Java 通过 xpath 找到元素

ruby-on-rails - 在不重新加载的情况下将大型数据集留在测试数据库中