Skip to content

Instantly share code, notes, and snippets.

@krzystof
Created February 17, 2017 16:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save krzystof/6213ad28ad4af5d83b6d327a36c675fe to your computer and use it in GitHub Desktop.
Save krzystof/6213ad28ad4af5d83b6d327a36c675fe to your computer and use it in GitHub Desktop.
import test from 'ava'
import sinon from 'sinon'
import Vue from 'vue/dist/vue.js'
import axios from 'axios'
// Helpers to simulate user interaction (fires event, click buttons, ...)
import interactWith from './helpers/browser'
let noteForm = {
template: `
<form @submit.prevent="saveNote">
<input name="title" v-model="title"/>
<span v-text="errors.title"></span>
<input name="content" v-model="content"/>
<button type="submit" class="button" :class="{ 'is-loading': processing }">Ay</button>
</form>
`,
data() {
return {
processing: false,
title: '',
content: '',
errors: {}
}
},
methods: {
saveNote() {
this.processing = true
let { title, content } = this
return axios.post('/notes', { title, content })
.then(r => log(r))
.catch(e => this.errors = e.response.data.errors)
}
}
}
/*
What is the behaviour expected from the note form?
- [x] shows a loading spinner
- [x] submit to a url
- [x] displays errors when invalid
- [ ] set error class on the input
- [ ] redirect to /notes on success
- [ ] button is disabled when processing
*/
test.beforeEach(t => {
axios.post = sinon.stub()
let Note = Vue.extend(noteForm)
t.context = new Note().$mount()
})
test('not processing initially', t => {
let btn = t.context.$el.querySelector('button')
let btnIsLoading = btn.className.includes('is-loading')
t.false(btnIsLoading)
})
test('processing when form is submitted', async t => {
let btn = t.context.$el.querySelector('button')
btn.click()
t.context.$nextTick(() => {
let btnIsLoading = btn.className.includes('is-loading')
t.true(btnIsLoading)
})
})
test('POST to /notes', t => {
t.context.$el.querySelector('button').click()
let wasCalled = axios.post.withArgs('/notes', { title: '', content: '' }).calledOnce
t.true(wasCalled)
})
test('sends input data', async t => {
let u = interactWith(t.context.$el)
.type('input[name=title]', 'Test')
.type('input[name=content]', 'That works!')
t.context.$nextTick(() => {
u.click('button')
let wasCalled = axios.post.withArgs('/notes', { title: 'Test', content: 'That works!' }).calledOnce
t.true(wasCalled)
})
})
/*
* Not ideal!!!
*
* however for now its the only way I found to assert
* later on a Promise (see tests after that one) because
* then I can assert on vm.saveNote().then( ... )
*
* Ideally, I would need to do:
* - click the button
* - when resolved assert
* Problem currently to link the Dom and the vm
*
*/
test('click on the button calls the saveNote method', t => {
t.context.saveNote = sinon.spy()
interactWith(t.context.$el).click('button')
let calledTimes = t.context.saveNote.callCount
t.is(calledTimes, 1)
})
test('sets errors on the form', async t => {
let e = new Error('Oops')
e.response = { data: { errors: { title: 'Is not there' }}}
axios.post.returns(Promise.reject(e))
t.context.saveNote().then(() => {
let hintText = interactWith(t.context.$el).readText('span')
t.true(hintText.includes('Is not there'))
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment