From 6db325c321b6a8969ebeb3a0d3b950b0e9096916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Chopin?= Date: Tue, 4 Feb 2020 19:36:22 +0100 Subject: [PATCH] feat(vue-app): new fetch syntax (#6880) --- examples/new-fetch/README.md | 5 + examples/new-fetch/components/Author.vue | 30 ++++ examples/new-fetch/layouts/default.vue | 28 +++ examples/new-fetch/nuxt.config.js | 18 ++ examples/new-fetch/package.json | 18 ++ examples/new-fetch/pages/index.vue | 43 +++++ examples/new-fetch/pages/posts/_id.vue | 54 ++++++ .../new-fetch/plugins/vue-placeholders.js | 4 + packages/vue-app/src/index.js | 2 + packages/vue-app/template/App.js | 24 ++- packages/vue-app/template/client.js | 16 +- .../vue-app/template/components/nuxt-child.js | 23 +-- .../vue-app/template/mixins/fetch.client.js | 80 +++++++++ .../vue-app/template/mixins/fetch.server.js | 49 ++++++ packages/vue-app/template/server.js | 17 +- packages/vue-app/template/utils.js | 25 +++ test/e2e/fetch.browser.test.js | 159 ++++++++++++++++++ test/fixtures/basic/pages/error-object.vue | 2 +- test/fixtures/basic/pages/error-string.vue | 2 +- .../basic/pages/redirect-external.vue | 2 +- test/fixtures/basic/pages/redirect-name.vue | 2 +- test/fixtures/basic/pages/redirect.vue | 2 +- test/fixtures/basic/pages/special-state.vue | 2 +- test/fixtures/basic/pages/store-module.vue | 2 +- test/fixtures/fetch/components/Team.vue | 26 +++ test/fixtures/fetch/fetch.test.js | 3 + test/fixtures/fetch/layouts/default.vue | 52 ++++++ test/fixtures/fetch/nuxt.config.js | 1 + test/fixtures/fetch/pages/fetch-button.vue | 26 +++ test/fixtures/fetch/pages/fetch-client.vue | 22 +++ test/fixtures/fetch/pages/fetch-component.vue | 13 ++ .../fetch/pages/fetch-conditional.vue | 27 +++ test/fixtures/fetch/pages/fetch-deep.vue | 35 ++++ test/fixtures/fetch/pages/fetch-delay.vue | 24 +++ test/fixtures/fetch/pages/fetch-error.vue | 24 +++ test/fixtures/fetch/pages/index.vue | 23 +++ test/fixtures/fetch/pages/old-fetch.vue | 18 ++ test/fixtures/fetch/static/team.json | 11 ++ .../spa/pages/error-handler-object.vue | 2 +- .../spa/pages/error-handler-string.vue | 2 +- test/fixtures/spa/pages/error-handler.vue | 2 +- 41 files changed, 893 insertions(+), 27 deletions(-) create mode 100644 examples/new-fetch/README.md create mode 100644 examples/new-fetch/components/Author.vue create mode 100644 examples/new-fetch/layouts/default.vue create mode 100644 examples/new-fetch/nuxt.config.js create mode 100644 examples/new-fetch/package.json create mode 100644 examples/new-fetch/pages/index.vue create mode 100644 examples/new-fetch/pages/posts/_id.vue create mode 100644 examples/new-fetch/plugins/vue-placeholders.js create mode 100644 packages/vue-app/template/mixins/fetch.client.js create mode 100644 packages/vue-app/template/mixins/fetch.server.js create mode 100644 test/e2e/fetch.browser.test.js create mode 100644 test/fixtures/fetch/components/Team.vue create mode 100644 test/fixtures/fetch/fetch.test.js create mode 100644 test/fixtures/fetch/layouts/default.vue create mode 100644 test/fixtures/fetch/nuxt.config.js create mode 100644 test/fixtures/fetch/pages/fetch-button.vue create mode 100644 test/fixtures/fetch/pages/fetch-client.vue create mode 100644 test/fixtures/fetch/pages/fetch-component.vue create mode 100644 test/fixtures/fetch/pages/fetch-conditional.vue create mode 100644 test/fixtures/fetch/pages/fetch-deep.vue create mode 100644 test/fixtures/fetch/pages/fetch-delay.vue create mode 100644 test/fixtures/fetch/pages/fetch-error.vue create mode 100644 test/fixtures/fetch/pages/index.vue create mode 100644 test/fixtures/fetch/pages/old-fetch.vue create mode 100644 test/fixtures/fetch/static/team.json diff --git a/examples/new-fetch/README.md b/examples/new-fetch/README.md new file mode 100644 index 0000000000..3b31939e1a --- /dev/null +++ b/examples/new-fetch/README.md @@ -0,0 +1,5 @@ +# New fetch() with Nuxt.js + +Nuxt.js `v2.12` introduces a new hook called `fetch` in any of your Vue components. + +See [live demo](https://nuxt-new-fetch.surge.sh) and [documentation](https://nuxtjs.org/api/pages-fetch). diff --git a/examples/new-fetch/components/Author.vue b/examples/new-fetch/components/Author.vue new file mode 100644 index 0000000000..05e6cda279 --- /dev/null +++ b/examples/new-fetch/components/Author.vue @@ -0,0 +1,30 @@ + + + diff --git a/examples/new-fetch/layouts/default.vue b/examples/new-fetch/layouts/default.vue new file mode 100644 index 0000000000..07cb60a9a1 --- /dev/null +++ b/examples/new-fetch/layouts/default.vue @@ -0,0 +1,28 @@ + + + + + diff --git a/examples/new-fetch/nuxt.config.js b/examples/new-fetch/nuxt.config.js new file mode 100644 index 0000000000..7e25ad865f --- /dev/null +++ b/examples/new-fetch/nuxt.config.js @@ -0,0 +1,18 @@ +const fetch = require('node-fetch') + +export default { + plugins: [ + '@/plugins/vue-placeholders.js' + ], + modules: [ + '@nuxt/http' + ], + generate: { + async routes () { + const posts = await fetch('https://jsonplaceholder.typicode.com/posts').then(res => res.json()).then(d => d.slice(0, 20)) + const routes = posts.map(post => `/posts/${post.id}`) + + return ['/'].concat(routes) + } + } +} diff --git a/examples/new-fetch/package.json b/examples/new-fetch/package.json new file mode 100644 index 0000000000..1c893ab9a6 --- /dev/null +++ b/examples/new-fetch/package.json @@ -0,0 +1,18 @@ +{ + "name": "example-hello-world", + "dependencies": { + "@nuxt/http": "^0.3.8", + "nuxt-start": "latest", + "vue-content-placeholders": "^0.2.1" + }, + "devDependencies": { + "nuxt": "latest" + }, + "scripts": { + "dev": "nuxt", + "build": "nuxt build", + "start": "nuxt start", + "generate": "nuxt generate", + "post-update": "yarn upgrade --latest" + } +} diff --git a/examples/new-fetch/pages/index.vue b/examples/new-fetch/pages/index.vue new file mode 100644 index 0000000000..f3a5d75aa5 --- /dev/null +++ b/examples/new-fetch/pages/index.vue @@ -0,0 +1,43 @@ + + + diff --git a/examples/new-fetch/pages/posts/_id.vue b/examples/new-fetch/pages/posts/_id.vue new file mode 100644 index 0000000000..ab58607eb7 --- /dev/null +++ b/examples/new-fetch/pages/posts/_id.vue @@ -0,0 +1,54 @@ + + + diff --git a/examples/new-fetch/plugins/vue-placeholders.js b/examples/new-fetch/plugins/vue-placeholders.js new file mode 100644 index 0000000000..40bfc7e19a --- /dev/null +++ b/examples/new-fetch/plugins/vue-placeholders.js @@ -0,0 +1,4 @@ +import Vue from 'vue' +import VueContentPlaceholders from 'vue-content-placeholders' + +Vue.use(VueContentPlaceholders) diff --git a/packages/vue-app/src/index.js b/packages/vue-app/src/index.js index 93700aee9a..9d1aaac16c 100644 --- a/packages/vue-app/src/index.js +++ b/packages/vue-app/src/index.js @@ -13,6 +13,8 @@ export const template = { 'server.js', 'utils.js', 'empty.js', + 'mixins/fetch.server.js', + 'mixins/fetch.client.js', 'components/nuxt-error.vue', 'components/nuxt-child.js', 'components/nuxt-link.server.js', diff --git a/packages/vue-app/template/App.js b/packages/vue-app/template/App.js index ce1ae6ef2e..29699e57c3 100644 --- a/packages/vue-app/template/App.js +++ b/packages/vue-app/template/App.js @@ -2,6 +2,7 @@ import Vue from 'vue' <% if (features.asyncData || features.fetch) { %> import { getMatchedComponentsInstances, + getChildrenComponentInstancesUsingFetch, promisify, globalHandleError } from './utils' @@ -88,9 +89,12 @@ export default { <% } %> <% if (features.layouts) { %> layout: null, - layoutName: '' + layoutName: '', <% } %> - }), + <% if (features.fetch) { %> + nbFetching: 0 + <% } %> + }), <% } %> beforeCreate () { Vue.util.defineReactive(this, 'nuxt', this.$options.nuxt) @@ -125,7 +129,12 @@ export default { computed: { isOffline () { return !this.isOnline + }, + <% if (features.fetch) { %> + isFetching() { + return this.nbFetching > 0 } + <% } %> }, <% } %> methods: { @@ -157,9 +166,18 @@ export default { const p = [] <% if (features.fetch) { %> - if (page.$options.fetch) { + // Old fetch + if (page.$options.fetch && page.$options.fetch.length) { p.push(promisify(page.$options.fetch, this.context)) } + if (page.$fetch) { + p.push(page.$fetch()) + } else { + // Get all component instance to call $fetch + for (const component of getChildrenComponentInstancesUsingFetch(page.$vnode.componentInstance)) { + p.push(component.$fetch()) + } + } <% } %> <% if (features.asyncData) { %> if (page.$options.asyncData) { diff --git a/packages/vue-app/template/client.js b/packages/vue-app/template/client.js index 904f10659f..156d24003d 100644 --- a/packages/vue-app/template/client.js +++ b/packages/vue-app/template/client.js @@ -17,8 +17,17 @@ import { globalHandleError } from './utils.js' import { createApp<% if (features.layouts) { %>, NuxtError<% } %> } from './index.js' +<% if (features.fetch) { %>import fetchMixin from './mixins/fetch.client'<% } %> import NuxtLink from './components/nuxt-link.<%= features.clientPrefetch ? "client" : "server" %>.js' // should be included after ./index.js +<% if (features.fetch) { %> +// Fetch mixin +if (!Vue.__nuxt__fetch__mixin__) { + Vue.mixin(fetchMixin) + Vue.__nuxt__fetch__mixin__ = true +} +<% } %> + // Component: Vue.component(NuxtLink.name, NuxtLink) <% if (features.componentAliases) { %>Vue.component('NLink', NuxtLink)<% } %> @@ -458,7 +467,10 @@ async function render (to, from, next) { <% } %> <% if (features.fetch) { %> - const hasFetch = Boolean(Component.options.fetch) + const hasFetch = Boolean(Component.options.fetch) && Component.options.fetch.length + if (hasFetch) { + console.warn('fetch(context) has been deprecated, please use middleware(context)') + } <% } else { %> const hasFetch = false <% } %> @@ -738,7 +750,7 @@ function addHotReload ($component, depth) { <% if (features.fetch) { %> // Call fetch() Component.options.fetch = Component.options.fetch || noopFetch - let pFetch = Component.options.fetch(context) + let pFetch = Component.options.fetch.length && Component.options.fetch(context) if (!pFetch || (!(pFetch instanceof Promise) && (typeof pFetch.then !== 'function'))) { pFetch = Promise.resolve(pFetch) } <%= (loading ? 'pFetch.then(() => this.$loading.increase && this.$loading.increase(30))' : '') %> promises.push(pFetch) diff --git a/packages/vue-app/template/components/nuxt-child.js b/packages/vue-app/template/components/nuxt-child.js index a2996c4e3c..0b36b3491f 100644 --- a/packages/vue-app/template/components/nuxt-child.js +++ b/packages/vue-app/template/components/nuxt-child.js @@ -13,7 +13,8 @@ export default { default: undefined } }, - render (h, { parent, data, props }) { + render (_, { parent, data, props }) { + const h = parent.$createElement <% if (features.transitions) { %> data.nuxtChild = true const _parent = parent @@ -42,15 +43,17 @@ export default { listeners[key] = transition[key].bind(_parent) } }) - // Add triggerScroll event on beforeEnter (fix #1376) - const beforeEnter = listeners.beforeEnter - listeners.beforeEnter = (el) => { - // Ensure to trigger scroll event after calling scrollBehavior - window.<%= globals.nuxt %>.$nextTick(() => { - window.<%= globals.nuxt %>.$emit('triggerScroll') - }) - if (beforeEnter) { - return beforeEnter.call(_parent, el) + if (process.client) { + // Add triggerScroll event on beforeEnter (fix #1376) + const beforeEnter = listeners.beforeEnter + listeners.beforeEnter = (el) => { + // Ensure to trigger scroll event after calling scrollBehavior + window.<%= globals.nuxt %>.$nextTick(() => { + window.<%= globals.nuxt %>.$emit('triggerScroll') + }) + if (beforeEnter) { + return beforeEnter.call(_parent, el) + } } } diff --git a/packages/vue-app/template/mixins/fetch.client.js b/packages/vue-app/template/mixins/fetch.client.js new file mode 100644 index 0000000000..5c866718fe --- /dev/null +++ b/packages/vue-app/template/mixins/fetch.client.js @@ -0,0 +1,80 @@ +import Vue from 'vue' +import { hasFetch, normalizeError, addLifecycleHook } from '../utils' + +const isSsrHydration = (vm) => vm.$vnode && vm.$vnode.elm && vm.$vnode.elm.dataset && vm.$vnode.elm.dataset.ssrKey +const nuxtState = window.<%= globals.context %> + +export default { + beforeCreate () { + if (!hasFetch(this)) { + return + } + + this._fetchDelay = typeof this.$options.fetchDelay === 'number' ? this.$options.fetchDelay : 200 + + Vue.util.defineReactive(this, '$fetchState', { + pending: false, + error: null, + timestamp: Date.now() + }) + + this.$fetch = $fetch.bind(this) + addLifecycleHook(this, 'created', created) + addLifecycleHook(this, 'beforeMount', beforeMount) + } +} + +function beforeMount() { + if (!this._hydrated) { + return this.$fetch() + } +} + +function created() { + if (!isSsrHydration(this)) { + return + } + + // Hydrate component + this._hydrated = true + this._ssrKey = +this.$vnode.elm.dataset.ssrKey + const data = nuxtState.fetch[this._ssrKey] + + // If fetch error + if (data && data._error) { + this.$fetchState.error = data._error + return + } + + // Merge data + for (const key in data) { + Vue.set(this.$data, key, data[key]) + } +} + +async function $fetch() { + this.$nuxt.nbFetching++ + this.$fetchState.pending = true + this.$fetchState.error = null + this._hydrated = false + let error = null + const startTime = Date.now() + + try { + await this.$options.fetch.call(this) + } catch (err) { + error = normalizeError(err) + } + + const delayLeft = this._fetchDelay - (Date.now() - startTime) + if (delayLeft > 0) { + await new Promise(resolve => setTimeout(resolve, delayLeft)) + } + + this.$fetchState.error = error + this.$fetchState.pending = false + this.$fetchState.timestamp = Date.now() + + this.$nextTick(() => this.$nuxt.nbFetching--) +} + diff --git a/packages/vue-app/template/mixins/fetch.server.js b/packages/vue-app/template/mixins/fetch.server.js new file mode 100644 index 0000000000..a65eec1151 --- /dev/null +++ b/packages/vue-app/template/mixins/fetch.server.js @@ -0,0 +1,49 @@ +import Vue from 'vue' +import { hasFetch, normalizeError, addLifecycleHook } from '../utils' + +async function serverPrefetch() { + if (!this._fetchOnServer) { + return + } + + // Call and await on $fetch + try { + await this.$options.fetch.call(this) + } catch (err) { + this.$fetchState.error = normalizeError(err) + } + this.$fetchState.pending = false + + + // Define an ssrKey for hydration + this._ssrKey = this.$ssrContext.nuxt.fetch.length + + // Add data-ssr-key on parent element of Component + const attrs = this.$vnode.data.attrs = this.$vnode.data.attrs || {} + attrs['data-ssr-key'] = this._ssrKey + + // Call asyncData & add to ssrContext for window.__NUXT__.fetch + this.$ssrContext.nuxt.fetch.push(this.$fetchState.error ? { _error: this.$fetchState.error } : this._data) +} + +export default { + beforeCreate() { + if (!hasFetch(this)) { + return + } + + if (typeof this.$options.fetchOnServer === 'function') { + this._fetchOnServer = this.$options.fetchOnServer.call(this) !== false + } else { + this._fetchOnServer = this.$options.fetchOnServer !== false + } + + Vue.util.defineReactive(this, '$fetchState', { + pending: true, + error: null, + timestamp: Date.now() + }) + + addLifecycleHook(this, 'serverPrefetch', serverPrefetch) + } +} diff --git a/packages/vue-app/template/server.js b/packages/vue-app/template/server.js index 1a5c72a42a..4cdf793792 100644 --- a/packages/vue-app/template/server.js +++ b/packages/vue-app/template/server.js @@ -9,9 +9,21 @@ import { getMatchedComponents, promisify } from './utils.js' +<% if (features.fetch) { %>import fetchMixin from './mixins/fetch.server'<% } %> import { createApp<% if (features.layouts) { %>, NuxtError<% } %> } from './index.js' import NuxtLink from './components/nuxt-link.server.js' // should be included after ./index.js +<% if (features.fetch) { %> +// Update serverPrefetch strategy +Vue.config.optionMergeStrategies.serverPrefetch = Vue.config.optionMergeStrategies.created + +// Fetch mixin +if (!Vue.__nuxt__fetch__mixin__) { + Vue.mixin(fetchMixin) + Vue.__nuxt__fetch__mixin__ = true +} +<% } %> + // Component: Vue.component(NuxtLink.name, NuxtLink) <% if (features.componentAliases) { %>Vue.component('NLink', NuxtLink)<% } %> @@ -60,7 +72,7 @@ export default async (ssrContext) => { // Used for beforeNuxtRender({ Components, nuxtState }) ssrContext.beforeRenderFns = [] // Nuxt object (window{{globals.context}}, defaults to window.__NUXT__) - ssrContext.nuxt = { <% if (features.layouts) { %>layout: 'default', <% } %>data: [], error: null<%= (store ? ', state: null' : '') %>, serverRendered: true } + ssrContext.nuxt = { <% if (features.layouts) { %>layout: 'default', <% } %>data: [], <% if (features.fetch) { %>fetch: [], <% } %>error: null<%= (store ? ', state: null' : '') %>, serverRendered: true } // Create the app definition and the instance (created for each request) const { app, router<%= (store ? ', store' : '') %> } = await createApp(ssrContext) const _app = new Vue(app) @@ -267,7 +279,8 @@ export default async (ssrContext) => { <% if (features.fetch) { %> // Call fetch(context) - if (Component.options.fetch) { + if (Component.options.fetch && Component.options.fetch.length) { + console.warn('fetch(context) has been deprecated, please use middleware(context)') promises.push(Component.options.fetch(app.context)) } else { promises.push(null) diff --git a/packages/vue-app/template/utils.js b/packages/vue-app/template/utils.js index 82ede520a6..0db77009cc 100644 --- a/packages/vue-app/template/utils.js +++ b/packages/vue-app/template/utils.js @@ -21,6 +21,24 @@ export function interopDefault (promise) { return promise.then(m => m.default || m) } +<% if (features.fetch) { %> +export function hasFetch(vm) { + return vm.$options && typeof vm.$options.fetch === 'function' && !vm.$options.fetch.length +} +export function getChildrenComponentInstancesUsingFetch(vm, instances = []) { + const children = vm.$children || [] + for (const child of children) { + if (child.$fetch) { + instances.push(child) + continue; // Don't get the children since it will reload the template + } + if (child.$children) { + getChildrenComponentInstancesUsingFetch(child, instances) + } + } + return instances +} +<% } %> <% if (features.asyncData) { %> export function applyAsyncData (Component, asyncData) { if ( @@ -615,3 +633,10 @@ function formatQuery (query) { }).filter(Boolean).join('&') } <% } %> + +export function addLifecycleHook(vm, hook, fn) { + if (!vm.$options[hook]) { + vm.$options[hook] = [] + } + vm.$options[hook].push(fn) +} diff --git a/test/e2e/fetch.browser.test.js b/test/e2e/fetch.browser.test.js new file mode 100644 index 0000000000..0e7bd2e8e8 --- /dev/null +++ b/test/e2e/fetch.browser.test.js @@ -0,0 +1,159 @@ +import Browser from '../utils/browser' +import { loadFixture, getPort, Nuxt } from '../utils' + +let port +const browser = new Browser() +const url = route => 'http://localhost:' + port + route + +let nuxt = null +let page = null + +describe('basic browser', () => { + beforeAll(async () => { + const config = await loadFixture('fetch') + nuxt = new Nuxt(config) + await nuxt.ready() + + port = await getPort() + await nuxt.server.listen(port, 'localhost') + + await browser.start({ + // slowMo: 50, + // headless: false + }) + }) + + test('Open /', async () => { + page = await browser.page(url('/')) + expect(await page.$text('pre')).toContain('Atinux') + }) + + test('/fetch-client', async () => { + await page.nuxt.navigate('/fetch-client') + expect(await page.$text('p')).toContain('Fetching...') + await page.waitForSelector('pre') + expect(await page.$text('pre')).toContain('pi0') + }) + + test('/fetch-error', async () => { + await page.nuxt.navigate('/fetch-error') + expect(await page.$text('p')).toContain('Fetching...') + await page.waitForSelector('#error') + expect(await page.$text('#error')).toContain('fetch-error') + }) + + test('/fetch-component', async () => { + await page.nuxt.navigate('/fetch-component') + expect(await page.$text('p')).toContain('Fetching...') + await page.waitForSelector('pre') + expect(await page.$text('pre')).toContain('clarkdo') + }) + + test('/fetch-delay', async () => { + const now = Date.now() + await page.nuxt.navigate('/fetch-delay') + expect(await page.$text('p')).toContain('Fetching for 1 second') + await page.waitForSelector('pre') + const delay = Date.now() - now + expect(await page.$text('pre')).toContain('alexchopin') + expect(delay).toBeGreaterThanOrEqual(1000) + }) + + test('/fetch-button', async () => { + await page.nuxt.navigate('/fetch-button') + expect(await page.$text('p')).toContain('Fetching...') + await page.waitForSelector('pre') + expect(await page.$text('pre')).toContain('kevinmarrec') + await page.click('button') + expect(await page.$text('p')).toContain('Fetching...') + await page.waitForSelector('pre') + expect(await page.$text('pre')).toContain('kevinmarrec') + }) + + test('/old-fetch', async () => { + const msg = new Promise(resolve => + page.on('console', msg => resolve(msg.text())) + ) + await page.nuxt.navigate('/old-fetch') + expect(await msg).toBe('fetch(context) has been deprecated, please use middleware(context)') + }) + + test('ssr: /fetch-client', async () => { + const page = await browser.page(url('/fetch-client')) + expect(await page.$text('p')).toContain('Fetching...') + await page.waitForSelector('pre') + expect(await page.$text('pre')).toContain('pi0') + page.close() + }) + + test('ssr: /fetch-conditional', async () => { + const page = await browser.page(url('/fetch-conditional')) + expect(await page.$text('pre')).toContain('galvez') + page.close() + }) + + test('ssr: /fetch-conditional?fetch_client=true', async () => { + const page = await browser.page(url('/fetch-conditional?fetch_client=true')) + expect(await page.$text('p')).toContain('Fetching...') + await page.waitForSelector('pre') + expect(await page.$text('pre')).toContain('pimlie') + page.close() + }) + + test('ssr: /fetch-error', async () => { + const page = await browser.page(url('/fetch-error')) + expect(await page.$text('#error')).toContain('fetch-error') + page.close() + }) + + test('ssr: /fetch-deep', async () => { + const page = await browser.page(url('/fetch-deep')) + const expectedState = { + foo: 'barbar', + user: { + name: 'Potato', + inventory: { + type: 'green', + items: ['A', 'B'] + } + }, + async: 'data', + async2: 'data2fetch' + } + + // Hydrated HTML + const renderedData = await page.$text('#data').then(t => JSON.parse(t)) + expect(renderedData).toMatchObject(expectedState) + + // Fragments + const { data, fetch } = await page.evaluate(() => window.__NUXT__) + expect(data.length).toBe(1) + expect(fetch.length).toBe(1) + + // asyncData mutations + expect(data[0]).toMatchObject({ async: 'data', async2: 'data2' }) + + // fetch mutations + expect(fetch[0]).toMatchObject({ + user: { + inventory: { items: ['A', 'B'] }, + name: 'Potato' + }, + foo: 'barbar', + async2: 'data2fetch' + }) + + page.close() + }) + + // Close server and ask nuxt to stop listening to file changes + afterAll(async () => { + await nuxt.close() + }) + + // Stop browser + afterAll(async () => { + await page.close() + await browser.close() + }) +}) diff --git a/test/fixtures/basic/pages/error-object.vue b/test/fixtures/basic/pages/error-object.vue index 02af257039..b73f9f28c5 100644 --- a/test/fixtures/basic/pages/error-object.vue +++ b/test/fixtures/basic/pages/error-object.vue @@ -1,7 +1,7 @@ diff --git a/test/fixtures/fetch/fetch.test.js b/test/fixtures/fetch/fetch.test.js new file mode 100644 index 0000000000..8a10805c97 --- /dev/null +++ b/test/fixtures/fetch/fetch.test.js @@ -0,0 +1,3 @@ +import { buildFixture } from '../../utils/build' + +buildFixture('fetch') diff --git a/test/fixtures/fetch/layouts/default.vue b/test/fixtures/fetch/layouts/default.vue new file mode 100644 index 0000000000..4a4ad8b5a0 --- /dev/null +++ b/test/fixtures/fetch/layouts/default.vue @@ -0,0 +1,52 @@ + diff --git a/test/fixtures/fetch/nuxt.config.js b/test/fixtures/fetch/nuxt.config.js new file mode 100644 index 0000000000..b1c6ea436a --- /dev/null +++ b/test/fixtures/fetch/nuxt.config.js @@ -0,0 +1 @@ +export default {} diff --git a/test/fixtures/fetch/pages/fetch-button.vue b/test/fixtures/fetch/pages/fetch-button.vue new file mode 100644 index 0000000000..4617fa31bf --- /dev/null +++ b/test/fixtures/fetch/pages/fetch-button.vue @@ -0,0 +1,26 @@ + + + diff --git a/test/fixtures/fetch/pages/fetch-client.vue b/test/fixtures/fetch/pages/fetch-client.vue new file mode 100644 index 0000000000..af7312c52a --- /dev/null +++ b/test/fixtures/fetch/pages/fetch-client.vue @@ -0,0 +1,22 @@ + + + diff --git a/test/fixtures/fetch/pages/fetch-component.vue b/test/fixtures/fetch/pages/fetch-component.vue new file mode 100644 index 0000000000..9a3b4484dd --- /dev/null +++ b/test/fixtures/fetch/pages/fetch-component.vue @@ -0,0 +1,13 @@ + + + diff --git a/test/fixtures/fetch/pages/fetch-conditional.vue b/test/fixtures/fetch/pages/fetch-conditional.vue new file mode 100644 index 0000000000..df43951487 --- /dev/null +++ b/test/fixtures/fetch/pages/fetch-conditional.vue @@ -0,0 +1,27 @@ + + + diff --git a/test/fixtures/fetch/pages/fetch-deep.vue b/test/fixtures/fetch/pages/fetch-deep.vue new file mode 100644 index 0000000000..250a3342e6 --- /dev/null +++ b/test/fixtures/fetch/pages/fetch-deep.vue @@ -0,0 +1,35 @@ + + + diff --git a/test/fixtures/fetch/pages/fetch-delay.vue b/test/fixtures/fetch/pages/fetch-delay.vue new file mode 100644 index 0000000000..37bb499f6a --- /dev/null +++ b/test/fixtures/fetch/pages/fetch-delay.vue @@ -0,0 +1,24 @@ + + + diff --git a/test/fixtures/fetch/pages/fetch-error.vue b/test/fixtures/fetch/pages/fetch-error.vue new file mode 100644 index 0000000000..035429ad7a --- /dev/null +++ b/test/fixtures/fetch/pages/fetch-error.vue @@ -0,0 +1,24 @@ + + + diff --git a/test/fixtures/fetch/pages/index.vue b/test/fixtures/fetch/pages/index.vue new file mode 100644 index 0000000000..d2f100cdac --- /dev/null +++ b/test/fixtures/fetch/pages/index.vue @@ -0,0 +1,23 @@ + + + diff --git a/test/fixtures/fetch/pages/old-fetch.vue b/test/fixtures/fetch/pages/old-fetch.vue new file mode 100644 index 0000000000..069b9f207f --- /dev/null +++ b/test/fixtures/fetch/pages/old-fetch.vue @@ -0,0 +1,18 @@ + + + diff --git a/test/fixtures/fetch/static/team.json b/test/fixtures/fetch/static/team.json new file mode 100644 index 0000000000..a39a7b61df --- /dev/null +++ b/test/fixtures/fetch/static/team.json @@ -0,0 +1,11 @@ +[ + "Atinux", + "alexchopin", + "pi0", + "clarkdo", + "manniL", + "galvez", + "aldarund", + "kevinmarrec", + "pimlie" +] diff --git a/test/fixtures/spa/pages/error-handler-object.vue b/test/fixtures/spa/pages/error-handler-object.vue index 61befefe5c..efcf70fc6a 100644 --- a/test/fixtures/spa/pages/error-handler-object.vue +++ b/test/fixtures/spa/pages/error-handler-object.vue @@ -1,7 +1,7 @@