test: improve coverage
This commit is contained in:
parent
e67084e5a1
commit
cae03f616d
@ -5,8 +5,9 @@ exports[`compiler: codegen callExpression + objectExpression + arrayExpression 1
|
||||
with (this) {
|
||||
return createVNode(\\"div\\", {
|
||||
id: \\"foo\\",
|
||||
[prop]: bar
|
||||
}, [
|
||||
[prop]: bar,
|
||||
[foo + bar]: bar
|
||||
}, [createVNode(\\"p\\", { \\"some-key\\": \\"foo\\" })], [
|
||||
foo,
|
||||
createVNode(\\"p\\")
|
||||
])
|
||||
@ -22,6 +23,14 @@ exports[`compiler: codegen comment 1`] = `
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen compound expression 1`] = `
|
||||
"return function render() {
|
||||
with (this) {
|
||||
return toString(_ctx.foo)
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen forNode 1`] = `
|
||||
"return function render() {
|
||||
with (this) {
|
||||
@ -30,6 +39,30 @@ exports[`compiler: codegen forNode 1`] = `
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen forNode w/ skipped key alias 1`] = `
|
||||
"return function render() {
|
||||
with (this) {
|
||||
return renderList(list, (v, __key, i) => toString(v))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen forNode w/ skipped value alias 1`] = `
|
||||
"return function render() {
|
||||
with (this) {
|
||||
return renderList(list, (__value, k, i) => toString(v))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen forNode w/ skipped value and key aliases 1`] = `
|
||||
"return function render() {
|
||||
with (this) {
|
||||
return renderList(list, (__value, __key, i) => toString(v))
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen function mode preamble 1`] = `
|
||||
"const { helperOne, helperTwo } = Vue
|
||||
|
||||
@ -52,6 +85,18 @@ exports[`compiler: codegen ifNode 1`] = `
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen ifNode with no v-else 1`] = `
|
||||
"return function render() {
|
||||
with (this) {
|
||||
return (foo)
|
||||
? \\"foo\\"
|
||||
: (bar)
|
||||
? toString(bye)
|
||||
: null
|
||||
}
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`compiler: codegen interpolation 1`] = `
|
||||
"return function render() {
|
||||
with (this) {
|
||||
|
@ -7,9 +7,11 @@ import {
|
||||
createExpression,
|
||||
Namespaces,
|
||||
ElementTypes,
|
||||
CallExpression,
|
||||
createObjectExpression,
|
||||
createObjectProperty,
|
||||
createArrayExpression
|
||||
createArrayExpression,
|
||||
ElementNode
|
||||
} from '../src'
|
||||
import { SourceMapConsumer, RawSourceMap } from 'source-map'
|
||||
import { CREATE_VNODE, COMMENT, TO_STRING } from '../src/runtimeConstants'
|
||||
@ -145,6 +147,25 @@ describe('compiler: codegen', () => {
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('compound expression', () => {
|
||||
const { code } = generate(
|
||||
createRoot({
|
||||
children: [
|
||||
{
|
||||
type: NodeTypes.EXPRESSION,
|
||||
content: 'foo',
|
||||
isStatic: false,
|
||||
isInterpolation: true,
|
||||
loc: mockLoc,
|
||||
children: [`_ctx.`, createExpression(`foo`, false, mockLoc)]
|
||||
}
|
||||
]
|
||||
})
|
||||
)
|
||||
expect(code).toMatch(`return toString(_ctx.foo)`)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('ifNode', () => {
|
||||
const { code } = generate(
|
||||
createRoot({
|
||||
@ -202,6 +223,50 @@ describe('compiler: codegen', () => {
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('ifNode with no v-else', () => {
|
||||
const { code } = generate(
|
||||
createRoot({
|
||||
children: [
|
||||
{
|
||||
type: NodeTypes.IF,
|
||||
loc: mockLoc,
|
||||
isRoot: true,
|
||||
branches: [
|
||||
{
|
||||
type: NodeTypes.IF_BRANCH,
|
||||
condition: createExpression('foo', false, mockLoc),
|
||||
loc: mockLoc,
|
||||
isRoot: true,
|
||||
children: [
|
||||
{
|
||||
type: NodeTypes.TEXT,
|
||||
content: 'foo',
|
||||
isEmpty: false,
|
||||
loc: mockLoc
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: NodeTypes.IF_BRANCH,
|
||||
condition: createExpression('bar', false, mockLoc),
|
||||
loc: mockLoc,
|
||||
isRoot: true,
|
||||
children: [createExpression(`bye`, false, mockLoc, true)]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
)
|
||||
expect(code).toMatch(`
|
||||
return (foo)
|
||||
? "foo"
|
||||
: (bar)
|
||||
? ${TO_STRING}(bye)
|
||||
: null`)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('forNode', () => {
|
||||
const { code } = generate(
|
||||
createRoot({
|
||||
@ -222,63 +287,166 @@ describe('compiler: codegen', () => {
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('callExpression + objectExpression + arrayExpression', () => {
|
||||
test('forNode w/ skipped value alias', () => {
|
||||
const { code } = generate(
|
||||
createRoot({
|
||||
children: [
|
||||
{
|
||||
type: NodeTypes.ELEMENT,
|
||||
type: NodeTypes.FOR,
|
||||
loc: mockLoc,
|
||||
ns: Namespaces.HTML,
|
||||
tag: 'div',
|
||||
tagType: ElementTypes.ELEMENT,
|
||||
isSelfClosing: false,
|
||||
props: [],
|
||||
children: [],
|
||||
codegenNode: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
loc: mockLoc,
|
||||
callee: CREATE_VNODE,
|
||||
arguments: [
|
||||
`"div"`,
|
||||
source: createExpression(`list`, false, mockLoc),
|
||||
valueAlias: undefined,
|
||||
keyAlias: createExpression(`k`, false, mockLoc),
|
||||
objectIndexAlias: createExpression(`i`, false, mockLoc),
|
||||
children: [createExpression(`v`, false, mockLoc, true)]
|
||||
}
|
||||
]
|
||||
})
|
||||
)
|
||||
expect(code).toMatch(`renderList(list, (__value, k, i) => toString(v))`)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('forNode w/ skipped key alias', () => {
|
||||
const { code } = generate(
|
||||
createRoot({
|
||||
children: [
|
||||
{
|
||||
type: NodeTypes.FOR,
|
||||
loc: mockLoc,
|
||||
source: createExpression(`list`, false, mockLoc),
|
||||
valueAlias: createExpression(`v`, false, mockLoc),
|
||||
keyAlias: undefined,
|
||||
objectIndexAlias: createExpression(`i`, false, mockLoc),
|
||||
children: [createExpression(`v`, false, mockLoc, true)]
|
||||
}
|
||||
]
|
||||
})
|
||||
)
|
||||
expect(code).toMatch(`renderList(list, (v, __key, i) => toString(v))`)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('forNode w/ skipped value and key aliases', () => {
|
||||
const { code } = generate(
|
||||
createRoot({
|
||||
children: [
|
||||
{
|
||||
type: NodeTypes.FOR,
|
||||
loc: mockLoc,
|
||||
source: createExpression(`list`, false, mockLoc),
|
||||
valueAlias: undefined,
|
||||
keyAlias: undefined,
|
||||
objectIndexAlias: createExpression(`i`, false, mockLoc),
|
||||
children: [createExpression(`v`, false, mockLoc, true)]
|
||||
}
|
||||
]
|
||||
})
|
||||
)
|
||||
expect(code).toMatch(`renderList(list, (__value, __key, i) => toString(v))`)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('callExpression + objectExpression + arrayExpression', () => {
|
||||
function createElementWithCodegen(
|
||||
args: CallExpression['arguments']
|
||||
): ElementNode {
|
||||
return {
|
||||
type: NodeTypes.ELEMENT,
|
||||
loc: mockLoc,
|
||||
ns: Namespaces.HTML,
|
||||
tag: 'div',
|
||||
tagType: ElementTypes.ELEMENT,
|
||||
isSelfClosing: false,
|
||||
props: [],
|
||||
children: [],
|
||||
codegenNode: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
loc: mockLoc,
|
||||
callee: CREATE_VNODE,
|
||||
arguments: args
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const { code } = generate(
|
||||
createRoot({
|
||||
children: [
|
||||
createElementWithCodegen([
|
||||
// string
|
||||
`"div"`,
|
||||
// ObjectExpression
|
||||
createObjectExpression(
|
||||
[
|
||||
createObjectProperty(
|
||||
createExpression(`id`, true, mockLoc),
|
||||
createExpression(`foo`, true, mockLoc),
|
||||
mockLoc
|
||||
),
|
||||
createObjectProperty(
|
||||
createExpression(`prop`, false, mockLoc),
|
||||
createExpression(`bar`, false, mockLoc),
|
||||
mockLoc
|
||||
),
|
||||
// compound expression as computed key
|
||||
createObjectProperty(
|
||||
{
|
||||
type: NodeTypes.EXPRESSION,
|
||||
content: ``,
|
||||
loc: mockLoc,
|
||||
isStatic: false,
|
||||
isInterpolation: false,
|
||||
children: [
|
||||
`foo + `,
|
||||
createExpression(`bar`, false, mockLoc)
|
||||
]
|
||||
},
|
||||
createExpression(`bar`, false, mockLoc),
|
||||
mockLoc
|
||||
)
|
||||
],
|
||||
mockLoc
|
||||
),
|
||||
// ChildNode[]
|
||||
[
|
||||
createElementWithCodegen([
|
||||
`"p"`,
|
||||
createObjectExpression(
|
||||
[
|
||||
createObjectProperty(
|
||||
createExpression(`id`, true, mockLoc),
|
||||
// should quote the key!
|
||||
createExpression(`some-key`, true, mockLoc),
|
||||
createExpression(`foo`, true, mockLoc),
|
||||
mockLoc
|
||||
),
|
||||
createObjectProperty(
|
||||
createExpression(`prop`, false, mockLoc),
|
||||
createExpression(`bar`, false, mockLoc),
|
||||
mockLoc
|
||||
)
|
||||
],
|
||||
mockLoc
|
||||
),
|
||||
createArrayExpression(
|
||||
[
|
||||
'foo',
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
loc: mockLoc,
|
||||
callee: CREATE_VNODE,
|
||||
arguments: [`"p"`]
|
||||
}
|
||||
],
|
||||
mockLoc
|
||||
)
|
||||
]
|
||||
}
|
||||
}
|
||||
])
|
||||
],
|
||||
// ArrayExpression
|
||||
createArrayExpression(
|
||||
[
|
||||
'foo',
|
||||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
loc: mockLoc,
|
||||
callee: CREATE_VNODE,
|
||||
arguments: [`"p"`]
|
||||
}
|
||||
],
|
||||
mockLoc
|
||||
)
|
||||
])
|
||||
]
|
||||
})
|
||||
)
|
||||
expect(code).toMatch(`
|
||||
return ${CREATE_VNODE}("div", {
|
||||
id: "foo",
|
||||
[prop]: bar
|
||||
}, [
|
||||
[prop]: bar,
|
||||
[foo + bar]: bar
|
||||
}, [${CREATE_VNODE}("p", { "some-key": "foo" })], [
|
||||
foo,
|
||||
${CREATE_VNODE}("p")
|
||||
])`)
|
||||
|
@ -80,6 +80,46 @@ describe('compiler: element transform', () => {
|
||||
])
|
||||
})
|
||||
|
||||
test('props + children', () => {
|
||||
const { node } = parseWithElementTransform(`<div id="foo"><span/></div>`)
|
||||
expect(node.callee).toBe(CREATE_VNODE)
|
||||
expect(node.arguments).toMatchObject([
|
||||
`"div"`,
|
||||
createStaticObjectMatcher({
|
||||
id: 'foo'
|
||||
}),
|
||||
[
|
||||
{
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: 'span',
|
||||
codegenNode: {
|
||||
callee: CREATE_VNODE,
|
||||
arguments: [`"span"`]
|
||||
}
|
||||
}
|
||||
]
|
||||
])
|
||||
})
|
||||
|
||||
test('0 placeholder for children with no props', () => {
|
||||
const { node } = parseWithElementTransform(`<div><span/></div>`)
|
||||
expect(node.callee).toBe(CREATE_VNODE)
|
||||
expect(node.arguments).toMatchObject([
|
||||
`"div"`,
|
||||
`0`,
|
||||
[
|
||||
{
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: 'span',
|
||||
codegenNode: {
|
||||
callee: CREATE_VNODE,
|
||||
arguments: [`"span"`]
|
||||
}
|
||||
}
|
||||
]
|
||||
])
|
||||
})
|
||||
|
||||
test('v-bind="obj"', () => {
|
||||
const { root, node } = parseWithElementTransform(`<div v-bind="obj" />`)
|
||||
// single v-bind doesn't need mergeProps
|
||||
|
@ -5,16 +5,21 @@ import {
|
||||
ElementNode,
|
||||
DirectiveNode,
|
||||
NodeTypes,
|
||||
ForNode
|
||||
ForNode,
|
||||
CompilerOptions
|
||||
} from '../../src'
|
||||
import { transformFor } from '../..//src/transforms/vFor'
|
||||
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||
|
||||
function parseWithExpressionTransform(template: string) {
|
||||
function parseWithExpressionTransform(
|
||||
template: string,
|
||||
options: CompilerOptions = {}
|
||||
) {
|
||||
const ast = parse(template)
|
||||
transform(ast, {
|
||||
prefixIdentifiers: true,
|
||||
nodeTransforms: [transformFor, transformExpression]
|
||||
nodeTransforms: [transformFor, transformExpression],
|
||||
...options
|
||||
})
|
||||
return ast.children[0]
|
||||
}
|
||||
@ -297,4 +302,10 @@ describe('compiler: expression transform', () => {
|
||||
`]`
|
||||
])
|
||||
})
|
||||
|
||||
test('should handle parse error', () => {
|
||||
const onError = jest.fn()
|
||||
parseWithExpressionTransform(`{{ a( }}`, { onError })
|
||||
expect(onError.mock.calls[0][0].message).toMatch(`Expected ')'`)
|
||||
})
|
||||
})
|
||||
|
@ -277,6 +277,7 @@ function genNode(node: CodegenNode, context: CodegenContext) {
|
||||
genArrayExpression(node, context)
|
||||
break
|
||||
default:
|
||||
/* istanbul ignore next */
|
||||
__DEV__ &&
|
||||
assert(false, `unhandled codegen node type: ${(node as any).type}`)
|
||||
}
|
||||
@ -399,7 +400,7 @@ function genFor(node: ForNode, context: CodegenContext) {
|
||||
}
|
||||
if (keyAlias) {
|
||||
if (!valueAlias) {
|
||||
push(`_`)
|
||||
push(`__value`)
|
||||
}
|
||||
push(`, `)
|
||||
genExpression(keyAlias, context)
|
||||
@ -407,9 +408,9 @@ function genFor(node: ForNode, context: CodegenContext) {
|
||||
if (objectIndexAlias) {
|
||||
if (!keyAlias) {
|
||||
if (!valueAlias) {
|
||||
push(`_, __`)
|
||||
push(`__value, __key`)
|
||||
} else {
|
||||
push(`__`)
|
||||
push(`, __key`)
|
||||
}
|
||||
}
|
||||
push(`, `)
|
||||
@ -447,12 +448,9 @@ function genObjectExpression(node: ObjectExpression, context: CodegenContext) {
|
||||
// value
|
||||
genExpression(value, context)
|
||||
if (i < properties.length - 1) {
|
||||
if (multilines) {
|
||||
push(`,`)
|
||||
newline()
|
||||
} else {
|
||||
push(`, `)
|
||||
}
|
||||
// will only reach this if it's multilines
|
||||
push(`,`)
|
||||
newline()
|
||||
}
|
||||
}
|
||||
multilines && deindent()
|
||||
|
@ -199,6 +199,7 @@ function pushNode(
|
||||
node: ChildNode
|
||||
): void {
|
||||
// ignore comments in production
|
||||
/* istanbul ignore next */
|
||||
if (!__DEV__ && node.type === NodeTypes.COMMENT) {
|
||||
return
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ function createTransformContext(
|
||||
childIndex: 0,
|
||||
currentNode: null,
|
||||
replaceNode(node) {
|
||||
/* istanbul ignore if */
|
||||
if (__DEV__ && !context.currentNode) {
|
||||
throw new Error(`node being replaced is already removed.`)
|
||||
}
|
||||
@ -97,6 +98,7 @@ function createTransformContext(
|
||||
: context.currentNode
|
||||
? context.childIndex
|
||||
: -1
|
||||
/* istanbul ignore if */
|
||||
if (__DEV__ && removalIndex < 0) {
|
||||
throw new Error(`node being removed is not a child of current parent`)
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ export function advancePositionWithMutation(
|
||||
}
|
||||
|
||||
export function assert(condition: boolean, msg?: string) {
|
||||
/* istanbul ignore if */
|
||||
if (!condition) {
|
||||
throw new Error(msg || `unexpected compiler condition`)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user