-
Notifications
You must be signed in to change notification settings - Fork 668
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes #973 Fixes #994 Fixes #995 BREAKING CHANGE: The tag name rendered by snapshots will use the rendered component tag, rather than the registered component name
- Loading branch information
1 parent
7a1a49e
commit e1fd705
Showing
19 changed files
with
327 additions
and
309 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import { createStubFromComponent } from 'shared/create-component-stubs' | ||
import { resolveComponent, semVerGreaterThan } from 'shared/util' | ||
import { isReservedTag } from 'shared/validators' | ||
import { addHook } from './add-hook' | ||
import Vue from 'vue' | ||
|
||
const isWhitelisted = (el, whitelist) => resolveComponent(el, whitelist) | ||
const isAlreadyStubbed = (el, stubs) => stubs.has(el) | ||
const isDynamicComponent = cmp => typeof cmp === 'function' && !cmp.cid | ||
|
||
const CREATE_ELEMENT_ALIAS = semVerGreaterThan(Vue.version, '2.1.5') | ||
? '_c' | ||
: '_h' | ||
const LIFECYCLE_HOOK = semVerGreaterThan(Vue.version, '2.1.8') | ||
? 'beforeCreate' | ||
: 'beforeMount' | ||
|
||
function shouldExtend (component, _Vue) { | ||
return ( | ||
(typeof component === 'function' && !isDynamicComponent(component)) || | ||
(component && component.extends) | ||
) | ||
} | ||
|
||
function extend (component, _Vue) { | ||
const stub = _Vue.extend(component.options) | ||
stub.options.$_vueTestUtils_original = component | ||
return stub | ||
} | ||
|
||
function createStubIfNeeded (shouldStub, component, _Vue, el) { | ||
if (shouldStub) { | ||
return createStubFromComponent(component || {}, el) | ||
} | ||
|
||
if (shouldExtend(component, _Vue)) { | ||
return extend(component, _Vue) | ||
} | ||
} | ||
|
||
function shouldNotBeStubbed (el, whitelist, modifiedComponents) { | ||
return ( | ||
(typeof el === 'string' && isReservedTag(el)) || | ||
isWhitelisted(el, whitelist) || | ||
isAlreadyStubbed(el, modifiedComponents) | ||
) | ||
} | ||
|
||
function isConstructor (el) { | ||
return typeof el === 'function' | ||
} | ||
|
||
export function patchRender (_Vue, stubs, stubAllComponents) { | ||
// This mixin patches vm.$createElement so that we can stub all components | ||
// before they are rendered in shallow mode. We also need to ensure that | ||
// component constructors were created from the _Vue constructor. If not, | ||
// we must replace them with components created from the _Vue constructor | ||
// before calling the original $createElement. This ensures that components | ||
// have the correct instance properties and stubs when they are rendered. | ||
function patchRenderMixin () { | ||
const vm = this | ||
|
||
if (vm.$options.$_doNotStubChildren || vm._isFunctionalContainer) { | ||
return | ||
} | ||
|
||
const modifiedComponents = new Set() | ||
const originalCreateElement = vm.$createElement | ||
const originalComponents = vm.$options.components | ||
|
||
const createElement = (el, ...args) => { | ||
if (shouldNotBeStubbed(el, stubs, modifiedComponents)) { | ||
return originalCreateElement(el, ...args) | ||
} | ||
|
||
if (isConstructor(el)) { | ||
if (stubAllComponents) { | ||
const stub = createStubFromComponent(el, el.name || 'anonymous') | ||
return originalCreateElement(stub, ...args) | ||
} | ||
|
||
const Constructor = shouldExtend(el, _Vue) ? extend(el, _Vue) : el | ||
|
||
return originalCreateElement(Constructor, ...args) | ||
} | ||
|
||
if (typeof el === 'string') { | ||
let original = resolveComponent(el, originalComponents) | ||
|
||
if ( | ||
original && | ||
original.options && | ||
original.options.$_vueTestUtils_original | ||
) { | ||
original = original.options.$_vueTestUtils_original | ||
} | ||
|
||
if (isDynamicComponent(original)) { | ||
return originalCreateElement(el, ...args) | ||
} | ||
|
||
const stub = createStubIfNeeded(stubAllComponents, original, _Vue, el) | ||
|
||
if (stub) { | ||
vm.$options.components = { | ||
...vm.$options.components, | ||
[el]: stub | ||
} | ||
modifiedComponents.add(el) | ||
} | ||
} | ||
|
||
return originalCreateElement(el, ...args) | ||
} | ||
|
||
vm[CREATE_ELEMENT_ALIAS] = createElement | ||
vm.$createElement = createElement | ||
} | ||
|
||
addHook(_Vue.options, LIFECYCLE_HOOK, patchRenderMixin) | ||
} |
Oops, something went wrong.