2022-02-18 18:14:57 +00:00
|
|
|
import { fileURLToPath } from 'url'
|
|
|
|
import { describe, expect, it } from 'vitest'
|
2022-03-24 12:33:42 +00:00
|
|
|
import { setup, fetch, $fetch, startServer } from '@nuxt/test-utils'
|
2022-02-18 18:14:57 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
await setup({
|
|
|
|
rootDir: fileURLToPath(new URL('./fixtures/basic', import.meta.url)),
|
|
|
|
server: true
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('server api', () => {
|
|
|
|
it('should serialize', async () => {
|
|
|
|
expect(await $fetch('/api/hello')).toBe('Hello API')
|
|
|
|
expect(await $fetch('/api/hey')).toEqual({
|
|
|
|
foo: 'bar',
|
|
|
|
baz: 'qux'
|
2022-03-08 18:03:21 +00:00
|
|
|
})
|
2022-03-22 18:12:54 +00:00
|
|
|
})
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
it('should preserve states', async () => {
|
|
|
|
expect(await $fetch('/api/counter')).toEqual({ count: 0 })
|
|
|
|
expect(await $fetch('/api/counter')).toEqual({ count: 1 })
|
|
|
|
expect(await $fetch('/api/counter')).toEqual({ count: 2 })
|
|
|
|
expect(await $fetch('/api/counter')).toEqual({ count: 3 })
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('pages', () => {
|
|
|
|
it('render index', async () => {
|
|
|
|
const html = await $fetch('/')
|
|
|
|
|
|
|
|
// Snapshot
|
|
|
|
// expect(html).toMatchInlineSnapshot()
|
|
|
|
|
|
|
|
// should render text
|
|
|
|
expect(html).toContain('Hello Nuxt 3!')
|
|
|
|
// should render <Head> components
|
|
|
|
expect(html).toContain('<title>Basic fixture</title>')
|
|
|
|
// should inject runtime config
|
|
|
|
expect(html).toContain('RuntimeConfig | testConfig: 123')
|
|
|
|
// composables auto import
|
|
|
|
expect(html).toContain('Composable | foo: auto imported from ~/components/foo.ts')
|
|
|
|
expect(html).toContain('Composable | bar: auto imported from ~/components/useBar.ts')
|
|
|
|
// plugins
|
|
|
|
expect(html).toContain('Plugin | myPlugin: Injected by my-plugin')
|
|
|
|
// should import components
|
|
|
|
expect(html).toContain('This is a custom component with a named export.')
|
2022-03-08 18:03:21 +00:00
|
|
|
})
|
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
it('render 404', async () => {
|
|
|
|
const html = await $fetch('/not-found')
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
// Snapshot
|
|
|
|
// expect(html).toMatchInlineSnapshot()
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
expect(html).toContain('[...slug].vue')
|
|
|
|
expect(html).toContain('404 at not-found')
|
|
|
|
})
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
it('/nested/[foo]/[bar].vue', async () => {
|
|
|
|
const html = await $fetch('/nested/one/two')
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
// Snapshot
|
|
|
|
// expect(html).toMatchInlineSnapshot()
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
expect(html).toContain('nested/[foo]/[bar].vue')
|
|
|
|
expect(html).toContain('foo: one')
|
|
|
|
expect(html).toContain('bar: two')
|
|
|
|
})
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
it('/nested/[foo]/index.vue', async () => {
|
|
|
|
const html = await $fetch('/nested/foobar')
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
// TODO: should resolved to same entry
|
|
|
|
// const html2 = await $fetch('/nested/foobar/index')
|
|
|
|
// expect(html).toEqual(html2)
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
// Snapshot
|
|
|
|
// expect(html).toMatchInlineSnapshot()
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
expect(html).toContain('nested/[foo]/index.vue')
|
|
|
|
expect(html).toContain('foo: foobar')
|
|
|
|
})
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
it('/nested/[foo]/user-[group].vue', async () => {
|
|
|
|
const html = await $fetch('/nested/foobar/user-admin')
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
// Snapshot
|
|
|
|
// expect(html).toMatchInlineSnapshot()
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
expect(html).toContain('nested/[foo]/user-[group].vue')
|
|
|
|
expect(html).toContain('foo: foobar')
|
|
|
|
expect(html).toContain('group: admin')
|
|
|
|
})
|
|
|
|
})
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
describe('navigate', () => {
|
|
|
|
it('should redirect to index with navigateTo', async () => {
|
|
|
|
const html = await $fetch('/navigate-to/')
|
|
|
|
|
|
|
|
// Snapshot
|
|
|
|
// expect(html).toMatchInlineSnapshot()
|
|
|
|
|
|
|
|
expect(html).toContain('Hello Nuxt 3!')
|
2022-03-08 18:03:21 +00:00
|
|
|
})
|
2022-03-22 18:12:54 +00:00
|
|
|
})
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
describe('middlewares', () => {
|
|
|
|
it('should redirect to index with global middleware', async () => {
|
|
|
|
const html = await $fetch('/redirect/')
|
2022-03-16 21:39:47 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
// Snapshot
|
|
|
|
// expect(html).toMatchInlineSnapshot()
|
2022-03-16 21:39:47 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
expect(html).toContain('Hello Nuxt 3!')
|
2022-03-16 21:39:47 +00:00
|
|
|
})
|
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
it('should inject auth', async () => {
|
|
|
|
const html = await $fetch('/auth')
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
// Snapshot
|
|
|
|
// expect(html).toMatchInlineSnapshot()
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
expect(html).toContain('auth.vue')
|
|
|
|
expect(html).toContain('auth: Injected by injectAuth middleware')
|
|
|
|
})
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
it('should not inject auth', async () => {
|
|
|
|
const html = await $fetch('/no-auth')
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
// Snapshot
|
|
|
|
// expect(html).toMatchInlineSnapshot()
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
expect(html).toContain('no-auth.vue')
|
|
|
|
expect(html).toContain('auth: ')
|
|
|
|
expect(html).not.toContain('Injected by injectAuth middleware')
|
|
|
|
})
|
|
|
|
})
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
describe('layouts', () => {
|
|
|
|
it('should apply custom layout', async () => {
|
|
|
|
const html = await $fetch('/with-layout')
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
// Snapshot
|
|
|
|
// expect(html).toMatchInlineSnapshot()
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
expect(html).toContain('with-layout.vue')
|
|
|
|
expect(html).toContain('Custom Layout:')
|
2022-02-25 20:14:53 +00:00
|
|
|
})
|
2022-03-22 18:12:54 +00:00
|
|
|
})
|
2022-02-25 20:14:53 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
describe('reactivity transform', () => {
|
|
|
|
it('should works', async () => {
|
|
|
|
const html = await $fetch('/')
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
expect(html).toContain('Sugar Counter 12 x 2 = 24')
|
|
|
|
})
|
|
|
|
})
|
2022-03-08 18:03:21 +00:00
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
describe('extends support', () => {
|
2022-03-24 12:33:42 +00:00
|
|
|
describe('layouts & pages', () => {
|
|
|
|
it('extends foo/layouts/default & foo/pages/index', async () => {
|
2022-03-22 18:12:54 +00:00
|
|
|
const html = await $fetch('/foo')
|
2022-03-24 12:33:42 +00:00
|
|
|
expect(html).toContain('Extended layout from foo')
|
|
|
|
expect(html).toContain('Extended page from foo')
|
2022-03-22 18:12:54 +00:00
|
|
|
})
|
|
|
|
|
2022-03-24 12:33:42 +00:00
|
|
|
it('extends [bar/layouts/override & bar/pages/override] over [foo/layouts/override & foo/pages/override]', async () => {
|
2022-03-22 18:12:54 +00:00
|
|
|
const html = await $fetch('/override')
|
2022-03-24 12:33:42 +00:00
|
|
|
expect(html).toContain('Extended layout from bar')
|
2022-03-22 18:12:54 +00:00
|
|
|
expect(html).toContain('Extended page from bar')
|
2022-03-08 18:03:21 +00:00
|
|
|
})
|
2022-02-18 18:14:57 +00:00
|
|
|
})
|
2022-03-17 22:17:59 +00:00
|
|
|
|
2022-03-24 12:33:42 +00:00
|
|
|
describe('components', () => {
|
|
|
|
it('extends foo/components/ExtendsFoo', async () => {
|
|
|
|
const html = await $fetch('/foo')
|
|
|
|
expect(html).toContain('Extended component from foo')
|
|
|
|
})
|
|
|
|
|
|
|
|
it('extends bar/components/ExtendsOverride over foo/components/ExtendsOverride', async () => {
|
|
|
|
const html = await $fetch('/override')
|
|
|
|
expect(html).toContain('Extended component from bar')
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2022-03-22 18:12:54 +00:00
|
|
|
describe('middlewares', () => {
|
|
|
|
it('extends foo/middleware/foo', async () => {
|
2022-03-24 12:33:42 +00:00
|
|
|
const html = await $fetch('/foo')
|
|
|
|
expect(html).toContain('Middleware | foo: Injected by extended middleware from foo')
|
|
|
|
})
|
|
|
|
|
|
|
|
it('extends bar/middleware/override over foo/middleware/override', async () => {
|
|
|
|
const html = await $fetch('/override')
|
|
|
|
expect(html).toContain('Middleware | override: Injected by extended middleware from bar')
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('composables', () => {
|
|
|
|
it('extends foo/composables/foo', async () => {
|
|
|
|
const html = await $fetch('/foo')
|
|
|
|
expect(html).toContain('Composable | useExtendsFoo: foo')
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('plugins', () => {
|
|
|
|
it('extends foo/plugins/foo', async () => {
|
|
|
|
const html = await $fetch('/foo')
|
|
|
|
expect(html).toContain('Plugin | foo: String generated from foo plugin!')
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('server', () => {
|
|
|
|
it('extends foo/server/api/foo', async () => {
|
|
|
|
expect(await $fetch('/api/foo')).toBe('foo')
|
2022-03-22 18:12:54 +00:00
|
|
|
})
|
2022-03-17 22:17:59 +00:00
|
|
|
|
2022-03-24 12:33:42 +00:00
|
|
|
it('extends foo/server/middleware/foo', async () => {
|
|
|
|
const { headers } = await fetch('/')
|
|
|
|
expect(headers.get('injected-header')).toEqual('foo')
|
2022-03-17 22:17:59 +00:00
|
|
|
})
|
|
|
|
})
|
2022-03-23 14:57:35 +00:00
|
|
|
})
|
2022-03-22 15:51:26 +00:00
|
|
|
|
2022-03-23 14:57:35 +00:00
|
|
|
describe('dynamic paths', () => {
|
|
|
|
it('should work with no overrides', async () => {
|
|
|
|
const html = await $fetch('/assets')
|
|
|
|
for (const match of html.matchAll(/(href|src)="(.*?)"/g)) {
|
|
|
|
const url = match[2]
|
|
|
|
expect(url.startsWith('/_nuxt/') || url === '/public.svg').toBeTruthy()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
it('adds relative paths to CSS', async () => {
|
|
|
|
const html = await $fetch('/assets')
|
|
|
|
const urls = Array.from(html.matchAll(/(href|src)="(.*?)"/g)).map(m => m[2])
|
|
|
|
const cssURL = urls.find(u => /_nuxt\/entry.*\.css$/.test(u))
|
|
|
|
if (process.env.TEST_WITH_WEBPACK) {
|
|
|
|
// Webpack injects CSS differently
|
|
|
|
return
|
|
|
|
}
|
|
|
|
const css = await $fetch(cssURL)
|
|
|
|
const imageUrls = Array.from(css.matchAll(/url\(([^)]*)\)/g)).map(m => m[1].replace(/[-.][\w]{8}\./g, '.'))
|
|
|
|
expect(imageUrls).toMatchInlineSnapshot(`
|
2022-03-22 15:51:26 +00:00
|
|
|
[
|
|
|
|
"./logo.svg",
|
|
|
|
"../public.svg",
|
|
|
|
]
|
|
|
|
`)
|
2022-03-23 14:57:35 +00:00
|
|
|
})
|
2022-03-22 15:51:26 +00:00
|
|
|
|
2022-03-23 14:57:35 +00:00
|
|
|
it('should allow setting base URL and build assets directory', async () => {
|
|
|
|
process.env.NUXT_APP_BUILD_ASSETS_DIR = '/_other/'
|
|
|
|
process.env.NUXT_APP_BASE_URL = '/foo/'
|
|
|
|
await startServer()
|
2022-03-22 15:51:26 +00:00
|
|
|
|
2022-03-23 14:57:35 +00:00
|
|
|
const html = await $fetch('/assets')
|
|
|
|
for (const match of html.matchAll(/(href|src)="(.*?)"/g)) {
|
|
|
|
const url = match[2]
|
|
|
|
// TODO: webpack does not yet support dynamic static paths
|
|
|
|
expect(url.startsWith('/foo/_other/') || url === '/foo/public.svg' || (process.env.TEST_WITH_WEBPACK && url === '/public.svg')).toBeTruthy()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should allow setting CDN URL', async () => {
|
|
|
|
process.env.NUXT_APP_BASE_URL = '/foo/'
|
|
|
|
process.env.NUXT_APP_CDN_URL = 'https://example.com/'
|
|
|
|
process.env.NUXT_APP_BUILD_ASSETS_DIR = '/_cdn/'
|
|
|
|
await startServer()
|
|
|
|
|
|
|
|
const html = await $fetch('/assets')
|
|
|
|
for (const match of html.matchAll(/(href|src)="(.*?)"/g)) {
|
|
|
|
const url = match[2]
|
|
|
|
// TODO: webpack does not yet support dynamic static paths
|
|
|
|
expect(url.startsWith('https://example.com/_cdn/') || url === 'https://example.com/public.svg' || (process.env.TEST_WITH_WEBPACK && url === '/public.svg')).toBeTruthy()
|
|
|
|
}
|
2022-03-22 15:51:26 +00:00
|
|
|
})
|
2022-02-18 18:14:57 +00:00
|
|
|
})
|