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

@delayed causing unit test to fail #512

Closed
rinobatin opened this issue Jun 6, 2016 · 3 comments
Closed

@delayed causing unit test to fail #512

rinobatin opened this issue Jun 6, 2016 · 3 comments

Comments

@rinobatin
Copy link

I have a class that looks like this:

//imports...
export class Widget {

 @delayed()
 attached(){
    this.kendoTree.expand('.k-item');
 }

}

And unit test (spec)

//imports...
describe('Widget', () => {
  let sut;
  let container;
beforeEach(() => {    
    container = new Container();
    Container.instance = container;
    sut = new Widget();
  });

 it('test1', () => {
     expect(1).toBe(1);
  });

})

If I run the test, I get Error: Cannot read property 'get' of undefined. Error loading <spec>. If I remove @delayed(), it works. I looked the code of delayed decorator and its using Container.instance.get() (DI container). I think beforeEach has setup the container properly.

A similar problem was logged here and it was suggested not to use DI inside decorators.

I like @delayed because it's more convenient than

 this.tq.queueTask( () => {
     this.kendoTree.expand('.k-item'); 
 });

Any suggestions to restructure my code so I can continue using @delayed?

@charlespockert
Copy link
Member

charlespockert commented Jun 6, 2016

@rinobatin You can probably get this unit test working if you use https://github.com/aurelia/testing, it allows you to bootstrap Aurelia with just the bits you need which you can include the TaskQueue which should enable the DI to work

I can only imagine this to be one of the following issues:

  • You somehow have multiple type definitions of Container (less likely)

or

  • The decorators for the type are running before the container is configured (as you have stated). This could make sense as Aurelia imports modules dynamically on the fly, and since you are importing the modules into your tests you are likely running the decorators on import.

The above library works by running a mini Aurelia app lifecycle, so it imports your component dynamically, ensuring that the app is in the right state before you test your components.

Here's an example of some tests I wrote for router-view:

import {StageComponent} from 'aurelia-testing';
import {RouteLoader, AppRouter, Router} from 'aurelia-router';
import {TemplatingRouteLoader} from 'src/route-loader';
import {testConstants} from 'test/test-constants';

describe('router-view', () => {
  let component;

  beforeEach(done => {
    done();
  });

  afterEach(done => {
    component.viewModel.router.navigate('default').then(() => {
      component.dispose();
      done();
    });
  });

function bootstrap(component, defaultRoute, routeConfig) {
  component.bootstrap(aurelia => {
    aurelia.use.defaultBindingLanguage()
              .defaultResources()
              .history()
              .developmentLogging();

    aurelia.use.singleton(RouteLoader, TemplatingRouteLoader)
               .singleton(Router, AppRouter)
               .globalResources('src/router-view', 'src/route-href');

    if (routeConfig) {
      routeConfig.activationStrategy = 'replace';
      routeConfig.route = 'route';
      routeConfig = [defaultRoute, routeConfig];
    } else {
      routeConfig = [defaultRoute];
    }

    aurelia.use.container.viewModel = {
      configureRouter: (config, router) => {
        config.map(routeConfig);
      }
    };
  });

  function withDefaultViewport(routeConfig) {
    let component = StageComponent
        .withResources('src/router-view')
        .inView('<router-view></router-view>');
    bootstrap(component, { route: ['', 'default'], moduleId: 'test/module-default-slot', activationStrategy: 'replace'}, routeConfig);
    return component;
  }

  it('has a router instance', done => {
    component = withDefaultViewport({ moduleId: 'test/module-default-slot' });
    component.create()
    .then(() => {
      expect(component.viewModel.router).not.toBe(undefined);
    })
    .then(done);
  });

// ... etc

As you can see, there are no imports for the router-view module

(I've got a couple of helpers to set up routes etc but hopefully there's enough clarity in the above)

@rinobatin
Copy link
Author

@charlespockert, thanks for the reply. I also tried aurelia-testing but keep getting undefined StageComponent. I used jspm to install the npm package v0.3.0 but when I manually replaced the files with the github release, it worked!!! I logged an issue for someone to confirm.

Are you using the aurelia-testing npm package? My setup is typscript/systemjs/jasmine/karma.

@rinobatin
Copy link
Author

Setting aside the issue with the aurelia-testing npm package, @delayed works fine with aurelia-testing but this.kendoTree is undefined which defeats the purpose of @delayed'.

The view looks like this

<template> 
    Tree
    <div ak-treeview="k-data-source.bind: treeDS; 
        k-data-text-field.bind:'label';
        k-widget.bind:kendoTree; " >         
    </div> 
 </template>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants