Javascript 用Jest为vanilla JS编写测试

Javascript 用Jest为vanilla JS编写测试,javascript,testing,jestjs,Javascript,Testing,Jestjs,我跟随deveds创建了一个todo列表,但是现在我想编写一些测试来测试代码。我想使用Jest,但我不知道如何编写测试来确保创建并删除了todo 我在下面添加了app.js文件(还有html/css文件)。我试图在app.js文件下编写测试 //Selectors const todoInput = document.querySelector('.todo-input'); const todoButton = document.querySelector('.todo-button'); c

我跟随deveds创建了一个todo列表,但是现在我想编写一些测试来测试代码。我想使用Jest,但我不知道如何编写测试来确保创建并删除了todo

我在下面添加了app.js文件(还有html/css文件)。我试图在app.js文件下编写测试

//Selectors
const todoInput = document.querySelector('.todo-input');
const todoButton = document.querySelector('.todo-button');
const todoList = document.querySelector('.todo-list');
const filterOption = document.querySelector('.filter-todo');

//Event Listeners
todoButton.addEventListener('click', addTodo);
todoList.addEventListener('click', deleteCheck);
filterOption.addEventListener('change', filterTodo);

//Functions
function addTodo(event){
    //console.log(event.target);
    // prevent form from submitting
    event.preventDefault();
    const todoDiv = document.createElement("div");
    todoDiv.classList.add("todo");
    //create LI
    const newTodo = document.createElement('li');
    newTodo.innerText = todoInput.value;
    newTodo.classList.add('todo-item');
    todoDiv.appendChild(newTodo);
    // Checkmark button
    const completedButton = document.createElement('button');
    completedButton.innerHTML = '<i class="fas fa-check"></i>'
    completedButton.classList.add("complete-btn");
    todoDiv.appendChild(completedButton);
    // Delete button
    const deleteButton = document.createElement('button');
    deleteButton.innerHTML = '<i class="fas fa-trash"></i>'
    deleteButton.classList.add("delete-btn");
    todoDiv.appendChild(deleteButton);
    // Append to list
    todoList.appendChild(todoDiv);
    // clear todo input value
    todoInput.value = "";
}

function deleteCheck(e){
    //console.log(e.target);
    const item = e.target;
    if(item.classList[0] === 'delete-btn'){
        const todo = item.parentElement;
        // animation
        todo.classList.add("fall");
        todo.addEventListener("transitionend", function() {
            todo.remove();
        });
    }
    // check mark
    if(item.classList[0] === "complete-btn"){
        const todo = item.parentElement;
        todo.classList.toggle('completed');
    }
}

function filterTodo(e) {
    const todos = todoList.childNodes;
    todos.forEach(function(todo) {
      switch (e.target.value) {
        case "all":
          todo.style.display = "flex";
          break;
        case "completed":
          if (todo.classList.contains("completed")) {
            todo.style.display = "flex";
          } else {
            todo.style.display = "none";
          }
          break;
        case "uncompleted":
          if (!todo.classList.contains("completed")) {
            todo.style.display = "flex";
          } else {
            todo.style.display = "none";
          }
      }
    });
  }

但是测试失败了。

首先,您需要决定是测试UI还是测试UI环绕的系统/引擎。除了在todo(“buy milk”之后缺少
,您正在尝试测试引擎,而不是UI

在您的例子中,您应该考虑从UI层拆分实际的待办事项引擎代码。然后您可以测试待办事项的CRUD

让我们举一个基本的例子:

    const Todo = function() {
        let list = [];
        let items = {};
        return {
            create: function(task) { 
                let id = Date.now();
                items[id] = { id, task };
                list.push(id);
                return id;
            },
            read: function(id) {
                return items[id];
            },
            readAll: function() {
                return list.map(id => items[id]);
            },
            delete: function(id) {
                list = list.filter(itemId => itemId !== id);
                delete items[id];
                return true;
            }
        }
    }
这是一个可测试的todo引擎,测试结果如下(使用摩卡和柴):


当您进行前端测试时,您将使用类似或的工具。如果语法错误,您试图在字符串上调用toBe方法。还要注意Jasmine和Jest是两件不同的事情(尽管Jest使用Jasmine作为默认测试运行程序)。
expect(todo(“buy milk”).toBe(“buy milk”))
可能需要更改为
expect(todo(“buy milk”)。toBe(“buy milk”)
@jornsharpe编辑了我的帖子!我正在使用Jasmine,但切换到了Jest。谢谢!我收到的一个错误是TypeError:无法读取null 7 | 8 |//事件侦听器>9 | todoButton.addEventListener的属性'AddEvent Listener'('click',addTodo);^10 | todoList.addEventListener('click',deleteCheck);11 | filterOption.addEventListener('change',filterTodo);12 |你知道为什么会出现这种情况吗?我使用chai+mocha进行测试。错误指向app.js中的第9行
    const Todo = function() {
        let list = [];
        let items = {};
        return {
            create: function(task) { 
                let id = Date.now();
                items[id] = { id, task };
                list.push(id);
                return id;
            },
            read: function(id) {
                return items[id];
            },
            readAll: function() {
                return list.map(id => items[id]);
            },
            delete: function(id) {
                list = list.filter(itemId => itemId !== id);
                delete items[id];
                return true;
            }
        }
    }

const { expect } = require("chai");
const Todo = require("./Todo.js"); // replace with your file

describe("Todo", function() {
    const todo = Todo();
    it("should create a todo item and return an ID", function() {
        let id = todo.create("My first todo");
        expect(id).to.be.a("integer");
    });
    it("should create a todo item with text 'My second todo'", function() {
        let id = todo.create("My second todo");
        let text = todo.read(id);
        expect(text).to.equal("My second todo");
    });
    it("should return an array with two todo items", function() {
        let items = todo.readAll();
        // you can also test for exact strings
        expect(items.length).to.equal(2);
    });
    it("should delete first item", function() {
        let items = todo.readAll();
        let id = items[0].id;
        todo.delete(id);
        items = todo.readAll();
        expect(items.length).to.equal(1);
    });
});