import { BindingTypes } from '@vue/compiler-core'
import { assertCode, compileSFCScript as compile } from '../utils'
describe('defineEmits', () => {
test('basic usage', () => {
const { content, bindings } = compile(`
`)
assertCode(content)
expect(bindings).toStrictEqual({
myEmit: BindingTypes.SETUP_CONST,
})
// should remove defineEmits import and call
expect(content).not.toMatch('defineEmits')
// should generate correct setup signature
expect(content).toMatch(
`setup(__props, { expose: __expose, emit: __emit }) {`,
)
expect(content).toMatch('const myEmit = __emit')
// should include context options in default export
expect(content).toMatch(`export default {
emits: ['foo', 'bar'],`)
})
test('w/ runtime options', () => {
const { content } = compile(`
`)
assertCode(content)
expect(content).toMatch(`export default /*@__PURE__*/_defineComponent({
emits: ['a', 'b'],
setup(__props, { expose: __expose, emit: __emit }) {`)
expect(content).toMatch('const emit = __emit')
})
test('w/ type', () => {
const { content } = compile(`
`)
assertCode(content)
expect(content).toMatch(`emits: ["foo", "bar"]`)
})
test('w/ type (union)', () => {
const type = `((e: 'foo' | 'bar') => void) | ((e: 'baz', id: number) => void)`
const { content } = compile(`
`)
assertCode(content)
expect(content).toMatch(`emits: ["foo", "bar", "baz"]`)
})
test('w/ type (type literal w/ call signatures)', () => {
const type = `{(e: 'foo' | 'bar'): void; (e: 'baz', id: number): void;}`
const { content } = compile(`
`)
assertCode(content)
expect(content).toMatch(`emits: ["foo", "bar", "baz"]`)
})
test('w/ type (interface)', () => {
const { content } = compile(`
`)
assertCode(content)
expect(content).toMatch(`emits: ["foo", "bar"]`)
})
test('w/ type (interface w/ extends)', () => {
const { content } = compile(`
`)
assertCode(content)
expect(content).toMatch(`emits: ["bar", "foo"]`)
})
test('w/ type (exported interface)', () => {
const { content } = compile(`
`)
assertCode(content)
expect(content).toMatch(`emits: ["foo", "bar"]`)
})
test('w/ type from normal script', () => {
const { content } = compile(`
`)
assertCode(content)
expect(content).toMatch(`emits: ["foo", "bar"]`)
})
test('w/ type (type alias)', () => {
const { content } = compile(`
`)
assertCode(content)
expect(content).toMatch(`emits: ["foo", "bar"]`)
})
test('w/ type (exported type alias)', () => {
const { content } = compile(`
`)
assertCode(content)
expect(content).toMatch(`emits: ["foo", "bar"]`)
})
test('w/ type (referenced function type)', () => {
const { content } = compile(`
`)
assertCode(content)
expect(content).toMatch(`emits: ["foo", "bar"]`)
})
test('w/ type (referenced exported function type)', () => {
const { content } = compile(`
`)
assertCode(content)
expect(content).toMatch(`emits: ["foo", "bar"]`)
})
// #5393
test('w/ type (interface ts type)', () => {
const { content } = compile(`
`)
assertCode(content)
expect(content).toMatch(`emits: ['foo']`)
})
test('w/ type (property syntax)', () => {
const { content } = compile(`
`)
expect(content).toMatch(`emits: ["foo", "bar"]`)
assertCode(content)
})
// #8040
test('w/ type (property syntax string literal)', () => {
const { content } = compile(`
`)
expect(content).toMatch(`emits: ["foo:bar"]`)
assertCode(content)
})
// #7943
test('w/ type (type references in union)', () => {
const { content } = compile(`
`)
expect(content).toMatch(`emits: ["some", "emit", "change", "another"]`)
assertCode(content)
})
describe('errors', () => {
test('w/ both type and non-type args', () => {
expect(() => {
compile(``)
}).toThrow(`cannot accept both type and non-type arguments`)
})
test('mixed usage of property / call signature', () => {
expect(() =>
compile(``),
).toThrow(
`defineEmits() type cannot mixed call signature and property syntax.`,
)
})
})
})