昨天,我們為了讓大家更加了解 Cypress 的語法以及要如何攥寫 E2E 測試,所以開始規劃為 Vue.js • TodoMVC 攥寫 E2E 測試,列出了我們要測試的內容,也實際地為了第一個 case 攥寫測試程式。

大家可以透過連結自由操作一下,會對於接下來的測試例子更佳有感!
詳細完整的內容,就請大家直接查看昨天的文章吧!那我們就馬上開始今天的內容!
在實際攥寫 Case 2 之前,先帶大家看一下程式碼的樣子以及額外宣告的變數
describe('Todo MVC', () => {
  const selectors = {
    main: '.main',
    footer: '.footer',
    todoItems: '.todo-list .todo',
    newTodo: '.new-todo',
    lastOne: '.todo-list .todo:last-child'
  }
  const TODO_ITEM_ONE = 'Item 1'
  const TODO_ITEM_TWO = 'Item 2'
  beforeEach(() => {
    cy.visit('https://todomvc.com/examples/vue')
  })
  context('Case 1: Initial State', () => {
    it('Case 1-1: start with zero todo item', () => {
      cy.get(selectors.todoItems).should('have.length', 0)
    })
    it('Case 1-2: hide .main and .footer', () => {
      cy.get(selectors.main).should('not.be.visible')
      cy.get(selectors.footer).should('not.be.visible')
    })
  })
  context('Case 2: New Todo', () => {
    // ...
  })
  context('Case 3: Edit Todo', () => {
    // ...
  })
})
context('Case 2: New Todo', () => {
  it('Case 2-1: create items', () => {
    // create first item
    cy.get(selectors.newTodo).type(`${TODO_ITEM_ONE}{enter}`)
    cy.get(selectors.todoItems)
      .eq(0)
      .find('label')
      .should('contain', TODO_ITEM_ONE)
    // create second item
    cy.get(selectors.newTodo).type(`${TODO_ITEM_TWO}{enter}`)
    cy.get(selectors.todoItems)
      .eq(1)
      .find('label')
      .should('contain', TODO_ITEM_TWO)
    cy.get(selectors.todoItems).should('have.length', 2)
  })
  it('Case 2-2: append new items to the bottom of the list', () => {
    const TODO_ITEM_LAST_ONE = 'Item Last One'
    for (let i = 0; i < 10; i++) {
      cy.get(selectors.newTodo).type(`Item ${i}{enter}`)
    }
    cy.get(selectors.newTodo).type(`${TODO_ITEM_LAST_ONE}{enter}`)
    cy.get(selectors.lastOne)
      .find('label')
      .should('contain', TODO_ITEM_LAST_ONE)
  })
  it('Case 2-3: clear input text after an item is added', () => {
    cy.get(selectors.newTodo).type(`${TODO_ITEM_ONE}{enter}`)
    cy.get(selectors.newTodo).should('have.text', '')
  })
  it('Case 2-4: show .main and .footer when items added', () => {
    cy.get(selectors.newTodo).type(`${TODO_ITEM_ONE}{enter}`)
    cy.get(selectors.main).should('be.visible')
    cy.get(selectors.footer).should('be.visible')
  })
})
語法說明:
type():  輸入文字至 DOM 中,不過傳給 type() 的字串可能包含特殊字符,這些特殊字符是用來表示在輸入文字期間發出的事件,例如此處的 {enter} 即表示按下 enter 鍵,又或者是 {selectall} 表示選取輸入的文字。(更完整的列表可參考此文件)
eq(): 取得元素陣列中特定 index 的 DOM 元素,不過特別的是 index 可以為負值,表示從尾巴開始在元素陣列中查找元素。
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
</ul>
cy.get('li').eq(0).should('contain', '1')
cy.get('li').eq(1).should('contain', '2')
cy.get('li').eq(-1).should('contain', '5')
cy.get('li').eq(-2).should('contain', '4')
find(): 從特定選擇器的元素後代開始尋找特定的元素。
// success
cy.get('.todo-list .todo:last-child').find('label')
// error
cy.find('.todo-list .todo:last-child label') 
context('Case 3: Edit Todo', () => {
  it('Case 3-1: save edits on blur', () => {
    cy.get(selectors.newTodo).type(`${TODO_ITEM_ONE}{enter}`)
    cy.get(selectors.todoItems)
      .eq(0)
      .find('label')
      .should('contain', TODO_ITEM_ONE)
      .dblclick()
    cy.get(selectors.todoItems)
      .eq(0)
      .find('.edit')
      .type('{selectall}{backspace}') // same as .clear()
      .type(`${TODO_ITEM_TWO}`)
      .blur()
    cy.get(selectors.todoItems)
      .eq(0)
      .find('label')
      .should('contain', TODO_ITEM_TWO)
  })
  it('Case 3-2: remove the item if an empty text was entered', () => {
    cy.get(selectors.newTodo).type(`${TODO_ITEM_ONE}{enter}`)
    cy.get(selectors.todoItems)
      .eq(0)
      .find('label')
      .should('contain', TODO_ITEM_ONE)
      .dblclick()
    cy.get(selectors.todoItems)
      .eq(0)
      .find('.edit')
      .clear() // same as .type('{selectall}{backspace}')
      .blur()
    cy.get(selectors.todoItems).should('have.length', 0)
  })
})
語法說明:
'{selectall}{backspace}' 來達到選取後按下刪除鍵,不過我們也可以直接使用 clear() 來達到同樣的功能。今天的分享就到這邊,如果大家對我分享的內容有興趣歡迎點擊追蹤 & 訂閱系列文章,如果對內容有任何疑問,或是文章內容有錯誤,都非常歡迎留言討論或指教的!
我們明天見!
Hello, 想問一下 2-3 部分
it('Case 2-3: clear input text after an item is added', () => {
    cy.get(selectors.newTodo).type(`${TODO_ITEM_ONE}{enter}`)
    cy.get(selectors.newTodo).should('have.text', '')
  })
我想把它改成『輸入完後不要點擊 Enter,確認我所輸入的值是不是我所輸入的』
it('Case 2-3: clear input text after an item is added', () => {
    cy.get(selectors.newTodo).type(`${TODO_ITEM_ONE}`)
    cy.get(selectors.newTodo).should('have.text', TODO_ITEM_ONE)
  })
會出現錯誤,因為他認為是空值,是不是應該要使用 have.value 來確認值才是呢?