Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sidenav, unit test : Cannot read property 'classList' of undefined #169

Closed
chych opened this issue Jul 24, 2017 · 5 comments
Closed

Sidenav, unit test : Cannot read property 'classList' of undefined #169

chych opened this issue Jul 24, 2017 · 5 comments
Assignees

Comments

@chych
Copy link

chych commented Jul 24, 2017

Hello,

my project is under angular4 and i used angular-cli to run the test (ng test)

I used the mz-sidenav component on my code without change anything for the moment (https://sherweb.github.io/ng2-materialize/sidenav) and when
i tried to run unit test i had this error :

TypeError: Cannot read property 'classList' of undefined at EmulatedEncapsulationDomRenderer2.webpackJsonp../node_modules/@angular/platform-browser/@angular/platform-browser.es5.js.DefaultDomRenderer2.addClass (http://localhost:9876/_karma_webpack_/vendor.bundle.js:57837:70) at DebugRenderer2.webpackJsonp../node_modules/@angular/core/@angular/core.es5.js.DebugRenderer2.addClass (http://localhost:9876/_karma_webpack_/vendor.bundle.js:44310:23) at RendererAdapter.webpackJsonp../node_modules/@angular/core/@angular/core.es5.js.RendererAdapter.setElementClass (http://localhost:9876/_karma_webpack_/vendor.bundle.js:41533:27) at MzSidenavComponent.webpackJsonp../node_modules/ng2-materialize/dist/sidenav/sidenav.component.js.MzSidenavComponent.initCollapseButton (http://localhost:9876/_karma_webpack_/vendor.bundle.js:69355:27) at MzSidenavComponent.webpackJsonp../node_modules/ng2-materialize/dist/sidenav/sidenav.component.js.MzSidenavComponent.ngAfterViewInit (http://localhost:9876/_karma_webpack_/vendor.bundle.js:69340:14) at callProviderLifecycles (http://localhost:9876/_karma_webpack_/vendor.bundle.js:42156:18) at callElementProvidersLifecycles (http://localhost:9876/_karma_webpack_/vendor.bundle.js:42131:13) at callLifecycleHooksChildrenFirst (http://localhost:9876/_karma_webpack_/vendor.bundle.js:42115:17) at checkAndUpdateView (http://localhost:9876/_karma_webpack_/vendor.bundle.js:43133:5) at callViewAction (http://localhost:9876/_karma_webpack_/vendor.bundle.js:43440:17) at execComponentViewsAction (http://localhost:9876/_karma_webpack_/vendor.bundle.js:43386:13) at checkAndUpdateView (http://localhost:9876/_karma_webpack_/vendor.bundle.js:43131:5) at callWithDebugContext (http://localhost:9876/_karma_webpack_/vendor.bundle.js:44113:42) at Object.debugCheckAndUpdateView [as checkAndUpdateView] (http://localhost:9876/_karma_webpack_/vendor.bundle.js:43653:12) at ViewRef_.webpackJsonp../node_modules/@angular/core/@angular/core.es5.js.ViewRef_.detectChanges (http://localhost:9876/_karma_webpack_/vendor.bundle.js:41223:63)

@jfcere
Copy link
Contributor

jfcere commented Jul 24, 2017

Hi @chych, can you provide a sample of your html, component and test code? I'm wondering if the error is related to your test code or to our library ...

@chych
Copy link
Author

chych commented Jul 24, 2017

Actually my component is empty, no code except constructor...,
html template just content mz-sidenav component
the problem appear with the [collapseButtonId]="'btnSidenav'" because i split the header and sidenav in two differents component.

My home component contains :


<app-header></app-header>
<app-home-sidenav></app-home-sidenav>

My header template:

<header>
    <div class="navbar-fixed navbar-mycj">
        <nav class="nav-mycj blue-grey" [ngClass]="{navFixed: navIsFixed}" role="navigation">
            <div class="nav-wrapper container">
                <a id="logo-container" href="#" class="brand-logo position">
                    <img alt="logo mycloudjob" src="./assets/images/mycj/logo-navbar.png">
                </a>
                <ul class="right hide-on-med-and-down">
                    <li><a href="#" class="btn blue-grey">Se connecter</a></li>
                    <li><a href="#" class="btn pink">S'inscrire</a></li>
                </ul>

                <a href="#"
                   [id]="'btnSidenav'"
                   class="button-collapse hide-on-large-only right"><i class="material-icons">menu</i></a>

            </div>
        </nav>
    </div>
</header>

My component containing(app-home-sidenav) :

import {Component, OnInit} from "@angular/core";

@Component({
    selector: 'app-home-sidenav',
    templateUrl: './home-sidenav.component.html',
    styleUrls: ['./home-sidenav.component.css']
})
export class HomeSidenavComponent implements OnInit {


    constructor() { }

    ngOnInit() {
    }

}

My component html(app-home-sidenav) :

<mz-sidenav
    [id]="'sidenav'"
    [collapseButtonId]="'btnSidenav'">
    <mz-sidenav-header>
        Sidenav header
    </mz-sidenav-header>
    <mz-sidenav-subheader>Link Subheader</mz-sidenav-subheader>
    <mz-sidenav-link>
        <a href="#">First Link</a>
    </mz-sidenav-link>
    <!--<mz-sidenav-divider></mz-sidenav-divider>-->
    <mz-sidenav-link [active]="true">
        <a href="#">Active Link</a>
    </mz-sidenav-link>
    <mz-sidenav-divider></mz-sidenav-divider>
    <mz-sidenav-link>
        <a href="#" class="waves-effect">Second Link With Waves</a>
    </mz-sidenav-link>
</mz-sidenav>

My component test(app-home-sidenav)

import {async, ComponentFixture, TestBed} from "@angular/core/testing";
import {HomeSidenavComponent} from "./home-sidenav.component";
import {MaterializeModule} from "ng2-materialize";

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

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [
                HomeSidenavComponent,
            ],
            imports: [
                MaterializeModule,
            ],
        })
            .compileComponents();
    }));

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

    });

    it('should be created', () => {
        expect(component).toBeTruthy();
    });
});

