functional.spec.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import Vue from 'vue'
  2. describe('Options functional', () => {
  3. it('should work', done => {
  4. const vm = new Vue({
  5. data: { test: 'foo' },
  6. template: '<div><wrap :msg="test">bar</wrap></div>',
  7. components: {
  8. wrap: {
  9. functional: true,
  10. props: ['msg'],
  11. render (h, { props, children }) {
  12. return h('div', null, [props.msg, ' '].concat(children))
  13. }
  14. }
  15. }
  16. }).$mount()
  17. expect(vm.$el.innerHTML).toBe('<div>foo bar</div>')
  18. vm.test = 'qux'
  19. waitForUpdate(() => {
  20. expect(vm.$el.innerHTML).toBe('<div>qux bar</div>')
  21. }).then(done)
  22. })
  23. it('should support returning more than one root node', () => {
  24. const vm = new Vue({
  25. template: `<div><test></test></div>`,
  26. components: {
  27. test: {
  28. functional: true,
  29. render (h) {
  30. return [h('span', 'foo'), h('span', 'bar')]
  31. }
  32. }
  33. }
  34. }).$mount()
  35. expect(vm.$el.innerHTML).toBe('<span>foo</span><span>bar</span>')
  36. })
  37. it('should support slots', () => {
  38. const vm = new Vue({
  39. data: { test: 'foo' },
  40. template: '<div><wrap><div slot="a">foo</div><div slot="b">bar</div></wrap></div>',
  41. components: {
  42. wrap: {
  43. functional: true,
  44. props: ['msg'],
  45. render (h, { slots }) {
  46. slots = slots()
  47. return h('div', null, [slots.b, slots.a])
  48. }
  49. }
  50. }
  51. }).$mount()
  52. expect(vm.$el.innerHTML).toBe('<div><div>bar</div><div>foo</div></div>')
  53. })
  54. it('should let vnode raw data pass through', done => {
  55. const onValid = jasmine.createSpy('valid')
  56. const vm = new Vue({
  57. data: { msg: 'hello' },
  58. template: `<div>
  59. <validate field="field1" @valid="onValid">
  60. <input type="text" v-model="msg">
  61. </validate>
  62. </div>`,
  63. components: {
  64. validate: {
  65. functional: true,
  66. props: ['field'],
  67. render (h, { props, children, data: { on }}) {
  68. props.child = children[0]
  69. return h('validate-control', { props, on })
  70. }
  71. },
  72. 'validate-control': {
  73. props: ['field', 'child'],
  74. render () {
  75. return this.child
  76. },
  77. mounted () {
  78. this.$el.addEventListener('input', this.onInput)
  79. },
  80. destroyed () {
  81. this.$el.removeEventListener('input', this.onInput)
  82. },
  83. methods: {
  84. onInput (e) {
  85. const value = e.target.value
  86. if (this.validate(value)) {
  87. this.$emit('valid', this)
  88. }
  89. },
  90. // something validation logic here
  91. validate (val) {
  92. return val.length > 0
  93. }
  94. }
  95. }
  96. },
  97. methods: { onValid }
  98. }).$mount()
  99. document.body.appendChild(vm.$el)
  100. const input = vm.$el.querySelector('input')
  101. expect(onValid).not.toHaveBeenCalled()
  102. waitForUpdate(() => {
  103. input.value = 'foo'
  104. triggerEvent(input, 'input')
  105. }).then(() => {
  106. expect(onValid).toHaveBeenCalled()
  107. }).then(() => {
  108. document.body.removeChild(vm.$el)
  109. vm.$destroy()
  110. }).then(done)
  111. })
  112. })