* Copyright (c) 2023 - present TinyEngine Authors.
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { describe, it, expect, beforeAll } from 'vitest'
import { transformSFC } from '../src/transform-sfc.js'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
beforeAll(() => {
const testDir = path.join(__dirname, 'temp/transform-sfc-test-cases')
if (!fs.existsSync(testDir)) {
fs.mkdirSync(testDir, { recursive: true })
}
const metaJsContent = `
export default {
id: 'test-meta',
name: '测试元数据'
}
`
const metaJsPath = path.join(__dirname, 'temp/transform-sfc-test-cases/meta.js')
fs.writeFileSync(metaJsPath, metaJsContent, 'utf8')
})
const createTestFile = (filename, content) => {
const filePath = path.join(__dirname, 'temp/transform-sfc-test-cases', filename)
fs.writeFileSync(filePath, content, 'utf8')
return filePath
}
const testTransformAndVerify = async (fileName, expectTransformed = true) => {
const filePath = path.join(__dirname, 'temp/transform-sfc-test-cases', fileName)
const code = fs.readFileSync(filePath, 'utf8')
const result = transformSFC(code, filePath)
if (expectTransformed) {
expect(result).toBeTruthy()
expect(result.length).toBeGreaterThan(0)
await expect(result).toMatchFileSnapshot(`./expected/${fileName}.output.vue`)
} else {
expect(result).toBeUndefined()
}
return result
}
describe('transform-sfc.js', () => {
describe('转换包含metaService注释的Vue SFC', () => {
it('应该正确转换单文件组件并添加callEntry调用', async () => {
const content = `<template>
<div>
<h1>{{ title }}</h1>
<button @click="increment">Count: {{ state.count }}</button>
</div>
</template>
<script>
/* metaService */
import { reactive, ref } from 'vue'
export default {
name: 'TestComponent',
setup() {
const title = ref('Test Component')
const state = reactive({
count: 0
})
const increment = () => {
state.count++
}
return {
title,
state,
increment
}
}
}
</script>
<style>
h1 {
color: blue;
}
</style>`
createTestFile('meta-service.vue', content)
const result = await testTransformAndVerify('meta-service.vue')
expect(result).toMatch(/callEntry\(/)
expect(result).toMatch(/<template>/)
expect(result).toMatch(/<style>/)
})
})
describe('转换包含script setup的Vue SFC', () => {
it('应该正确转换使用setup语法糖的组件', async () => {
const content = `<template>
<div>
<h1>{{ title }}</h1>
<button @click="increment">Count: {{ count }}</button>
</div>
</template>
<script setup>
/* metaService */
import { ref } from 'vue'
const title = ref('Script Setup Component')
const count = ref(0)
const increment = () => {
count.value++
}
</script>
<style>
h1 {
color: green;
}
</style>`
createTestFile('script-setup.vue', content)
const result = await testTransformAndVerify('script-setup.vue')
expect(result).toMatch(/callEntry\(/)
expect(result).toMatch(/<script setup>/)
})
})
describe('转换不包含元注释的Vue SFC', () => {
it('不应转换没有元注释的组件', async () => {
const content = `<template>
<div>
<h1>{{ title }}</h1>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
name: 'RegularComponent',
setup() {
const title = ref('Regular Component')
return {
title
}
}
}
</script>`
createTestFile('no-meta.vue', content)
await testTransformAndVerify('no-meta.vue', false)
})
})
})