Search code examples
jasmineaurelia

aurelia test view change not reflected in viewmodel


i have a basic custom element.

//my-component.html
<template>
  <input type="text" id="my-input" value.bind="searchText">
</template>

//my-component.js
export class MyComponent {  
  searchText = 'initial text';
}

what i am trying to assert in my unit test is that when i update the value of my input field (id=my-input) in the dom the correct bound value (searchText) is also updated.

heres my test (jasmine/karma)

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

describe('some desc', () => {
  let component;

  beforeEach(() => {    
    component = StageComponent
      .withResources('src/my-component')
      .inView('<div><my-component></my-component></div>');      
  });  

  it('some it', done => {
    component.create(bootstrap).then(() => {
      const inpuElement = document.querySelector('#my-input');

      inpuElement.value = 'new text';
      //component.viewModel.searchText = 'new text';      
      expect(component.viewModel.searchText).toBe('new text');

      done();
    }).catch(e => { console.log(e.toString()) });
  });

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

when i run this the test fails with
Expected 'initial text' to be 'new text'

to get it passing i need to replace component.viewModel.searchText = 'new text'; with inpuElement.value = 'new text';

i really dont want to do this as i am trying to mimic the user inputing text directly into the input field.

can this be done and if so what am i missing?


Solution

  • I guess you are looking for something like this: https://github.com/aurelia/testing/issues/70

    Aurelia is observing the DOM events to update the VM. As you do not trigger any event, the VM is not "notifying" the change. Do something like this (assuming you use aurelia-pal):

    import {StageComponent} from 'aurelia-testing';
    import {bootstrap} from 'aurelia-bootstrapper';
    import {DOM} from 'aurelia-pal';
    
    describe('some desc', () => {
      let component;
    
      beforeEach(() => {    
        component = StageComponent
          .withResources('src/my-component')
          .inView('<div><my-component></my-component></div>');      
      });  
    
      it('some it', done => {
        component.create(bootstrap).then(() => {
          const inputElement = DOM.getElementById('my-input');
          inputElement.value = 'new text';
          inputElement.dispatchEvent(DOM.createCustomEvent('change'));
    
          setTimeout(() => {
              expect(component.viewModel.searchText).toBe('new text');
              done();
          }, 50);
        }).catch(e => { console.log(e.toString()) });
      });
    
      afterEach(() => {
        component.dispose();
      });
    });