From d35141e85e423e9c47860744c6bd7eb2d08e5b2e Mon Sep 17 00:00:00 2001 From: eddyerburgh Date: Sun, 18 Feb 2018 19:41:41 +0000 Subject: [PATCH 1/9] feat(render): add render method --- package.json | 2 + src/index.js | 2 + src/lib/add-slots.js | 3 + src/mount.js | 2 +- src/render.js | 30 +++++ test/resources/test-utils.js | 20 ++- .../mounting-options/attachToDocument.spec.js | 10 ++ test/specs/mounting-options/attrs.spec.js | 13 +- test/specs/mounting-options/context.spec.js | 22 ++-- test/specs/mounting-options/localVue.spec.js | 27 +++-- test/specs/mounting-options/mocks.spec.js | 84 ++++++++----- test/specs/mounting-options/provide.spec.js | 55 +++++---- test/specs/mounting-options/slots.spec.js | 114 +++++++++++++++--- test/specs/mounting-options/stubs.spec.js | 58 ++++++--- 14 files changed, 329 insertions(+), 113 deletions(-) create mode 100644 src/render.js diff --git a/package.json b/package.json index a6f4c0c4a..3e4c1e1db 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "vue-class-component": "^6.1.2", "vue-loader": "^13.6.2", "vue-router": "^3.0.1", + "vue-server-renderer": "2.5.13", "vue-template-compiler": "^2.5.13", "vuetify": "^0.16.9", "vuex": "^3.0.1", @@ -96,6 +97,7 @@ }, "peerDependencies": { "vue": "2.x", + "vue-server-renderer": "2.x", "vue-template-compiler": "^2.x" }, "dependencies": { diff --git a/src/index.js b/src/index.js index 3eb71602b..92d9853da 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,6 @@ import shallow from './shallow' import mount from './mount' +import render from './render' import createLocalVue from './create-local-vue' import TransitionStub from './components/TransitionStub' import TransitionGroupStub from './components/TransitionGroupStub' @@ -11,6 +12,7 @@ export default { config, mount, shallow, + render, TransitionStub, TransitionGroupStub, RouterLinkStub diff --git a/src/lib/add-slots.js b/src/lib/add-slots.js index d0583d640..5e1619a99 100644 --- a/src/lib/add-slots.js +++ b/src/lib/add-slots.js @@ -54,6 +54,9 @@ function addSlots (vm: Component, slots: Object): void { if (Array.isArray(slots[key])) { slots[key].forEach((slotValue) => { + if (!isValidSlot(slotValue)) { + throwError('slots[key] must be a Component, string or an array of Components') + } addSlotToVm(vm, key, slotValue) }) } else { diff --git a/src/mount.js b/src/mount.js index 3fc0d350c..2e27b43ae 100644 --- a/src/mount.js +++ b/src/mount.js @@ -11,8 +11,8 @@ import errorHandler from './lib/error-handler' import { findAllVueComponentsFromVm } from './lib/find-vue-components' Vue.config.productionTip = false -Vue.config.errorHandler = errorHandler Vue.config.devtools = false +Vue.config.errorHandler = errorHandler export default function mount (component: Component, options: Options = {}): VueWrapper { // Remove cached constructor diff --git a/src/render.js b/src/render.js new file mode 100644 index 000000000..fec5c3267 --- /dev/null +++ b/src/render.js @@ -0,0 +1,30 @@ +// @flow + +import Vue from 'vue' +import createInstance from './lib/create-instance' +import './lib/polyfills/object-assign-polyfill' +const renderer = require('vue-server-renderer').createRenderer() +import { throwError } from './lib/util' + +Vue.config.productionTip = false +Vue.config.devtools = false + +export default function render (component: Component, options: Options = {}): VueWrapper { + // Remove cached constructor + delete component._Ctor + + if (options.attachToDocument) { + throwError('you cannot use attachToDocument with render') + } + + const vm = createInstance(component, options) + + let string + renderer.renderToString(vm, (err, res) => { + if (err) { + throwError(err) + } + string = res + }) + return string +} diff --git a/test/resources/test-utils.js b/test/resources/test-utils.js index 5350ccb8b..c57c9d988 100644 --- a/test/resources/test-utils.js +++ b/test/resources/test-utils.js @@ -1,7 +1,7 @@ /* global describe, it*/ import Vue from 'vue' -import { shallow, mount } from '~vue-test-utils' +import { shallow, mount, render } from '~vue-test-utils' export const vueVersion = Number(`${Vue.version.split('.')[0]}.${Vue.version.split('.')[1]}`) @@ -27,6 +27,24 @@ export function describeWithShallowAndMount (spec, cb) { }) } +export function describeWithMountingMethods (spec, cb) { + ;[mount, shallow, render].forEach(method => { + describe(`${spec} with ${method.name}`, () => cb(method)) + }) +} + +describeWithMountingMethods.skip = function (spec, cb) { + ;[mount, shallow, render].forEach(method => { + describe.skip(`${spec} with ${method.name}`, () => cb(method)) + }) +} + +describeWithMountingMethods.only = function (spec, cb) { + ;[mount, shallow, render].forEach(method => { + describe.only(`${spec} with ${method.name}`, () => cb(method)) + }) +} + describeWithShallowAndMount.skip = function (spec, cb) { ;[mount, shallow].forEach(method => { describe.skip(`${spec} with ${method.name}`, () => cb(method)) diff --git a/test/specs/mounting-options/attachToDocument.spec.js b/test/specs/mounting-options/attachToDocument.spec.js index 82f73bdca..81df5045c 100644 --- a/test/specs/mounting-options/attachToDocument.spec.js +++ b/test/specs/mounting-options/attachToDocument.spec.js @@ -1,5 +1,6 @@ import { compileToFunctions } from 'vue-template-compiler' import { describeWithShallowAndMount } from '~resources/test-utils' +import { render } from '~vue-test-utils' describeWithShallowAndMount('options.attachToDocument', (mountingMethod) => { it('returns VueWrapper with attachedToDocument set to true when passed attachToDocument in options', () => { @@ -8,3 +9,12 @@ describeWithShallowAndMount('options.attachToDocument', (mountingMethod) => { expect(wrapper.options.attachedToDocument).to.equal(true) }) }) + +describe('options.attachToDocument with render', () => { + it('throws error that render does not accept attachToDocument', () => { + const compiled = compileToFunctions('
') + const fn = () => render(compiled, { attachToDocument: true }) + const message = '[vue-test-utils]: you cannot use attachToDocument with render' + expect(fn).to.throw().with.property('message', message) + }) +}) diff --git a/test/specs/mounting-options/attrs.spec.js b/test/specs/mounting-options/attrs.spec.js index 8eb82b038..149181a4a 100644 --- a/test/specs/mounting-options/attrs.spec.js +++ b/test/specs/mounting-options/attrs.spec.js @@ -1,9 +1,13 @@ import { compileToFunctions } from 'vue-template-compiler' import { attrsSupported } from '~resources/test-utils' -import { describeWithShallowAndMount } from '~resources/test-utils' +import { + describeWithMountingMethods, + itSkipIf + } from '~resources/test-utils' -describeWithShallowAndMount('options.attrs', (mountingMethod) => { - it('handles inherit attrs', () => { +describeWithMountingMethods('options.attrs', (mountingMethod) => { + itSkipIf(mountingMethod.name === 'render', + 'handles inherit attrs', () => { if (!attrsSupported()) return const wrapper = mountingMethod(compileToFunctions('

'), { attrs: { @@ -15,7 +19,8 @@ describeWithShallowAndMount('options.attrs', (mountingMethod) => { expect(wrapper.vm.$attrs.anAttr).to.equal('an attribute') }) - it('defines attrs as empty object even when not passed', () => { + itSkipIf(mountingMethod.name === 'render', + 'defines attrs as empty object even when not passed', () => { const wrapper = mountingMethod(compileToFunctions('

')) expect(wrapper.vm.$attrs).to.deep.equal({}) }) diff --git a/test/specs/mounting-options/context.spec.js b/test/specs/mounting-options/context.spec.js index 63730eb92..4518eec68 100644 --- a/test/specs/mounting-options/context.spec.js +++ b/test/specs/mounting-options/context.spec.js @@ -1,8 +1,8 @@ import Vue from 'vue' import { vueVersion } from '~resources/test-utils' -import { describeWithShallowAndMount } from '~resources/test-utils' +import { describeWithMountingMethods } from '~resources/test-utils' -describeWithShallowAndMount('options.context', (mountingMethod) => { +describeWithMountingMethods('options.context', (mountingMethod) => { it('mounts functional component when passed context object', () => { if (vueVersion <= 2.2) { console.log('WARN: no current way to test functional component is component in v2.1.x') @@ -21,8 +21,7 @@ describeWithShallowAndMount('options.context', (mountingMethod) => { props: { show: true } } - const wrapper = mountingMethod(Component, { context }) - expect(wrapper.is(Component)).to.equal(true) + mountingMethod(Component, { context }) }) it('throws error if non functional component is passed with context option', () => { @@ -69,7 +68,10 @@ describeWithShallowAndMount('options.context', (mountingMethod) => { render: (h, { props }) => h('div', props.testProp) } const wrapper = mountingMethod(Component) - expect(wrapper.element.textContent).to.equal(defaultValue) + const HTML = mountingMethod.name === 'render' + ? wrapper + : wrapper.html() + expect(HTML).to.contain(defaultValue) }) it('mounts functional component with a defined context.children text', () => { @@ -84,7 +86,10 @@ describeWithShallowAndMount('options.context', (mountingMethod) => { children: ['render text'] } }) - expect(wrapper.text()).to.equal('render text') + const HTML = mountingMethod.name === 'render' + ? wrapper + : wrapper.html() + expect(HTML).to.contain('render text') }) it('mounts functional component with a defined context.children element', () => { @@ -99,6 +104,9 @@ describeWithShallowAndMount('options.context', (mountingMethod) => { children: [h => h('div', 'render component')] } }) - expect(wrapper.text()).to.equal('render component') + const HTML = mountingMethod.name === 'render' + ? wrapper + : wrapper.html() + expect(HTML).to.contain('render component') }) }) diff --git a/test/specs/mounting-options/localVue.spec.js b/test/specs/mounting-options/localVue.spec.js index 43ed502b5..f7f68a6a0 100644 --- a/test/specs/mounting-options/localVue.spec.js +++ b/test/specs/mounting-options/localVue.spec.js @@ -1,14 +1,27 @@ import Vue from 'vue' -import Component from '~resources/components/component.vue' -import { describeWithShallowAndMount } from '~resources/test-utils' +import { describeWithMountingMethods } from '~resources/test-utils' -describeWithShallowAndMount('options.localVue', (mountingMethod) => { +describeWithMountingMethods('options.localVue', (mountingMethod) => { it('mounts component using passed localVue as base Vue', () => { + const TestComponent = { + template: ` +

{{test}}
+ ` + } const localVue = Vue.extend() localVue.version = '2.3' - const wrapper = mountingMethod(Component, { localVue: localVue, mocks: { test: true }}) - expect(wrapper.vm.test).to.equal(true) - const freshWrapper = mountingMethod(Component) - expect(typeof freshWrapper.vm.test).to.equal('undefined') + const wrapper = mountingMethod(TestComponent, { + localVue: localVue, + mocks: { test: 'some value' } + }) + const HTML = mountingMethod.name === 'render' + ? wrapper + : wrapper.html() + expect(HTML).to.contain('some value') + const freshWrapper = mountingMethod(TestComponent) + const freshHTML = mountingMethod.name === 'render' + ? freshWrapper + : freshWrapper.html() + expect(freshHTML).to.not.contain('some value') }) }) diff --git a/test/specs/mounting-options/mocks.spec.js b/test/specs/mounting-options/mocks.spec.js index 4e047f727..5e2fd0128 100644 --- a/test/specs/mounting-options/mocks.spec.js +++ b/test/specs/mounting-options/mocks.spec.js @@ -2,51 +2,64 @@ import { createLocalVue } from '~vue-test-utils' import Component from '~resources/components/component.vue' import ComponentWithVuex from '~resources/components/component-with-vuex.vue' import { - describeWithShallowAndMount, + describeWithMountingMethods, itDoNotRunIf } from '~resources/test-utils' -describeWithShallowAndMount('options.mocks', (mountingMethod) => { - it('adds variables to vm when passed as mocks object', () => { +describeWithMountingMethods('options.mocks', (mountingMethod) => { + it('adds variables to vm when passed', () => { + const TestComponent = { + template: ` +
+ {{$store.store}} + {{$route.path}} +
+ ` + } const $store = { store: true } const $route = { path: 'http://test.com' } - const wrapper = mountingMethod(Component, { + const wrapper = mountingMethod(TestComponent, { mocks: { $store, $route } }) - expect(wrapper.vm.$store).to.equal($store) - expect(wrapper.vm.$route).to.equal($route) + const HTML = mountingMethod.name === 'render' + ? wrapper + : wrapper.html() + expect(HTML).contains('true') + expect(HTML).contains('http://test.com') }) - it('adds variables to vm when passed as mocks object', () => { - const stub = sinon.stub() - const $reactiveMock = { value: 'value' } - const wrapper = mountingMethod({ - template: ` + // render returns a string so reactive does not apply + itDoNotRunIf(mountingMethod.name === 'render', + 'adds variables as reactive properties to vm when passed', () => { + const stub = sinon.stub() + const $reactiveMock = { value: 'value' } + const wrapper = mountingMethod({ + template: `
{{value}}
`, - computed: { - value () { - return this.$reactiveMock.value - } - }, - watch: { - value () { - stub() - } - } - }, { - mocks: { $reactiveMock } - }) - expect(wrapper.text()).to.contain('value') - $reactiveMock.value = 'changed value' - wrapper.update() - expect(wrapper.text()).to.contain('changed value') - }) + computed: { + value () { + return this.$reactiveMock.value + } + }, + watch: { + value () { + stub() + } + } + }, { + mocks: { $reactiveMock } + }) + expect(wrapper.text()).to.contain('value') + $reactiveMock.value = 'changed value' + wrapper.update() + expect(wrapper.text()).to.contain('changed value') + }) itDoNotRunIf(mountingMethod.name === 'shallow', 'adds variables available to nested vms', () => { @@ -59,7 +72,10 @@ describeWithShallowAndMount('options.mocks', (mountingMethod) => { }, { mocks: { $store: { state: { count, foo: {}}}} }) - expect(wrapper.text()).contains(count) + const HTML = mountingMethod.name === 'render' + ? wrapper + : wrapper.html() + expect(HTML).contains(count) }) itDoNotRunIf(mountingMethod.name === 'shallow', @@ -75,10 +91,14 @@ describeWithShallowAndMount('options.mocks', (mountingMethod) => { mocks: { $store: { state: { count, foo: {}}}}, localVue }) - expect(wrapper.text()).contains(count) + const HTML = mountingMethod.name === 'render' + ? wrapper + : wrapper.html() + expect(HTML).contains(count) }) - it('does not affect global vue class when passed as mocks object', () => { + itDoNotRunIf(mountingMethod.name === 'render', + 'does not affect global vue class when passed as mocks object', () => { const $store = { store: true } const wrapper = mountingMethod(Component, { mocks: { diff --git a/test/specs/mounting-options/provide.spec.js b/test/specs/mounting-options/provide.spec.js index 2ca2fe94a..85f375e5a 100644 --- a/test/specs/mounting-options/provide.spec.js +++ b/test/specs/mounting-options/provide.spec.js @@ -1,22 +1,26 @@ -import { mount } from '~vue-test-utils' import ComponentWithInject from '~resources/components/component-with-inject.vue' import { injectSupported } from '~resources/test-utils' -import { describeWithShallowAndMount } from '~resources/test-utils' - -describeWithShallowAndMount('options.provide', (mountingMethod) => { - it('provides objects which is injected by mounted component', () => { - if (!injectSupported()) return - - const wrapper = mount(ComponentWithInject, { - provide: { fromMount: 'objectValue' } +import { + describeWithMountingMethods, + itDoNotRunIf + } from '~resources/test-utils' + +describeWithMountingMethods('options.provide', (mountingMethod) => { + itDoNotRunIf(!injectSupported(), + 'provides objects which is injected by mounted component', () => { + if (!injectSupported()) return + + const wrapper = mountingMethod(ComponentWithInject, { + provide: { fromMount: 'objectValue' } + }) + const HTML = mountingMethod.name === 'render' + ? wrapper + : wrapper.html() + expect(HTML).to.contain('objectValue') }) - expect(wrapper.text()).to.contain('objectValue') - }) - - it('provides function which is injected by mounted component', () => { - if (!injectSupported()) return - + itDoNotRunIf(!injectSupported(), + 'provides function which is injected by mounted component', () => { const wrapper = mountingMethod(ComponentWithInject, { provide () { return { @@ -24,17 +28,20 @@ describeWithShallowAndMount('options.provide', (mountingMethod) => { } } }) - - expect(wrapper.text()).to.contain('functionValue') + const HTML = mountingMethod.name === 'render' + ? wrapper + : wrapper.html() + expect(HTML).to.contain('functionValue') }) - it('supports beforeCreate in component', () => { - if (!injectSupported()) return + itDoNotRunIf(!injectSupported() || mountingMethod.name === 'render', + 'supports beforeCreate in component', () => { + if (!injectSupported()) return - const wrapper = mountingMethod(ComponentWithInject, { - provide: { fromMount: '_' } - }) + const wrapper = mountingMethod(ComponentWithInject, { + provide: { fromMount: '_' } + }) - expect(wrapper.vm.setInBeforeCreate).to.equal('created') - }) + expect(wrapper.vm.setInBeforeCreate).to.equal('created') + }) }) diff --git a/test/specs/mounting-options/slots.spec.js b/test/specs/mounting-options/slots.spec.js index bad0e0c99..816037410 100644 --- a/test/specs/mounting-options/slots.spec.js +++ b/test/specs/mounting-options/slots.spec.js @@ -3,11 +3,11 @@ import Component from '~resources/components/component.vue' import ComponentWithSlots from '~resources/components/component-with-slots.vue' import ComponentAsAClass from '~resources/components/component-as-a-class.vue' import { - describeWithShallowAndMount, + describeWithMountingMethods, vueVersion } from '~resources/test-utils' -describeWithShallowAndMount('options.slots', (mountingMethod) => { +describeWithMountingMethods('options.slots', (mountingMethod) => { let _window beforeEach(() => { @@ -22,23 +22,40 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { it('mounts component with default slot if passed component in slot object', () => { const wrapper = mountingMethod(ComponentWithSlots, { slots: { default: Component }}) - expect(wrapper.contains(Component)).to.equal(true) + console.log(mountingMethod.name) + if (mountingMethod.name === 'render') { + expect(wrapper).contains('
') + } else { + expect(wrapper.contains(Component)).to.equal(true) + } }) it('mounts component with default slot if passed component in array in slot object', () => { const wrapper = mountingMethod(ComponentWithSlots, { slots: { default: [Component] }}) - expect(wrapper.contains(Component)).to.equal(true) + if (mountingMethod.name === 'render') { + expect(wrapper).contains('
') + } else { + expect(wrapper.contains(Component)).to.equal(true) + } }) it('mounts component with default slot if passed object with template prop in slot object', () => { const compiled = compileToFunctions('
') const wrapper = mountingMethod(ComponentWithSlots, { slots: { default: [compiled] }}) - expect(wrapper.contains('#div')).to.equal(true) + if (mountingMethod.name === 'render') { + expect(wrapper).contains('div id="div"') + } else { + expect(wrapper.contains('#div')).to.equal(true) + } }) it('mounts component with default slot if passed string in slot object', () => { const wrapper = mountingMethod(ComponentWithSlots, { slots: { default: '' }}) - expect(wrapper.contains('span')).to.equal(true) + if (mountingMethod.name === 'render') { + expect(wrapper).contains(' { @@ -46,7 +63,11 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { return } const wrapper = mountingMethod(ComponentAsAClass, { slots: { default: '' }}) - expect(wrapper.contains('span')).to.equal(true) + if (mountingMethod.name === 'render') { + expect(wrapper).contains(' { @@ -60,6 +81,9 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { }) it('mounts component with default slot if passed string in slot object', () => { + if (mountingMethod.name === 'render') { + return + } const wrapper1 = mountingMethod(ComponentWithSlots, { slots: { default: 'foo123{{ foo }}' }}) expect(wrapper1.find('main').html()).to.equal('
foo123bar
') const wrapper2 = mountingMethod(ComponentWithSlots, { slots: { default: '

1

{{ foo }}2' }}) @@ -96,12 +120,20 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { it('mounts component with default slot if passed string in slot array object', () => { const wrapper = mountingMethod(ComponentWithSlots, { slots: { default: [''] }}) - expect(wrapper.contains('span')).to.equal(true) + if (mountingMethod.name === 'render') { + expect(wrapper).contains(' { const wrapper = mountingMethod(ComponentWithSlots, { slots: { default: ['{{ foo }}1', 'bar'] }}) - expect(wrapper.find('main').html()).to.equal('
bar1bar
') + if (mountingMethod.name === 'render') { + expect(wrapper).contains('
bar1bar
') + } else { + expect(wrapper.find('main').html()).to.equal('
bar1bar
') + } }) it('throws error if passed string in default slot array vue-template-compiler is undefined', () => { @@ -127,7 +159,11 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { footer: [Component] } }) - expect(wrapper.findAll(Component).length).to.equal(2) + if (mountingMethod.name === 'render') { + expect(wrapper).contains('
') + } else { + expect(wrapper.findAll(Component).length).to.equal(2) + } }) it('mounts component with named slot if passed component in slot object', () => { @@ -136,8 +172,12 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { header: Component } }) - expect(wrapper.findAll(Component).length).to.equal(1) - expect(Array.isArray(wrapper.vm.$slots.header)).to.equal(true) + if (mountingMethod.name === 'render') { + expect(wrapper).contains('
') + } else { + expect(wrapper.findAll(Component).length).to.equal(1) + expect(Array.isArray(wrapper.vm.$slots.header)).to.equal(true) + } }) it('mounts functional component with default slot if passed component in slot object', () => { @@ -147,7 +187,11 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { render: (h, ctx) => h('div', ctx.data, ctx.slots().default) } const wrapper = mountingMethod(TestComponent, { slots: { default: Component }}) - expect(wrapper.contains(Component)).to.equal(true) + if (mountingMethod.name === 'render') { + expect(wrapper).contains('
') + } else { + expect(wrapper.contains(Component)).to.equal(true) + } }) it('mounts component with default slot if passed component in slot object', () => { @@ -157,7 +201,11 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { render: (h, ctx) => h('div', ctx.data, ctx.slots().default) } const wrapper = mountingMethod(TestComponent, { slots: { default: [Component] }}) - expect(wrapper.contains(Component)).to.equal(true) + if (mountingMethod.name === 'render') { + expect(wrapper).contains('
') + } else { + expect(wrapper.contains(Component)).to.equal(true) + } }) it('mounts component with default slot if passed object with template prop in slot object', () => { @@ -168,7 +216,11 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { } const compiled = compileToFunctions('
') const wrapper = mountingMethod(TestComponent, { slots: { default: [compiled] }}) - expect(wrapper.contains('#div')).to.equal(true) + if (mountingMethod.name === 'render') { + expect(wrapper).contains('
') + } else { + expect(wrapper.contains('#div')).to.equal(true) + } }) it('mounts component with default slot if passed string in slot object', () => { @@ -178,7 +230,11 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { render: (h, ctx) => h('div', ctx.data, ctx.slots().default) } const wrapper = mountingMethod(TestComponent, { slots: { default: '' }}) - expect(wrapper.contains('span')).to.equal(true) + if (mountingMethod.name === 'render') { + expect(wrapper).contains(' { @@ -187,7 +243,11 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { render: (h, ctx) => h('div', {}, ctx.slots().named) } const wrapper = mountingMethod(TestComponent, { slots: { named: Component }}) - expect(wrapper.contains(Component)).to.equal(true) + if (mountingMethod.name === 'render') { + expect(wrapper).contains('
') + } else { + expect(wrapper.contains(Component)).to.equal(true) + } }) it('mounts component with named slot if passed string in slot object in array', () => { @@ -196,7 +256,11 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { render: (h, ctx) => h('div', {}, ctx.slots().named) } const wrapper = mountingMethod(TestComponent, { slots: { named: [Component] }}) - expect(wrapper.contains(Component)).to.equal(true) + if (mountingMethod.name === 'render') { + expect(wrapper).contains('
') + } else { + expect(wrapper.contains(Component)).to.equal(true) + } }) it('mounts component with named slot if passed string in slot object in array', () => { @@ -205,7 +269,11 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { render: (h, ctx) => h('div', {}, ctx.slots().named) } const wrapper = mountingMethod(TestComponent, { slots: { named: '' }}) - expect(wrapper.contains('span')).to.equal(true) + if (mountingMethod.name === 'render') { + expect(wrapper).contains(' { @@ -214,7 +282,11 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { render: (h, ctx) => h('div', {}, ctx.slots().named) } const wrapper = mountingMethod(TestComponent, { slots: { named: [''] }}) - expect(wrapper.contains('span')).to.equal(true) + if (mountingMethod.name === 'render') { + expect(wrapper).contains(' { @@ -238,6 +310,7 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { const message = '[vue-test-utils]: slots[key] must be a Component, string or an array of Components' expect(fn).to.throw().with.property('message', message) }) + it('throws error if passed false for named slots', () => { const TestComponent = { name: 'component-with-slots', @@ -259,6 +332,7 @@ describeWithShallowAndMount('options.slots', (mountingMethod) => { const message = '[vue-test-utils]: slots[key] must be a Component, string or an array of Components' expect(fn).to.throw().with.property('message', message) }) + it('throws error if passed string in default slot array when vue-template-compiler is undefined', () => { const TestComponent = { name: 'component-with-slots', diff --git a/test/specs/mounting-options/stubs.spec.js b/test/specs/mounting-options/stubs.spec.js index 26dea2c6a..98a0b482e 100644 --- a/test/specs/mounting-options/stubs.spec.js +++ b/test/specs/mounting-options/stubs.spec.js @@ -6,11 +6,11 @@ import ComponentAsAClass from '~resources/components/component-as-a-class.vue' import { createLocalVue } from '~vue-test-utils' import Vue from 'vue' import { - describeWithShallowAndMount, + describeWithMountingMethods, itDoNotRunIf } from '~resources/test-utils' -describeWithShallowAndMount('options.stub', (mountingMethod) => { +describeWithMountingMethods('options.stub', (mountingMethod) => { let info let warn let configStubsSave @@ -48,15 +48,20 @@ describeWithShallowAndMount('options.stub', (mountingMethod) => { ChildComponent: '
' } }) - expect(wrapper.findAll('.stub').length).to.equal(1) - expect(wrapper.findAll(Component).length).to.equal(1) + if (mountingMethod.name === 'render') { + expect(wrapper).to.contain('"stub"') + } else { + expect(wrapper.findAll('.stub').length).to.equal(1) + expect(wrapper.findAll(Component).length).to.equal(1) + } }) - it('replaces component with a component', () => { + itDoNotRunIf(mountingMethod.name === 'render', + 'replaces component with a component', () => { const wrapper = mountingMethod(ComponentWithChild, { stubs: { ChildComponent: { - render: h => h('div'), + render: h => h('time'), mounted () { console.info('stubbed') } @@ -75,7 +80,8 @@ describeWithShallowAndMount('options.stub', (mountingMethod) => { }) }) - itDoNotRunIf(mountingMethod.name === 'shallow', + itDoNotRunIf(mountingMethod.name === 'shallow' || + mountingMethod.name === 'render', 'does not modify component directly', () => { const wrapper = mountingMethod(ComponentWithNestedChildren, { stubs: { @@ -83,6 +89,7 @@ describeWithShallowAndMount('options.stub', (mountingMethod) => { } }) expect(wrapper.findAll(Component).length).to.equal(0) + const mountedWrapper = mountingMethod(ComponentWithNestedChildren) expect(mountedWrapper.findAll(Component).length).to.equal(1) }) @@ -96,7 +103,10 @@ describeWithShallowAndMount('options.stub', (mountingMethod) => { 'registered-component': Component } }) - expect(wrapper.findAll(Component).length).to.equal(1) + const HTML = mountingMethod.name === 'render' + ? wrapper + : wrapper.html() + expect(HTML).to.contain('
') }) it('stubs components with dummy when passed as an array', () => { @@ -162,12 +172,15 @@ describeWithShallowAndMount('options.stub', (mountingMethod) => { stubs: { ChildComponent: false }}) - expect(wrapper.find('span').contains('div')).to.equal(true) + const HTML = mountingMethod.name === 'render' + ? wrapper + : wrapper.html() + expect(HTML).to.contain('
') }) it('combines with stubs from config', () => { const localVue = createLocalVue() - config.stubs['time-component'] = '

' + config.stubs['time-component'] = '
' const SpanComponent = { render: h => h('span') } @@ -189,7 +202,11 @@ describeWithShallowAndMount('options.stub', (mountingMethod) => { }, localVue }) - expect(wrapper.findAll('p').length).to.equal(2) + const HTML = mountingMethod.name === 'render' + ? wrapper + : wrapper.html() + expect(HTML).to.contain('
') + expect(HTML).to.contain('

') }) it('prioritize mounting options over config', () => { @@ -211,7 +228,10 @@ describeWithShallowAndMount('options.stub', (mountingMethod) => { }, localVue }) - expect(wrapper.contains('span')).to.equal(true) + const HTML = mountingMethod.name === 'render' + ? wrapper + : wrapper.html() + expect(HTML).to.contain('') }) it('converts config to array if stubs is an array', () => { @@ -231,9 +251,11 @@ describeWithShallowAndMount('options.stub', (mountingMethod) => { stubs: ['a-component'], localVue }) - expect(wrapper.contains('time')).to.equal(false) - expect(wrapper.contains('p')).to.equal(false) - expect(wrapper.html()).to.equal('

') + + const HTML = mountingMethod.name === 'render' + ? wrapper + : wrapper.html() + expect(HTML).to.contain('
') }) it('handles components without a render function', () => { @@ -256,8 +278,10 @@ describeWithShallowAndMount('options.stub', (mountingMethod) => { 'stub-component': StubComponent } }) - - expect(wrapper.text()).contains('No render function') + const HTML = mountingMethod.name === 'render' + ? wrapper + : wrapper.html() + expect(HTML).contains('No render function') }) it('throws an error when passed an invalid value as stub', () => { From 5528ec045693bd3d3a1253f32267e99cc744a5d0 Mon Sep 17 00:00:00 2001 From: eddyerburgh Date: Mon, 19 Feb 2018 06:59:42 +0000 Subject: [PATCH 2/9] feat(renderToString): add docs and types --- docs/en/README.md | 1 + docs/en/SUMMARY.md | 1 + docs/en/api/README.md | 1 + docs/en/api/renderToString.md | 103 ++++++++++++++++++ flow/modules.flow.js | 4 + scripts/test-compat.sh | 2 +- src/index.js | 4 +- src/{render.js => renderToString.js} | 15 +-- test/resources/test-utils.js | 35 +++--- .../components/TransitionGroupStub.spec.js | 1 - .../mounting-options/attachToDocument.spec.js | 14 ++- test/specs/mounting-options/attrs.spec.js | 4 +- test/specs/mounting-options/context.spec.js | 6 +- test/specs/mounting-options/localVue.spec.js | 4 +- test/specs/mounting-options/mocks.spec.js | 10 +- test/specs/mounting-options/provide.spec.js | 6 +- test/specs/mounting-options/slots.spec.js | 43 ++++---- test/specs/mounting-options/stubs.spec.js | 37 ++++--- test/specs/wrapper-array/hasStyle.spec.js | 1 - test/specs/wrapper/hasStyle.spec.js | 1 - types/index.d.ts | 5 + types/test/renderToString.ts | 47 ++++++++ 22 files changed, 260 insertions(+), 85 deletions(-) create mode 100644 docs/en/api/renderToString.md rename src/{render.js => renderToString.js} (57%) create mode 100644 types/test/renderToString.ts diff --git a/docs/en/README.md b/docs/en/README.md index cb1468fcd..84919dbc2 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -18,6 +18,7 @@ * [API](api/README.md) * [mount](api/mount.md) * [shallow](api/shallow.md) + * [renderToString](api/renderToString.md) * [Mounting Options](api/options.md) - [context](api/options.md#context) - [slots](api/options.md#slots) diff --git a/docs/en/SUMMARY.md b/docs/en/SUMMARY.md index 0a5379876..f3c276469 100644 --- a/docs/en/SUMMARY.md +++ b/docs/en/SUMMARY.md @@ -14,6 +14,7 @@ * [API](api/README.md) * [mount](api/mount.md) * [shallow](api/shallow.md) + * [renderToString](api/renderToString.md) * [Mounting Options](api/options.md) - [context](api/options.md#context) - [slots](api/options.md#slots) diff --git a/docs/en/api/README.md b/docs/en/api/README.md index e0bce900d..d636709b0 100644 --- a/docs/en/api/README.md +++ b/docs/en/api/README.md @@ -2,6 +2,7 @@ * [mount](./mount.md) * [shallow](./shallow.md) +* [renderToString](./renderToString.md) * [Mounting Options](./options.md) - [context](./options.md#context) - [slots](./options.md#slots) diff --git a/docs/en/api/renderToString.md b/docs/en/api/renderToString.md new file mode 100644 index 000000000..4955c616a --- /dev/null +++ b/docs/en/api/renderToString.md @@ -0,0 +1,103 @@ +# `renderToString(component {, options}])` + +- **Arguments:** + + - `{Component} component` + - `{Object} options` + - `{Object} context` + - `{Array|Component} children` + - `{Object} slots` + - `{Array|Component|String} default` + - `{Array|Component|String} named` + - `{Object} mocks` + - `{Object|Array} stubs` + - `{Vue} localVue` + +- **Returns:** `{string}` + +- **Options:** + +See [options](./options.md) + +- **Usage:** + +Renders a component to HTML. + +`renderToString` uses [`vue-server-renderer`](https://ssr.vuejs.org/en/basic.html) under the hood, to render a component to HTML. + +**Without options:** + +```js +import { renderToString } from '@vue/test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +describe('Foo', () => { + it('renders a div', () => { + const renderedString = renderToString(Foo) + expect(renderedString).toContain('
') + }) +}) +``` + +**With Vue options:** + +```js +import { renderToString } from '@vue/test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +describe('Foo', () => { + it('renders a div', () => { + const renderedString = renderToString(Foo, { + propsData: { + color: 'red' + } + }) + expect(renderedString).toContain('red') + }) +}) +``` + +**Default and named slots:** + +```js +import { renderToString } from '@vue/test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' +import Bar from './Bar.vue' +import FooBar from './FooBar.vue' + +describe('Foo', () => { + it('renders a div', () => { + const renderedString = renderToString(Foo, { + slots: { + default: [Bar, FooBar], + fooBar: FooBar, // Will match , + foo: '
' + } + }) + expect(renderedString).toContain('
') + }) +}) +``` + +**Stubbing global properties:** + +```js +import { renderToString } from '@vue/test-utils' +import { expect } from 'chai' +import Foo from './Foo.vue' + +describe('Foo', () => { + it('renders a div', () => { + const $route = { path: 'http://www.example-path.com' } + const renderedString = renderToString(Foo, { + mocks: { + $route + } + }) + expect(renderedString).toContain($route.path) + }) +}) +``` diff --git a/flow/modules.flow.js b/flow/modules.flow.js index 730828917..eb193125e 100644 --- a/flow/modules.flow.js +++ b/flow/modules.flow.js @@ -15,3 +15,7 @@ declare module 'lodash/cloneDeep' { declare module 'vue-template-compiler' { declare module.exports: any; } + +declare module 'vue-server-renderer' { + declare module.exports: any; +} diff --git a/scripts/test-compat.sh b/scripts/test-compat.sh index 6f6d94ed4..79e12ee23 100755 --- a/scripts/test-compat.sh +++ b/scripts/test-compat.sh @@ -4,7 +4,7 @@ set -e test_version_number(){ echo "running unit tests with Vue $1" - yarn add vue@$1 vue-template-compiler@$1 + yarn add vue@$1 vue-template-compiler@$1 vue-server-renderer@$1 yarn test:unit yarn test:unit:karma } diff --git a/src/index.js b/src/index.js index 92d9853da..bae2ffc52 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,6 @@ import shallow from './shallow' import mount from './mount' -import render from './render' +import renderToString from './renderToString' import createLocalVue from './create-local-vue' import TransitionStub from './components/TransitionStub' import TransitionGroupStub from './components/TransitionGroupStub' @@ -12,7 +12,7 @@ export default { config, mount, shallow, - render, + renderToString, TransitionStub, TransitionGroupStub, RouterLinkStub diff --git a/src/render.js b/src/renderToString.js similarity index 57% rename from src/render.js rename to src/renderToString.js index fec5c3267..a05f38625 100644 --- a/src/render.js +++ b/src/renderToString.js @@ -3,28 +3,29 @@ import Vue from 'vue' import createInstance from './lib/create-instance' import './lib/polyfills/object-assign-polyfill' -const renderer = require('vue-server-renderer').createRenderer() import { throwError } from './lib/util' Vue.config.productionTip = false Vue.config.devtools = false -export default function render (component: Component, options: Options = {}): VueWrapper { +export default function renderToString (component: Component, options: Options = {}): string { + const renderer = require('vue-server-renderer').createRenderer() // Remove cached constructor delete component._Ctor if (options.attachToDocument) { - throwError('you cannot use attachToDocument with render') + throwError('you cannot use attachToDocument with renderToString') } const vm = createInstance(component, options) - let string + let renderedString = '' + renderer.renderToString(vm, (err, res) => { if (err) { - throwError(err) + console.log(err) } - string = res + renderedString = res }) - return string + return renderedString } diff --git a/test/resources/test-utils.js b/test/resources/test-utils.js index c57c9d988..f015815bd 100644 --- a/test/resources/test-utils.js +++ b/test/resources/test-utils.js @@ -1,7 +1,7 @@ /* global describe, it*/ import Vue from 'vue' -import { shallow, mount, render } from '~vue-test-utils' +import { shallow, mount, renderToString } from '~vue-test-utils' export const vueVersion = Number(`${Vue.version.split('.')[0]}.${Vue.version.split('.')[1]}`) @@ -21,38 +21,43 @@ export function functionalSFCsSupported () { return vueVersion >= 2.5 } +const shallowAndMount = [mount, shallow] +const shallowMountAndRender = (navigator.userAgent.includes && navigator.userAgent.includes('jsdom')) + ? [mount, shallow, renderToString] + : [mount, shallow] + export function describeWithShallowAndMount (spec, cb) { - ;[mount, shallow].forEach(method => { + shallowAndMount.forEach(method => { describe(`${spec} with ${method.name}`, () => cb(method)) }) } -export function describeWithMountingMethods (spec, cb) { - ;[mount, shallow, render].forEach(method => { - describe(`${spec} with ${method.name}`, () => cb(method)) +describeWithShallowAndMount.skip = function (spec, cb) { + shallowAndMount.forEach(method => { + describe.skip(`${spec} with ${method.name}`, () => cb(method)) }) } -describeWithMountingMethods.skip = function (spec, cb) { - ;[mount, shallow, render].forEach(method => { - describe.skip(`${spec} with ${method.name}`, () => cb(method)) +describeWithShallowAndMount.only = function (spec, cb) { + shallowAndMount.forEach(method => { + describe.only(`${spec} with ${method.name}`, () => cb(method)) }) } -describeWithMountingMethods.only = function (spec, cb) { - ;[mount, shallow, render].forEach(method => { - describe.only(`${spec} with ${method.name}`, () => cb(method)) +export function describeWithMountingMethods (spec, cb) { + shallowMountAndRender.forEach(method => { + describe(`${spec} with ${method.name}`, () => cb(method)) }) } -describeWithShallowAndMount.skip = function (spec, cb) { - ;[mount, shallow].forEach(method => { +describeWithMountingMethods.skip = function (spec, cb) { + shallowMountAndRender.forEach(method => { describe.skip(`${spec} with ${method.name}`, () => cb(method)) }) } -describeWithShallowAndMount.only = function (spec, cb) { - ;[mount, shallow].forEach(method => { +describeWithMountingMethods.only = function (spec, cb) { + shallowMountAndRender.forEach(method => { describe.only(`${spec} with ${method.name}`, () => cb(method)) }) } diff --git a/test/specs/components/TransitionGroupStub.spec.js b/test/specs/components/TransitionGroupStub.spec.js index b1f071bae..d94a04741 100644 --- a/test/specs/components/TransitionGroupStub.spec.js +++ b/test/specs/components/TransitionGroupStub.spec.js @@ -22,7 +22,6 @@ describe('TransitionGroupStub', () => { }), watch: { someWatchedData (newData) { - console.log('asd') this.someData = newData } }, diff --git a/test/specs/mounting-options/attachToDocument.spec.js b/test/specs/mounting-options/attachToDocument.spec.js index 81df5045c..9d4fa595f 100644 --- a/test/specs/mounting-options/attachToDocument.spec.js +++ b/test/specs/mounting-options/attachToDocument.spec.js @@ -1,6 +1,6 @@ import { compileToFunctions } from 'vue-template-compiler' import { describeWithShallowAndMount } from '~resources/test-utils' -import { render } from '~vue-test-utils' +import { renderToString } from '~vue-test-utils' describeWithShallowAndMount('options.attachToDocument', (mountingMethod) => { it('returns VueWrapper with attachedToDocument set to true when passed attachToDocument in options', () => { @@ -10,11 +10,15 @@ describeWithShallowAndMount('options.attachToDocument', (mountingMethod) => { }) }) -describe('options.attachToDocument with render', () => { - it('throws error that render does not accept attachToDocument', () => { +describe('options.attachToDocument with renderToString', () => { + it('throws error that renderToString does not accept attachToDocument', () => { + // renderToString can only be run in node + if (!(navigator.userAgent.includes && navigator.userAgent.includes('jsdom'))) { + return + } const compiled = compileToFunctions('
') - const fn = () => render(compiled, { attachToDocument: true }) - const message = '[vue-test-utils]: you cannot use attachToDocument with render' + const fn = () => renderToString(compiled, { attachToDocument: true }) + const message = '[vue-test-utils]: you cannot use attachToDocument with renderToString' expect(fn).to.throw().with.property('message', message) }) }) diff --git a/test/specs/mounting-options/attrs.spec.js b/test/specs/mounting-options/attrs.spec.js index 149181a4a..7acb7a3fd 100644 --- a/test/specs/mounting-options/attrs.spec.js +++ b/test/specs/mounting-options/attrs.spec.js @@ -6,7 +6,7 @@ import { } from '~resources/test-utils' describeWithMountingMethods('options.attrs', (mountingMethod) => { - itSkipIf(mountingMethod.name === 'render', + itSkipIf(mountingMethod.name === 'renderToString', 'handles inherit attrs', () => { if (!attrsSupported()) return const wrapper = mountingMethod(compileToFunctions('

'), { @@ -19,7 +19,7 @@ describeWithMountingMethods('options.attrs', (mountingMethod) => { expect(wrapper.vm.$attrs.anAttr).to.equal('an attribute') }) - itSkipIf(mountingMethod.name === 'render', + itSkipIf(mountingMethod.name === 'renderToString', 'defines attrs as empty object even when not passed', () => { const wrapper = mountingMethod(compileToFunctions('

')) expect(wrapper.vm.$attrs).to.deep.equal({}) diff --git a/test/specs/mounting-options/context.spec.js b/test/specs/mounting-options/context.spec.js index 4518eec68..3dc1e8051 100644 --- a/test/specs/mounting-options/context.spec.js +++ b/test/specs/mounting-options/context.spec.js @@ -68,7 +68,7 @@ describeWithMountingMethods('options.context', (mountingMethod) => { render: (h, { props }) => h('div', props.testProp) } const wrapper = mountingMethod(Component) - const HTML = mountingMethod.name === 'render' + const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() expect(HTML).to.contain(defaultValue) @@ -86,7 +86,7 @@ describeWithMountingMethods('options.context', (mountingMethod) => { children: ['render text'] } }) - const HTML = mountingMethod.name === 'render' + const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() expect(HTML).to.contain('render text') @@ -104,7 +104,7 @@ describeWithMountingMethods('options.context', (mountingMethod) => { children: [h => h('div', 'render component')] } }) - const HTML = mountingMethod.name === 'render' + const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() expect(HTML).to.contain('render component') diff --git a/test/specs/mounting-options/localVue.spec.js b/test/specs/mounting-options/localVue.spec.js index f7f68a6a0..cc69b8c2f 100644 --- a/test/specs/mounting-options/localVue.spec.js +++ b/test/specs/mounting-options/localVue.spec.js @@ -14,12 +14,12 @@ describeWithMountingMethods('options.localVue', (mountingMethod) => { localVue: localVue, mocks: { test: 'some value' } }) - const HTML = mountingMethod.name === 'render' + const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() expect(HTML).to.contain('some value') const freshWrapper = mountingMethod(TestComponent) - const freshHTML = mountingMethod.name === 'render' + const freshHTML = mountingMethod.name === 'renderToString' ? freshWrapper : freshWrapper.html() expect(freshHTML).to.not.contain('some value') diff --git a/test/specs/mounting-options/mocks.spec.js b/test/specs/mounting-options/mocks.spec.js index 5e2fd0128..e2bb8fac5 100644 --- a/test/specs/mounting-options/mocks.spec.js +++ b/test/specs/mounting-options/mocks.spec.js @@ -24,7 +24,7 @@ describeWithMountingMethods('options.mocks', (mountingMethod) => { $route } }) - const HTML = mountingMethod.name === 'render' + const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() expect(HTML).contains('true') @@ -32,7 +32,7 @@ describeWithMountingMethods('options.mocks', (mountingMethod) => { }) // render returns a string so reactive does not apply - itDoNotRunIf(mountingMethod.name === 'render', + itDoNotRunIf(mountingMethod.name === 'renderToString', 'adds variables as reactive properties to vm when passed', () => { const stub = sinon.stub() const $reactiveMock = { value: 'value' } @@ -72,7 +72,7 @@ describeWithMountingMethods('options.mocks', (mountingMethod) => { }, { mocks: { $store: { state: { count, foo: {}}}} }) - const HTML = mountingMethod.name === 'render' + const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() expect(HTML).contains(count) @@ -91,13 +91,13 @@ describeWithMountingMethods('options.mocks', (mountingMethod) => { mocks: { $store: { state: { count, foo: {}}}}, localVue }) - const HTML = mountingMethod.name === 'render' + const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() expect(HTML).contains(count) }) - itDoNotRunIf(mountingMethod.name === 'render', + itDoNotRunIf(mountingMethod.name === 'renderToString', 'does not affect global vue class when passed as mocks object', () => { const $store = { store: true } const wrapper = mountingMethod(Component, { diff --git a/test/specs/mounting-options/provide.spec.js b/test/specs/mounting-options/provide.spec.js index 85f375e5a..b08163dd3 100644 --- a/test/specs/mounting-options/provide.spec.js +++ b/test/specs/mounting-options/provide.spec.js @@ -13,7 +13,7 @@ describeWithMountingMethods('options.provide', (mountingMethod) => { const wrapper = mountingMethod(ComponentWithInject, { provide: { fromMount: 'objectValue' } }) - const HTML = mountingMethod.name === 'render' + const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() expect(HTML).to.contain('objectValue') @@ -28,13 +28,13 @@ describeWithMountingMethods('options.provide', (mountingMethod) => { } } }) - const HTML = mountingMethod.name === 'render' + const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() expect(HTML).to.contain('functionValue') }) - itDoNotRunIf(!injectSupported() || mountingMethod.name === 'render', + itDoNotRunIf(!injectSupported() || mountingMethod.name === 'renderToString', 'supports beforeCreate in component', () => { if (!injectSupported()) return diff --git a/test/specs/mounting-options/slots.spec.js b/test/specs/mounting-options/slots.spec.js index 816037410..1e6dbbf07 100644 --- a/test/specs/mounting-options/slots.spec.js +++ b/test/specs/mounting-options/slots.spec.js @@ -22,8 +22,7 @@ describeWithMountingMethods('options.slots', (mountingMethod) => { it('mounts component with default slot if passed component in slot object', () => { const wrapper = mountingMethod(ComponentWithSlots, { slots: { default: Component }}) - console.log(mountingMethod.name) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).contains('

') } else { expect(wrapper.contains(Component)).to.equal(true) @@ -32,7 +31,7 @@ describeWithMountingMethods('options.slots', (mountingMethod) => { it('mounts component with default slot if passed component in array in slot object', () => { const wrapper = mountingMethod(ComponentWithSlots, { slots: { default: [Component] }}) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).contains('
') } else { expect(wrapper.contains(Component)).to.equal(true) @@ -42,7 +41,7 @@ describeWithMountingMethods('options.slots', (mountingMethod) => { it('mounts component with default slot if passed object with template prop in slot object', () => { const compiled = compileToFunctions('
') const wrapper = mountingMethod(ComponentWithSlots, { slots: { default: [compiled] }}) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).contains('div id="div"') } else { expect(wrapper.contains('#div')).to.equal(true) @@ -51,7 +50,7 @@ describeWithMountingMethods('options.slots', (mountingMethod) => { it('mounts component with default slot if passed string in slot object', () => { const wrapper = mountingMethod(ComponentWithSlots, { slots: { default: '' }}) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).contains(' { return } const wrapper = mountingMethod(ComponentAsAClass, { slots: { default: '' }}) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).contains(' { }) it('mounts component with default slot if passed string in slot object', () => { - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { return } const wrapper1 = mountingMethod(ComponentWithSlots, { slots: { default: 'foo123{{ foo }}' }}) @@ -120,7 +119,7 @@ describeWithMountingMethods('options.slots', (mountingMethod) => { it('mounts component with default slot if passed string in slot array object', () => { const wrapper = mountingMethod(ComponentWithSlots, { slots: { default: [''] }}) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).contains(' { it('mounts component with default slot if passed string in slot text array object', () => { const wrapper = mountingMethod(ComponentWithSlots, { slots: { default: ['{{ foo }}1', 'bar'] }}) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).contains('
bar1bar
') } else { expect(wrapper.find('main').html()).to.equal('
bar1bar
') @@ -159,7 +158,7 @@ describeWithMountingMethods('options.slots', (mountingMethod) => { footer: [Component] } }) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).contains('
') } else { expect(wrapper.findAll(Component).length).to.equal(2) @@ -172,7 +171,7 @@ describeWithMountingMethods('options.slots', (mountingMethod) => { header: Component } }) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).contains('
') } else { expect(wrapper.findAll(Component).length).to.equal(1) @@ -187,8 +186,9 @@ describeWithMountingMethods('options.slots', (mountingMethod) => { render: (h, ctx) => h('div', ctx.data, ctx.slots().default) } const wrapper = mountingMethod(TestComponent, { slots: { default: Component }}) - if (mountingMethod.name === 'render') { - expect(wrapper).contains('
') + if (mountingMethod.name === 'renderToString') { + const renderedAttribute = vueVersion < 2.3 ? 'server-rendered' : 'data-server-rendered' + expect(wrapper).contains(`
`) } else { expect(wrapper.contains(Component)).to.equal(true) } @@ -201,8 +201,9 @@ describeWithMountingMethods('options.slots', (mountingMethod) => { render: (h, ctx) => h('div', ctx.data, ctx.slots().default) } const wrapper = mountingMethod(TestComponent, { slots: { default: [Component] }}) - if (mountingMethod.name === 'render') { - expect(wrapper).contains('
') + if (mountingMethod.name === 'renderToString') { + const renderedAttribute = vueVersion < 2.3 ? 'server-rendered' : 'data-server-rendered' + expect(wrapper).contains(`
`) } else { expect(wrapper.contains(Component)).to.equal(true) } @@ -216,7 +217,7 @@ describeWithMountingMethods('options.slots', (mountingMethod) => { } const compiled = compileToFunctions('
') const wrapper = mountingMethod(TestComponent, { slots: { default: [compiled] }}) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).contains('
') } else { expect(wrapper.contains('#div')).to.equal(true) @@ -230,7 +231,7 @@ describeWithMountingMethods('options.slots', (mountingMethod) => { render: (h, ctx) => h('div', ctx.data, ctx.slots().default) } const wrapper = mountingMethod(TestComponent, { slots: { default: '' }}) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).contains(' { render: (h, ctx) => h('div', {}, ctx.slots().named) } const wrapper = mountingMethod(TestComponent, { slots: { named: Component }}) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).contains('
') } else { expect(wrapper.contains(Component)).to.equal(true) @@ -256,7 +257,7 @@ describeWithMountingMethods('options.slots', (mountingMethod) => { render: (h, ctx) => h('div', {}, ctx.slots().named) } const wrapper = mountingMethod(TestComponent, { slots: { named: [Component] }}) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).contains('
') } else { expect(wrapper.contains(Component)).to.equal(true) @@ -269,7 +270,7 @@ describeWithMountingMethods('options.slots', (mountingMethod) => { render: (h, ctx) => h('div', {}, ctx.slots().named) } const wrapper = mountingMethod(TestComponent, { slots: { named: '' }}) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).contains(' { render: (h, ctx) => h('div', {}, ctx.slots().named) } const wrapper = mountingMethod(TestComponent, { slots: { named: [''] }}) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).contains(' { ChildComponent: '
' } }) - if (mountingMethod.name === 'render') { + if (mountingMethod.name === 'renderToString') { expect(wrapper).to.contain('"stub"') } else { expect(wrapper.findAll('.stub').length).to.equal(1) @@ -56,7 +56,7 @@ describeWithMountingMethods('options.stub', (mountingMethod) => { } }) - itDoNotRunIf(mountingMethod.name === 'render', + itDoNotRunIf(mountingMethod.name === 'renderToString', 'replaces component with a component', () => { const wrapper = mountingMethod(ComponentWithChild, { stubs: { @@ -81,7 +81,7 @@ describeWithMountingMethods('options.stub', (mountingMethod) => { }) itDoNotRunIf(mountingMethod.name === 'shallow' || - mountingMethod.name === 'render', + mountingMethod.name === 'renderToString', 'does not modify component directly', () => { const wrapper = mountingMethod(ComponentWithNestedChildren, { stubs: { @@ -103,7 +103,7 @@ describeWithMountingMethods('options.stub', (mountingMethod) => { 'registered-component': Component } }) - const HTML = mountingMethod.name === 'render' + const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() expect(HTML).to.contain('
') @@ -111,25 +111,30 @@ describeWithMountingMethods('options.stub', (mountingMethod) => { it('stubs components with dummy when passed as an array', () => { const ComponentWithGlobalComponent = { - render: h => h('registered-component') + render: h => h('div', [h('registered-component')]) } - mountingMethod(ComponentWithGlobalComponent, { + const wrapper = mountingMethod(ComponentWithGlobalComponent, { stubs: ['registered-component'] }) - - expect(warn.called).to.equal(false) + const HTML = mountingMethod.name === 'renderToString' + ? wrapper + : wrapper.html() + expect(HTML).to.contain('') }) it('stubs components with dummy when passed a boolean', () => { const ComponentWithGlobalComponent = { - render: h => h('registered-component') + render: h => h('div', [h('registered-component')]) } - mountingMethod(ComponentWithGlobalComponent, { + const wrapper = mountingMethod(ComponentWithGlobalComponent, { stubs: { 'registered-component': true } }) - expect(warn.called).to.equal(false) + const HTML = mountingMethod.name === 'renderToString' + ? wrapper + : wrapper.html() + expect(HTML).to.contain('') }) it('stubs components with dummy when passed as an array', () => { @@ -172,7 +177,7 @@ describeWithMountingMethods('options.stub', (mountingMethod) => { stubs: { ChildComponent: false }}) - const HTML = mountingMethod.name === 'render' + const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() expect(HTML).to.contain('
') @@ -202,7 +207,7 @@ describeWithMountingMethods('options.stub', (mountingMethod) => { }, localVue }) - const HTML = mountingMethod.name === 'render' + const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() expect(HTML).to.contain('
') @@ -228,7 +233,7 @@ describeWithMountingMethods('options.stub', (mountingMethod) => { }, localVue }) - const HTML = mountingMethod.name === 'render' + const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() expect(HTML).to.contain('') @@ -252,7 +257,7 @@ describeWithMountingMethods('options.stub', (mountingMethod) => { localVue }) - const HTML = mountingMethod.name === 'render' + const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() expect(HTML).to.contain('
') @@ -278,7 +283,7 @@ describeWithMountingMethods('options.stub', (mountingMethod) => { 'stub-component': StubComponent } }) - const HTML = mountingMethod.name === 'render' + const HTML = mountingMethod.name === 'renderToString' ? wrapper : wrapper.html() expect(HTML).contains('No render function') diff --git a/test/specs/wrapper-array/hasStyle.spec.js b/test/specs/wrapper-array/hasStyle.spec.js index 3b76a8700..87d4cc0c1 100644 --- a/test/specs/wrapper-array/hasStyle.spec.js +++ b/test/specs/wrapper-array/hasStyle.spec.js @@ -13,7 +13,6 @@ describe('hasStyle', () => { if (navigator.userAgent.includes && navigator.userAgent.includes('jsdom')) { return } - console.log(navigator.userAgent.includes('jsdom')) const wrapper = mount(ComponentWithStyle) expect(wrapper.findAll('div').hasStyle('color', 'red')).to.equal(true) }) diff --git a/test/specs/wrapper/hasStyle.spec.js b/test/specs/wrapper/hasStyle.spec.js index e74101c03..57a7c4f05 100644 --- a/test/specs/wrapper/hasStyle.spec.js +++ b/test/specs/wrapper/hasStyle.spec.js @@ -13,7 +13,6 @@ describeWithShallowAndMount('hasStyle', (mountingMethod) => { if (navigator.userAgent.includes && navigator.userAgent.includes('jsdom')) { return } - console.log(navigator.userAgent.includes('jsdom')) const wrapper = mountingMethod(ComponentWithStyle) expect(wrapper.find('div').hasStyle('color', 'red')).to.equal(true) }) diff --git a/types/index.d.ts b/types/index.d.ts index 066075b9f..5a169c6d6 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -138,5 +138,10 @@ export declare function shallow (component: VueClass, options? export declare function shallow (component: ComponentOptions, options?: ThisTypedShallowOptions): Wrapper export declare function shallow (component: FunctionalComponentOptions, options?: ShallowOptions): Wrapper + +export declare function renderToString (component: VueClass, options?: ThisTypedShallowOptions): string +export declare function renderToString (component: ComponentOptions, options?: ThisTypedShallowOptions): string +export declare function renderToString (component: FunctionalComponentOptions, options?: ShallowOptions): string + export declare let TransitionStub: Component | string | true export declare let TransitionGroupStub: Component | string | true diff --git a/types/test/renderToString.ts b/types/test/renderToString.ts new file mode 100644 index 000000000..4e2c47cd5 --- /dev/null +++ b/types/test/renderToString.ts @@ -0,0 +1,47 @@ +import Vuex from 'vuex' +import { mount, renderToString, createLocalVue } from '../' +import { normalOptions, functionalOptions, Normal, ClassComponent } from './resources' + +/** + * Should create wrapper vm based on (function) component options or constructors + * The users can specify component type via the type parameter + */ +const normalWrapper = mount(normalOptions) +const normalFoo: string = normalWrapper.vm.foo + +const classWrapper = mount(ClassComponent) +const classFoo: string = classWrapper.vm.bar + +const functinalWrapper = mount(functionalOptions) + +/** + * Test for mount options + */ +const localVue = createLocalVue() +localVue.use(Vuex) + +const store = new Vuex.Store({}) + +renderToString(ClassComponent, { + localVue, + mocks: { + $store: store + }, + slots: { + default: `
Foo
`, + foo: [normalOptions, functionalOptions], + bar: ClassComponent + }, + stubs: { + foo: normalOptions, + bar: functionalOptions, + baz: ClassComponent, + qux: `
Test
` + }, + attrs: { + attribute: 'attr' + }, + listeners: { + listener: () => {} + } +}) From b21d5ab972935e38ce6bc565a9abfae15296a7e8 Mon Sep 17 00:00:00 2001 From: eddyerburgh Date: Mon, 19 Feb 2018 18:08:35 +0000 Subject: [PATCH 3/9] Throw error if not in node in renderToString --- src/lib/util.js | 6 ++++++ src/renderToString.js | 4 ++++ test/resources/test-utils.js | 4 +++- test/setup/karma.conf.js | 4 ++-- test/setup/loadTests.js | 3 +++ test/setup/webpack.test.config.js | 5 ++++- .../mounting-options/attachToDocument.spec.js | 7 +++++-- test/specs/renderToString.spec.js | 15 +++++++++++++++ 8 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 test/setup/loadTests.js create mode 100644 test/specs/renderToString.spec.js diff --git a/src/lib/util.js b/src/lib/util.js index 153f468ed..cf785a300 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -21,3 +21,9 @@ export const capitalize = (str: string): string => str.charAt(0).toUpperCase() + */ const hyphenateRE = /\B([A-Z])/g export const hyphenate = (str: string): string => str.replace(hyphenateRE, '-$1').toLowerCase() + +export const runningInNode = typeof require === 'function' && + typeof Buffer === 'function' && + typeof Buffer.byteLength === 'function' && + typeof Buffer.prototype !== 'undefined' && + typeof Buffer.prototype.write === 'function' diff --git a/src/renderToString.js b/src/renderToString.js index a05f38625..845d2c8d9 100644 --- a/src/renderToString.js +++ b/src/renderToString.js @@ -4,11 +4,15 @@ import Vue from 'vue' import createInstance from './lib/create-instance' import './lib/polyfills/object-assign-polyfill' import { throwError } from './lib/util' +import { runningInNode } from './lib/util' Vue.config.productionTip = false Vue.config.devtools = false export default function renderToString (component: Component, options: Options = {}): string { + if (runningInNode) { + throwError('renderToString must be run in node. It cannot be run in a browser') + } const renderer = require('vue-server-renderer').createRenderer() // Remove cached constructor delete component._Ctor diff --git a/test/resources/test-utils.js b/test/resources/test-utils.js index f015815bd..3770243c1 100644 --- a/test/resources/test-utils.js +++ b/test/resources/test-utils.js @@ -5,6 +5,8 @@ import { shallow, mount, renderToString } from '~vue-test-utils' export const vueVersion = Number(`${Vue.version.split('.')[0]}.${Vue.version.split('.')[1]}`) +export const isRunningJSDOM = navigator.userAgent.includes && navigator.userAgent.includes('jsdom') + export function injectSupported () { return vueVersion > 2.2 } @@ -22,7 +24,7 @@ export function functionalSFCsSupported () { } const shallowAndMount = [mount, shallow] -const shallowMountAndRender = (navigator.userAgent.includes && navigator.userAgent.includes('jsdom')) +const shallowMountAndRender = isRunningJSDOM ? [mount, shallow, renderToString] : [mount, shallow] diff --git a/test/setup/karma.conf.js b/test/setup/karma.conf.js index 7777394a2..e011b65dd 100644 --- a/test/setup/karma.conf.js +++ b/test/setup/karma.conf.js @@ -7,10 +7,10 @@ module.exports = function (config) { reporters: ['spec'], files: [ '../../node_modules/babel-polyfill/dist/polyfill.js', - '../specs/**/*.+(vue|js)' + 'loadtests.js' ], preprocessors: { - '../specs/**/*.+(vue|js)': ['webpack', 'sourcemap'] + 'loadtests.js': ['webpack', 'sourcemap'] }, client: { mocha: { timeout: 20000 }}, webpack: webpackConfig, diff --git a/test/setup/loadTests.js b/test/setup/loadTests.js new file mode 100644 index 000000000..9563fff0e --- /dev/null +++ b/test/setup/loadTests.js @@ -0,0 +1,3 @@ +const testsContext = require.context('../specs', true, /\.spec\.(js|vue)$/) + +testsContext.keys().forEach(testsContext) diff --git a/test/setup/webpack.test.config.js b/test/setup/webpack.test.config.js index 74f710f71..6660d520c 100644 --- a/test/setup/webpack.test.config.js +++ b/test/setup/webpack.test.config.js @@ -38,5 +38,8 @@ module.exports = { devtoolModuleFilenameTemplate: '[absolute-resource-path]', devtoolFallbackModuleFilenameTemplate: '[absolute-resource-path]?[hash]' }, - devtool: '#inline-cheap-module-source-map' + devtool: '#inline-cheap-module-source-map', + node: { + fs: 'empty' + } } diff --git a/test/specs/mounting-options/attachToDocument.spec.js b/test/specs/mounting-options/attachToDocument.spec.js index 9d4fa595f..500bd7b3b 100644 --- a/test/specs/mounting-options/attachToDocument.spec.js +++ b/test/specs/mounting-options/attachToDocument.spec.js @@ -1,5 +1,8 @@ import { compileToFunctions } from 'vue-template-compiler' -import { describeWithShallowAndMount } from '~resources/test-utils' +import { + describeWithShallowAndMount, + isRunningJSDOM +} from '~resources/test-utils' import { renderToString } from '~vue-test-utils' describeWithShallowAndMount('options.attachToDocument', (mountingMethod) => { @@ -13,7 +16,7 @@ describeWithShallowAndMount('options.attachToDocument', (mountingMethod) => { describe('options.attachToDocument with renderToString', () => { it('throws error that renderToString does not accept attachToDocument', () => { // renderToString can only be run in node - if (!(navigator.userAgent.includes && navigator.userAgent.includes('jsdom'))) { + if (!isRunningJSDOM) { return } const compiled = compileToFunctions('
') diff --git a/test/specs/renderToString.spec.js b/test/specs/renderToString.spec.js new file mode 100644 index 000000000..af2100a68 --- /dev/null +++ b/test/specs/renderToString.spec.js @@ -0,0 +1,15 @@ +import { renderToString } from '~vue-test-utils' +import Component from '~resources/components/component.vue' +import { + isRunningJSDOM, + itDoNotRunIf +} from '~resources/test-utils' + +describe('renderToString', () => { + itDoNotRunIf(isRunningJSDOM, + 'throws error when not run in node', () => { + const fn = () => renderToString(Component) + const message = '[vue-test-utils]: renderToString must be run in node. It cannot be run in a browser' + expect(fn).to.throw().with.property('message', message) + }) +}) From 1daf59ac9bced5c8f2a83aee4961d2a2a8c22423 Mon Sep 17 00:00:00 2001 From: eddyerburgh Date: Mon, 19 Feb 2018 18:32:34 +0000 Subject: [PATCH 4/9] fix flow errors --- src/lib/util.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lib/util.js b/src/lib/util.js index cf785a300..458d82c6f 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -24,6 +24,4 @@ export const hyphenate = (str: string): string => str.replace(hyphenateRE, '-$1' export const runningInNode = typeof require === 'function' && typeof Buffer === 'function' && - typeof Buffer.byteLength === 'function' && - typeof Buffer.prototype !== 'undefined' && - typeof Buffer.prototype.write === 'function' + typeof Buffer.byteLength === 'function' From 35263aa876a0f58e78e921af76cb37e0c9f5cb03 Mon Sep 17 00:00:00 2001 From: eddyerburgh Date: Mon, 19 Feb 2018 21:05:30 +0000 Subject: [PATCH 5/9] fix: change runningInNode check --- src/lib/util.js | 6 +++--- src/renderToString.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/util.js b/src/lib/util.js index 458d82c6f..8f45dcad2 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -22,6 +22,6 @@ export const capitalize = (str: string): string => str.charAt(0).toUpperCase() + const hyphenateRE = /\B([A-Z])/g export const hyphenate = (str: string): string => str.replace(hyphenateRE, '-$1').toLowerCase() -export const runningInNode = typeof require === 'function' && - typeof Buffer === 'function' && - typeof Buffer.byteLength === 'function' +export const runningInNode = + Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]' || + !process.browser diff --git a/src/renderToString.js b/src/renderToString.js index 845d2c8d9..3702d126b 100644 --- a/src/renderToString.js +++ b/src/renderToString.js @@ -10,7 +10,7 @@ Vue.config.productionTip = false Vue.config.devtools = false export default function renderToString (component: Component, options: Options = {}): string { - if (runningInNode) { + if (!runningInNode) { throwError('renderToString must be run in node. It cannot be run in a browser') } const renderer = require('vue-server-renderer').createRenderer() From a098f062afc83f6b092dafd0b67b2a5a4eef0b77 Mon Sep 17 00:00:00 2001 From: eddyerburgh Date: Mon, 19 Feb 2018 21:19:40 +0000 Subject: [PATCH 6/9] fix flow error --- src/lib/util.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/util.js b/src/lib/util.js index 8f45dcad2..a1fdfcfec 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -24,4 +24,5 @@ export const hyphenate = (str: string): string => str.replace(hyphenateRE, '-$1' export const runningInNode = Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]' || + // $FlowIgnore !process.browser From e3d91394cd697a6b98e2b0339b95801b9b568528 Mon Sep 17 00:00:00 2001 From: eddyerburgh Date: Mon, 19 Feb 2018 21:40:17 +0000 Subject: [PATCH 7/9] fix: remove isNode check --- src/lib/util.js | 5 ----- src/renderToString.js | 8 +++++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/lib/util.js b/src/lib/util.js index a1fdfcfec..153f468ed 100644 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -21,8 +21,3 @@ export const capitalize = (str: string): string => str.charAt(0).toUpperCase() + */ const hyphenateRE = /\B([A-Z])/g export const hyphenate = (str: string): string => str.replace(hyphenateRE, '-$1').toLowerCase() - -export const runningInNode = - Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]' || - // $FlowIgnore - !process.browser diff --git a/src/renderToString.js b/src/renderToString.js index 3702d126b..eb012ab2b 100644 --- a/src/renderToString.js +++ b/src/renderToString.js @@ -4,16 +4,18 @@ import Vue from 'vue' import createInstance from './lib/create-instance' import './lib/polyfills/object-assign-polyfill' import { throwError } from './lib/util' -import { runningInNode } from './lib/util' Vue.config.productionTip = false Vue.config.devtools = false export default function renderToString (component: Component, options: Options = {}): string { - if (!runningInNode) { + let renderer + try { + renderer = require('vue-server-renderer').createRenderer() + } catch (e) {} + if (!renderer) { throwError('renderToString must be run in node. It cannot be run in a browser') } - const renderer = require('vue-server-renderer').createRenderer() // Remove cached constructor delete component._Ctor From decc61be57becba73c0abe258ebf71087bf240f5 Mon Sep 17 00:00:00 2001 From: eddyerburgh Date: Mon, 19 Feb 2018 21:52:01 +0000 Subject: [PATCH 8/9] Fix flow error --- src/renderToString.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/renderToString.js b/src/renderToString.js index eb012ab2b..c040f88f2 100644 --- a/src/renderToString.js +++ b/src/renderToString.js @@ -13,6 +13,7 @@ export default function renderToString (component: Component, options: Options = try { renderer = require('vue-server-renderer').createRenderer() } catch (e) {} + if (!renderer) { throwError('renderToString must be run in node. It cannot be run in a browser') } @@ -27,6 +28,7 @@ export default function renderToString (component: Component, options: Options = let renderedString = '' + // $FlowIgnore renderer.renderToString(vm, (err, res) => { if (err) { console.log(err) From 74a14bf38993e1f3d8df82dec8e646a5e034e282 Mon Sep 17 00:00:00 2001 From: eddyerburgh Date: Mon, 19 Feb 2018 22:19:00 +0000 Subject: [PATCH 9/9] fix karma load-test caing --- test/setup/karma.conf.js | 4 ++-- test/setup/{loadTests.js => load-tests.js} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename test/setup/{loadTests.js => load-tests.js} (100%) diff --git a/test/setup/karma.conf.js b/test/setup/karma.conf.js index e011b65dd..17a9c0e7f 100644 --- a/test/setup/karma.conf.js +++ b/test/setup/karma.conf.js @@ -7,10 +7,10 @@ module.exports = function (config) { reporters: ['spec'], files: [ '../../node_modules/babel-polyfill/dist/polyfill.js', - 'loadtests.js' + 'load-tests.js' ], preprocessors: { - 'loadtests.js': ['webpack', 'sourcemap'] + 'load-tests.js': ['webpack', 'sourcemap'] }, client: { mocha: { timeout: 20000 }}, webpack: webpackConfig, diff --git a/test/setup/loadTests.js b/test/setup/load-tests.js similarity index 100% rename from test/setup/loadTests.js rename to test/setup/load-tests.js