Masalah: Saya ingin menguji arahan yang seharusnya mengubah gaya elemen setelah acara 'window:scroll' tetapi tidak tahu cara memicu acara

Petunjuk:

@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;
        }
    }
}

Yang saya coba:

@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(....);
        });
    });
});

Dalam pengujian saya, saya mencoba membuat komponen dengan templat yang memiliki div dengan arahan itu. Apa yang tidak dapat saya lakukan adalah memicu acara gulir karena saya harus akses langsung ke arahan dan tidak dapat memanggil fungsi "addScrollTrigger", bukan?

1
headofhappiness 29 Oktober 2020, 19:18

1 menjawab

Jawaban Terbaik

Inilah solusinya:

@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(....);
        });
    });
});
1
David Buck 30 Oktober 2020, 01:10