diff --git a/packages/@ember/-internals/glimmer/tests/integration/application/engine-test.js b/packages/@ember/-internals/glimmer/tests/integration/application/engine-test.js
index 49f3499b046..b518a074f98 100644
--- a/packages/@ember/-internals/glimmer/tests/integration/application/engine-test.js
+++ b/packages/@ember/-internals/glimmer/tests/integration/application/engine-test.js
@@ -974,5 +974,64 @@ moduleFor(
assert.equal(error.message, 'Whoops! Something went wrong...');
});
}
+
+ ['@test visit() with `shouldRender: true` queryParams are properly deserialized for lazy routes'](
+ assert
+ ) {
+ assert.expect(2);
+
+ let hooks = [];
+
+ this.setupAppAndRoutableEngine(hooks);
+
+ this.add(
+ 'engine:blog',
+ Engine.extend({
+ Resolver: ModuleBasedTestResolver,
+
+ init() {
+ this._super(...arguments);
+ this.register(
+ 'controller:application',
+ Controller.extend({
+ queryParams: ['lazyQueryParam'],
+ })
+ );
+
+ this.register(
+ 'template:application',
+ compile('Engine
{{this.lazyQueryParam}}
{{outlet}}')
+ );
+
+ this.register(
+ 'route:application',
+ Route.extend({
+ queryParams: {
+ lazyQueryParam: {
+ defaultValue: null,
+ },
+ },
+ deserializeQueryParam() {
+ hooks.push('engine - deserialize query param');
+ return 'foo';
+ },
+ model() {
+ hooks.push('engine - application');
+ },
+ })
+ );
+ },
+ })
+ );
+
+ return this.visit('/blog?lazyQueryParam=bar', { shouldRender: true }).then(() => {
+ assert.deepEqual(
+ hooks,
+ ['application - application', 'engine - deserialize query param', 'engine - application'],
+ 'the expected hooks were fired'
+ );
+ assert.strictEqual(this.element.querySelector('.lazy-query-param').innerHTML, 'foo');
+ });
+ }
}
);
diff --git a/packages/@ember/-internals/routing/lib/system/route.ts b/packages/@ember/-internals/routing/lib/system/route.ts
index 1b295201c04..69dcd37e48b 100644
--- a/packages/@ember/-internals/routing/lib/system/route.ts
+++ b/packages/@ember/-internals/routing/lib/system/route.ts
@@ -2026,11 +2026,21 @@ export function getFullQueryParams(router: EmberRouter, state: TransitionState routeInfo.route);
- router._deserializeQueryParams(state.routeInfos, state['fullQueryParams'] as QueryParam);
- return state['fullQueryParams'];
+ assign(fullQueryParamsState, state.queryParams);
+
+ router._deserializeQueryParams(state.routeInfos, fullQueryParamsState as QueryParam);
+
+ // only cache query params state if all routeinfos have resolved; it's possible
+ // for lazy routes to not have resolved when `getFullQueryParams` is called, so
+ // we wait until all routes have resolved prior to caching query params state
+ if (haveAllRouteInfosResolved) {
+ state['fullQueryParams'] = fullQueryParamsState;
+ }
+
+ return fullQueryParamsState;
}
function getQueryParamsFor(route: Route, state: TransitionState) {