From: Evan You Date: Thu, 20 Jun 2019 13:28:37 +0000 (+0800) Subject: wip: update test runtime X-Git-Tag: v3.0.0-alpha.0~932 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=645c1eceea36aaad7bb24a82e769889f2f0eae58;p=thirdparty%2Fvuejs%2Fcore.git wip: update test runtime --- diff --git a/packages/runtime-dom/src/index.ts b/packages/runtime-dom/src/index.ts index dd9d7c31b4..e687f1da77 100644 --- a/packages/runtime-dom/src/index.ts +++ b/packages/runtime-dom/src/index.ts @@ -1,10 +1,11 @@ import { createRenderer, VNode } from '@vue/runtime-core' -import { DOMRendererOptions } from './rendererOptions' +import { nodeOps } from './nodeOps' +import { patchProp } from './patchProp' -export const render = createRenderer(DOMRendererOptions) as ( - vnode: VNode | null, - container: HTMLElement -) => VNode +export const render = createRenderer({ + patchProp, + ...nodeOps +}) as (vnode: VNode | null, container: HTMLElement) => VNode // re-export everything from core // h, Component, observer API, nextTick, flags & types diff --git a/packages/runtime-dom/src/rendererOptions.ts b/packages/runtime-dom/src/nodeOps.ts similarity index 84% rename from packages/runtime-dom/src/rendererOptions.ts rename to packages/runtime-dom/src/nodeOps.ts index af2325d05f..9316571f92 100644 --- a/packages/runtime-dom/src/rendererOptions.ts +++ b/packages/runtime-dom/src/nodeOps.ts @@ -1,12 +1,7 @@ -import { RendererOptions } from '@vue/runtime-core' -import { patchProp } from './patchProp' - const doc = document const svgNS = 'http://www.w3.org/2000/svg' -export const DOMRendererOptions: RendererOptions = { - patchProp, - +export const nodeOps = { insert: (child: Node, parent: Node, anchor?: Node) => { if (anchor != null) { parent.insertBefore(child, anchor) @@ -16,7 +11,6 @@ export const DOMRendererOptions: RendererOptions = { }, remove: (child: Node) => { - if (!child) debugger const parent = child.parentNode if (parent != null) { parent.removeChild(child) diff --git a/packages/runtime-test/__tests__/testRuntime.spec.ts b/packages/runtime-test/__tests__/testRuntime.spec.ts index ad7c421e57..ce0b8c83f8 100644 --- a/packages/runtime-test/__tests__/testRuntime.spec.ts +++ b/packages/runtime-test/__tests__/testRuntime.spec.ts @@ -1,36 +1,32 @@ import { - h, + createVNode as h, render, - Component, nodeOps, NodeTypes, TestElement, - TestText, - dumpOps, - NodeOpTypes, - nextTick, - observable, - resetOps, - serialize, - renderInstance, - triggerEvent + TestText + // dumpOps, + // NodeOpTypes, + // nextTick, + // state, + // resetOps, + // serialize, + // triggerEvent } from '../src' describe('test renderer', () => { it('should work', async () => { - class App extends Component { - render() { - return h( - 'div', - { - id: 'test' - }, - 'hello' - ) - } - } const root = nodeOps.createElement('div') - await render(h(App), root) + render( + h( + 'div', + { + id: 'test' + }, + 'hello' + ), + root + ) expect(root.children.length).toBe(1) @@ -44,137 +40,137 @@ describe('test renderer', () => { expect(text.text).toBe('hello') }) - it('should record ops', async () => { - const state = observable({ - id: 'test', - text: 'hello' - }) - - class App extends Component { - render() { - return h( - 'div', - { - id: state.id - }, - state.text - ) - } - } - const root = nodeOps.createElement('div') - - resetOps() - await render(h(App), root) - const ops = dumpOps() - - expect(ops.length).toBe(5) - - expect(ops[0]).toEqual({ - type: NodeOpTypes.CREATE, - nodeType: NodeTypes.ELEMENT, - tag: 'div', - targetNode: root.children[0] - }) - - expect(ops[1]).toEqual({ - type: NodeOpTypes.PATCH, - targetNode: root.children[0], - propKey: 'id', - propPrevValue: null, - propNextValue: 'test' - }) - - expect(ops[2]).toEqual({ - type: NodeOpTypes.CREATE, - nodeType: NodeTypes.TEXT, - text: 'hello', - targetNode: (root.children[0] as TestElement).children[0] - }) - - expect(ops[3]).toEqual({ - type: NodeOpTypes.APPEND, - targetNode: (root.children[0] as TestElement).children[0], - parentNode: root.children[0] - }) - - expect(ops[4]).toEqual({ - type: NodeOpTypes.APPEND, - targetNode: root.children[0], - parentNode: root - }) - - // test update ops - state.id = 'foo' - state.text = 'bar' - await nextTick() - - const updateOps = dumpOps() - expect(updateOps.length).toBe(2) - - expect(updateOps[0]).toEqual({ - type: NodeOpTypes.PATCH, - targetNode: root.children[0], - propKey: 'id', - propPrevValue: 'test', - propNextValue: 'foo' - }) - - expect(updateOps[1]).toEqual({ - type: NodeOpTypes.SET_TEXT, - targetNode: (root.children[0] as TestElement).children[0], - text: 'bar' - }) - }) - - it('should be able to serialize nodes', async () => { - class App extends Component { - render() { - return h( - 'div', - { - id: 'test' - }, - [h('span', 'foo'), 'hello'] - ) - } - } - const root = nodeOps.createElement('div') - await render(h(App), root) - expect(serialize(root)).toEqual( - `
foohello
` - ) - expect(serialize(root, 2)).toEqual( - `
-
- - foo - - hello -
-
` - ) - }) - - it('should be able to trigger events', async () => { - class App extends Component { - count = 0 - inc() { - this.count++ - } - render() { - return h( - 'div', - { - onClick: this.inc - }, - this.count - ) - } - } - const app = await renderInstance(App) - triggerEvent(app.$el, 'click') - expect(app.count).toBe(1) - await nextTick() - expect(serialize(app.$el)).toBe(`
1
`) - }) + // it('should record ops', async () => { + // const store = state({ + // id: 'test', + // text: 'hello' + // }) + + // class App extends Component { + // render() { + // return h( + // 'div', + // { + // id: store.id + // }, + // store.text + // ) + // } + // } + // const root = nodeOps.createElement('div') + + // resetOps() + // await render(h(App), root) + // const ops = dumpOps() + + // expect(ops.length).toBe(5) + + // expect(ops[0]).toEqual({ + // type: NodeOpTypes.CREATE, + // nodeType: NodeTypes.ELEMENT, + // tag: 'div', + // targetNode: root.children[0] + // }) + + // expect(ops[1]).toEqual({ + // type: NodeOpTypes.PATCH, + // targetNode: root.children[0], + // propKey: 'id', + // propPrevValue: null, + // propNextValue: 'test' + // }) + + // expect(ops[2]).toEqual({ + // type: NodeOpTypes.CREATE, + // nodeType: NodeTypes.TEXT, + // text: 'hello', + // targetNode: (root.children[0] as TestElement).children[0] + // }) + + // expect(ops[3]).toEqual({ + // type: NodeOpTypes.APPEND, + // targetNode: (root.children[0] as TestElement).children[0], + // parentNode: root.children[0] + // }) + + // expect(ops[4]).toEqual({ + // type: NodeOpTypes.APPEND, + // targetNode: root.children[0], + // parentNode: root + // }) + + // // test update ops + // store.id = 'foo' + // store.text = 'bar' + // await nextTick() + + // const updateOps = dumpOps() + // expect(updateOps.length).toBe(2) + + // expect(updateOps[0]).toEqual({ + // type: NodeOpTypes.PATCH, + // targetNode: root.children[0], + // propKey: 'id', + // propPrevValue: 'test', + // propNextValue: 'foo' + // }) + + // expect(updateOps[1]).toEqual({ + // type: NodeOpTypes.SET_TEXT, + // targetNode: (root.children[0] as TestElement).children[0], + // text: 'bar' + // }) + // }) + + // it('should be able to serialize nodes', async () => { + // class App extends Component { + // render() { + // return h( + // 'div', + // { + // id: 'test' + // }, + // [h('span', 'foo'), 'hello'] + // ) + // } + // } + // const root = nodeOps.createElement('div') + // await render(h(App), root) + // expect(serialize(root)).toEqual( + // `
foohello
` + // ) + // expect(serialize(root, 2)).toEqual( + // `
+ //
+ // + // foo + // + // hello + //
+ //
` + // ) + // }) + + // it('should be able to trigger events', async () => { + // class App extends Component { + // count = 0 + // inc() { + // this.count++ + // } + // render() { + // return h( + // 'div', + // { + // onClick: this.inc + // }, + // this.count + // ) + // } + // } + // const app = await renderInstance(App) + // triggerEvent(app.$el, 'click') + // expect(app.count).toBe(1) + // await nextTick() + // expect(serialize(app.$el)).toBe(`
1
`) + // }) }) diff --git a/packages/runtime-test/src/index.ts b/packages/runtime-test/src/index.ts index 5e1d35a986..db8d0cad6a 100644 --- a/packages/runtime-test/src/index.ts +++ b/packages/runtime-test/src/index.ts @@ -1,36 +1,11 @@ -import { - h, - createRenderer, - Component, - createComponentInstance -} from '@vue/runtime-core' +import { createRenderer, VNode } from '@vue/runtime-core' import { nodeOps, TestElement } from './nodeOps' -import { patchData } from './patchData' +import { patchProp } from './patchProp' -const { render: _render } = createRenderer({ - nodeOps, - patchData -}) - -type publicRender = ( - node: {} | null, - container: TestElement -) => Promise -export const render = _render as publicRender - -export function createInstance( - Class: new () => T, - props?: any -): T { - return createComponentInstance(h(Class, props)).$proxy as any -} - -export function renderInstance( - Class: new () => T, - props?: any -): Promise { - return render(h(Class, props), nodeOps.createElement('div')) as any -} +export const render = createRenderer({ + patchProp, + ...nodeOps +}) as (node: VNode | null, container: TestElement) => VNode export { serialize } from './serialize' export { triggerEvent } from './triggerEvent' diff --git a/packages/runtime-test/src/nodeOps.ts b/packages/runtime-test/src/nodeOps.ts index 9b4e48462f..926b36182c 100644 --- a/packages/runtime-test/src/nodeOps.ts +++ b/packages/runtime-test/src/nodeOps.ts @@ -1,6 +1,7 @@ export const enum NodeTypes { TEXT = 'text', - ELEMENT = 'element' + ELEMENT = 'element', + COMMENT = 'comment' } export interface TestElement { @@ -20,15 +21,21 @@ export interface TestText { text: string } -export type TestNode = TestElement | TestText +export interface TestComment { + id: number + type: NodeTypes.COMMENT + parentNode: TestElement | null + text: string +} + +export type TestNode = TestElement | TestText | TestComment export const enum NodeOpTypes { CREATE = 'create', INSERT = 'insert', - APPEND = 'append', REMOVE = 'remove', SET_TEXT = 'setText', - CLEAR = 'clearContent', + SET_ELEMENT_TEXT = 'setElementText', PATCH = 'patch' } @@ -39,7 +46,7 @@ export interface NodeOp { text?: string targetNode?: TestNode parentNode?: TestElement - refNode?: TestNode + refNode?: TestNode | null propKey?: string propPrevValue?: any propNextValue?: any @@ -97,37 +104,40 @@ function createText(text: string): TestText { return node } -function setText(node: TestText, text: string) { +function createComment(text: string): TestComment { + const node: TestComment = { + id: nodeId++, + type: NodeTypes.COMMENT, + text, + parentNode: null + } logNodeOp({ - type: NodeOpTypes.SET_TEXT, + type: NodeOpTypes.CREATE, + nodeType: NodeTypes.COMMENT, targetNode: node, text }) - node.text = text + return node } -function appendChild(parent: TestElement, child: TestNode) { +function setText(node: TestText, text: string) { logNodeOp({ - type: NodeOpTypes.APPEND, - targetNode: child, - parentNode: parent + type: NodeOpTypes.SET_TEXT, + targetNode: node, + text }) - if (child.parentNode) { - removeChild(child.parentNode, child) - } - parent.children.push(child) - child.parentNode = parent + node.text = text } -function insertBefore(parent: TestElement, child: TestNode, ref: TestNode) { - if (child.parentNode) { - removeChild(child.parentNode, child) - } - const refIndex = parent.children.indexOf(ref) - if (refIndex === -1) { - console.error('ref: ', ref) - console.error('parent: ', parent) - throw new Error('ref is not a child of parent') +function insert(child: TestNode, parent: TestElement, ref?: TestNode | null) { + let refIndex + if (ref != null) { + refIndex = parent.children.indexOf(ref) + if (refIndex === -1) { + console.error('ref: ', ref) + console.error('parent: ', parent) + throw new Error('ref is not a child of parent') + } } logNodeOp({ type: NodeOpTypes.INSERT, @@ -135,40 +145,46 @@ function insertBefore(parent: TestElement, child: TestNode, ref: TestNode) { parentNode: parent, refNode: ref }) - parent.children.splice(refIndex, 0, child) - child.parentNode = parent + remove(child) + if (refIndex === undefined) { + parent.children.push(child) + child.parentNode = parent + } else { + parent.children.splice(refIndex, 0, child) + child.parentNode = parent + } } -function removeChild(parent: TestElement, child: TestNode) { - logNodeOp({ - type: NodeOpTypes.REMOVE, - targetNode: child, - parentNode: parent - }) - const i = parent.children.indexOf(child) - if (i > -1) { - parent.children.splice(i, 1) - } else { - console.error('target: ', child) - console.error('parent: ', parent) - throw Error('target is not a childNode of parent') +function remove(child: TestNode) { + const parent = child.parentNode + if (parent != null) { + logNodeOp({ + type: NodeOpTypes.REMOVE, + targetNode: child, + parentNode: parent + }) + const i = parent.children.indexOf(child) + if (i > -1) { + parent.children.splice(i, 1) + } else { + console.error('target: ', child) + console.error('parent: ', parent) + throw Error('target is not a childNode of parent') + } + child.parentNode = null } - child.parentNode = null } -function clearContent(node: TestNode) { +function setElementText(el: TestElement, text: string) { logNodeOp({ - type: NodeOpTypes.CLEAR, - targetNode: node + type: NodeOpTypes.SET_ELEMENT_TEXT, + targetNode: el, + text }) - if (node.type === NodeTypes.ELEMENT) { - node.children.forEach(c => { - c.parentNode = null - }) - node.children = [] - } else { - node.text = '' - } + el.children.forEach(c => { + c.parentNode = null + }) + el.children = [createText(text)] } function parentNode(node: TestNode): TestElement | null { @@ -189,16 +205,14 @@ function querySelector() { } export const nodeOps = { + insert, + remove, createElement, createText, + createComment, setText, - appendChild, - insertBefore, - removeChild, - clearContent, + setElementText, parentNode, nextSibling, querySelector } - -export function patchData() {} diff --git a/packages/runtime-test/src/patchData.ts b/packages/runtime-test/src/patchProp.ts similarity index 87% rename from packages/runtime-test/src/patchData.ts rename to packages/runtime-test/src/patchProp.ts index c46f82a085..381d73b2d4 100644 --- a/packages/runtime-test/src/patchData.ts +++ b/packages/runtime-test/src/patchProp.ts @@ -1,11 +1,11 @@ import { TestElement, logNodeOp, NodeOpTypes } from './nodeOps' import { isOn } from '@vue/shared' -export function patchData( +export function patchProp( el: TestElement, key: string, - prevValue: any, - nextValue: any + nextValue: any, + prevValue: any ) { logNodeOp({ type: NodeOpTypes.PATCH, diff --git a/packages/runtime-test/src/serialize.ts b/packages/runtime-test/src/serialize.ts index c4ec82ea8f..fa401f4ad2 100644 --- a/packages/runtime-test/src/serialize.ts +++ b/packages/runtime-test/src/serialize.ts @@ -1,4 +1,10 @@ -import { TestElement, TestNode, NodeTypes, TestText } from './nodeOps' +import { + TestElement, + TestNode, + NodeTypes, + TestText, + TestComment +} from './nodeOps' import { isOn } from '@vue/shared' export function serialize( @@ -37,7 +43,14 @@ function serializeElement( ) } -function serializeText(node: TestText, indent: number, depth: number): string { +function serializeText( + node: TestText | TestComment, + indent: number, + depth: number +): string { const padding = indent ? ` `.repeat(indent).repeat(depth) : `` - return padding + node.text + return ( + padding + + (node.type === NodeTypes.COMMENT ? `` : node.text) + ) }