test: unit test for islandsTransform

This commit is contained in:
julien huang 2023-08-19 12:06:32 +02:00
parent ba917cb2cf
commit 26dff83a84
2 changed files with 185 additions and 2 deletions

View File

@ -25,7 +25,7 @@ interface ComponentChunkOptions {
} }
const SCRIPT_RE = /<script[^>]*>/g const SCRIPT_RE = /<script[^>]*>/g
const HAS_SLOT_RE = /<slot[ /]/ const HAS_SLOT_OR_CLIENT_RE = /(<slot[ /])|(nuxt-client)/
const TEMPLATE_RE = /<template>([\s\S]*)<\/template>/ const TEMPLATE_RE = /<template>([\s\S]*)<\/template>/
const NUXTCLIENT_ATTR_RE = /\snuxt-client(="[^"]*")?/g const NUXTCLIENT_ATTR_RE = /\snuxt-client(="[^"]*")?/g
@ -46,7 +46,7 @@ export const islandsTransform = createUnplugin((options: ServerOnlyComponentTran
return islands.some(c => c.filePath === pathname) return islands.some(c => c.filePath === pathname)
}, },
async transform (code, id) { async transform (code, id) {
if (!HAS_SLOT_RE.test(code)) { return } if (!HAS_SLOT_OR_CLIENT_RE.test(code)) { return }
const template = code.match(TEMPLATE_RE) const template = code.match(TEMPLATE_RE)
if (!template) { return } if (!template) { return }
const startingIndex = template.index || 0 const startingIndex = template.index || 0

View File

@ -0,0 +1,183 @@
import { describe, expect, it, vi } from 'vitest'
import type { Plugin } from 'vite'
import type { Component } from '@nuxt/schema'
import type { UnpluginOptions } from 'unplugin'
import { islandsTransform } from '../src/components/islandsTransform'
import { normalizeLineEndings } from './utils'
const getComponents = () => [{
filePath: 'hello.server.vue',
mode: 'server',
pascalName: 'HelloWorld',
island: true,
kebabName: 'hello-world',
chunkName: 'components/hello-world',
export: 'default',
shortPath: '',
prefetch: false,
preload: false
}] as Component[]
const pluginVite = islandsTransform.raw({
getComponents,
rootDir: ''
}, { framework: 'vite' }) as Plugin
const pluginWebpack = islandsTransform.raw({
getComponents,
rootDir: ''
}, { framework: 'webpack', webpack: { compiler: {} as any } })
const viteTransform = async (source: string, id: string) => {
const result = await (pluginVite.transform! as Function).call({ error: null, warn: null } as any, source, id)
return typeof result === 'string' ? result : result?.code
}
const webpackTransform = async (source: string, id: string) => {
const result = await ((pluginWebpack as UnpluginOptions).transform! as Function).call({ error: null, warn: null } as any, source, id)
return typeof result === 'string' ? result : result?.code
}
describe('islandTransform - server and island components', () => {
describe('slots', () => {
it('expect slot transform to match inline snapshot', async () => {
const result = await viteTransform(`<template>
<div>
<slot />
<slot name="named" :some-data="someData" />
</div>
</template>
<script setup lang="ts">
const someData = 'some data'
</script>`
, 'hello.server.vue')
expect(normalizeLineEndings(result)).toMatchInlineSnapshot(`
"<template>
<div>
<div style=\\"display: contents;\\" nuxt-ssr-slot-name=\\"default\\" />
<div style=\\"display: contents;\\" nuxt-ssr-slot-name=\\"named\\" :nuxt-ssr-slot-data=\\"JSON.stringify([{ some-data: someData }])\\"/>
</div>
</template>
<script setup lang=\\"ts\\">
import { vforToArray as __vforToArray } from '#app/components/utils'
import TeleportIfClient from '#app/components/TeleportIfClient'
const someData = 'some data'
</script>"
`)
})
it('expect slot fallback transform to match inline snapshot', async () => {
const result = await viteTransform(`<template>
<div>
<slot :some-data="someData">
<div>fallback</div>
</slot>
</div>
</template>
<script setup lang="ts">
const someData = 'some data'
</script>`
, 'hello.server.vue')
expect(normalizeLineEndings(result)).toMatchInlineSnapshot(`
"<template>
<div>
<div style=\\"display: contents;\\" nuxt-ssr-slot-name=\\"default\\" :nuxt-ssr-slot-data=\\"JSON.stringify([{ some-data: someData }])\\"><div nuxt-slot-fallback-start=\\"default\\"/><div style=\\"display: contents;\\">
<div>fallback</div>
</div><div nuxt-slot-fallback-end/></div>
</div>
</template>
<script setup lang=\\"ts\\">
import { vforToArray as __vforToArray } from '#app/components/utils'
import TeleportIfClient from '#app/components/TeleportIfClient'
const someData = 'some data'
</script>"
`)
})
})
describe('nuxt-client', () => {
it('test transform with vite', async () => {
const result = await viteTransform(`<template>
<div>
<!-- should not be wrapped by TeleportIfClient -->
<HelloWorld />
<!-- should be wrapped by TeleportIfClient -->
<HelloWorld nuxt-client />
</div>
</template>
<script setup lang="ts">
import HelloWorld from './HelloWorld.vue'
</script>
`, 'hello.server.vue')
expect(normalizeLineEndings(result)).toMatchInlineSnapshot(`
"<template>
<div>
<!-- should not be wrapped by TeleportIfClient -->
<HelloWorld />
<!-- should be wrapped by TeleportIfClient -->
<TeleportIfClient to=\\"HelloWorld-5tg8bjdS1w\\" :nuxt-client=\\"true\\"><HelloWorld /></TeleportIfClient>
</div>
</template>
<script setup lang=\\"ts\\">
import { vforToArray as __vforToArray } from '#app/components/utils'
import TeleportIfClient from '#app/components/TeleportIfClient'
import HelloWorld from './HelloWorld.vue'
</script>
"
`)
})
it('test transform with webpack', async () => {
const spyOnWarn = vi.spyOn(console, 'warn')
const result = await webpackTransform(`<template>
<div>
<!-- should not be wrapped by TeleportIfClient -->
<HelloWorld />
<!-- should be not wrapped by TeleportIfClient for now -->
<HelloWorld nuxt-client />
</div>
</template>
<script setup lang="ts">
import HelloWorld from './HelloWorld.vue'
const someData = 'some data'
</script>
`, 'hello.server.vue')
expect(normalizeLineEndings(result)).toMatchInlineSnapshot(`
"<template>
<div>
<!-- should not be wrapped by TeleportIfClient -->
<HelloWorld />
<!-- should be not wrapped by TeleportIfClient for now -->
<HelloWorld nuxt-client />
</div>
</template>
<script setup lang=\\"ts\\">
import { vforToArray as __vforToArray } from '#app/components/utils'
import TeleportIfClient from '#app/components/TeleportIfClient'
import HelloWorld from './HelloWorld.vue'
const someData = 'some data'
</script>
"
`)
expect(spyOnWarn).toHaveBeenCalledWith('nuxt-client attribute and client components within islands is only supported in vite mode. file: hello.server.vue')
})
})
})