From e50cabfed1984c341af0d0c056a325a8aec26980 Mon Sep 17 00:00:00 2001 From: Alexander Date: Fri, 26 May 2023 00:29:22 +0600 Subject: [PATCH] fix(nuxt): show error page after fatal `abortNavigation` (#21047) --- packages/nuxt/src/app/composables/router.ts | 14 ++++++++++---- test/basic.test.ts | 8 ++++++++ test/fixtures/basic/pages/middleware-abort.vue | 18 ++++++++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 test/fixtures/basic/pages/middleware-abort.vue diff --git a/packages/nuxt/src/app/composables/router.ts b/packages/nuxt/src/app/composables/router.ts index 5c58ff864603..1446bddbf23f 100644 --- a/packages/nuxt/src/app/composables/router.ts +++ b/packages/nuxt/src/app/composables/router.ts @@ -6,7 +6,7 @@ import { hasProtocol, joinURL, parseURL } from 'ufo' import { useNuxtApp, useRuntimeConfig } from '../nuxt' import type { NuxtError } from './error' -import { createError } from './error' +import { createError, showError } from './error' import { useState } from './state' import type { PageMeta } from '#app' @@ -155,10 +155,16 @@ export const abortNavigation = (err?: string | Partial) => { if (process.dev && !isProcessingMiddleware()) { throw new Error('abortNavigation() is only usable inside a route middleware handler.') } - if (err) { - throw createError(err) + + if (!err) { return false } + + err = createError(err) + + if (err.fatal) { + useNuxtApp().runWithContext(() => showError(err as NuxtError)) } - return false + + throw err } export const setPageLayout = (layout: string) => { diff --git a/test/basic.test.ts b/test/basic.test.ts index e221b8443648..c44f5569d085 100644 --- a/test/basic.test.ts +++ b/test/basic.test.ts @@ -710,6 +710,14 @@ describe('middlewares', () => { expect(res.status).toEqual(401) }) + it('should allow aborting navigation fatally on client-side', async () => { + const html = await $fetch('/middleware-abort') + expect(html).not.toContain('This is the error page') + const page = await createPage('/middleware-abort') + await page.waitForLoadState('networkidle') + expect(await page.innerHTML('body')).toContain('This is the error page') + }) + it('should inject auth', async () => { const html = await $fetch('/auth') diff --git a/test/fixtures/basic/pages/middleware-abort.vue b/test/fixtures/basic/pages/middleware-abort.vue new file mode 100644 index 000000000000..bb97403eb6c5 --- /dev/null +++ b/test/fixtures/basic/pages/middleware-abort.vue @@ -0,0 +1,18 @@ + + +