From 608b913b8a1c8f151b3dc18457eb2b298ad408ab Mon Sep 17 00:00:00 2001 From: Jonas Galvez Date: Sat, 25 Aug 2018 06:42:00 -0300 Subject: [PATCH] feat: async validate() (#3797) --- lib/app/client.js | 27 ++++++++++++++++---- lib/app/server.js | 27 ++++++++++++++++---- test/e2e/basic.browser.test.js | 15 +++++++++++ test/fixtures/basic/pages/validate-async.vue | 15 +++++++++++ test/unit/basic.ssr.test.js | 10 ++++++++ 5 files changed, 84 insertions(+), 10 deletions(-) create mode 100644 test/fixtures/basic/pages/validate-async.vue diff --git a/lib/app/client.js b/lib/app/client.js index d210a0c24b..c2c5b0c4bd 100644 --- a/lib/app/client.js +++ b/lib/app/client.js @@ -292,11 +292,28 @@ async function render (to, from, next) { // Call .validate() let isValid = true - Components.forEach((Component) => { - if (!isValid) return - if (typeof Component.options.validate !== 'function') return - isValid = Component.options.validate(app.context) - }) + let validationError + try { + for (const Component of Components) { + if (typeof Component.options.validate !== 'function') { + continue + } + + isValid = await Component.options.validate(app.context) + + if (!isValid) { + break + } + } + } catch (validationError) { + // ...If .validate() threw an error + this.error({ + statusCode: validationError.statusCode || '500', + message: validationError.message + }) + return next() + } + // ...If .validate() returned false if (!isValid) { this.error({ statusCode: 404, message: `<%= messages.error_404 %>` }) diff --git a/lib/app/server.js b/lib/app/server.js index 76070d8504..4e0f1c5e78 100644 --- a/lib/app/server.js +++ b/lib/app/server.js @@ -154,11 +154,28 @@ export default async (ssrContext) => { ** Call .validate() */ let isValid = true - Components.forEach((Component) => { - if (!isValid) return - if (typeof Component.options.validate !== 'function') return - isValid = Component.options.validate(app.context) - }) + let validationError + try { + for (const Component of Components) { + if (typeof Component.options.validate !== 'function') { + continue + } + + isValid = await Component.options.validate(app.context) + + if (!isValid) { + break + } + } + } catch (validationError) { + // ...If .validate() threw an error + app.context.error({ + statusCode: validationError.statusCode || '500', + message: validationError.message + }) + return renderErrorPage() + } + // ...If .validate() returned false if (!isValid) { // Don't server-render the page in generate mode diff --git a/test/e2e/basic.browser.test.js b/test/e2e/basic.browser.test.js index 70c73eed73..86442cceee 100644 --- a/test/e2e/basic.browser.test.js +++ b/test/e2e/basic.browser.test.js @@ -123,12 +123,27 @@ describe('basic browser', () => { expect(error.message).toBe('This page could not be found') }) + test('/validate-async should display a 404', async () => { + await page.nuxt.navigate('/validate-async') + + const error = await page.nuxt.errorData() + + expect(error.statusCode).toBe(404) + expect(error.message).toBe('This page could not be found') + }) + test('/validate?valid=true', async () => { await page.nuxt.navigate('/validate?valid=true') expect(await page.$text('h1')).toBe('I am valid') }) + test('/validate-async?valid=true', async () => { + await page.nuxt.navigate('/validate-async?valid=true') + + expect(await page.$text('h1')).toBe('I am valid') + }) + test('/redirect', async () => { await page.nuxt.navigate('/redirect') diff --git a/test/fixtures/basic/pages/validate-async.vue b/test/fixtures/basic/pages/validate-async.vue new file mode 100644 index 0000000000..8637d0f81a --- /dev/null +++ b/test/fixtures/basic/pages/validate-async.vue @@ -0,0 +1,15 @@ + + + diff --git a/test/unit/basic.ssr.test.js b/test/unit/basic.ssr.test.js index e56a33de73..f9e6f6a6f5 100644 --- a/test/unit/basic.ssr.test.js +++ b/test/unit/basic.ssr.test.js @@ -96,11 +96,21 @@ describe('basic ssr', () => { expect(html.includes('This page could not be found')).toBe(true) }) + test('/validate-async should display a 404', async () => { + const { html } = await nuxt.renderRoute('/validate-async') + expect(html.includes('This page could not be found')).toBe(true) + }) + test('/validate?valid=true', async () => { const { html } = await nuxt.renderRoute('/validate?valid=true') expect(html.includes('

I am valid

')).toBe(true) }) + test('/validate-async?valid=true', async () => { + const { html } = await nuxt.renderRoute('/validate-async?valid=true') + expect(html.includes('

I am valid

')).toBe(true) + }) + test('/before-enter', async () => { const { html } = await nuxt.renderRoute('/before-enter') expect(html.includes('

Index page

')).toBe(true)