Skip to content

Commit

Permalink
feat(stubs): render function props deterministically (#1834)
Browse files Browse the repository at this point in the history
  • Loading branch information
MitchLillie committed Apr 30, 2021
1 parent a1b4d05 commit 97fdf18
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 2 deletions.
27 changes: 25 additions & 2 deletions packages/create-instance/create-component-stubs.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
} from '../shared/validators'
import { compileTemplate } from '../shared/compile-template'

const FUNCTION_PLACEHOLDER = '[Function]'

function isVueComponentStub(comp): boolean {
return (comp && comp.template) || isVueComponent(comp)
}
Expand Down Expand Up @@ -116,13 +118,13 @@ export function createStubFromComponent(
? {
...context.data,
attrs: {
...context.props,
...shapeStubProps(context.props),
...context.data.attrs
}
}
: {
attrs: {
...this.$props
...shapeStubProps(this.$props)
}
},
context
Expand All @@ -136,6 +138,27 @@ export function createStubFromComponent(
}
}

function shapeStubProps(props) {
const shapedProps: Object = {}
for (const propName in props) {
if (typeof props[propName] === 'function') {
shapedProps[propName] = FUNCTION_PLACEHOLDER
continue
}

if (Array.isArray(props[propName])) {
shapedProps[propName] = props[propName].map(value => {
return typeof value === 'function' ? FUNCTION_PLACEHOLDER : value
})
continue
}

shapedProps[propName] = props[propName]
}

return shapedProps
}

// DEPRECATED: converts string stub to template stub.
function createStubFromString(templateString: string, name: string): Component {
warnDeprecated('Using a string for stubs')
Expand Down
65 changes: 65 additions & 0 deletions test/specs/mounting-options/stubs.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -639,4 +639,69 @@ describeWithShallowAndMount('options.stub', mountingMethod => {
)
config.showDeprecationWarnings = false
})

it('should render functions in props as a deterministic string', () => {
const ChildComponent = {
name: 'child-component',
props: {
foo: {
type: Function,
required: true
},
bar: {
type: Array,
required: true
},
qux: {
type: String,
required: true
}
},
template: '<div />'
}

const FunctionalChildComponent = {
...ChildComponent,
name: 'functional-child-component',
functional: true
}

const ParentComponent = {
components: {
ChildComponent,
FunctionalChildComponent
},
name: 'parent-component',
template: `
<div>
<child-component
:foo="foo"
:bar="bar"
:qux="qux" />
<functional-child-component
:foo="foo"
:bar="bar"
:qux="qux" />
</div>
`,
data() {
return {
foo: () => 42,
bar: [1, 'string', () => true],
qux: 'qux'
}
}
}

const wrapper = mountingMethod(ParentComponent, {
stubs: ['child-component', 'functional-child-component']
})

expect(wrapper.html()).toEqual(
`<div>\n` +
` <child-component-stub foo="[Function]" bar="1,string,[Function]" qux="qux"></child-component-stub>\n` +
` <functional-child-component-stub foo="[Function]" bar="1,string,[Function]" qux="qux"></functional-child-component-stub>\n` +
`</div>`
)
})
})

0 comments on commit 97fdf18

Please sign in to comment.