mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 00:23:53 +00:00
test: init hmr testing (#4372)
This commit is contained in:
parent
625022cf28
commit
5ede291a14
@ -18,6 +18,7 @@
|
||||
"vue/one-component-per-file": "off",
|
||||
"vue/require-default-prop": "off",
|
||||
"vue/no-multiple-template-root": "off",
|
||||
"vue/no-v-model-argument": "off",
|
||||
"jsdoc/require-jsdoc": "off",
|
||||
"jsdoc/require-param": "off",
|
||||
"jsdoc/require-returns": "off",
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -61,3 +61,5 @@ Temporary Items
|
||||
.build-*
|
||||
.env
|
||||
.netlify
|
||||
|
||||
fixtures-temp
|
||||
|
@ -1,15 +1,18 @@
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { promises as fsp } from 'node:fs'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { joinURL, withQuery } from 'ufo'
|
||||
import { isWindows } from 'std-env'
|
||||
import { normalize } from 'pathe'
|
||||
import { join, normalize } from 'pathe'
|
||||
// eslint-disable-next-line import/order
|
||||
import { setup, fetch, $fetch, startServer, createPage, url } from '@nuxt/test-utils'
|
||||
import type { NuxtIslandResponse } from '../packages/nuxt/src/core/runtime/nitro/renderer'
|
||||
import { expectNoClientErrors, renderPage, withLogs } from './utils'
|
||||
import { setup, fetch, $fetch, startServer, isDev, createPage, url } from '@nuxt/test-utils'
|
||||
|
||||
import type { NuxtIslandResponse } from '../packages/nuxt/src/core/runtime/nitro/renderer'
|
||||
import { expectNoClientErrors, fixturesDir, expectWithPolling, renderPage, withLogs } from './utils'
|
||||
|
||||
const fixturePath = join(fixturesDir, 'basic')
|
||||
await setup({
|
||||
rootDir: fileURLToPath(new URL('./fixtures/basic', import.meta.url)),
|
||||
rootDir: fixturePath,
|
||||
server: true,
|
||||
browser: true,
|
||||
setupTimeout: (isWindows ? 240 : 120) * 1000
|
||||
@ -981,3 +984,50 @@ describe.skipIf(isWindows)('useAsyncData', () => {
|
||||
await expectNoClientErrors('/useAsyncData/promise-all')
|
||||
})
|
||||
})
|
||||
|
||||
// HMR should be at the last
|
||||
// TODO: fix HMR on Windows
|
||||
if (isDev() && !isWindows) {
|
||||
describe('hmr', () => {
|
||||
it('should work', async () => {
|
||||
const { page, pageErrors, consoleLogs } = await renderPage('/')
|
||||
|
||||
expect(await page.title()).toBe('Basic fixture')
|
||||
expect((await page.$('.sugar-counter').then(r => r!.textContent()))!.trim())
|
||||
.toEqual('Sugar Counter 12 x 2 = 24 Inc')
|
||||
|
||||
// reactive
|
||||
await page.$('.sugar-counter button').then(r => r!.click())
|
||||
expect((await page.$('.sugar-counter').then(r => r!.textContent()))!.trim())
|
||||
.toEqual('Sugar Counter 13 x 2 = 26 Inc')
|
||||
|
||||
// modify file
|
||||
let indexVue = await fsp.readFile(join(fixturePath, 'pages/index.vue'), 'utf8')
|
||||
indexVue = indexVue
|
||||
.replace('<Title>Basic fixture</Title>', '<Title>Basic fixture HMR</Title>')
|
||||
.replace('<h1>Hello Nuxt 3!</h1>', '<h1>Hello Nuxt 3! HMR</h1>')
|
||||
indexVue += '<style scoped>\nh1 { color: red }\n</style>'
|
||||
await fsp.writeFile(join(fixturePath, 'pages/index.vue'), indexVue)
|
||||
|
||||
await expectWithPolling(
|
||||
() => page.title(),
|
||||
'Basic fixture HMR'
|
||||
)
|
||||
|
||||
// content HMR
|
||||
const h1 = await page.$('h1')
|
||||
expect(await h1!.textContent()).toBe('Hello Nuxt 3! HMR')
|
||||
|
||||
// style HMR
|
||||
const h1Color = await h1!.evaluate(el => window.getComputedStyle(el).getPropertyValue('color'))
|
||||
expect(h1Color).toMatchInlineSnapshot('"rgb(255, 0, 0)"')
|
||||
|
||||
// ensure no errors
|
||||
const consoleLogErrors = consoleLogs.filter(i => i.type === 'error')
|
||||
const consoleLogWarnings = consoleLogs.filter(i => i.type === 'warn')
|
||||
expect(pageErrors).toEqual([])
|
||||
expect(consoleLogErrors).toEqual([])
|
||||
expect(consoleLogWarnings).toEqual([])
|
||||
}, isWindows ? 60_000 : 30_000)
|
||||
})
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
defineProps({
|
||||
count: {
|
||||
multiplier: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
@ -9,6 +9,6 @@ defineProps({
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<SugarCounter :count="count" />
|
||||
<SugarCounter :multiplier="multiplier" />
|
||||
</div>
|
||||
</template>
|
||||
|
15
test/fixtures/basic/components/SugarCounter.vue
vendored
15
test/fixtures/basic/components/SugarCounter.vue
vendored
@ -1,14 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
count: number,
|
||||
// eslint-disable-next-line vue/no-setup-props-destructure
|
||||
const { multiplier } = defineProps<{
|
||||
multiplier: number
|
||||
}>()
|
||||
// eslint-disable-next-line prefer-const
|
||||
let multiplier = $ref(2)
|
||||
const doubled = $computed(() => props.count * multiplier)
|
||||
const count = $ref(12)
|
||||
const doubled = $computed(() => count * multiplier)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div class="sugar-counter">
|
||||
Sugar Counter {{ count }} x {{ multiplier }} = {{ doubled }}
|
||||
<button @click="count += 1">
|
||||
Inc
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
2
test/fixtures/basic/pages/index.vue
vendored
2
test/fixtures/basic/pages/index.vue
vendored
@ -14,7 +14,7 @@
|
||||
<NuxtLink to="/">
|
||||
Link
|
||||
</NuxtLink>
|
||||
<NestedSugarCounter :count="12" />
|
||||
<NestedSugarCounter :multiplier="2" />
|
||||
<CustomComponent />
|
||||
<component :is="`test${'-'.toString()}global`" />
|
||||
<component :is="`with${'-'.toString()}suffix`" />
|
||||
|
20
test/setup.ts
Normal file
20
test/setup.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { dirname, join } from 'node:path'
|
||||
import fs from 'fs-extra'
|
||||
|
||||
const dir = dirname(fileURLToPath(import.meta.url))
|
||||
const fixtureDir = join(dir, 'fixtures')
|
||||
const tempDir = join(dir, 'fixtures-temp')
|
||||
|
||||
export async function setup () {
|
||||
if (fs.existsSync(tempDir)) {
|
||||
await fs.remove(tempDir)
|
||||
}
|
||||
await fs.copy(fixtureDir, tempDir)
|
||||
}
|
||||
|
||||
export async function teardown () {
|
||||
if (fs.existsSync(tempDir)) {
|
||||
await fs.remove(tempDir)
|
||||
}
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { expect } from 'vitest'
|
||||
import type { Page } from 'playwright'
|
||||
import { createPage, getBrowser, url, useTestContext } from '@nuxt/test-utils'
|
||||
|
||||
export const fixturesDir = fileURLToPath(new URL(process.env.NUXT_TEST_DEV ? './fixtures-temp' : './fixtures', import.meta.url))
|
||||
|
||||
export async function renderPage (path = '/') {
|
||||
const ctx = useTestContext()
|
||||
if (!ctx.options.browser) {
|
||||
@ -50,6 +53,23 @@ export async function expectNoClientErrors (path: string) {
|
||||
expect(consoleLogWarnings).toEqual([])
|
||||
}
|
||||
|
||||
export async function expectWithPolling (
|
||||
get: () => Promise<string> | string,
|
||||
expected: string,
|
||||
retries = process.env.CI ? 100 : 30,
|
||||
delay = process.env.CI ? 500 : 100
|
||||
) {
|
||||
let result: string | undefined
|
||||
for (let i = retries; i >= 0; i--) {
|
||||
result = await get()
|
||||
if (result === expected) {
|
||||
break
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, delay))
|
||||
}
|
||||
expect(result).toEqual(expected)
|
||||
}
|
||||
|
||||
export async function withLogs (callback: (page: Page, logs: string[]) => Promise<void>) {
|
||||
let done = false
|
||||
const page = await createPage()
|
||||
|
@ -14,8 +14,11 @@ export default defineConfig({
|
||||
tsconfigRaw: '{}'
|
||||
},
|
||||
test: {
|
||||
globalSetup: 'test/setup.ts',
|
||||
testTimeout: isWindows ? 60000 : 10000,
|
||||
// Excluded plugin because it should throw an error when accidentally loaded via Nuxt
|
||||
exclude: [...configDefaults.exclude, '**/this-should-not-load.spec.js']
|
||||
exclude: [...configDefaults.exclude, '**/this-should-not-load.spec.js'],
|
||||
maxThreads: process.env.NUXT_TEST_DEV ? 1 : undefined,
|
||||
minThreads: process.env.NUXT_TEST_DEV ? 1 : undefined
|
||||
}
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user