-
Notifications
You must be signed in to change notification settings - Fork 82
Update tests for slower load of async route components #1770
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,13 +18,24 @@ loadAsync() has a couple of benefits: | |
| - webpack magic comments will not be repeated across files. | ||
| */ | ||
|
|
||
| let loadingCount = 0; | ||
|
|
||
| const loader = (load) => { | ||
| const obj = { | ||
| loaded: false, | ||
| load: async () => { | ||
| const m = await load(); | ||
| obj.loaded = true; | ||
| return m; | ||
| loadingCount += 1; | ||
| try { | ||
| const m = await load(); | ||
| obj.loaded = true; | ||
| return m; | ||
| } catch (error) { | ||
| // eslint-disable-next-line no-console | ||
| if (import.meta.env.NODE_ENV === 'development') console.error(error); | ||
| throw error; | ||
| } finally { | ||
| loadingCount -= 1; | ||
| } | ||
| } | ||
| }; | ||
| return obj; | ||
|
|
@@ -209,10 +220,23 @@ const loaders = new Map() | |
| '../components/user/list.vue' | ||
| ))); | ||
|
|
||
| export const loadAsync = (name) => loaders.get(name).load; | ||
| export const loadedAsync = (name) => loaders.get(name).loaded; | ||
| const getLoader = (name) => { | ||
| if (!loaders.has(name)) throw new Error(`loader not found for ${name}`); | ||
| return loaders.get(name); | ||
| }; | ||
|
Comment on lines
+223
to
+226
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This part wasn't part of the original commit. I just added it when I rebased now. I added it because I removed some error-logging in test/util/http.js as part of resolving a merge conflict. |
||
|
|
||
| export const loadAsync = (name) => getLoader(name).load; | ||
| export const loadedAsync = (name) => getLoader(name).loaded; | ||
|
|
||
|
|
||
|
|
||
| //////////////////////////////////////////////////////////////////////////////// | ||
| // TEST UTILS | ||
|
|
||
| // These functions are exported for use in testing. | ||
|
|
||
| export const loadingAnyAsync = () => loadingCount !== 0; | ||
|
|
||
| // Exported for use in testing | ||
| export const setLoader = (name, load) => { | ||
| loaders.set(name, loader(load)); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -278,14 +278,14 @@ import { clone, identity, last, pick } from 'ramda'; | |
|
|
||
| import App from '../../src/components/app.vue'; | ||
|
|
||
| import { loadAsync, loadingAnyAsync } from '../../src/util/load-async'; | ||
| import { noop } from '../../src/util/util'; | ||
| import { routeProps } from '../../src/util/router'; | ||
|
|
||
| import createTestContainer from './container'; | ||
| import requestDataByComponent from './http/data'; | ||
| import testData from '../data'; | ||
| import * as commonTests from './http/common'; | ||
| import { loadAsyncCache } from './load-async'; | ||
| import { mockAxiosError, mockResponse } from './axios'; | ||
| import { mockRouter, setInstallLocation, testRouter } from './router'; | ||
| import { mount as lifecycleMount, withSetup } from './lifecycle'; | ||
|
|
@@ -295,20 +295,13 @@ import { wait, waitUntil } from './util'; | |
| const routeResolver = createTestContainer({ router: testRouter() }).router; | ||
| const resolveRoute = (location) => routeResolver.resolve(location); | ||
| // Returns the components associated with a route. If the route is lazy-loaded, | ||
| // any async component will be unwrapped from AsyncRoute. | ||
| // any async component will be unwrapped from AsyncRoute. If a component is | ||
| // async, only its name will be returned, not the full component. | ||
| const routeComponents = (route) => route.matched.map(routeRecord => { | ||
| const { asyncRoute } = routeRecord.meta; | ||
| if (asyncRoute == null) return routeRecord.components.default; | ||
|
|
||
| const m = loadAsyncCache.get(asyncRoute.componentName); | ||
| if (m == null) { | ||
| // eslint-disable-next-line no-console | ||
| console.error(`Component ${asyncRoute.componentName} was not found in the loadAsync() cache.`); | ||
| // eslint-disable-next-line no-console | ||
| console.error('The loadAsync() cache contains', loadAsyncCache.size, 'entries.'); | ||
| throw new Error('component not found in loadAsync() cache'); | ||
|
Comment on lines
-306
to
-309
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this error-logging existed back when I was working on Vitest: when rebasing these commits, I got a merge conflict in this area of the code. I think it makes sense to remove this error-logging, since |
||
| } | ||
| return m.default; | ||
| return asyncRoute == null | ||
| ? routeRecord.components.default | ||
| : { name: asyncRoute.componentName }; | ||
| }); | ||
|
|
||
| class MockHttp { | ||
|
|
@@ -384,8 +377,11 @@ class MockHttp { | |
| ? containerOption | ||
| : createTestContainer(containerOption)); | ||
|
|
||
| const mount = () => { | ||
| const wrapper = lifecycleMount(component, { ...options, container }); | ||
| const mount = async () => { | ||
| const loadedComponent = typeof component === 'string' | ||
| ? (await loadAsync(component)()).default | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of calling |
||
| : component; | ||
| const wrapper = lifecycleMount(loadedComponent, { ...options, container }); | ||
|
|
||
| if (throwIfEmit != null) { | ||
| const emitted = wrapper.emitted(); | ||
|
|
@@ -643,24 +639,24 @@ class MockHttp { | |
| : noop; | ||
|
|
||
| try { | ||
| const routeBefore = router != null ? router.currentRoute.value : null; | ||
| if (this._location != null) await router.push(this._location); | ||
| if (this._mount != null) { | ||
| this._component = this._mount(); | ||
| this._component = await this._mount(); | ||
| // Mounting may have triggered the initial navigation. | ||
| if (router != null) await router.isReady(); | ||
| } | ||
| // If there was a navigation, then we need to wait for any async | ||
| // components associated with the route to load. | ||
| await waitUntil(() => !loadingAnyAsync()); | ||
|
|
||
| if (this._request != null) { | ||
| // If there has been a navigation, then wait for any async components | ||
| // associated with the route to load. | ||
| if (router != null && router.currentRoute.value !== routeBefore) | ||
| await wait(); | ||
|
|
||
| this._checkStateBeforeRequest(); | ||
| await this._request(this._component); | ||
| } | ||
| } finally { | ||
| // Wait for any router navigation to finish. | ||
| if (router != null) await wait(); | ||
| await waitUntil(() => !loadingAnyAsync()); | ||
|
Comment on lines
+657
to
+659
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here, I think we're waiting for two things. That's why there's both
|
||
| // Wait for any responses to be processed. | ||
| await wait(); | ||
| if (pollWork != null) await waitUntil(() => pollWork(this._component)); | ||
|
|
@@ -951,7 +947,11 @@ const loadBottomComponent = (location, mountOptions, respondForOptions) => { | |
| const throwIfEmit = `${bottomComponent.name} emitted an event, but it is not expected to do so. In this case, root cannot be specified as false.`; | ||
|
|
||
| return mockHttp() | ||
| .mount(bottomComponent, fullMountOptions, throwIfEmit) | ||
| .mount( | ||
| bottomComponent.render != null ? bottomComponent : bottomComponent.name, | ||
| fullMountOptions, | ||
| throwIfEmit | ||
| ) | ||
| .modify(series => (respondForOptions !== false | ||
| ? series.respondForComponent(bottomComponent.name, respondForOptions) | ||
| : series)); | ||
|
|
||
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.
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.
I understand the
finallybelow: it's needed to decrementloadingCount. But I don't remember the point of thiscatch. Why is it useful toconsole.error()the error if we're also re-throwing it? Perhaps #1743 means that this part is unnecessary now.Also, the use of
import.meta.env.NODE_ENVseems a little unusual to me. What isNODE_ENVin the context of testing? Is it'development'? I assume so, because if not, this line seems kind of irrelevant to the rest of the work of the commit in which it was added.In most of the app, we use
buildModeinstead of something likeNODE_ENV. I guessbuildModeisn't available in the context of this file though, since it doesn't have access to the Frontendcontainerobject.Another thing I'm wondering: why
NODE_ENVinstead ofMODE?