-
Notifications
You must be signed in to change notification settings - Fork 668
fix: wrap extended child components #840
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 5 commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
3a476b3
Extend all extended components
eddyerburgh 06e3f6e
Support nested extended components
eddyerburgh e00e0d6
Initial implementation
eddyerburgh ff1d4aa
test: skip tests in Vue < 2.3, because of incomplete extended support
eddyerburgh 66dcac5
test: skip in Vue < 2.3
eddyerburgh 6b0343c
refactor: improve error message
eddyerburgh fe7452a
refactor: remove some details from comment
eddyerburgh b1c68fc
chore: merge
eddyerburgh a87d5e0
refactor: move stub logic to addStubs function
eddyerburgh 2f2fdf0
test: fix broken tests
eddyerburgh 9f60e66
fix: do not extend component in Vue < 2.3
eddyerburgh fe8f339
test: skip tests that rely on extended inheritance in Vue < 2.3
eddyerburgh a0d0252
fix: use correct check for vue version
eddyerburgh a30565b
refactor: extract compile from string logic
eddyerburgh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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,100 @@ | ||
import { warn } from 'shared/util' | ||
|
||
function createdFrom (extendOptions, componentOptions) { | ||
while (extendOptions) { | ||
if (extendOptions === componentOptions) { | ||
return true | ||
} | ||
if (extendOptions._vueTestUtilsRoot === componentOptions) { | ||
return true | ||
} | ||
extendOptions = extendOptions.extendOptions | ||
} | ||
} | ||
|
||
function resolveComponents (options = {}, components = {}) { | ||
let extendOptions = options.extendOptions | ||
while (extendOptions) { | ||
resolveComponents(extendOptions, components) | ||
extendOptions = extendOptions.extendOptions | ||
} | ||
let extendsFrom = options.extends | ||
while (extendsFrom) { | ||
resolveComponents(extendsFrom, components) | ||
extendsFrom = extendsFrom.extends | ||
} | ||
Object.keys(options.components || {}).forEach((c) => { | ||
components[c] = options.components[c] | ||
}) | ||
return components | ||
} | ||
|
||
function shouldExtend (component) { | ||
while (component) { | ||
if (component.extendOptions) { | ||
return true | ||
} | ||
component = component.extends | ||
} | ||
} | ||
|
||
// Components created with Vue.extend will not inherit from | ||
// a localVue constructor by default. To make sure they inherit | ||
// from a localVue constructor, we must create new components by | ||
// extending the original extended components from the localVue constructor. | ||
// The registered original extended components should only be | ||
// overwritten in the component that they are registered on. | ||
// We apply a global mixin that overwrites the components original | ||
// components with the extended components when they are created. | ||
export function extendExtendedComponents ( | ||
component, | ||
_Vue, | ||
logModifiedComponents, | ||
excludedComponents = { }, | ||
stubAllComponents = false | ||
) { | ||
const extendedComponents = Object.create(null) | ||
const components = resolveComponents(component) | ||
|
||
Object.keys(components).forEach(c => { | ||
const comp = components[c] | ||
const shouldExtendComponent = | ||
(shouldExtend(comp) && | ||
!excludedComponents[c]) || | ||
stubAllComponents | ||
if (shouldExtendComponent) { | ||
if (logModifiedComponents) { | ||
warn( | ||
`an extended child component <${c}> has been modified ` + | ||
`to ensure it has the correct instance properties. ` + | ||
`This means it is not possible to find the component ` + | ||
`with a component selector. To find the component, ` + | ||
`you must stub it manually using the stubs mounting ` + | ||
`option.` | ||
) | ||
} | ||
extendedComponents[c] = _Vue.extend(comp) | ||
} | ||
// If a component has been replaced with an extended component | ||
// all its child components must also be replaced. | ||
extendExtendedComponents( | ||
comp, | ||
_Vue, | ||
logModifiedComponents, | ||
{}, | ||
shouldExtendComponent | ||
) | ||
}) | ||
if (extendedComponents) { | ||
_Vue.mixin({ | ||
created () { | ||
if (createdFrom(this.constructor, component)) { | ||
Object.assign( | ||
this.$options.components, | ||
extendedComponents | ||
) | ||
} | ||
} | ||
}) | ||
} | ||
} |
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
couldn't
find({ name: 'foo' })
still work in this case? If so maybe that should be added here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it would, I'll add it.
This PR also makes your suggestion of searching by string name a lot more attractive, as it would solve this problem entirely 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would be nice 👍 Lately I (and my team) have decided on the following practice:
querySelector
APIfind(Component)
API.which I think is the most intuitive for onboarding people new to Vue and TDD.