@@ -148,3 +148,115 @@ describe('Routing', () => {
148148 )
149149 } ) ;
150150} ) ;
151+
152+ /**
153+ * These tests verify that handlePageTransition does not
154+ * throw when enteringViewItem.ionPageElement is undefined.
155+ * This can happen when a page component is missing the
156+ * required <ion-page> wrapper.
157+ */
158+ describe ( 'handlePageTransition - undefined enteringEl' , ( ) => {
159+ const enteringViewItem = {
160+ ionPageElement : undefined ,
161+ vueComponent : { } ,
162+ vueComponentRef : { } ,
163+ routerAnimation : undefined ,
164+ mount : true ,
165+ matchedRoute : { path : '/' } ,
166+ pathname : '/' ,
167+ } ;
168+
169+ const leavingViewItem = {
170+ ionPageElement : document . createElement ( 'div' ) ,
171+ vueComponent : { } ,
172+ vueComponentRef : { } ,
173+ routerAnimation : undefined ,
174+ mount : true ,
175+ matchedRoute : { path : '/page2' } ,
176+ pathname : '/page2' ,
177+ } ;
178+
179+ const mockViewStacks = {
180+ getViewStack : vi . fn ( ) . mockReturnValue ( [ enteringViewItem , leavingViewItem ] ) ,
181+ findViewItemByRouteInfo : vi . fn ( ) . mockReturnValue ( enteringViewItem ) ,
182+ findLeavingViewItemByRouteInfo : vi . fn ( ) . mockReturnValue ( leavingViewItem ) ,
183+ getChildrenToRender : vi . fn ( ) . mockReturnValue ( [ ] ) ,
184+ createViewItem : vi . fn ( ) . mockReturnValue ( enteringViewItem ) ,
185+ add : vi . fn ( ) ,
186+ clear : vi . fn ( ) ,
187+ registerIonPage : vi . fn ( ) ,
188+ size : vi . fn ( ) . mockReturnValue ( 1 ) ,
189+ findViewItemByPathname : vi . fn ( ) ,
190+ unmountLeavingViews : vi . fn ( ) ,
191+ mountIntermediaryViews : vi . fn ( ) ,
192+ } ;
193+
194+ const mockNavManager = {
195+ getLeavingRouteInfo : vi . fn ( ) . mockReturnValue ( {
196+ pathname : '/page2' ,
197+ pushedByRoute : '/' ,
198+ routerAnimation : undefined ,
199+ } ) ,
200+ getCurrentRouteInfo : vi . fn ( ) . mockReturnValue ( {
201+ pathname : '/' ,
202+ pushedByRoute : '/' ,
203+ routerDirection : 'forward' ,
204+ routerAction : 'push' ,
205+ routerAnimation : undefined ,
206+ prevRouteLastPathname : '/page2' ,
207+ delta : 1 ,
208+ } ) ,
209+ canGoBack : vi . fn ( ) . mockReturnValue ( false ) ,
210+ handleNavigateBack : vi . fn ( ) ,
211+ } ;
212+
213+ const mountOutlet = async ( ) => {
214+ const router = createRouter ( {
215+ history : createWebHistory ( process . env . BASE_URL ) ,
216+ routes : [
217+ { path : '/' , component : BasePage } ,
218+ { path : '/page2' , component : BasePage }
219+ ]
220+ } ) ;
221+
222+ router . push ( '/' ) ;
223+ await router . isReady ( ) ;
224+
225+ return mount ( IonRouterOutlet , {
226+ global : {
227+ plugins : [ router , IonicVue ] ,
228+ provide : {
229+ navManager : mockNavManager ,
230+ viewStacks : mockViewStacks ,
231+ }
232+ }
233+ } ) ;
234+ } ;
235+
236+ it ( 'should warn when enteringEl is undefined' , async ( ) => {
237+ const warnSpy = vi . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => { } ) ;
238+
239+ await mountOutlet ( ) ;
240+ await waitForRouter ( ) ;
241+
242+ expect ( warnSpy ) . toHaveBeenCalledWith (
243+ expect . stringContaining ( 'does not have the required <ion-page> component' )
244+ ) ;
245+
246+ warnSpy . mockRestore ( ) ;
247+ } ) ;
248+
249+ it ( 'should not call transition when enteringEl is undefined' , async ( ) => {
250+ vi . spyOn ( console , 'warn' ) . mockImplementation ( ( ) => { } ) ;
251+
252+ const commitFn = vi . fn ( ) ;
253+ const wrapper = await mountOutlet ( ) ;
254+ wrapper . findComponent ( IonRouterOutlet ) . vm . $el . commit = commitFn ;
255+
256+ await waitForRouter ( ) ;
257+
258+ expect ( commitFn ) . not . toHaveBeenCalled ( ) ;
259+
260+ vi . restoreAllMocks ( ) ;
261+ } ) ;
262+ } ) ;
0 commit comments