Evan You 10 лет назад
Родитель
Сommit
ceab86d9df
8 измененных файлов с 602 добавлено и 10 удалено
  1. 5 7
      examples/todomvc/index.html
  2. 0 3
      examples/tree/tree.js
  3. 32 0
      test/e2e/commits.js
  4. 112 0
      test/e2e/grid.js
  5. 49 0
      test/e2e/markdown.js
  6. 60 0
      test/e2e/svg.js
  7. 291 0
      test/e2e/todomvc.js
  8. 53 0
      test/e2e/tree.js

+ 5 - 7
examples/todomvc/index.html

@@ -58,15 +58,13 @@
 
 		<!-- testing/benchmark only -->
 		<script>
-		var isPhantom = navigator.userAgent.indexOf('PhantomJS') > -1
-		if (isPhantom) {
+		if (navigator.userAgent.indexOf('PhantomJS') > -1) {
 			localStorage.clear()
-		} else {
-			var now = window.performance && window.performance.now
-				? function () { return window.performance.now() }
-				: Date.now
-			var metrics = { beforeLoad: now() }
 		}
+		var now = window.performance && window.performance.now
+			? function () { return window.performance.now() }
+			: Date.now
+		var metrics = { beforeLoad: now() }
 		</script>
 		<!-- end testing/bench -->
 

+ 0 - 3
examples/tree/tree.js

@@ -39,9 +39,6 @@ Vue.component('item', {
       open: false
     }
   },
-  updated: function () {
-    console.log(this._vnode)
-  },
   computed: {
     isFolder: function () {
       return this.model.children &&

+ 32 - 0
test/e2e/commits.js

@@ -0,0 +1,32 @@
+casper.test.begin('commits', 18, function (test) {
+  casper
+  .start('examples/commits/index.html')
+  .then(function () {
+    // radio inputs & labels
+    test.assertElementCount('input', 2)
+    test.assertElementCount('label', 2)
+    test.assertSelectorHasText('label[for="master"]', 'master')
+    test.assertSelectorHasText('label[for="dev"]', 'dev')
+    // initial fetched commits
+    test.assertField('branch', 'master')
+    test.assertSelectorHasText('p', 'vuejs/vue@master')
+    test.assertElementCount('li', 3)
+    test.assertSelectorHasText('li:first-child a.commit', '1111111')
+    test.assertSelectorHasText('li:first-child span.message', 'one')
+    test.assertSelectorHasText('li:first-child span.author', 'Evan')
+    test.assertSelectorHasText('li:first-child span.date', '2014-10-15 13:52:58')
+  })
+  .thenClick('input[value="dev"]', function () {
+    test.assertField('branch', 'dev')
+    test.assertSelectorHasText('p', 'vuejs/vue@dev')
+    test.assertElementCount('li', 3)
+    test.assertSelectorHasText('li:first-child a.commit', '2222222')
+    test.assertSelectorHasText('li:first-child span.message', 'two')
+    test.assertSelectorHasText('li:first-child span.author', 'Evan')
+    test.assertSelectorHasText('li:first-child span.date', '2014-10-15 13:52:58')
+  })
+  // run
+  .run(function () {
+    test.done()
+  })
+})

+ 112 - 0
test/e2e/grid.js

@@ -0,0 +1,112 @@
+casper.test.begin('grid', 73, function (test) {
+  casper
+  .start('examples/grid/index.html')
+  .then(function () {
+    // headers
+    test.assertElementCount('th', 2)
+    test.assertElementCount('th.active', 0)
+    test.assertSelectorHasText('th:nth-child(1)', 'Name')
+    test.assertSelectorHasText('th:nth-child(2)', 'Power')
+    assertTable(test, ['name', 'power'], [
+      { name: 'Chuck Norris', power: Infinity },
+      { name: 'Bruce Lee', power: 9000 },
+      { name: 'Jackie Chan', power: 7000 },
+      { name: 'Jet Li', power: 8000 }
+    ])
+  })
+  // test sorting
+  .thenClick('th:nth-child(1)', function () {
+    test.assertElementCount('th.active:nth-child(1)', 1)
+    test.assertElementCount('th.active:nth-child(2)', 0)
+    test.assertElementCount('th:nth-child(1) .arrow.dsc', 1)
+    test.assertElementCount('th:nth-child(2) .arrow.dsc', 0)
+    assertTable(test, ['name', 'power'], [
+      { name: 'Jet Li', power: 8000 },
+      { name: 'Jackie Chan', power: 7000 },
+      { name: 'Chuck Norris', power: Infinity },
+      { name: 'Bruce Lee', power: 9000 }
+    ])
+  })
+  .thenClick('th:nth-child(2)', function () {
+    test.assertElementCount('th.active:nth-child(1)', 0)
+    test.assertElementCount('th.active:nth-child(2)', 1)
+    test.assertElementCount('th:nth-child(1) .arrow.dsc', 1)
+    test.assertElementCount('th:nth-child(2) .arrow.dsc', 1)
+    assertTable(test, ['name', 'power'], [
+      { name: 'Chuck Norris', power: Infinity },
+      { name: 'Bruce Lee', power: 9000 },
+      { name: 'Jet Li', power: 8000 },
+      { name: 'Jackie Chan', power: 7000 }
+    ])
+  })
+  .thenClick('th:nth-child(2)', function () {
+    test.assertElementCount('th.active:nth-child(1)', 0)
+    test.assertElementCount('th.active:nth-child(2)', 1)
+    test.assertElementCount('th:nth-child(1) .arrow.dsc', 1)
+    test.assertElementCount('th:nth-child(2) .arrow.asc', 1)
+    assertTable(test, ['name', 'power'], [
+      { name: 'Jackie Chan', power: 7000 },
+      { name: 'Jet Li', power: 8000 },
+      { name: 'Bruce Lee', power: 9000 },
+      { name: 'Chuck Norris', power: Infinity }
+    ])
+  })
+  .thenClick('th:nth-child(1)', function () {
+    test.assertElementCount('th.active:nth-child(1)', 1)
+    test.assertElementCount('th.active:nth-child(2)', 0)
+    test.assertElementCount('th:nth-child(1) .arrow.asc', 1)
+    test.assertElementCount('th:nth-child(2) .arrow.asc', 1)
+    assertTable(test, ['name', 'power'], [
+      { name: 'Bruce Lee', power: 9000 },
+      { name: 'Chuck Norris', power: Infinity },
+      { name: 'Jackie Chan', power: 7000 },
+      { name: 'Jet Li', power: 8000 }
+    ])
+  })
+  // test search
+  .then(function () {
+    this.fill('#search', {
+      query: 'j'
+    })
+  })
+  .then(function () {
+    assertTable(test, ['name', 'power'], [
+      { name: 'Jackie Chan', power: 7000 },
+      { name: 'Jet Li', power: 8000 }
+    ])
+  })
+  .then(function () {
+    this.fill('#search', {
+      query: 'infinity'
+    })
+  })
+  .then(function () {
+    assertTable(test, ['name', 'power'], [
+      { name: 'Chuck Norris', power: Infinity }
+    ])
+  })
+  // run
+  .run(function () {
+    test.done()
+  })
+
+  /**
+   * Helper to assert the table data is rendered correctly.
+   *
+   * @param {CasperTester} test
+   * @param {Array} columns
+   * @param {Array} data
+   */
+
+  function assertTable (test, columns, data) {
+    test.assertElementCount('td', data.length * columns.length)
+    for (var i = 0; i < data.length; i++) {
+      for (var j = 0; j < columns.length; j++) {
+        test.assertSelectorHasText(
+          'tr:nth-child(' + (i + 1) + ') td:nth-child(' + (j + 1) + ')',
+          data[i][columns[j]]
+        )
+      }
+    }
+  }
+})

+ 49 - 0
test/e2e/markdown.js

@@ -0,0 +1,49 @@
+casper.test.begin('markdown', 5, function (test) {
+  casper
+  .start('examples/markdown/index.html')
+  .then(function () {
+    test.assertEval(function () {
+      return document.querySelector('textarea').value === '# hello'
+    })
+    test.assertEval(function () {
+      return document.querySelector('#editor div')
+        .innerHTML === '<h1 id="hello">hello</h1>\n'
+    })
+  })
+  .then(function () {
+    this.sendKeys(
+      'textarea',
+      '## foo\n\n' +
+      '- bar\n' +
+      '- baz\n\n',
+      { keepFocus: true }
+    )
+    // keyUp(13)
+  })
+  .then(function () {
+    // assert the output is not updated yet because of
+    // debounce
+    test.assertEval(function () {
+      return document.querySelector('#editor div')
+        .innerHTML === '<h1 id="hello">hello</h1>\n'
+    })
+  })
+  .wait(300) // wait for debounce
+  .then(function () {
+    test.assertEval(function () {
+      return document.querySelector('textarea').value ===
+        '## foo\n\n- bar\n- baz\n\n# hello'
+    })
+    test.assertEval(function () {
+      return document.querySelector('#editor div')
+        .innerHTML ===
+          '<h2 id="foo">foo</h2>\n' +
+          '<ul>\n<li>bar</li>\n<li>baz</li>\n</ul>\n' +
+          '<h1 id="hello">hello</h1>\n'
+    })
+  })
+  // run
+  .run(function () {
+    test.done()
+  })
+})

+ 60 - 0
test/e2e/svg.js

@@ -0,0 +1,60 @@
+/* global stats, valueToPoint */
+casper.on("page.error", function(msg, trace) {
+  console.log(JSON.stringify(trace, null, 2))
+})
+
+casper.test.begin('svg', 18, function (test) {
+  casper
+  .start('examples/svg/index.html')
+  .then(function () {
+    test.assertElementCount('g', 1)
+    test.assertElementCount('polygon', 1)
+    test.assertElementCount('circle', 1)
+    test.assertElementCount('text', 6)
+    test.assertElementCount('label', 6)
+    test.assertElementCount('button', 7)
+    test.assertElementCount('input[type="range"]', 6)
+    test.assertEval(function () {
+      var points = stats.map(function (stat, i) {
+        var point = valueToPoint(stat.value, i, 6)
+        return point.x + ',' + point.y
+      }).join(' ')
+      return document.querySelector('polygon').attributes[0].value === points
+    })
+  })
+  .thenClick('button.remove', function () {
+    test.assertElementCount('text', 5)
+    test.assertElementCount('label', 5)
+    test.assertElementCount('button', 6)
+    test.assertElementCount('input[type="range"]', 5)
+    test.assertEval(function () {
+      var points = stats.map(function (stat, i) {
+        var point = valueToPoint(stat.value, i, 5)
+        return point.x + ',' + point.y
+      }).join(' ')
+      return document.querySelector('polygon').attributes[0].value === points
+    })
+  })
+  .then(function () {
+    this.fill('#add', {
+      newlabel: 'foo'
+    })
+  })
+  .thenClick('#add > button', function () {
+    test.assertElementCount('text', 6)
+    test.assertElementCount('label', 6)
+    test.assertElementCount('button', 7)
+    test.assertElementCount('input[type="range"]', 6)
+    test.assertEval(function () {
+      var points = stats.map(function (stat, i) {
+        var point = valueToPoint(stat.value, i, 6)
+        return point.x + ',' + point.y
+      }).join(' ')
+      return document.querySelector('polygon').attributes[0].value === points
+    })
+  })
+  // run
+  .run(function () {
+    test.done()
+  })
+})

+ 291 - 0
test/e2e/todomvc.js

@@ -0,0 +1,291 @@
+/* global __utils__ */
+casper.on("page.error", function(msg, trace) {
+  console.log(JSON.stringify(trace, null, 2))
+})
+
+casper.test.begin('todomvc', 63, function (test) {
+  casper
+  .start('examples/todomvc/index.html')
+  .then(function () {
+    test.assertNotVisible('.main', '.main should be hidden')
+    test.assertNotVisible('.footer', '.footer should be hidden')
+    test.assertElementCount('.filters .selected', 1, 'should have one filter selected')
+    test.assertSelectorHasText('.filters .selected', 'All', 'default filter should be "All"')
+  })
+
+  // let's add a new item -----------------------------------------------
+
+  .then(function () {
+    casper.sendKeys('.new-todo', 'test')
+  })
+  .then(function () {
+    // wait before hitting enter
+    // so v-model unlocks
+    createNewItem()
+  })
+  .then(function () {
+    test.assertElementCount('.todo', 1, 'new item should be created')
+    test.assertNotVisible('.todo .edit', 'new item edit box should be hidden')
+    test.assertSelectorHasText('.todo label', 'test', 'new item should have correct label text')
+    test.assertSelectorHasText('.todo-count strong', '1', 'remaining count should be 1')
+    test.assertEvalEquals(function () {
+      return __utils__.findOne('.todo .toggle').checked
+    }, false, 'new item toggle should not be checked')
+    test.assertVisible('.main', '.main should now be visible')
+    test.assertVisible('.footer', '.footer should now be visible')
+    test.assertNotVisible('.clear-completed', '.clear-completed should be hidden')
+    test.assertField({type: 'css', path: '.new-todo'}, '', 'new todo input should be reset')
+  })
+
+  // add another item ---------------------------------------------------
+
+  .then(function () {
+    createNewItem('test2')
+  })
+  .then(function () {
+    test.assertElementCount('.todo', 2, 'should have 2 items now')
+    test.assertSelectorHasText('.todo:nth-child(2) label', 'test2', 'new item should have correct label text')
+    test.assertSelectorHasText('.todo-count strong', '2', 'remaining count should be 2')
+  })
+
+  // mark one item as completed -----------------------------------------
+
+  .thenClick('.todo .toggle', function () {
+    test.assertElementCount('.todo.completed', 1, 'should have 1 item completed')
+    test.assertEval(function () {
+      return __utils__.findOne('.todo').classList.contains('completed')
+    }, 'it should be the first one')
+    test.assertSelectorHasText('.todo-count strong', '1', 'remaining count should be 1')
+    test.assertVisible('.clear-completed', '.clear-completed should now be visible')
+  })
+
+  // add yet another item -----------------------------------------------
+
+  .then(function () {
+    createNewItem('test3')
+  })
+  .then(function () {
+    test.assertElementCount('.todo', 3, 'should have 3 items now')
+    test.assertSelectorHasText('.todo:nth-child(3) label', 'test3', 'new item should have correct label text')
+    test.assertSelectorHasText('.todo-count strong', '2', 'remaining count should be 2')
+  })
+
+  // add moreeee, now we assume they all work properly ------------------
+
+  .then(function () {
+    createNewItem('test4')
+    createNewItem('test5')
+  })
+  .then(function () {
+    test.assertElementCount('.todo', 5, 'should have 5 items now')
+    test.assertSelectorHasText('.todo-count strong', '4', 'remaining count should be 4')
+  })
+
+  // check more as completed --------------------------------------------
+  .then(function () {
+    this.click('.todo:nth-child(4) .toggle')
+    this.click('.todo:nth-child(5) .toggle')
+  })
+  .then(function () {
+    test.assertElementCount('.todo.completed', 3, 'should have 3 item completed')
+    test.assertSelectorHasText('.todo-count strong', '2', 'remaining count should be 2')
+  })
+
+  // remove a completed item --------------------------------------------
+
+  .thenClick('.todo:nth-child(1) .destroy', function () {
+    test.assertElementCount('.todo', 4, 'should have 4 items now')
+    test.assertElementCount('.todo.completed', 2, 'should have 2 item completed')
+    test.assertSelectorHasText('.todo-count strong', '2', 'remaining count should be 2')
+  })
+
+  // remove a incompleted item ------------------------------------------
+
+  .thenClick('.todo:nth-child(2) .destroy', function () {
+    test.assertElementCount('.todo', 3, 'should have 3 items now')
+    test.assertElementCount('.todo.completed', 2, 'should have 2 item completed')
+    test.assertSelectorHasText('.todo-count strong', '1', 'remaining count should be 1')
+  })
+
+  // remove all completed ------------------------------------------------
+
+  .thenClick('.clear-completed', function () {
+    test.assertElementCount('.todo', 1, 'should have 1 item now')
+    test.assertSelectorHasText('.todo label', 'test2', 'the remaining one should be the second one')
+    test.assertElementCount('.todo.completed', 0, 'should have no completed items now')
+    test.assertSelectorHasText('.todo-count strong', '1', 'remaining count should be 1')
+    test.assertNotVisible('.clear-completed', '.clear-completed should be hidden')
+  })
+
+  // prepare to test filters ------------------------------------------------
+  .then(function () {
+    createNewItem('test')
+    createNewItem('test')
+  })
+  .then(function () {
+    this.click('.todo:nth-child(2) .toggle')
+    this.click('.todo:nth-child(3) .toggle')
+  })
+
+  // active filter ----------------------------------------------------------
+  .thenClick('.filters li:nth-child(2) a', function () {
+    test.assertElementCount('.todo', 1, 'filter active should have 1 item')
+    test.assertElementCount('.todo.completed', 0, 'visible items should be incomplete')
+  })
+
+  // add item with filter active --------------------------------------------
+  // mostly make sure v-repeat works well with v-if
+  .then(function () {
+    createNewItem('test')
+  })
+  .then(function () {
+    test.assertElementCount('.todo', 2, 'should be able to create new item when fitler active')
+  })
+
+  // completed filter -------------------------------------------------------
+  .thenClick('.filters li:nth-child(3) a', function () {
+    test.assertElementCount('.todo', 2, 'filter completed should have 2 items')
+    test.assertElementCount('.todo.completed', 2, 'visible items should be completed')
+  })
+
+  // active filter on page load ---------------------------------------------
+  .thenOpen('examples/todomvc/index.html#/active', function () {
+    test.assertElementCount('.todo', 2, 'filter active should have 2 items')
+    test.assertElementCount('.todo.completed', 0, 'visible items should be incompleted')
+    test.assertSelectorHasText('.todo-count strong', '2', 'remaining count should be 2')
+  })
+
+  // completed filter on page load ------------------------------------------
+  .thenOpen('examples/todomvc/index.html#/completed', function () {
+    test.assertElementCount('.todo', 2, 'filter completed should have 2 items')
+    test.assertElementCount('.todo.completed', 2, 'visible items should be completed')
+    test.assertSelectorHasText('.todo-count strong', '2', 'remaining count should be 2')
+  })
+
+  // toggling todos when filter is active -----------------------------------
+  .thenClick('.todo .toggle', function () {
+    test.assertElementCount('.todo', 1, 'should have only 1 item left')
+  })
+  .thenClick('.filters li:nth-child(2) a', function () {
+    test.assertElementCount('.todo', 3, 'should have only 3 items now')
+  })
+  .thenClick('.todo .toggle', function () {
+    test.assertElementCount('.todo', 2, 'should have only 2 items now')
+  })
+
+  // test editing triggered by blur ------------------------------------------
+  .thenClick('.filters li:nth-child(1) a')
+  .then(function () {
+    doubleClick('.todo:nth-child(1) label')
+  })
+  .then(function () {
+    test.assertElementCount('.todo.editing', 1, 'should have one item being edited')
+    test.assertEval(function () {
+      var input = document.querySelector('.todo:nth-child(1) .edit')
+      return input === document.activeElement
+    }, 'edit input should be focused')
+  })
+  .then(function () {
+    resetField()
+    this.sendKeys('.todo:nth-child(1) .edit', 'edited!') // doneEdit triggered by blur
+  })
+  .then(function () {
+    test.assertElementCount('.todo.editing', 0, 'item should no longer be edited')
+    test.assertSelectorHasText('.todo:nth-child(1) label', 'edited!', 'item should have updated text')
+  })
+
+  // test editing triggered by enter ----------------------------------------
+  .then(function () {
+    doubleClick('.todo label')
+  })
+  .then(function () {
+    resetField()
+    this.sendKeys('.todo:nth-child(1) .edit', 'edited again!', { keepFocus: true })
+    keyUp(13) // Enter
+  })
+  .then(function () {
+    test.assertElementCount('.todo.editing', 0, 'item should no longer be edited')
+    test.assertSelectorHasText('.todo:nth-child(1) label', 'edited again!', 'item should have updated text')
+  })
+
+  // test cancel ------------------------------------------------------------
+  .then(function () {
+    doubleClick('.todo label')
+  })
+  .then(function () {
+    resetField()
+    this.sendKeys('.todo:nth-child(1) .edit', 'cancel test', { keepFocus: true })
+    keyUp(27) // ESC
+  })
+  .then(function () {
+    test.assertElementCount('.todo.editing', 0, 'item should no longer be edited')
+    test.assertSelectorHasText('.todo label', 'edited again!', 'item should not have updated text')
+  })
+
+  // test empty input remove ------------------------------------------------
+  .then(function () {
+    doubleClick('.todo label')
+  })
+  .then(function () {
+    resetField()
+    this.sendKeys('.todo:nth-child(1) .edit', ' ')
+  })
+  .then(function () {
+    test.assertElementCount('.todo', 3, 'item should have been deleted')
+  })
+
+  // test toggle all
+  .thenClick('.toggle-all', function () {
+    test.assertElementCount('.todo.completed', 3, 'should toggle all items to completed')
+  })
+  .thenClick('.toggle-all', function () {
+    test.assertElementCount('.todo:not(.completed)', 3, 'should toggle all items to active')
+  })
+
+  // run
+  .run(function () {
+    test.done()
+  })
+
+  // helper ===============
+
+  function createNewItem (text) {
+    if (text) {
+      casper.sendKeys('.new-todo', text)
+    }
+    casper.evaluate(function () {
+      // casper.mouseEvent can't set keyCode
+      var field = document.querySelector('.new-todo')
+      var e = document.createEvent('HTMLEvents')
+      e.initEvent('keyup', true, true)
+      e.keyCode = 13
+      field.dispatchEvent(e)
+    })
+  }
+
+  function doubleClick (selector) {
+    casper.evaluate(function (selector) {
+      var el = document.querySelector(selector)
+      var e = document.createEvent('MouseEvents')
+      e.initMouseEvent('dblclick', true, true, null, 1, 0, 0, 0, 0, false, false, false, false, 0, null)
+      el.dispatchEvent(e)
+    }, selector)
+  }
+
+  function keyUp (code) {
+    casper.evaluate(function (code) {
+      var input = document.querySelector('.todo:nth-child(1) .edit')
+      var e = document.createEvent('HTMLEvents')
+      e.initEvent('keyup', true, true)
+      e.keyCode = code
+      input.dispatchEvent(e)
+    }, code)
+  }
+
+  function resetField () {
+    // somehow casper.sendKey() option reset:true doesn't work
+    casper.evaluate(function () {
+      document.querySelector('.todo:nth-child(1) .edit').value = ''
+    })
+  }
+})

+ 53 - 0
test/e2e/tree.js

@@ -0,0 +1,53 @@
+casper.test.begin('tree', 22, function (test) {
+  casper
+  .start('examples/tree/index.html')
+  .then(function () {
+    test.assertElementCount('.item', 12)
+    test.assertElementCount('.item > ul', 4)
+    test.assertNotVisible('#demo li ul')
+    test.assertSelectorHasText('#demo li div span', '[+]')
+  })
+  .thenClick('.bold', function () {
+    test.assertVisible('#demo ul')
+    test.assertSelectorHasText('#demo li div span', '[-]')
+    test.assertSelectorHasText('#demo ul > .item:nth-child(1)', 'hello')
+    test.assertSelectorHasText('#demo ul > .item:nth-child(2)', 'wat')
+    test.assertSelectorHasText('#demo ul > .item:nth-child(3)', 'child folder')
+    test.assertSelectorHasText('#demo ul > .item:nth-child(3)', '[+]')
+    test.assertEval(function () {
+      return document.querySelector('#demo li ul').children.length === 4
+    })
+  })
+  .thenClick('#demo ul .bold', function () {
+    test.assertVisible('#demo ul ul')
+    test.assertSelectorHasText('#demo ul > .item:nth-child(3)', '[-]')
+    test.assertEval(function () {
+      return document.querySelector('#demo ul ul').children.length === 5
+    })
+  })
+  .thenClick('.bold', function () {
+    test.assertNotVisible('#demo ul')
+    test.assertSelectorHasText('#demo li div span', '[+]')
+  })
+  .thenClick('.bold', function () {
+    test.assertVisible('#demo ul')
+    test.assertSelectorHasText('#demo li div span', '[-]')
+  })
+  .then(function () {
+    casper.mouseEvent('dblclick', '#demo ul > .item div')
+  })
+  .then(function () {
+    test.assertElementCount('.item', 13)
+    test.assertElementCount('.item > ul', 5)
+    test.assertSelectorHasText('#demo ul > .item:nth-child(1)', '[-]')
+    test.assertEval(function () {
+      var firstItem = document.querySelector('#demo ul > .item:nth-child(1)')
+      var ul = firstItem.querySelector('ul')
+      return ul.children.length === 2
+    })
+  })
+  // run
+  .run(function () {
+    test.done()
+  })
+})