Skip to content

Profiscience/ko-component-tester

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

52 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ko-component-tester

NPM WTFPL Travis Coverage Status Dependency Status Peer Dependency Status NPM Downloads

TDD Helpers for Knockout components and bindings

Sample tests for a Knockout binding

'use strict'

const { renderHtml } = require('ko-component-tester')
const { expect } = require('chai')

describe ('Hello World text-binding', () => {
  let $el
  beforeEach(() => {
    $el = renderHtml({
      template: `<div data-bind="text: greeting"></div>`,
      viewModel: { greeting: 'Hello World'}
      })
  })
  it('renders', () => {
    expect($el).to.exist
  })
  it('renders correct text', () => {
    expect($el.html()).equals('Hello World')
  })
})

Sample tests for a Knockout component

'use strict'

const { renderComponent } = require('ko-component-tester')
const { expect } = require('chai')

describe('Hello World Component' , () => {
  let $el
  beforeEach(() => {
    $el = renderComponent({
      template: `<span data-bind="text: greeting"></span>`,
      viewModel: function() { this.greeting = 'Hello World' }
    })
  })
  afterEach(() => {
    $el.dispose()
  })
  it('renders', () => {
    expect($el).to.exist
  })
  it('renders correct content', () => {
    expect($el.html()).contains('Hello World')
  })
})

Sample Login test

'use strict'

const ko = require('knockout')
const { expect } = require('chai')
const sinon = require('sinon')
const { renderComponent } = require('../src')

class LoginComponent {
  constructor() {
    this.username = ko.observable()
    this.password = ko.observable()
  }
  submit() {}
}

describe('sample login component' , () => {
  let $el

  before(() => {
    $el = renderComponent({
      viewModel: LoginComponent,
      template: `
        <form data-bind="submit: submit">
          <input name="user" type="text" data-bind="value: username">
          <input name="pass" type="text" data-bind="value: password">
          <input type="submit">
        </form>`
    })
  })

  after(() => {
    $el.dispose()
  })

  it('renders correctly', () => {
    expect($el).to.exist
    expect($el.find('form'), 'contains a form').to.exist
    expect($el.find('input[name="user"]', 'contains a username field')).to.exist
    expect($el.find('input[name="pass"]', 'contains a password field')).to.exist
    expect($el.find('input[type="submit"]', 'contains a submit button')).to.exist
  })

  it('updates the viewmodel when a value is changed', () => {
    $el.find('input[name=user]').simulate('change', 'john')
    expect($el.$data().username()).equals('john')
  })

  it('can submit the form', () => {
    const submitSpy = sinon.spy($el.$data().submit)
    $el.find('input[name=user]').simulate('change', 'john')
    $el.find('input[name=pass]').simulate('change', 'p455w0rd')
    $el.find('input[type="submit"]').simulate('click')

    expect(submitSpy).to.be.called
  })
})

renderHtml(options)

returns a jQuery element containing the rendered html output

  • options.template - a string of html to be rendered
  • options.viewModel - an object, function, or class

Example with viewModel function:

const options = {
  template: `<div data-bind="text: greeting"></div>`,
  viewModel: function() { this.greeting = 'Hello Text Binding' }
}
const $el = renderHtml(options)

Example with viewModel class:

const options = {
  template: `<div data-bind="text: greeting"></div>`,
  viewModel: class ViewModel {
    constructor() {
      this.greeting = 'Hello Text Binding'
    }
  }
}
const $el = renderHtml(options)

Example with viewModel object:

const options = {
  template: `<div data-bind="text: greeting"></div>`,
  viewModel: { greeting: 'Hello Text Binding' }
}
const $el = renderHtml(options)

See spec for more examples of renderHtml().

renderComponent(component, params, bindingContext)

returns a jQuery element containing the rendered html output

  • component.template - a string of html to be rendered
  • component.viewModel - a function, class, or instance
  • params - optional params to be passed into the viewModel's constructor
  • bindingContext - optional bindingContext to inject (useful for stubbing $parent or $index)

Example with viewModel function:

const component = {
  template: `<div data-bind="text: greeting"></div>`,
  viewModel: function() { this.greeting = 'Hello Text Binding' }
}
const $el = renderComponent(component)
// $el.dispose()

Example with viewModel class:

const component = {
  template: `<div data-bind="text: greeting"></div>`,
  viewModel: class ViewModel {
    constructor(params) {
      this.greeting = params.greeting
    }
  }
}
const params = {
  greeting: 'Hello Text Binding'
}
const $el = renderComponent(component, params)
// $el.dispose()

Example with viewModel instance:

class ViewModel {
  constructor(params) {
    this.greeting = params.greeting
  }
}
const component = {
  template: `<div data-bind="text: greeting"></div>`,
  viewModel: { instance: new ViewModel(params) }
}
const $el = renderComponent(component)
// $el.dispose()

See spec for more examples of renderComponent().

$el.getComponentParams()

see spec for examples

$el.waitForBinding()

see spec for examples

$el.waitForProperty()

see spec for examples

$el.simulate(event, value)

  • event - the event to simulate, eg 'click', or 'change'
  • value - if provided this value will be assigned. It's handy for assigning a value to a textbox and triggering a change event like this.
// simulate changing the value of a textbox
$input.simulate('change', 'new value')
// simulate clicking a button
$submit.simulate('click')

Attribution

https://github.com/jeremija/kotest