Skip to content
This repository was archived by the owner on Dec 26, 2018. It is now read-only.

universal/isomorphic example #8

Closed
wagerfield opened this issue Jan 31, 2018 · 3 comments
Closed

universal/isomorphic example #8

wagerfield opened this issue Jan 31, 2018 · 3 comments

Comments

@wagerfield
Copy link

wagerfield commented Jan 31, 2018

How can I test Vue components in a node environment?

Jest provides a few mechanisms for setting the test environment to either jsdom (default) or node.

The simplest and most flexible way to do this is by adding a docblock comment to the top of a test file:

/**
 * @jest-environment node
 */

However, when doing so vue-test-utils throws the error:

[vue-test-utils]: window is undefined, vue-test-utils needs to be run in a browser environment.
You can run the tests in node using jsdom + jsdom-global.
See https://vue-test-utils.vuejs.org/en/guides/common-tips.html for more details.

My use case:

I have written a custom directive that performs different operations on the client and server.

I am using the Vue instance property $isServer to determine which function to call based on the environment that the directive is run in:

Vue.directive('universal', {
  bind(element, binding, vnode) {
    const context = vnode.context
    const handler = context.$isServer
      ? serverHandler
      : clientHandler
    handler(context)
  }
})

When run in the default jsdom test environment, $isServer is always false so I am only able to test the clientHandler branch of my directive.

How do I test the server branch of this directive?

@eddyerburgh
Copy link
Member

eddyerburgh commented Feb 3, 2018

As you found, we check that window is defined and throw an error if it's not. That's because mount and shallow create a component instance, which needs DOM methods like document.createElement, and document.createComment.

That said, we definitely need a way to test server-side code.

I'm closing this issue, but we should definitely carry this conversation on. Are you able to create a new feature request in vue-test-utils using the issue creator?

@wagerfield
Copy link
Author

Thanks for your response @eddyerburgh.

I managed to hack my way round the problem and test both the client and server branches of my logic by creating a helper that overrides prototype.$isServer of a localVue instance:

import { createLocalVue, mount } from 'vue-test-utils'

const setLocalVueEnv = (localVue, isServer) => {
  Object.defineProperty(localVue.prototype, '$isServer', {
    get: () => isServer
  })
}

const EnvTextComponent = {
  render(createElement) {
    const text = this.$isServer ? 'server' : 'client'
    return createElement('span', text)
  }
}

test('client env', () => {
  const isServer = false
  const localVue = createLocalVue()

  setLocalVueEnv(localVue, isServer) // not required obviously

  const wrapper = mount(EnvTextComponent, { localVue })
  expect(wrapper.vm.$isServer).toBe(isServer)
  expect(wrapper.text()).toBe('client')
})

test('server env', () => {
  const isServer = true
  const localVue = createLocalVue()

  setLocalVueEnv(localVue, isServer)

  const wrapper = mount(EnvTextComponent, { localVue })
  expect(wrapper.vm.$isServer).toBe(isServer)
  expect(wrapper.text()).toBe('server')
})

...perhaps passing some options to createLocalVue() would be a nice way of working around this?

const localVue = createLocalVue({ node: true }) // could use 'server' or 'isServer' here?
const wrapper = mount(SomeComponent, { localVue })

I will create a new feature request in vue-test-utils today.

@wagerfield
Copy link
Author

Done: vuejs/vue-test-utils#427

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants