test: add transform tests to `v-html` / `v-text` tests (#49)

Co-authored-by: 三咲智子 Kevin Deng <sxzz@sxzz.moe>
This commit is contained in:
Rizumu Ayaka 2023-12-11 03:05:11 +08:00 committed by GitHub
parent 28b11f5cf7
commit c87512f592
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 237 additions and 51 deletions

View File

@ -1,5 +1,19 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`v-html > should convert v-html to innerHTML 1`] = `
"import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor';
export function render(_ctx) {
const t0 = _template("<div></div>")
const n0 = t0()
const { 0: [n1],} = _children(n0)
_effect(() => {
_setHtml(n1, undefined, _ctx.code)
})
return n0
}"
`;
exports[`v-html > should raise error and ignore children when v-html is present 1`] = ` exports[`v-html > should raise error and ignore children when v-html is present 1`] = `
"import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor'; "import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor';
@ -25,17 +39,3 @@ export function render(_ctx) {
return n0 return n0
}" }"
`; `;
exports[`v-html > simple expression 1`] = `
"import { template as _template, children as _children, effect as _effect, setHtml as _setHtml } from 'vue/vapor';
export function render(_ctx) {
const t0 = _template("<div></div>")
const n0 = t0()
const { 0: [n1],} = _children(n0)
_effect(() => {
_setHtml(n1, undefined, _ctx.code)
})
return n0
}"
`;

View File

@ -1,18 +1,6 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`v-text > no expression 1`] = ` exports[`v-text > should convert v-text to textContent 1`] = `
"import { template as _template, children as _children, setText as _setText } from 'vue/vapor';
export function render(_ctx) {
const t0 = _template("<div></div>")
const n0 = t0()
const { 0: [n1],} = _children(n0)
_setText(n1, undefined, "")
return n0
}"
`;
exports[`v-text > simple expression 1`] = `
"import { template as _template, children as _children, effect as _effect, setText as _setText } from 'vue/vapor'; "import { template as _template, children as _children, effect as _effect, setText as _setText } from 'vue/vapor';
export function render(_ctx) { export function render(_ctx) {
@ -25,3 +13,29 @@ export function render(_ctx) {
return n0 return n0
}" }"
`; `;
exports[`v-text > should raise error and ignore children when v-text is present 1`] = `
"import { template as _template, children as _children, effect as _effect, setText as _setText } from 'vue/vapor';
export function render(_ctx) {
const t0 = _template("<div></div>")
const n0 = t0()
const { 0: [n1],} = _children(n0)
_effect(() => {
_setText(n1, undefined, _ctx.test)
})
return n0
}"
`;
exports[`v-text > should raise error if has no expression 1`] = `
"import { template as _template, children as _children, setText as _setText } from 'vue/vapor';
export function render(_ctx) {
const t0 = _template("<div></div>")
const n0 = t0()
const { 0: [n1],} = _children(n0)
_setText(n1, undefined, "")
return n0
}"
`;

View File

@ -1,39 +1,119 @@
import { type RootNode, BindingTypes, DOMErrorCodes } from '@vue/compiler-dom' import {
import { type CompilerOptions, compile as _compile } from '../../src' BindingTypes,
DOMErrorCodes,
NodeTypes,
parse,
} from '@vue/compiler-dom'
import {
type CompilerOptions,
compile as _compile,
RootIRNode,
transform,
generate,
IRNodeTypes,
} from '../../src'
import { getBaseTransformPreset } from '../../src/compile'
function compile(template: string | RootNode, options: CompilerOptions = {}) { function compileWithVHtml(
let { code } = _compile(template, { template: string,
...options, options: CompilerOptions = {},
mode: 'module', ): {
ir: RootIRNode
code: string
} {
const ast = parse(template, { prefixIdentifiers: true, ...options })
const [nodeTransforms, directiveTransforms] = getBaseTransformPreset(true)
const ir = transform(ast, {
nodeTransforms,
directiveTransforms,
prefixIdentifiers: true, prefixIdentifiers: true,
...options,
}) })
return code const { code } = generate(ir, { prefixIdentifiers: true, ...options })
return { ir, code }
} }
describe('v-html', () => { describe('v-html', () => {
test('simple expression', () => { test('should convert v-html to innerHTML', () => {
const code = compile(`<div v-html="code"></div>`, { const { code, ir } = compileWithVHtml(`<div v-html="code"></div>`, {
bindingMetadata: { bindingMetadata: {
code: BindingTypes.SETUP_REF, code: BindingTypes.SETUP_REF,
}, },
}) })
expect(ir.vaporHelpers).contains('setHtml')
expect(ir.helpers.size).toBe(0)
expect(ir.operation).toEqual([])
expect(ir.effect).toMatchObject([
{
expressions: [
{
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'code',
isStatic: false,
},
],
operations: [
{
type: IRNodeTypes.SET_HTML,
element: 1,
value: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'code',
isStatic: false,
},
},
],
},
])
expect(code).matchSnapshot() expect(code).matchSnapshot()
}) })
test('should raise error and ignore children when v-html is present', () => { test('should raise error and ignore children when v-html is present', () => {
const onError = vi.fn() const onError = vi.fn()
const code = compile(`<div v-html="test">hello</div>`, { const { code, ir } = compileWithVHtml(`<div v-html="test">hello</div>`, {
onError, onError,
}) })
expect(code).matchSnapshot()
expect(ir.vaporHelpers).contains('setHtml')
expect(ir.helpers.size).toBe(0)
expect(ir.operation).toEqual([])
expect(ir.effect).toMatchObject([
{
expressions: [
{
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'test',
isStatic: false,
},
],
operations: [
{
type: IRNodeTypes.SET_HTML,
element: 1,
value: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'test',
isStatic: false,
},
},
],
},
])
expect(onError.mock.calls).toMatchObject([ expect(onError.mock.calls).toMatchObject([
[{ code: DOMErrorCodes.X_V_HTML_WITH_CHILDREN }], [{ code: DOMErrorCodes.X_V_HTML_WITH_CHILDREN }],
]) ])
expect(code).matchSnapshot()
}) })
test('should raise error if has no expression', () => { test('should raise error if has no expression', () => {
const onError = vi.fn() const onError = vi.fn()
const code = compile(`<div v-html></div>`, { const { code } = compileWithVHtml(`<div v-html></div>`, {
onError, onError,
}) })
expect(code).matchSnapshot() expect(code).matchSnapshot()

View File

@ -1,28 +1,120 @@
import { type RootNode, BindingTypes, DOMErrorCodes } from '@vue/compiler-dom' import {
import { type CompilerOptions, compile as _compile } from '../../src' BindingTypes,
DOMErrorCodes,
NodeTypes,
parse,
} from '@vue/compiler-dom'
import {
type CompilerOptions,
compile as _compile,
RootIRNode,
transform,
generate,
IRNodeTypes,
} from '../../src'
import { getBaseTransformPreset } from '../../src/compile'
function compile(template: string | RootNode, options: CompilerOptions = {}) { function compileWithVText(
let { code } = _compile(template, { template: string,
...options, options: CompilerOptions = {},
mode: 'module', ): {
ir: RootIRNode
code: string
} {
const ast = parse(template, { prefixIdentifiers: true, ...options })
const [nodeTransforms, directiveTransforms] = getBaseTransformPreset(true)
const ir = transform(ast, {
nodeTransforms,
directiveTransforms,
prefixIdentifiers: true, prefixIdentifiers: true,
...options,
}) })
return code const { code } = generate(ir, { prefixIdentifiers: true, ...options })
return { ir, code }
} }
describe('v-text', () => { describe('v-text', () => {
test('simple expression', () => { test('should convert v-text to textContent', () => {
const code = compile(`<div v-text="str"></div>`, { const { code, ir } = compileWithVText(`<div v-text="str"></div>`, {
bindingMetadata: { bindingMetadata: {
str: BindingTypes.SETUP_REF, str: BindingTypes.SETUP_REF,
}, },
}) })
expect(ir.vaporHelpers).contains('setText')
expect(ir.helpers.size).toBe(0)
expect(ir.operation).toEqual([])
expect(ir.effect).toMatchObject([
{
expressions: [
{
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'str',
isStatic: false,
},
],
operations: [
{
type: IRNodeTypes.SET_TEXT,
element: 1,
value: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'str',
isStatic: false,
},
},
],
},
])
expect(code).matchSnapshot() expect(code).matchSnapshot()
}) })
test('no expression', () => { test('should raise error and ignore children when v-text is present', () => {
const onError = vi.fn() const onError = vi.fn()
const code = compile(`<div v-text></div>`, { onError }) const { code, ir } = compileWithVText(`<div v-text="test">hello</div>`, {
onError,
})
expect(onError.mock.calls).toMatchObject([
[{ code: DOMErrorCodes.X_V_TEXT_WITH_CHILDREN }],
])
// children should have been removed
expect(ir.template).toMatchObject([{ template: '<div></div>' }])
expect(ir.effect).toMatchObject([
{
expressions: [
{
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'test',
isStatic: false,
},
],
operations: [
{
type: IRNodeTypes.SET_TEXT,
element: 1,
value: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'test',
isStatic: false,
},
},
],
},
])
expect(code).matchSnapshot()
// children should have been removed
expect(code).contains('template("<div></div>")')
})
test('should raise error if has no expression', () => {
const onError = vi.fn()
const { code } = compileWithVText(`<div v-text></div>`, { onError })
expect(code).matchSnapshot() expect(code).matchSnapshot()
expect(onError.mock.calls).toMatchObject([ expect(onError.mock.calls).toMatchObject([
[{ code: DOMErrorCodes.X_V_TEXT_NO_EXPRESSION }], [{ code: DOMErrorCodes.X_V_TEXT_NO_EXPRESSION }],

View File

@ -13,7 +13,7 @@ export const transformVText: DirectiveTransform = (dir, node, context) => {
context.options.onError( context.options.onError(
createDOMCompilerError(DOMErrorCodes.X_V_TEXT_WITH_CHILDREN, loc), createDOMCompilerError(DOMErrorCodes.X_V_TEXT_WITH_CHILDREN, loc),
) )
node.children.length = 0 context.childrenTemplate.length = 0
} }
context.registerEffect( context.registerEffect(