@chych
Copy link
Author

chych commented Jul 24, 2017

The solution i found it's to not separate my colapse button and the sidenav :

<header>
    <div class="navbar-fixed navbar-mycj">
        <nav class="nav-mycj blue-grey" [ngClass]="{navFixed: navIsFixed}" role="navigation">
            <div class="nav-wrapper container">
                <a id="logo-container" href="#" class="brand-logo position">
                    <img alt="logo mycloudjob" src="./assets/images/mycj/logo-navbar.png">
                </a>
                <ul class="right hide-on-med-and-down">
                    <li><a href="" class="btn blue-grey">Se connecter</a></li>
                    <li><a href="" class="btn pink">S'inscrire</a></li>
                </ul>

                <a href=""
                   [id]="'btnSidenav'"
                   class="button-collapse hide-on-large-only right"><i class="material-icons">menu</i></a>

            </div>
        </nav>
    </div>
</header>

<mz-sidenav
    [id]="'sidenav'"
    [collapseButtonId]="'btnSidenav'">
    <mz-sidenav-header>
        Sidenav header
    </mz-sidenav-header>
    <mz-sidenav-subheader>Link Subheader</mz-sidenav-subheader>
    <mz-sidenav-link>
        <a href="#">First Link</a>
    </mz-sidenav-link>
    <!--<mz-sidenav-divider></mz-sidenav-divider>-->
    <mz-sidenav-link [active]="true">
        <a href="#">Active Link</a>
    </mz-sidenav-link>
    <mz-sidenav-divider></mz-sidenav-divider>
    <mz-sidenav-link>
        <a href="#" class="waves-effect">Second Link With Waves</a>
    </mz-sidenav-link>
</mz-sidenav>

@jfcere jfcere self-assigned this Aug 2, 2017
@jfcere
Copy link
Contributor

jfcere commented Aug 4, 2017

@chych the reason why your test fails is because it cannot find the provided collapseButtonId as it does not exist in the context of your test which only include the app-home-sidenav component.

If you absolutely want to keep them seperated you will need to create a fake collapse button element with the exact same button id in your app-home-sidenav test file.

function createCollapseButton(id: string): void {
  const collapseButton = document.createElement('a');
  collapseButton.setAttribute('id', id);
  document.body.appendChild(collapseButton);
}

beforeEach(() => {
  fixture = TestBed.createComponent(HomeSidenavComponent);
  component = fixture.componentInstance;
  // create fake collapse button in DOM before triggering 
  // change detection that initialize the component
  createCollapseButton('btnSidenav');
  fixture.detectChanges();
});

Although this would work I don't suggest you to seperate the collapse button and the sidenav because your test won't assure you that the button is really there at runtime or is really having the right id.

@chych
Copy link
Author

chych commented Aug 4, 2017

I'm agree with you it's the solution that i adopted

@chych chych closed this as completed Aug 4, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants