From 155ef19e0a89c5cc8e56b05e9aae751f2bd9657d Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Fri, 29 Nov 2019 10:03:10 +0100 Subject: [PATCH 01/10] Add shared-internals package --- package.json | 6 +- shared-internals/mangle.json | 48 ++++++++++++++++ shared-internals/package.json | 19 +++++++ shared-internals/src/README.md | 3 + shared-internals/src/index.d.ts | 10 ++++ shared-internals/src/index.js | 99 +++++++++++++++++++++++++++++++++ 6 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 shared-internals/mangle.json create mode 100644 shared-internals/package.json create mode 100644 shared-internals/src/README.md create mode 100644 shared-internals/src/index.d.ts create mode 100644 shared-internals/src/index.js diff --git a/package.json b/package.json index 0a8f8b0dc30..9d047ff7e3f 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "build:hooks": "microbundle build --raw --cwd hooks", "build:test-utils": "microbundle build --raw --cwd test-utils", "build:compat": "microbundle build --raw --cwd compat --globals 'preact/hooks=preactHooks'", + "build:shared-internals": "microbundle build --raw --cwd shared-internals", "dev": "microbundle watch --raw --format cjs", "dev:hooks": "microbundle watch --raw --format cjs --cwd hooks", "dev:compat": "microbundle watch --raw --format cjs --cwd compat --globals 'preact/hooks=preactHooks'", @@ -118,7 +119,10 @@ "hooks/package.json", "test-utils/src", "test-utils/package.json", - "test-utils/dist" + "test-utils/dist", + "shared-internals/src", + "shared-internals/package.json", + "shared-internals/dist" ], "keywords": [ "preact", diff --git a/shared-internals/mangle.json b/shared-internals/mangle.json new file mode 100644 index 00000000000..221e76e3e2c --- /dev/null +++ b/shared-internals/mangle.json @@ -0,0 +1,48 @@ +{ + "help": { + "what is this file?": "It controls protected/private property mangling so that minified builds have consistent property names.", + "why are there duplicate minified properties?": "Most properties are only used on one type of objects, so they can have the same name since they will never collide. Doing this reduces size." + }, + "minify": { + "mangle": { + "properties": { + "regex": "^_" + } + }, + "compress": { + "hoist_vars": true, + "reduce_funcs": false + } + }, + "props": { + "cname": 6, + "props": { + "$_depth": "__b", + "$_lastDomChild": "__d", + "$_dirty": "__d", + "$_force": "__e", + "$_nextState": "__s", + "$_renderCallbacks": "__h", + "$_vnode": "__v", + "$_children": "__k", + "$_suspensions": "__u", + "$_dom": "__e", + "$_component": "__c", + "$__html": "__html", + "$_parent": "__", + "$_pendingError": "__E", + "$_processingException": "__", + "$_context": "__n", + "$_defaultValue": "__", + "$_id": "__c", + "$_parentDom": "__P", + "$_root": "__", + "$_diff": "__b", + "$_commit": "__c", + "$_render": "__r", + "$_hook": "__h", + "$_catchError": "__e", + "$_unmount": "_e" + } + } +} \ No newline at end of file diff --git a/shared-internals/package.json b/shared-internals/package.json new file mode 100644 index 00000000000..32fb4a6708d --- /dev/null +++ b/shared-internals/package.json @@ -0,0 +1,19 @@ +{ + "name": "shared-internals", + "amdName": "sharedInternals", + "version": "0.1.0", + "private": true, + "description": "Shared internals for testing or debugging adapters", + "main": "dist/shared-internals.js", + "module": "dist/shared-internals.module.js", + "umd:main": "dist/shared-internals.umd.js", + "source": "src/index.js", + "license": "MIT", + "types": "src/index.d.ts", + "peerDependencies": { + "preact": "^10.0.0" + }, + "mangle": { + "regex": "^_" + } +} diff --git a/shared-internals/src/README.md b/shared-internals/src/README.md new file mode 100644 index 00000000000..a66e6957cad --- /dev/null +++ b/shared-internals/src/README.md @@ -0,0 +1,3 @@ +# Shared internals + +This package is only intended to be used for testing frameworks or debuggers which need to access private internals of Preact. Examples for that are the devtools and adapter for the enzyme testing library. Don't use this for "normal" apps. Please use the public API for those. diff --git a/shared-internals/src/index.d.ts b/shared-internals/src/index.d.ts new file mode 100644 index 00000000000..5bbc02329a2 --- /dev/null +++ b/shared-internals/src/index.d.ts @@ -0,0 +1,10 @@ +import * as preact from '../../src'; + +export function getParent(vnode: preact.VNode): preact.VNode | null; +export function getComponent(vnode: preact.VNode): preact.Component | null; +export function getDom(vnode: preact.VNode): HTMLElement | Text | null; +export function getLastDomChild(vnode: preact.VNode): HTMLElement | Text | null; +export function getChildren( + vnode: preact.VNode +): Array; +export function getComponentVNode(component: preact.Component): preact.VNode; diff --git a/shared-internals/src/index.js b/shared-internals/src/index.js new file mode 100644 index 00000000000..01bc943b71b --- /dev/null +++ b/shared-internals/src/index.js @@ -0,0 +1,99 @@ +/** + * Get the direct parent of a `VNode`. + * @param {import('../../src/internal').VNode} vnode + * @returns {import('../../src/internal').VNode | null} + */ +export function getParent(vnode) { + return vnode._parent; +} + +/** + * Return the `Component` instance associated with a rendered `VNode`. + * @param {import('../../src/internal').VNode} vnode + * @returns {import('../../src/internal').Component | null} + */ +export function getComponent(vnode) { + return vnode._component; +} + +/** + * Return the rendered DOM node associated with a rendered `VNode`. + * + * "Associated" here means either the DOM node directly output as a result of + * rendering the vnode (for DOM vnodes) or the first DOM node output by a + * child vnode for component vnodes. + * + * @param {import('../../src/internal').VNode} vnode + * @returns {import('../../src/internal').PreactElement | Text | null} + */ +export function getDom(vnode) { + return vnode._dom; +} + +/** + * Get the last dom child of a `vnode`. This will only be set for + * Fragment-like components. + * @param {import('../../src/internal').VNode} vnode + * @returns {import('../../src/internal').PreactElement | Text | null} + */ +export function getLastDomChild(vnode) { + return vnode._lastDomChild; +} + +/** + * Return the child `VNodes` associated with a rendered `VNode`. + * @param {import('../../src/internal').VNode} vnode + * @returns {Array} + */ +export function getChildren(vnode) { + return vnode._children; +} + +/** + * Return the `VNode` of a `component` when it was last rendered. + * @param {import('../../src/internal').Component} component + * @returns {import('../../src/internal').VNode} + */ +export function getComponentVNode(component) { + return component._vnode; +} + +// Options getters/setters + +/** + * Return private `options._diff` hook that's called before `diff()`. + * @param {import('../../src/internal').Options} options + * @returns {import('../../src/internal').Options["_diff"]} + */ +export function getOptionsDiff(options) { + return options._diff; +} + +/** + * Return private `options._diff` hook that's called at the end of + * each commit. + * @param {import('../../src/internal').Options} options + * @returns {import('../../src/internal').Options["_commit"]} + */ +export function getOptionsCommit(options) { + return options._commit; +} + +/** + * Set private `options._diff` hook that's called before `diff()`. + * @param {import('../../src/internal').Options} options + * @param {import('../../src/internal').Options["_diff"]} fn + */ +export function setOptionsDiff(options, fn) { + options._diff = fn; +} + +/** + * Return private `options._diff` hook that's called at the end of + * each commit. + * @param {import('../../src/internal').Options} options + * @param {import('../../src/internal').Options["_commit"]} fn + */ +export function setOptionsCommit(options, fn) { + options._commit = fn; +} From 76ebb8671c7b12dc755ffa55acb003a62593ff83 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Fri, 29 Nov 2019 11:36:50 +0100 Subject: [PATCH 02/10] Fix copy-paste error --- shared-internals/src/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared-internals/src/index.js b/shared-internals/src/index.js index 01bc943b71b..cea080c60d1 100644 --- a/shared-internals/src/index.js +++ b/shared-internals/src/index.js @@ -70,7 +70,7 @@ export function getOptionsDiff(options) { } /** - * Return private `options._diff` hook that's called at the end of + * Return private `options._commit` hook that's called at the end of * each commit. * @param {import('../../src/internal').Options} options * @returns {import('../../src/internal').Options["_commit"]} @@ -89,7 +89,7 @@ export function setOptionsDiff(options, fn) { } /** - * Return private `options._diff` hook that's called at the end of + * Return private `options._commit` hook that's called at the end of * each commit. * @param {import('../../src/internal').Options} options * @param {import('../../src/internal').Options["_commit"]} fn From ec60a760e8cc4317265896f9fb7c219aca66e0e1 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Fri, 29 Nov 2019 11:38:18 +0100 Subject: [PATCH 03/10] Add options._root internal setter/getter --- shared-internals/src/index.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/shared-internals/src/index.js b/shared-internals/src/index.js index cea080c60d1..d22be0394be 100644 --- a/shared-internals/src/index.js +++ b/shared-internals/src/index.js @@ -79,6 +79,16 @@ export function getOptionsCommit(options) { return options._commit; } +/** + * Return private `options._root` hook that's called when a tree + * is rendered from the top via `render(vnode, dom)`. + * @param {import('../../src/internal').Options} options + * @returns {import('../../src/internal').Options["_root"]} + */ +export function getOptionsRoot(options) { + return options._root; +} + /** * Set private `options._diff` hook that's called before `diff()`. * @param {import('../../src/internal').Options} options @@ -97,3 +107,13 @@ export function setOptionsDiff(options, fn) { export function setOptionsCommit(options, fn) { options._commit = fn; } + +/** + * Return private `options._root` hook that's called at the end of + * each commit. + * @param {import('../../src/internal').Options} options + * @param {import('../../src/internal').Options["_root"]} fn + */ +export function setOptionsRoot(options, fn) { + options._root = fn; +} From 4d46fc355259e385172ee7bad6a33bba3c0bea0d Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Fri, 29 Nov 2019 11:46:18 +0100 Subject: [PATCH 04/10] Add options type to shared-internals --- shared-internals/src/index.d.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/shared-internals/src/index.d.ts b/shared-internals/src/index.d.ts index 5bbc02329a2..c18f9b24df5 100644 --- a/shared-internals/src/index.d.ts +++ b/shared-internals/src/index.d.ts @@ -8,3 +8,31 @@ export function getChildren( vnode: preact.VNode ): Array; export function getComponentVNode(component: preact.Component): preact.VNode; + +// +// Option hooks +// +// These are using the public types to avoid conflicts. Downside of that +// is that the return types need to be declared manually here. +type OptionsDiff = (vnode: preact.VNode) => void; +type OptionsCommit = ( + vnode: preact.VNode, + commitQueue: preact.Component[] +) => void; +type OptionsRoot = ( + vnode: preact.ComponentChild, + parent: Element | Document | ShadowRoot | DocumentFragment +) => void; + +// Getters +export function getOptionsDiff(options: preact.Options): OptionsDiff; +export function getOptionsCommit(options: preact.Options): OptionsCommit; +export function getOptionsRoot(options: preact.Options): OptionsRoot; + +// Setters +export function setOptionsDiff(options: preact.Options, fn: OptionsDiff): void; +export function setOptionsCommit( + options: preact.Options, + fn: OptionsCommit +): void; +export function setOptionsRoot(options: preact.Options, fn: OptionsRoot): void; From 3f959b15e7fadec664454813e79dd2d5300becbe Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Fri, 29 Nov 2019 17:26:51 +0100 Subject: [PATCH 05/10] Move Readme to package root --- shared-internals/{src => }/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename shared-internals/{src => }/README.md (100%) diff --git a/shared-internals/src/README.md b/shared-internals/README.md similarity index 100% rename from shared-internals/src/README.md rename to shared-internals/README.md From 600a05388ce04225c4601d92360ecca25e82c2c4 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Fri, 29 Nov 2019 20:11:13 +0100 Subject: [PATCH 06/10] Remove _lastDomChild getter, value is always null --- shared-internals/src/index.d.ts | 1 - shared-internals/src/index.js | 10 ---------- 2 files changed, 11 deletions(-) diff --git a/shared-internals/src/index.d.ts b/shared-internals/src/index.d.ts index c18f9b24df5..d83ff38a437 100644 --- a/shared-internals/src/index.d.ts +++ b/shared-internals/src/index.d.ts @@ -3,7 +3,6 @@ import * as preact from '../../src'; export function getParent(vnode: preact.VNode): preact.VNode | null; export function getComponent(vnode: preact.VNode): preact.Component | null; export function getDom(vnode: preact.VNode): HTMLElement | Text | null; -export function getLastDomChild(vnode: preact.VNode): HTMLElement | Text | null; export function getChildren( vnode: preact.VNode ): Array; diff --git a/shared-internals/src/index.js b/shared-internals/src/index.js index d22be0394be..2eaaccdb49f 100644 --- a/shared-internals/src/index.js +++ b/shared-internals/src/index.js @@ -30,16 +30,6 @@ export function getDom(vnode) { return vnode._dom; } -/** - * Get the last dom child of a `vnode`. This will only be set for - * Fragment-like components. - * @param {import('../../src/internal').VNode} vnode - * @returns {import('../../src/internal').PreactElement | Text | null} - */ -export function getLastDomChild(vnode) { - return vnode._lastDomChild; -} - /** * Return the child `VNodes` associated with a rendered `VNode`. * @param {import('../../src/internal').VNode} vnode From b4f7376c57608a9d5083adac75175f211e5e3554 Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Fri, 29 Nov 2019 20:30:13 +0100 Subject: [PATCH 07/10] Add tests for shared-internals package --- karma.conf.js | 11 +- .../test/browser/internals.test.js | 189 ++++++++++++++++++ 2 files changed, 198 insertions(+), 2 deletions(-) create mode 100644 shared-internals/test/browser/internals.test.js diff --git a/karma.conf.js b/karma.conf.js index c5b6b6b1e40..eae35dc96d0 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -114,13 +114,16 @@ module.exports = function(config) { { pattern: config.grep || - '{debug,hooks,compat,test-utils,}/test/{browser,shared}/**/*.test.js', + '{debug,hooks,compat,test-utils,shared-internals,}/test/{browser,shared}/**/*.test.js', watched: false } ], preprocessors: { - '{debug,hooks,compat,test-utils,}/test/**/*': ['webpack', 'sourcemap'] + '{debug,hooks,compat,test-utils,shared-internals,}/test/**/*': [ + 'webpack', + 'sourcemap' + ] }, webpack: { @@ -156,6 +159,10 @@ module.exports = function(config) { 'preact/compat': path.join(__dirname, './compat/src'), 'preact/hooks': path.join(__dirname, './hooks/src'), 'preact/test-utils': path.join(__dirname, './test-utils/src'), + 'preact/shared-internals': path.join( + __dirname, + './shared-internals/src' + ), preact: path.join(__dirname, './src') } }, diff --git a/shared-internals/test/browser/internals.test.js b/shared-internals/test/browser/internals.test.js new file mode 100644 index 00000000000..38a473d1dc7 --- /dev/null +++ b/shared-internals/test/browser/internals.test.js @@ -0,0 +1,189 @@ +import { createElement, render, Component, createRef, options } from 'preact'; +import { setupScratch, teardown } from '../../../test/_util/helpers'; +import { + getParent, + getComponent, + getDom, + getChildren, + getComponentVNode, + getOptionsDiff, + getOptionsCommit, + getOptionsRoot, + setOptionsDiff, + setOptionsCommit, + setOptionsRoot +} from '../../src'; + +/** @jsx createElement */ + +describe('shared-internals', () => { + /** @type {HTMLDivElement} */ + let scratch; + + beforeEach(() => { + scratch = setupScratch(); + }); + + afterEach(() => { + teardown(scratch); + }); + + describe('getParent', () => { + it('should get the parent of a vnode', () => { + const child = ; + const vnode =
{child}
; + render(vnode, scratch); + + expect(getParent(child)).to.equal(vnode); + }); + + it('should be null when there is no parent', () => { + const vnode =
; + render(vnode, scratch); + + const root = getParent(vnode); + expect(getParent(root)).to.equal(null); + }); + }); + + describe('getComponent', () => { + it('should return null for non-component vnodes', () => { + const vnode =
; + render(vnode, scratch); + expect(getComponent(vnode)).to.equal(null); + }); + + it('should return component instance', () => { + const Foo = () =>
; + const vnode = ; + render(vnode, scratch); + expect(getComponent(vnode) instanceof Component).to.equal(true); + }); + }); + + describe('getDom', () => { + it('should be null when not set', () => { + const vnode =
; + expect(getDom(vnode)).to.equal(null); + }); + + it('should return the dom node', () => { + const vnode =
; + render(vnode, scratch); + expect(getDom(vnode)).to.equal(scratch.firstChild); + }); + }); + + describe('getChildren', () => { + it('should be null initially', () => { + expect(getChildren(
)).to.equal(null); + }); + + it('should get children array', () => { + const Foo = props => props.children; + const vnode = ( + + foo + + + ); + render(vnode, scratch); + + const res = getChildren(vnode); + expect(Array.isArray(res)).to.equal(true); + expect(res.length).to.equal(2); + + // Should convert string to text ndoe + expect(typeof res[0]).to.equal('object'); + }); + }); + + describe('getComponentVNode', () => { + it('should get the vnode of a component', () => { + const Foo = () =>
; + let ref = createRef(); + const vnode = ; + render(vnode, scratch); + + expect(getComponentVNode(ref.current)).to.equal(vnode); + }); + }); + + describe('options', () => { + let prevDiff; + let prevCommit; + let prevRoot; + + beforeEach(() => { + prevDiff = options._diff; + prevCommit = options._commit; + prevRoot = options._root; + }); + + afterEach(() => { + options._diff = prevDiff; + options._commit = prevCommit; + options._root = prevRoot; + }); + + describe('getOptionsDiff', () => { + it('should be undefined if not set', () => { + expect(getOptionsDiff(options)).to.be.undefined; + }); + + it('should get option._diff', () => { + const spy = sinon.spy(); + options._diff = spy; + expect(getOptionsDiff(options)).to.equal(spy); + }); + }); + + describe('getOptionsCommit', () => { + it('should be undefined if not set', () => { + expect(getOptionsCommit(options)).to.be.undefined; + }); + + it('should get option._commit', () => { + const spy = sinon.spy(); + options._commit = spy; + expect(getOptionsCommit(options)).to.equal(spy); + }); + }); + + describe('getOptionsRoot', () => { + it('should be undefined if not set', () => { + expect(getOptionsRoot(options)).to.be.undefined; + }); + + it('should get option._commit', () => { + const spy = sinon.spy(); + options._root = spy; + expect(getOptionsRoot(options)).to.equal(spy); + }); + }); + + describe('setOptionsDiff', () => { + it('should set options._diff', () => { + const spy = sinon.spy(); + setOptionsDiff(options, spy); + expect(options._diff).to.equal(spy); + }); + }); + + describe('setOptionsCommit', () => { + it('should set options._commit', () => { + const spy = sinon.spy(); + setOptionsCommit(options, spy); + expect(options._commit).to.equal(spy); + }); + }); + + describe('setOptionsRoot', () => { + it('should set options._root', () => { + const spy = sinon.spy(); + setOptionsRoot(options, spy); + expect(options._root).to.equal(spy); + }); + }); + }); +}); From 5f4f9c3503400f1fb4b067743fde8703bd5e4e0e Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 3 Dec 2019 09:45:23 +0100 Subject: [PATCH 08/10] Fix wrong jsdoc comments --- shared-internals/src/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared-internals/src/index.js b/shared-internals/src/index.js index 2eaaccdb49f..69b7a083380 100644 --- a/shared-internals/src/index.js +++ b/shared-internals/src/index.js @@ -89,7 +89,7 @@ export function setOptionsDiff(options, fn) { } /** - * Return private `options._commit` hook that's called at the end of + * Set private `options._commit` hook that's called at the end of * each commit. * @param {import('../../src/internal').Options} options * @param {import('../../src/internal').Options["_commit"]} fn @@ -99,7 +99,7 @@ export function setOptionsCommit(options, fn) { } /** - * Return private `options._root` hook that's called at the end of + * Set private `options._root` hook that's called at the end of * each commit. * @param {import('../../src/internal').Options} options * @param {import('../../src/internal').Options["_root"]} fn From 52cde86baf5cc73cb30afe88379a2caad9a2934d Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 3 Dec 2019 09:51:33 +0100 Subject: [PATCH 09/10] Add section about stability guarantees to README --- shared-internals/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shared-internals/README.md b/shared-internals/README.md index a66e6957cad..38efe8e5b40 100644 --- a/shared-internals/README.md +++ b/shared-internals/README.md @@ -1,3 +1,5 @@ # Shared internals This package is only intended to be used for testing frameworks or debuggers which need to access private internals of Preact. Examples for that are the devtools and adapter for the enzyme testing library. Don't use this for "normal" apps. Please use the public API for those. + +Note that due to it being treated as internal, it doesn't follow the same stability guarantees as our public API. We may introduce breaking changes here at any point. From e51907dc629c9bde68e71a4955e44dfa65b0887f Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Tue, 3 Dec 2019 10:10:57 +0100 Subject: [PATCH 10/10] Add getContainerVNode getter --- shared-internals/src/index.d.ts | 3 +++ shared-internals/src/index.js | 11 ++++++++++ .../test/browser/internals.test.js | 21 ++++++++++++++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/shared-internals/src/index.d.ts b/shared-internals/src/index.d.ts index d83ff38a437..378c18ac379 100644 --- a/shared-internals/src/index.d.ts +++ b/shared-internals/src/index.d.ts @@ -7,6 +7,9 @@ export function getChildren( vnode: preact.VNode ): Array; export function getComponentVNode(component: preact.Component): preact.VNode; +export function getContainerVNode( + container: Element | Document | ShadowRoot | DocumentFragment +): preact.VNode | null; // // Option hooks diff --git a/shared-internals/src/index.js b/shared-internals/src/index.js index 69b7a083380..8453cac170f 100644 --- a/shared-internals/src/index.js +++ b/shared-internals/src/index.js @@ -48,6 +48,17 @@ export function getComponentVNode(component) { return component._vnode; } +/** + * Return the `VNode` that is associated with a DOM node that was rendered into. + * This property only exists on root nodes, commonly called containers. They + * are created via top-level `render(vnode, container)` calls. + * @param {Element | Document | ShadowRoot | DocumentFragment} container + * @returns {import('../../src/internal').VNode | null} + */ +export function getContainerVNode(container) { + return container._children; +} + // Options getters/setters /** diff --git a/shared-internals/test/browser/internals.test.js b/shared-internals/test/browser/internals.test.js index 38a473d1dc7..6aff9e6cc2d 100644 --- a/shared-internals/test/browser/internals.test.js +++ b/shared-internals/test/browser/internals.test.js @@ -1,4 +1,11 @@ -import { createElement, render, Component, createRef, options } from 'preact'; +import { + createElement, + render, + Component, + createRef, + options, + Fragment +} from 'preact'; import { setupScratch, teardown } from '../../../test/_util/helpers'; import { getParent, @@ -6,6 +13,7 @@ import { getDom, getChildren, getComponentVNode, + getContainerVNode, getOptionsDiff, getOptionsCommit, getOptionsRoot, @@ -109,6 +117,17 @@ describe('shared-internals', () => { }); }); + describe('getContainerVNode', () => { + it('should return undefined', () => { + expect(getContainerVNode(scratch)).to.equal(undefined); + }); + + it('should return root Fragment vnode', () => { + render(
, scratch); + expect(getContainerVNode(scratch).type).to.equal(Fragment); + }); + }); + describe('options', () => { let prevDiff; let prevCommit;