puddlejumper26 / blogs

Personal Tech Blogs
4 stars 1 forks source link

Mock a path in spec file[routerLink, routerLinkActive] #45

Open puddlejumper26 opened 4 years ago

puddlejumper26 commented 4 years ago

Here we need to mock a path,

Purpose of testing

When the link is clicked, extra css style should be added, The link itself is imbed with *ngFor

sample.component.html

 <a *ngFor="let item of clickItems"
                [routerLink]="item.path"
                [routerLinkActive]="['extra-style']">{{ item.name }}</a>

sample.component.spec.ts

import { Component } from '@angular/core';
...

@Component({                             ====> this is the decorator,
    template: '',                        ====>  with the following class, is a complete Dummy Comoponent
})
class DummyComponent {           
}

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

     beforeEach(async ( () => {
             TestBed.configureTestingModule({
            declarations: [DummyComponent, SampleComponent],   ====> needs to be declared, otherwise could not be used
            imports: [
                CommonModule,
                RouterTestingModule.withRoutes([         ====> to mock the Routes
                    {
                        component: DummyComponent,      ====> need to be with a component, that's why we need to create the DummyComponent
                        path: 'path1',
                    },
                    {
                        component: DummyComponent,
                        path: 'path2',
                    },
                ]),
            ],
        })
            .compileComponents();
     }));

     beforeEach(() => {
        fixture = TestBed.createComponent(SampleComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
    });

    it(' ....', async ( ) => {
          component.clickItems = [        ====> this part is only the mock of [routerLink]="item.path"
            {
                name: 'name1',
                path: 'path1',
            },
            {
                name: 'name2',
                path: 'path2',
            },
        ];

        fixture.detectChanges();

        const link1Element = fixture.debugElement.query(By.css('[href="/path1"]')).nativeElement as HTMLElement;
        const link2Element = fixture.debugElement.query(By.css('[href="/path2"]')).nativeElement as HTMLElement;

        expect(link1Element.innerHTML).toContain('name1');
        expect(link2Element.innerHTML).toContain('name2');

        link1Element.click();
        fixture.whenStable().then(() => {
           expect(link1Element.classList).toContain('extra-style');

           link2Element.click();           =====> notice the link2Element test is inside the link1Element
           fixture.whenStable().then(() => {
               expect(link2Element.classList).toContain('extra-style');
               done();            ====> done needs to be added
           });
        });
    });
    })
}

notice the link2Element test is inside the link1Element, thus during the excution, only the most inner part (link2Element) get passed, here with done ( ) conditions, then it will move the the level above (lin1Element), here we have only two layers, if there is three levels, the same theory.