test: add separate suspense test suite (#22947)

This commit is contained in:
Anthony Fu 2024-01-17 12:46:13 +01:00 committed by GitHub
parent d15f0c4e66
commit 6c6032782f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 167 additions and 1 deletions

View File

@ -22,7 +22,8 @@
"play:build": "nuxi build playground",
"play:preview": "nuxi preview playground",
"test": "pnpm test:fixtures && pnpm test:fixtures:dev && pnpm test:fixtures:webpack && pnpm test:unit && pnpm test:runtime && pnpm test:types && pnpm typecheck",
"test:fixtures": "nuxi prepare test/fixtures/basic && nuxi prepare test/fixtures/runtime-compiler && vitest run --dir test",
"test:prepare": "jiti ./test/prepare.ts",
"test:fixtures": "pnpm test:prepare && vitest run --dir test",
"test:fixtures:dev": "TEST_ENV=dev pnpm test:fixtures",
"test:fixtures:webpack": "TEST_BUILDER=webpack pnpm test:fixtures",
"test:runtime": "vitest -c vitest.nuxt.config.ts --coverage",

View File

@ -879,6 +879,19 @@ importers:
specifier: workspace:*
version: link:../../../packages/nuxt
test/fixtures/suspense:
dependencies:
nuxt:
specifier: workspace:*
version: link:../../../packages/nuxt
vue:
specifier: 3.4.14
version: 3.4.14(typescript@5.3.3)
devDependencies:
typescript:
specifier: latest
version: 5.3.3
packages:
/@aashutoshrathi/word-wrap@1.2.6:

3
test/fixtures/suspense/app.vue vendored Normal file
View File

@ -0,0 +1,3 @@
<template>
<NuxtPage />
</template>

14
test/fixtures/suspense/nuxt.config.ts vendored Normal file
View File

@ -0,0 +1,14 @@
import { fileURLToPath } from 'node:url'
const testWithInlineVue = process.env.EXTERNAL_VUE === 'false'
export default defineNuxtConfig({
experimental: {
externalVue: !testWithInlineVue
},
buildDir: testWithInlineVue ? '.nuxt-inline' : '.nuxt',
nitro: {
output: { dir: fileURLToPath(new URL(testWithInlineVue ? './.output-inline' : './.output', import.meta.url)) }
},
sourcemap: false
})

14
test/fixtures/suspense/package.json vendored Normal file
View File

@ -0,0 +1,14 @@
{
"private": true,
"name": "fixture-minimal",
"scripts": {
"build": "nuxi build"
},
"dependencies": {
"nuxt": "workspace:*",
"vue": "latest"
},
"devDependencies": {
"typescript": "latest"
}
}

29
test/fixtures/suspense/pages/index.vue vendored Normal file
View File

@ -0,0 +1,29 @@
<template>
<div>
<div>Index Page</div>
<NuxtLink
id="btn-a"
to="/target?a"
>
Target A
</NuxtLink>
<NuxtLink
id="btn-b"
to="/target?b"
>
Target B
</NuxtLink>
<button @click="trigger">
Trigger (for manual testing)
</button>
</div>
</template>
<script setup>
async function trigger () {
document.getElementById('btn-a').click()
await new Promise(resolve => setTimeout(resolve, 10))
document.getElementById('btn-b').click()
}
</script>

11
test/fixtures/suspense/pages/target.vue vendored Normal file
View File

@ -0,0 +1,11 @@
<template>
<div>
<div id="content">
Hello {{ Object.keys($route.query).join(' ') }}
</div>
</div>
</template>
<script setup lang="ts">
await new Promise(resolve => setTimeout(resolve, 200))
</script>

3
test/fixtures/suspense/tsconfig.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"extends": "./.nuxt/tsconfig.json"
}

25
test/prepare.ts Normal file
View File

@ -0,0 +1,25 @@
import { fileURLToPath } from 'node:url'
import { globby } from 'globby'
import fs from 'fs-extra'
import { execa } from 'execa'
async function initTesting () {
const dirs = await globby('*', {
onlyDirectories: true,
cwd: fileURLToPath(new URL('./fixtures', import.meta.url)),
absolute: true
})
await Promise.all([
// clear nuxt build files
...dirs.map(dir => fs.remove(`${dir}/.nuxt`)),
// clear vite cache
...dirs.map(dir => fs.remove(`${dir}/node_modules/.cache`), { force: true })
])
await Promise.all(
dirs.map(dir => execa('pnpm', ['nuxi', 'prepare'], { cwd: dir }))
)
}
initTesting()

53
test/suspense.test.ts Normal file
View File

@ -0,0 +1,53 @@
import { fileURLToPath } from 'node:url'
import { describe, expect, it } from 'vitest'
import { isWindows } from 'std-env'
import { setup } from '@nuxt/test-utils'
import { renderPage } from './utils'
const isWebpack = process.env.TEST_BUILDER === 'webpack'
await setup({
rootDir: fileURLToPath(new URL('./fixtures/suspense', import.meta.url)),
dev: process.env.TEST_ENV === 'dev',
server: true,
browser: true,
setupTimeout: (isWindows ? 360 : 120) * 1000,
nuxtConfig: {
builder: isWebpack ? 'webpack' : 'vite',
buildDir: process.env.NITRO_BUILD_DIR,
nitro: { output: { dir: process.env.NITRO_OUTPUT_DIR } }
}
})
describe('suspense multiple nav', () => {
it('should not throw error', async () => {
const { page, consoleLogs, pageErrors } = await renderPage('/')
await page.waitForLoadState('networkidle')
expect(await page.locator('#btn-a').textContent()).toMatchInlineSnapshot('" Target A "')
// Make sure it navigates to the correct page
await page.locator('#btn-a').click()
console.log(page.url())
expect(await page.locator('#content').textContent()).toContain('Hello a')
await page.goBack()
// When back
expect(await page.locator('body').textContent()).toContain('Index Page')
// So we click two navigations quickly, before the first one is resolved
await Promise.all([
page.locator('#btn-a').click(),
page.locator('#btn-b').click()
])
expect.soft(await page.locator('#content').textContent()).toContain('Hello b')
const consoleLogErrors = consoleLogs.filter(i => i.type === 'error')
const consoleLogWarnings = consoleLogs.filter(i => i.type === 'warning')
expect.soft(pageErrors).toEqual([])
expect.soft(consoleLogErrors).toEqual([])
expect.soft(consoleLogWarnings).toEqual([])
await page.close()
}, 60_000)
})