2023-12-19 12:21:29 +00:00
import { describe , expect , it , vi } from 'vitest'
2023-09-14 21:44:18 +00:00
import type { Plugin } from 'vite'
import type { Component } from '@nuxt/schema'
2023-12-19 12:21:29 +00:00
import type { UnpluginOptions } from 'unplugin'
2023-09-14 21:44:18 +00:00
import { islandsTransform } from '../src/components/islandsTransform'
import { normalizeLineEndings } from './utils'
const getComponents = ( ) = > [ {
filePath : '/root/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 [ ]
2023-12-19 12:21:29 +00:00
const pluginWebpack = islandsTransform . raw ( {
getComponents ,
selectiveClient : true
} , { framework : 'webpack' , webpack : { compiler : { } as any } } )
2023-09-14 21:44:18 +00:00
2023-12-19 12:21:29 +00:00
const viteTransform = async ( source : string , id : string , isDev = false , selectiveClient = false ) = > {
const vitePlugin = islandsTransform . raw ( {
getComponents ,
rootDir : '/root' ,
isDev ,
selectiveClient
} , { framework : 'vite' } ) as Plugin
const result = await ( vitePlugin . transform ! as Function ) ( 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 ) ( source , id )
2023-09-14 21:44:18 +00:00
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" / >
2023-11-09 13:45:45 +00:00
< slot
name = "other"
: some - data = "someData"
/ >
2023-09-14 21:44:18 +00:00
< / div >
< / template >
< script setup lang = "ts" >
const someData = 'some data'
2023-11-09 13:45:45 +00:00
2023-09-14 21:44:18 +00:00
< / script > `
2024-01-16 16:33:45 +00:00
, 'hello.server.vue' )
2023-09-14 21:44:18 +00:00
expect ( normalizeLineEndings ( result ) ) . toMatchInlineSnapshot ( `
" < template >
< div >
2024-01-16 13:22:50 +00:00
< NuxtTeleportSsrSlot name = "default" : props = "undefined" > < slot / > < / NuxtTeleportSsrSlot >
2023-09-14 21:44:18 +00:00
2024-01-16 13:22:50 +00:00
< NuxtTeleportSsrSlot name = "named" : props = "[{ some-data: someData }]" > < slot name = "named" : some - data = "someData" / > < / NuxtTeleportSsrSlot >
< NuxtTeleportSsrSlot name = "other" : props = "[{ some-data: someData }]" > < slot
name = "other"
: some - data = "someData"
/ > < / N u x t T e l e p o r t S s r S l o t >
2023-09-14 21:44:18 +00:00
< / div >
< / template >
2023-12-11 18:20:11 +00:00
< script setup lang = "ts" >
2023-09-14 21:44:18 +00:00
import { vforToArray as __vforToArray } from '#app/components/utils'
2024-01-16 16:33:45 +00:00
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
2024-01-16 13:22:50 +00:00
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
2023-09-14 21:44:18 +00:00
const someData = 'some data'
2023-11-09 13:45:45 +00:00
2023-09-14 21:44:18 +00:00
< / 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'
2023-11-09 13:45:45 +00:00
2023-09-14 21:44:18 +00:00
< / script > `
2024-01-16 16:33:45 +00:00
, 'hello.server.vue' )
2023-09-14 21:44:18 +00:00
expect ( normalizeLineEndings ( result ) ) . toMatchInlineSnapshot ( `
" < template >
< div >
2024-01-16 13:22:50 +00:00
< NuxtTeleportSsrSlot name = "default" : props = "[{ some-data: someData }]" > < slot : some - data = "someData" / > < template # fallback >
2023-09-14 21:44:18 +00:00
< div > fallback < / div >
2024-01-16 13:22:50 +00:00
< / template > < / NuxtTeleportSsrSlot >
2023-09-14 21:44:18 +00:00
< / div >
< / template >
2023-12-11 18:20:11 +00:00
< script setup lang = "ts" >
2023-09-14 21:44:18 +00:00
import { vforToArray as __vforToArray } from '#app/components/utils'
2024-01-16 16:33:45 +00:00
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
2024-01-16 13:22:50 +00:00
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
2023-09-14 21:44:18 +00:00
const someData = 'some data'
2023-11-09 13:45:45 +00:00
2023-09-14 21:44:18 +00:00
< / script > "
` )
} )
it ( 'expect slot transform with fallback and no name to match inline snapshot #23209' , async ( ) = > {
const result = await viteTransform ( ` <template>
< div >
< UCard >
< template # header >
< h3 > Partial Hydration Example - Server - { { count } } < / h3 >
< / template >
< template # default >
< p > message : { { message } } < / p >
< p > Below is the slot I want to be hydrated on the client < / p >
< div >
< slot >
This is the default content of the slot , I should not see this after
the client loading has completed .
< / slot >
< / div >
< p > Above is the slot I want to be hydrated on the client < / p >
< / template >
< / UCard >
< / div >
< / template >
2023-11-09 13:45:45 +00:00
2023-09-14 21:44:18 +00:00
< script setup lang = "ts" >
export interface Props {
count? : number ;
}
const props = withDefaults ( defineProps < Props > ( ) , { count : 0 } ) ;
2023-11-09 13:45:45 +00:00
2023-09-14 21:44:18 +00:00
const message = "Hello World" ;
< / script >
`
2024-01-16 16:33:45 +00:00
, 'hello.server.vue' )
2023-09-14 21:44:18 +00:00
expect ( normalizeLineEndings ( result ) ) . toMatchInlineSnapshot ( `
" < template >
< div >
< UCard >
< template # header >
< h3 > Partial Hydration Example - Server - { { count } } < / h3 >
< / template >
< template # default >
< p > message : { { message } } < / p >
< p > Below is the slot I want to be hydrated on the client < / p >
< div >
2024-01-16 13:22:50 +00:00
< NuxtTeleportSsrSlot name = "default" : props = "undefined" > < slot / > < template # fallback >
2023-09-14 21:44:18 +00:00
This is the default content of the slot , I should not see this after
the client loading has completed .
2024-01-16 13:22:50 +00:00
< / template > < / NuxtTeleportSsrSlot >
2023-09-14 21:44:18 +00:00
< / div >
< p > Above is the slot I want to be hydrated on the client < / p >
< / template >
< / UCard >
< / div >
< / template >
2023-11-09 13:45:45 +00:00
2023-12-11 18:20:11 +00:00
< script setup lang = "ts" >
2023-09-14 21:44:18 +00:00
import { vforToArray as __vforToArray } from '#app/components/utils'
2024-01-16 16:33:45 +00:00
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
2024-01-16 13:22:50 +00:00
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
2023-09-14 21:44:18 +00:00
export interface Props {
count? : number ;
}
const props = withDefaults ( defineProps < Props > ( ) , { count : 0 } ) ;
2023-11-09 13:45:45 +00:00
2023-12-11 18:20:11 +00:00
const message = "Hello World" ;
2023-09-14 21:44:18 +00:00
< / script >
"
` )
} )
} )
2023-12-19 12:21:29 +00:00
describe ( 'nuxt-client' , ( ) = > {
describe ( 'vite' , ( ) = > {
it ( 'test transform with vite in dev' , async ( ) = > {
const result = await viteTransform ( ` <template>
< div >
2024-01-16 16:33:45 +00:00
<!-- should not be wrapped by NuxtTeleportIslandComponent -- >
2023-12-19 12:21:29 +00:00
< HelloWorld / >
2024-01-16 16:33:45 +00:00
<!-- should be wrapped by NuxtTeleportIslandComponent with a rootDir attr -- >
2023-12-19 12:21:29 +00:00
< HelloWorld nuxt - client / >
< / div >
< / template >
2024-01-16 16:33:45 +00:00
2023-12-19 12:21:29 +00:00
< script setup lang = "ts" >
import HelloWorld from './HelloWorld.vue'
< / script >
` , 'hello.server.vue', true, true)
expect ( normalizeLineEndings ( result ) ) . toMatchInlineSnapshot ( `
" < template >
< div >
2024-01-16 16:33:45 +00:00
<!-- should not be wrapped by NuxtTeleportIslandComponent -- >
2023-12-19 12:21:29 +00:00
< HelloWorld / >
2024-01-16 16:33:45 +00:00
<!-- should be wrapped by NuxtTeleportIslandComponent with a rootDir attr -- >
< NuxtTeleportIslandComponent to = "HelloWorld-ZsRS8qEyqK" root - dir = "/root" : nuxt - client = "true" > < HelloWorld / > < / NuxtTeleportIslandComponent >
2023-12-19 12:21:29 +00:00
< / div >
< / template >
2024-01-16 16:33:45 +00:00
2023-12-19 20:03:09 +00:00
< script setup lang = "ts" >
2023-12-19 12:21:29 +00:00
import { vforToArray as __vforToArray } from '#app/components/utils'
2024-01-16 16:33:45 +00:00
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
2024-01-16 13:22:50 +00:00
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
2023-12-19 12:21:29 +00:00
import HelloWorld from './HelloWorld.vue'
< / script >
"
` )
// root-dir prop should never be used in production
expect ( result ) . toContain ( 'root-dir="/root"' )
} )
it ( 'test transform with vite in prod' , async ( ) = > {
const result = await viteTransform ( ` <template>
< div >
< HelloWorld / >
< HelloWorld nuxt - client / >
< / div >
< / template >
2024-01-16 16:33:45 +00:00
2023-12-19 12:21:29 +00:00
< script setup lang = "ts" >
import HelloWorld from './HelloWorld.vue'
< / script >
` , 'hello.server.vue', false, true)
expect ( normalizeLineEndings ( result ) ) . toMatchInlineSnapshot ( `
" < template >
< div >
< HelloWorld / >
2024-01-16 16:33:45 +00:00
< NuxtTeleportIslandComponent to = "HelloWorld-CyH3UXLuYA" : nuxt - client = "true" > < HelloWorld / > < / NuxtTeleportIslandComponent >
2023-12-19 12:21:29 +00:00
< / div >
< / template >
2024-01-16 16:33:45 +00:00
2023-12-19 20:03:09 +00:00
< script setup lang = "ts" >
2023-12-19 12:21:29 +00:00
import { vforToArray as __vforToArray } from '#app/components/utils'
2024-01-16 16:33:45 +00:00
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
2024-01-16 13:22:50 +00:00
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
2023-12-19 12:21:29 +00:00
import HelloWorld from './HelloWorld.vue'
< / script >
"
` )
// root-dir prop should never be used in production
expect ( result ) . not . toContain ( 'root-dir="' )
} )
it ( 'test dynamic nuxt-client' , async ( ) = > {
const result = await viteTransform ( ` <template>
< div >
< HelloWorld / >
< HelloWorld : nuxt - client = "nuxtClient" / >
< / div >
< / template >
2024-01-16 16:33:45 +00:00
2023-12-19 12:21:29 +00:00
< script setup lang = "ts" >
import HelloWorld from './HelloWorld.vue'
const nuxtClient = false
< / script >
` , 'hello.server.vue', false, true)
expect ( normalizeLineEndings ( result ) ) . toMatchInlineSnapshot ( `
" < template >
< div >
< HelloWorld / >
2024-01-16 16:33:45 +00:00
< NuxtTeleportIslandComponent to = "HelloWorld-eo0XycWCUV" : nuxt - client = "nuxtClient" > < HelloWorld : nuxt - client = "nuxtClient" / > < / NuxtTeleportIslandComponent >
2023-12-19 12:21:29 +00:00
< / div >
< / template >
2024-01-16 16:33:45 +00:00
2023-12-19 20:03:09 +00:00
< script setup lang = "ts" >
2023-12-19 12:21:29 +00:00
import { vforToArray as __vforToArray } from '#app/components/utils'
2024-01-16 16:33:45 +00:00
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
2024-01-16 13:22:50 +00:00
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
2023-12-19 12:21:29 +00:00
import HelloWorld from './HelloWorld.vue'
const nuxtClient = false
< / script >
"
` )
} )
it ( 'should not transform if disabled' , async ( ) = > {
const result = await viteTransform ( ` <template>
< div >
< HelloWorld / >
< HelloWorld : nuxt - client = "nuxtClient" / >
< / div >
< / template >
2024-01-16 16:33:45 +00:00
2023-12-19 12:21:29 +00:00
< script setup lang = "ts" >
import HelloWorld from './HelloWorld.vue'
const nuxtClient = false
< / script >
` , 'hello.server.vue', false, false)
expect ( normalizeLineEndings ( result ) ) . toMatchInlineSnapshot ( `
" < template >
< div >
< HelloWorld / >
2023-12-19 20:03:09 +00:00
< HelloWorld : nuxt - client = "nuxtClient" / >
2023-12-19 12:21:29 +00:00
< / div >
< / template >
2024-01-16 16:33:45 +00:00
2023-12-19 20:03:09 +00:00
< script setup lang = "ts" >
2023-12-19 12:21:29 +00:00
import { vforToArray as __vforToArray } from '#app/components/utils'
2024-01-16 16:33:45 +00:00
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
2024-01-16 13:22:50 +00:00
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
2023-12-19 12:21:29 +00:00
import HelloWorld from './HelloWorld.vue'
const nuxtClient = false
< / script >
"
` )
} )
2024-01-11 14:40:02 +00:00
it ( 'should add import if there is no scripts in the SFC' , async ( ) = > {
const result = await viteTransform ( ` <template>
< div >
< HelloWorld / >
< HelloWorld nuxt - client / >
< / div >
< / template >
2024-01-16 16:33:45 +00:00
2024-01-11 14:40:02 +00:00
` , 'hello.server.vue', false, true)
2024-01-16 16:33:45 +00:00
expect ( result ) . toMatchInlineSnapshot ( `
2024-01-11 14:40:02 +00:00
" < script setup >
import { vforToArray as __vforToArray } from '#app/components/utils'
2024-01-16 16:33:45 +00:00
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
2024-01-16 13:22:50 +00:00
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot' < / script > < template >
2024-01-11 14:40:02 +00:00
< div >
< HelloWorld / >
2024-01-16 16:33:45 +00:00
< NuxtTeleportIslandComponent to = "HelloWorld-CyH3UXLuYA" : nuxt - client = "true" > < HelloWorld / > < / NuxtTeleportIslandComponent >
2024-01-11 14:40:02 +00:00
< / div >
< / template >
2024-01-16 16:33:45 +00:00
2024-01-11 14:40:02 +00:00
"
` )
2024-01-16 16:33:45 +00:00
expect ( result ) . toContain ( ` import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component' ` )
2024-01-11 14:40:02 +00:00
} )
2023-12-19 12:21:29 +00:00
} )
describe ( 'webpack' , ( ) = > {
it ( 'test transform with webpack' , async ( ) = > {
const spyOnWarn = vi . spyOn ( console , 'warn' )
const result = await webpackTransform ( ` <template>
< div >
2024-01-16 16:33:45 +00:00
<!-- should not be wrapped by NuxtTeleportIslandComponent -- >
2023-12-19 12:21:29 +00:00
< HelloWorld / >
2024-01-16 16:33:45 +00:00
<!-- should be not wrapped by NuxtTeleportIslandComponent for now -- >
2023-12-19 12:21:29 +00:00
< HelloWorld nuxt - client / >
< / div >
< / template >
2024-01-16 16:33:45 +00:00
2023-12-19 12:21:29 +00:00
< script setup lang = "ts" >
import HelloWorld from './HelloWorld.vue'
2024-01-16 16:33:45 +00:00
2023-12-19 12:21:29 +00:00
const someData = 'some data'
< / script >
` , 'hello.server.vue')
expect ( normalizeLineEndings ( result ) ) . toMatchInlineSnapshot ( `
" < template >
< div >
2024-01-16 16:33:45 +00:00
<!-- should not be wrapped by NuxtTeleportIslandComponent -- >
2023-12-19 12:21:29 +00:00
< HelloWorld / >
2024-01-16 16:33:45 +00:00
<!-- should be not wrapped by NuxtTeleportIslandComponent for now -- >
2023-12-19 12:21:29 +00:00
< HelloWorld nuxt - client / >
< / div >
< / template >
2024-01-16 16:33:45 +00:00
2023-12-19 20:03:09 +00:00
< script setup lang = "ts" >
2023-12-19 12:21:29 +00:00
import { vforToArray as __vforToArray } from '#app/components/utils'
2024-01-16 16:33:45 +00:00
import NuxtTeleportIslandComponent from '#app/components/nuxt-teleport-island-component'
2024-01-16 13:22:50 +00:00
import NuxtTeleportSsrSlot from '#app/components/nuxt-teleport-island-slot'
2023-12-19 12:21:29 +00:00
import HelloWorld from './HelloWorld.vue'
2024-01-16 16:33:45 +00:00
2023-12-19 12:21:29 +00:00
const someData = 'some data'
< / script >
"
` )
expect ( spyOnWarn ) . toHaveBeenCalledWith ( 'nuxt-client attribute and client components within islands is only supported with Vite. file: hello.server.vue' )
} )
} )
} )
2023-09-14 21:44:18 +00:00
} )