Skip to content

Instantly share code, notes, and snippets.

@padcom
Last active October 14, 2020 13:15
Show Gist options
  • Save padcom/759565f374f08b45e02065e789e6806b to your computer and use it in GitHub Desktop.
Save padcom/759565f374f08b45e02065e789e6806b to your computer and use it in GitHub Desktop.
Testing with Cypress (https://youtu.be/NJpB047yp9s)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Todo</title>
<script src="https://unpkg.com/vue"></script>
<style>
.todo {
cursor: pointer;
}
.completed {
text-decoration: line-through;
}
</style>
</head>
<body>
<div id="app">
<h1>Todos</h1>
<add-todo-form @add-todo="addTodo"></add-todo-form>
<todo-list :todos="todos" @toggle="toggle" @remove="remove"></todo-list>
</div>
<template id="add-todo-form">
<div class="add-todo-form">
<label>
Todo
<input v-model="text">
<button @click="addTodo">Add</button>
</label>
</div>
</template>
<script>
Vue.component('add-todo-form', {
template: '#add-todo-form',
data() {
return {
text: ''
}
},
methods: {
addTodo() {
this.$emit('add-todo', this.text)
this.text = ''
}
}
})
</script>
<template id="todo-list">
<ul class="todos">
<todo-item v-for="todo in todos" :key="todo.id" :todo="todo" v-on="$listeners">
</todo-item>
</ul>
</template>
<script>
Vue.component('todo-list', {
template: '#todo-list',
props: {
todos: { type: Array, required: true }
}
})
</script>
<template id="todo-item">
<li :class="{ todo: true, completed: todo.completed }" @click="$emit('toggle', todo)">
<span class="todo-text">{{ todo.text }}</span>
<button @click="$emit('remove', todo)" data-test="remove-todo">X</button>
</li>
</template>
<script>
Vue.component('todo-item', {
template: '#todo-item',
props: {
todo: { type: Object, required: true }
}
})
</script>
<script>
new Vue({
el: '#app',
data: {
todos: [{
id: 1, text: 'Create cypress tests', completed: false
}]
},
methods: {
addTodo(text) {
this.todos.push({
id: this.todos.reduce((acc, item) => acc <= item.id ? item.id + 1 : acc, 0),
text,
completed: false
})
},
toggle(todo) {
todo.completed = !todo.completed
},
remove(todo) {
this.todos = this.todos.filter(item => item.id !== todo.id)
}
}
})
</script>
</body>
</html>
{
"name": "tests",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"cypress:open": "cypress open"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"cypress": "^4.7.0",
"uuid": "^8.1.0"
}
}
/// <reference types="cypress" />
import { v4 as uuid } from 'uuid'
class Wrapper {
/**
* @param {Cypress.Chainable<JQuery<HTMLElement>>} root
*/
constructor(root) {
this.id = uuid()
root.as(this.id)
}
get root() {
return cy.get(`@${this.id}`)
}
}
class AddTodoFormWrapper extends Wrapper {
get input() {
return this.root.find('input')
}
get button() {
return this.root.find('button')
}
addTodo(text) {
this.input.clear().type(text)
this.button.click()
}
}
class TodoItemWrapper extends Wrapper {
get text() {
return this.root.find('.todo-text')
}
get removeButton() {
return this.root.find('[data-test="remove-todo"]')
}
remove() {
this.removeButton.click()
}
toggle() {
this.text.click()
return this
}
shouldBeCompleted() {
this.root.should('have.class', 'completed')
return this
}
shouldNotBeCompleted() {
this.root.should('not.have.class', 'completed')
return this
}
}
class TodoListWrapper extends Wrapper {
get todos() {
return this.root.find('.todo')
}
getLastTodo() {
return new TodoItemWrapper(this.todos.last())
}
}
describe('Todo list', () => {
/** @type {TodoListWrapper} */
let todoList
/** @type {AddTodoFormWrapper} */
let addTodoForm
beforeEach(() => {
cy.visit('http://localhost:8080')
todoList = new TodoListWrapper(cy.get('.todos'))
addTodoForm = new AddTodoFormWrapper(cy.get('.add-todo-form'))
})
it('will create a new todo', () => {
todoList.todos.should('have.length', 1)
addTodoForm.addTodo('Hello, world!')
todoList.todos.should('have.length', 2)
})
it('will remove a todo', () => {
addTodoForm.addTodo('Hello, world!')
todoList.todos.should('have.length', 2)
todoList.getLastTodo().remove()
todoList.todos.should('have.length', 1)
})
it('will toggle a todo', () => {
addTodoForm.addTodo('Hello, world!')
todoList.getLastTodo()
.shouldNotBeCompleted()
.toggle()
.shouldBeCompleted()
.toggle()
.shouldNotBeCompleted()
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment