ソースを参照

test: test for attrs fallthrough

Evan You 7 年 前
コミット
a848466f07

+ 2 - 1
jest.config.js

@@ -2,7 +2,8 @@ module.exports = {
   preset: 'ts-jest',
   globals: {
     __DEV__: true,
-    __COMPAT__: false
+    __COMPAT__: false,
+    __JSDOM__: true
   },
   coverageDirectory: 'coverage',
   coverageReporters: ['html', 'lcov', 'text'],

+ 143 - 0
packages/core/__tests__/attrsFallthrough.spec.ts

@@ -0,0 +1,143 @@
+import { h, render, Component, nextTick } from '@vue/renderer-dom'
+
+describe('attribute fallthrough', () => {
+  it('should not fallthrough on components with no declared props', async () => {
+    const nativeClick = jest.fn()
+    const childUpdated = jest.fn()
+
+    class Hello extends Component {
+      data() {
+        return {
+          count: 0
+        }
+      }
+      inc() {
+        this.count++
+        nativeClick()
+      }
+      render() {
+        return h(Child, {
+          foo: 1,
+          id: 'test',
+          class: 'c' + this.count,
+          style: { color: this.count ? 'red' : 'green' },
+          nativeOnClick: this.inc
+        })
+      }
+    }
+
+    class Child extends Component {
+      updated() {
+        childUpdated()
+      }
+      render(props: any) {
+        return h(
+          'div',
+          {
+            class: 'c2',
+            style: { fontWeight: 'bold' }
+          },
+          props.foo
+        )
+      }
+    }
+
+    const root = document.createElement('div')
+    document.body.appendChild(root)
+    render(h(Hello), root)
+
+    const node = root.children[0] as HTMLElement
+
+    // attrs do not fallthrough because no props are declared
+    expect(node.hasAttribute('id')).toBe(false)
+    expect(node.hasAttribute('foo')).toBe(false)
+
+    // class, style and nativeOn* always fallthrough
+    expect(node.getAttribute('class')).toBe('c2 c0')
+    expect(node.style.color).toBe('green')
+    expect(node.style.fontWeight).toBe('bold')
+    node.dispatchEvent(new CustomEvent('click'))
+    expect(nativeClick).toHaveBeenCalled()
+
+    await nextTick()
+    expect(childUpdated).toHaveBeenCalled()
+    expect(node.hasAttribute('id')).toBe(false)
+    expect(node.hasAttribute('foo')).toBe(false)
+    expect(node.getAttribute('class')).toBe('c2 c1')
+    expect(node.style.color).toBe('red')
+    expect(node.style.fontWeight).toBe('bold')
+  })
+
+  it('should fallthrough on components with declared props', async () => {
+    const nativeClick = jest.fn()
+    const childUpdated = jest.fn()
+
+    class Hello extends Component {
+      data() {
+        return {
+          count: 0
+        }
+      }
+      inc() {
+        this.count++
+        nativeClick()
+      }
+      render() {
+        return h(Child, {
+          foo: 1,
+          id: 'test',
+          class: 'c' + this.count,
+          style: { color: this.count ? 'red' : 'green' },
+          nativeOnClick: this.inc
+        })
+      }
+    }
+
+    class Child extends Component {
+      static options = {
+        props: {
+          foo: Number
+        }
+      }
+      updated() {
+        childUpdated()
+      }
+      render(props: any) {
+        return h(
+          'div',
+          {
+            class: 'c2',
+            style: { fontWeight: 'bold' }
+          },
+          props.foo
+        )
+      }
+    }
+
+    const root = document.createElement('div')
+    document.body.appendChild(root)
+    render(h(Hello), root)
+
+    const node = root.children[0] as HTMLElement
+
+    // with declared props, any parent attr that isn't a prop falls through
+    expect(node.getAttribute('id')).toBe('test')
+    // ...while declared ones remain props
+    expect(node.hasAttribute('foo')).toBe(false)
+
+    // class, style and nativeOn* always fallthrough
+    expect(node.getAttribute('class')).toBe('c2 c0')
+    expect(node.style.color).toBe('green')
+    expect(node.style.fontWeight).toBe('bold')
+    node.dispatchEvent(new CustomEvent('click'))
+    expect(nativeClick).toHaveBeenCalled()
+
+    await nextTick()
+    expect(childUpdated).toHaveBeenCalled()
+    expect(node.getAttribute('id')).toBe('test')
+    expect(node.hasAttribute('foo')).toBe(false)
+    expect(node.getAttribute('class')).toBe('c2 c1')
+    expect(node.style.color).toBe('red')
+    expect(node.style.fontWeight).toBe('bold')
+  })
+})

+ 1 - 0
packages/global.d.ts

@@ -1,3 +1,4 @@
 // Global compile-time constants
 declare var __DEV__: boolean
 declare var __COMPAT__: boolean
+declare var __JSDOM__: boolean

+ 1 - 1
packages/renderer-dom/src/modules/events.ts

@@ -9,7 +9,7 @@ export function patchEvent(
   prevValue: EventValue | null,
   nextValue: EventValue | null
 ) {
-  if (delegateRE.test(name)) {
+  if (delegateRE.test(name) && !__JSDOM__) {
     handleDelegatedEvent(el, name, nextValue)
   } else {
     handleNormalEvent(el, name, prevValue, nextValue)

+ 3 - 1
rollup.config.js

@@ -124,7 +124,9 @@ function createReplacePlugin(isProduction, isBunlderESMBuild, isCompat) {
       : // hard coded dev/prod builds
         !isProduction,
     // compatibility builds
-    __COMPAT__: !!packageOptions.compat
+    __COMPAT__: !!packageOptions.compat,
+    // this is only used during tests
+    __JSDOM__: false
   })
 }