Skip to content

Commit f6ff2cc

Browse files
committed
test: add test coverage for error/edge cases
1 parent 09d5963 commit f6ff2cc

File tree

4 files changed

+37
-6
lines changed

4 files changed

+37
-6
lines changed

src/utils/script-setup.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const DEFINE_MODEL = 'defineModel'
2424
*/
2525
export async function preTranspileScriptSetup(sfc: SFCDescriptor, id: string): Promise<SFCScriptBlock> {
2626
if (!sfc.scriptSetup) {
27-
throw new Error('No script setup block found')
27+
throw new Error('[vue-sfc-transformer] No script setup block found')
2828
}
2929
const context = await prepareContext(sfc as SFCDescriptor & { scriptSetup: SFCScriptBlock }, id)
3030
const resultBuilder = new context.utils.MagicString(sfc.scriptSetup.content)
@@ -104,10 +104,10 @@ function processDefineEmits(node: Expression, context: Context): string | undefi
104104
return
105105
}
106106

107-
const emitsRuntimeDecl = node.arguments[0]
108107
if (!node.typeParameters) {
109108
return
110109
}
110+
const emitsRuntimeDecl = node.arguments[0]
111111
if (emitsRuntimeDecl) {
112112
context.ctx.error(
113113
`${DEFINE_EMITS}() cannot accept both type and non-type arguments `
@@ -228,10 +228,7 @@ function getDefineModelRuntimeDecl(node: CallExpression, context: Context): [Str
228228
const [arg0, arg1] = node.arguments
229229
if (arg0 && arg0.type === 'StringLiteral') {
230230
if (arg1 && arg1.type !== 'ObjectExpression') {
231-
context.ctx.error(
232-
`${DEFINE_MODEL}()'s second argument must be an object.`,
233-
arg1,
234-
)
231+
context.ctx.error(`${DEFINE_MODEL}()'s second argument must be an object.`, arg1)
235232
}
236233

237234
return [arg0, arg1 as ObjectExpression]

test/setup.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@ import { parse } from 'vue/compiler-sfc'
33
import { preTranspileScriptSetup } from '../src/utils/script-setup'
44

55
describe('transform typescript script setup', () => {
6+
it('throws error if no script setup block is present', async () => {
7+
const sfc = parse(`<template><div></div></template><script></script>`, {
8+
filename: 'test.vue',
9+
ignoreEmpty: true,
10+
})
11+
await expect(preTranspileScriptSetup(sfc.descriptor, 'test.vue')).rejects.toThrow(
12+
'[vue-sfc-transformer] No script setup block found',
13+
)
14+
})
15+
616
it('defineProps', async () => {
717
expect(
818
await fixture(
@@ -111,6 +121,10 @@ describe('transform typescript script setup', () => {
111121
})
112122
</script>"
113123
`)
124+
125+
await expect(fixture(`<script setup lang="ts">withDefaults(defineProps<{ msg?: string }>())</script>`)).rejects.toThrow(`[vue-sfc-transformer] The 2nd argument of withDefaults is required.`)
126+
127+
await expect(fixture(`<script setup lang="ts">withDefaults()</script>`)).rejects.toThrow(`[vue-sfc-transformer] withDefaults' first argument must be a defineProps call.`)
114128
})
115129

116130
it('defineEmits', async () => {
@@ -159,6 +173,8 @@ describe('transform typescript script setup', () => {
159173
defineEmits(["click"])
160174
</script>"
161175
`)
176+
177+
await expect(fixture(`<script setup lang="ts">defineEmits<{ click: [] }>('click')</script>`)).rejects.toThrow(`[vue-sfc-transformer] defineEmits() cannot accept both type and non-type arguments at the same time. Use one or the other.`)
162178
})
163179

164180
it('defineModel', async () => {
@@ -187,6 +203,15 @@ describe('transform typescript script setup', () => {
187203
defineModel("msg", { type: String })
188204
</script>"
189205
`)
206+
expect(
207+
await fixture(
208+
`<script setup lang="ts">defineModel<string | number | string[]>('msg')</script>`,
209+
),
210+
).toMatchInlineSnapshot(`
211+
"<script setup>
212+
defineModel("msg", { type: [String,Number,Array] })
213+
</script>"
214+
`)
190215
expect(
191216
await fixture(
192217
`<script setup lang="ts">defineModel<string>({ required: true })</script>`,
@@ -205,6 +230,8 @@ describe('transform typescript script setup', () => {
205230
defineModel("msg", { type: String, ...{ required: true } })
206231
</script>"
207232
`)
233+
234+
await expect(fixture('<script setup lang="ts">defineModel("foo", "bar")</script>')).rejects.toThrow(`[vue-sfc-transformer] defineModel()'s second argument must be an object.`)
208235
})
209236

210237
async function fixture(src: string): Promise<string> {

test/template.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ describe('transform typescript template', () => {
7474
).toMatchInlineSnapshot(`"<MyComponent v-slot="{ remaining, duration }">{{ remaining }}</MyComponent>"`)
7575
})
7676

77+
it('compound expressions', async () => {
78+
expect(await fixture(`<slot :name="(foo as string) + bar" />`)).toEqual(
79+
`<slot :name="foo + bar" />`,
80+
)
81+
})
82+
7783
it('custom directives', async () => {
7884
expect(
7985
await fixture(`<div v-highlight="(highlight as boolean)" />`),

vitest.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export default defineConfig({
1111
},
1212
test: {
1313
coverage: {
14+
enabled: true,
1415
include: ['src'],
1516
reporter: ['text', 'json', 'html'],
1617
},

0 commit comments

Comments
 (0)