Testing component life cycle

We need to ensure that our data is retrieved as expected, and the same way, we need to assert that our component behavior is going well too. To do this, we can tell the component we created that we will manually handle the life cycle methods; you will find the code very self-explanatory:

import {StageComponent} from 'aurelia-testing';
import {bootstrap} from 'aurelia-bootstrapper';

describe('CustomerComponent', () => {
let component;

beforeEach(() => {
component = StageComponent
.withResources('src/customer-component')
.inView('<customer-component cust-name.bind="custName"></customer-component>')
.boundTo({ custName: 'Diego' });
});

it('can manually handle life cycle', done => {
let nameElement;

component.manuallyHandleLifecycle().create()
.then(() => {
nameElement = document.querySelector('.custName');
expect(nameElement.innerHTML).toBe(' ');
})
.then(() => component.bind())
.then(() => {
expect(nameElement.innerHTML).toBe('Foo bind');
})
.then(() => component.attached())
.then(() => {
expect(nameElement.innerHTML).toBe('Foo attached');
})
.then(() => component.detached())
.then(() => component.unbind())
.then(() => {
expect(component.viewModel.custName).toBe(null);
})
.then(() => component.bind({ custName: 'Bar' }))
.then(() => {
expect(nameElement.innerHTML).toBe('Bar bind');
})
.then(() => component.attached())
.then(() => {
expect(nameElement.innerHTML).toBe('Bar attached');
})
.then(done)
.catch(done);
});

afterEach(() => {
component.dispose();
});

});

The imported libraries still being the same, the create() method of our component element will bootstrap the application and provide us with an easy way to check for our life cycle method responses; just ensure that you call them in the order they are executed.

What about components depending on external services? Don't worry, you just need to add some extra lines to the test code and create a class "mocking" the service.

First, our Mock class:

export class MockService {
      firstName;

      getFirstName() { return Promise.resolve(this.firstName);
}

Our test class will look like this:

describe('MyComponent', () => {
      let component;
      let service = new MockService(); //Our created Mock

      beforeEach(() => {
        service.firstName = undefined; 

        component = StageComponent
          .withResources('src/component')
          .inView('<component></component>');

        component.bootstrap(aurelia => {
          aurelia.use.standardConfiguration();
          aurelia.container.registerInstance(Service, service); //Register our mock service instance to the current container instance
        });
      });

      it('should render first name', done => {
        service.firstName = 'Diego';

        component.create(bootstrap).then(() => {
          const nameElement = document.querySelector('.first-name');
          expect(nameElement.innerHTML).toBe('Diego');

          done();
        });
      });

      afterEach(() => {
        component.dispose();
      });
});

First of all, we are declaring our mock service as a global variable. This will be used for injecting it into Aurelia's container context; this way, the component won't detect any difference between the real service class and our mocked service. Another thing you should pay attention to is that at the beforeEach() method level, we are declaring the firstName property as undefined; this is just to make it reusable and customizable for each test depending on their own needs. Remember that this method is executed independently for each unit test.

What if I need to define a more complex view, evaluating containers for my component? Easy, you are allowed to use template literals:

import {StageComponent} from 'aurelia-testing';
import {bootstrap} from 'aurelia-bootstrapper';

describe('MyAttribute', () => {
let component;

beforeEach(() => {
//Literal HTML syntax
let view = `
<div class="row">
<div class="col-xs-12">
<div my-attribute.bind="color">Diego</div>
</div>
</div>
`;
component = StageComponent
.withResources('src/my-attribute')
.inView(view)
.boundTo(viewModel);
});
//...
});

What do you think? It's easy right? That's good! Now, we are completely ready for the best part of this chapter; let's put everything in practice!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.226.169.212