2
\$\begingroup\$

I have the following jasmine test spec which triggers the mouse events in my directive. As you can see there is a lot of code duplication here, I am repeating the events here.

describe('Test for my module', () => {
        let fixture: ComponentFixture<TestComponent>;
        let de: DebugElement[];
        let service: MyService = new MyService();

        beforeEach(() => {
            TestBed.configureTestingModule({
                declarations: [Move, TestComponent],
                providers: [MyService]
            });
            fixture = TestBed.createComponent(TestComponent);
            service = fixture.debugElement.injector.get(MyService);
            fixture.detectChanges();
            de = fixture.debugElement.queryAll(By.directive(Move));
        });

// My test spec. This is where I need advice for removing the code duplication.
it('test the move event', inject([MyService], (service: MyService) => {
                let object = spyOn(service.x, 'emit');
                spyObj.and.callThrough();
                de[0].triggerEventHandler('mousedown', { pageX: 10, pageY: 10 });
                de[0].triggerEventHandler('mousemove', { pageX: 40, pageY: 20 });
                expect(service.x.emit).toHaveBeenCalledWith({ x: 30, y: 10 });
                object.calls.reset();
                de[0].triggerEventHandler('mousemove', { pageX: 45, pageY: 25 });
                expect(service.x.emit).toHaveBeenCalledWith({ x: 35, y: 15 });
                object.calls.reset();
                de[0].triggerEventHandler('mousemove', { pageX: 50, pageY: 30 });
                expect(service.x.emit).toHaveBeenCalledWith({ x: 40, y: 20 });

            }));

Could anyone help me by suggesting any way to avoid this duplication?

\$\endgroup\$
1
  • \$\begingroup\$ I was wondering if I can use an inline function here to avoid duplication? \$\endgroup\$
    – ShellZero
    Commented Jun 8, 2017 at 16:39

1 Answer 1

1
\$\begingroup\$

I did come up with one alternative which is as follows:

    function triggerEvents(debugElement: DebugElement, eventName: string, object: any){
            debugElement.triggerEventHandler(eventName, object);
        }

    function expectAndReset(spy: Function, object: any, spyObj: jasmine.Spy) {
        expect(spy).toHaveBeenCalledWith(object);
        spyObj.calls.reset();
    }

    it('test the move event', inject([MyService], (service: MyService) => {
        let spyObj = spyOn(service.x, 'emit');
        spyObj.and.callThrough();
        triggerEvents(de[0],'mousedown', { pageX: 10, pageY: 10 });
        triggerEvents(de[0],'mousemove', { pageX: 40, pageY: 20 });
        expectAndReset(service.x.emit,{ x: 30, y: 10 },spyObj);
        triggerEvents(de[0],'mousemove', { pageX: 45, pageY: 25 });
        expectAndReset(service.x.emit,{ x: 35, y: 15 },spyObj);
        triggerEvents(de[0],'mousemove', { pageX: 50, pageY: 30 });
        expectAndReset(service.x.emit,{ x: 40, y: 20 },spyObj);

    }));

I am not really satisfied with my own solution though, because the function implementation of triggerEvents is almost identical as the triggerEventHandler in the Angular Documentation. I am not doing anything special there. But I am hoping that the code reviewers on the community would comment or share their views and give me a better solution :)

Second Attempt:

        function triggerEvents(debugElement: DebugElement, eventName: string, object: any) {
            debugElement.triggerEventHandler(eventName, object);
        }

        function expectAndReset(spy: Function, object: any, spyObj: jasmine.Spy) {
            expect(spy).toHaveBeenCalledWith(object);
            spyObj.calls.reset();
        }

        it('test the move event', inject([MyService], (service: MyService) => {
            let spyObj = spyOn(service.x, 'emit');
            spyObj.and.callThrough();
            triggerEvents(de[0], 'mousedown', { pageX: 10, pageY: 10 });
            for (let i = 0; i <= 10; i += 5) {
                triggerEvents(de[0], 'mousemove', { pageX: 40 + i, pageY: 20 + i });
                expectAndReset(service.x.emit, { x: 30 + i, y: 10 + i }, spyObj);
            }

        }));

Somewhat satisfied with my second iteration.

Thank you.

\$\endgroup\$
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.