feat(compiler): basic v-bind & v-on transforms

This commit is contained in:
Evan You
2019-09-22 22:19:42 -04:00
parent 3ab016e44f
commit 914087edea
14 changed files with 749 additions and 715 deletions

View File

@@ -195,7 +195,9 @@ describe('compiler: parse', () => {
[
{
code: ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE,
loc: { offset: 4, line: 1, column: 5 }
loc: {
start: { offset: 4, line: 1, column: 5 }
}
}
]
])
@@ -249,7 +251,9 @@ describe('compiler: parse', () => {
[
{
code: ErrorCodes.MISSING_SEMICOLON_AFTER_CHARACTER_REFERENCE,
loc: { offset: 45, line: 1, column: 46 }
loc: {
start: { offset: 45, line: 1, column: 46 }
}
}
]
])
@@ -274,7 +278,9 @@ describe('compiler: parse', () => {
[
{
code: ErrorCodes.CONTROL_CHARACTER_REFERENCE,
loc: { offset: 0, line: 1, column: 1 }
loc: {
start: { offset: 0, line: 1, column: 1 }
}
}
]
])
@@ -1254,9 +1260,11 @@ describe('compiler: parse', () => {
{
code: ErrorCodes.X_MISSING_END_TAG,
loc: {
offset: 13,
line: 3,
column: 1
start: {
offset: 13,
line: 3,
column: 1
}
}
}
],
@@ -1264,9 +1272,11 @@ describe('compiler: parse', () => {
{
code: ErrorCodes.X_INVALID_END_TAG,
loc: {
offset: 20,
line: 4,
column: 1
start: {
offset: 20,
line: 4,
column: 1
}
}
}
]
@@ -2386,7 +2396,7 @@ describe('compiler: parse', () => {
expect(
spy.mock.calls.map(([err]) => ({
type: err.code,
loc: err.loc
loc: err.loc.start
}))
).toMatchObject(errors)
expect(ast).toMatchSnapshot()

View File

@@ -162,10 +162,10 @@ describe('compiler: transform', () => {
test('onError option', () => {
const ast = parse(`<div/>`)
const loc = ast.children[0].loc.start
const loc = ast.children[0].loc
const plugin: NodeTransform = (node, context) => {
context.onError(
createCompilerError(ErrorCodes.X_INVALID_END_TAG, node.loc.start)
createCompilerError(ErrorCodes.X_INVALID_END_TAG, node.loc)
)
}
const spy = jest.fn()

View File

@@ -0,0 +1,3 @@
describe('compiler: element transform', () => {
test.todo('should work')
})

View File

@@ -4,10 +4,293 @@ import { transformFor } from '../../src/transforms/vFor'
import { ForNode, NodeTypes } from '../../src/ast'
import { ErrorCodes } from '../../src/errors'
describe('v-for', () => {
describe('transform', () => {
test('number expression', () => {
const node = parse('<span v-for="index in 5" />')
describe('compiler: transform v-for', () => {
test('number expression', () => {
const node = parse('<span v-for="index in 5" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('index')
expect(forNode.source.content).toBe('5')
})
test('value', () => {
const node = parse('<span v-for="(item) in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.source.content).toBe('items')
})
test('object de-structured value', () => {
const node = parse('<span v-for="({ id, value }) in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('{ id, value }')
expect(forNode.source.content).toBe('items')
})
test('array de-structured value', () => {
const node = parse('<span v-for="([ id, value ]) in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('[ id, value ]')
expect(forNode.source.content).toBe('items')
})
test('value and key', () => {
const node = parse('<span v-for="(item, key) in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.keyAlias).not.toBeUndefined()
expect(forNode.keyAlias!.content).toBe('key')
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.source.content).toBe('items')
})
test('value, key and index', () => {
const node = parse('<span v-for="(value, key, index) in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).not.toBeUndefined()
expect(forNode.keyAlias!.content).toBe('key')
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias!.content).toBe('value')
expect(forNode.source.content).toBe('items')
})
test('skipped key', () => {
const node = parse('<span v-for="(value,,index) in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias!.content).toBe('value')
expect(forNode.source.content).toBe('items')
})
test('skipped value and key', () => {
const node = parse('<span v-for="(,,index) in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias).toBeUndefined()
expect(forNode.source.content).toBe('items')
})
test('unbracketed value', () => {
const node = parse('<span v-for="item in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.source.content).toBe('items')
})
test('unbracketed value and key', () => {
const node = parse('<span v-for="item, key in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).not.toBeUndefined()
expect(forNode.keyAlias!.content).toBe('key')
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.source.content).toBe('items')
})
test('unbracketed value, key and index', () => {
const node = parse('<span v-for="value, key, index in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).not.toBeUndefined()
expect(forNode.keyAlias!.content).toBe('key')
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias!.content).toBe('value')
expect(forNode.source.content).toBe('items')
})
test('unbracketed skipped key', () => {
const node = parse('<span v-for="value, , index in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias!.content).toBe('value')
expect(forNode.source.content).toBe('items')
})
test('unbracketed skipped value and key', () => {
const node = parse('<span v-for=", , index in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias).toBeUndefined()
expect(forNode.source.content).toBe('items')
})
test('missing expression', () => {
const node = parse('<span v-for />')
const onError = jest.fn()
transform(node, { nodeTransforms: [transformFor], onError })
expect(onError).toHaveBeenCalledTimes(1)
expect(onError).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_FOR_NO_EXPRESSION
})
)
})
test('empty expression', () => {
const node = parse('<span v-for="" />')
const onError = jest.fn()
transform(node, { nodeTransforms: [transformFor], onError })
expect(onError).toHaveBeenCalledTimes(1)
expect(onError).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_FOR_MALFORMED_EXPRESSION
})
)
})
test('invalid expression', () => {
const node = parse('<span v-for="items" />')
const onError = jest.fn()
transform(node, { nodeTransforms: [transformFor], onError })
expect(onError).toHaveBeenCalledTimes(1)
expect(onError).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_FOR_MALFORMED_EXPRESSION
})
)
})
test('missing source', () => {
const node = parse('<span v-for="item in" />')
const onError = jest.fn()
transform(node, { nodeTransforms: [transformFor], onError })
expect(onError).toHaveBeenCalledTimes(1)
expect(onError).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_FOR_MALFORMED_EXPRESSION
})
)
})
test('missing value', () => {
const node = parse('<span v-for="in items" />')
const onError = jest.fn()
transform(node, { nodeTransforms: [transformFor], onError })
expect(onError).toHaveBeenCalledTimes(1)
expect(onError).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_FOR_MALFORMED_EXPRESSION
})
)
})
describe('source location', () => {
test('value & source', () => {
const source = '<span v-for="item in items" />'
const node = parse(source)
transform(node, { nodeTransforms: [transformFor] })
@@ -16,30 +299,29 @@ describe('v-for', () => {
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('index')
expect(forNode.source.content).toBe('5')
})
test('value', () => {
const node = parse('<span v-for="(item) in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.valueAlias!.loc.start.offset).toBe(
source.indexOf('item') - 1
)
expect(forNode.valueAlias!.loc.start.line).toBe(1)
expect(forNode.valueAlias!.loc.start.column).toBe(source.indexOf('item'))
expect(forNode.valueAlias!.loc.end.line).toBe(1)
expect(forNode.valueAlias!.loc.end.column).toBe(
source.indexOf('item') + 4
)
expect(forNode.source.content).toBe('items')
expect(forNode.source.loc.start.offset).toBe(source.indexOf('items') - 1)
expect(forNode.source.loc.start.line).toBe(1)
expect(forNode.source.loc.start.column).toBe(source.indexOf('items'))
expect(forNode.source.loc.end.line).toBe(1)
expect(forNode.source.loc.end.column).toBe(source.indexOf('items') + 5)
})
test('object de-structured value', () => {
const node = parse('<span v-for="({ id, value }) in items" />')
test('bracketed value', () => {
const source = '<span v-for="( item ) in items" />'
const node = parse(source)
transform(node, { nodeTransforms: [transformFor] })
@@ -48,46 +330,29 @@ describe('v-for', () => {
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('{ id, value }')
expect(forNode.source.content).toBe('items')
})
test('array de-structured value', () => {
const node = parse('<span v-for="([ id, value ]) in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('[ id, value ]')
expect(forNode.source.content).toBe('items')
})
test('value and key', () => {
const node = parse('<span v-for="(item, key) in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.keyAlias).not.toBeUndefined()
expect(forNode.keyAlias!.content).toBe('key')
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.valueAlias!.loc.start.offset).toBe(
source.indexOf('item') - 1
)
expect(forNode.valueAlias!.loc.start.line).toBe(1)
expect(forNode.valueAlias!.loc.start.column).toBe(source.indexOf('item'))
expect(forNode.valueAlias!.loc.end.line).toBe(1)
expect(forNode.valueAlias!.loc.end.column).toBe(
source.indexOf('item') + 4
)
expect(forNode.source.content).toBe('items')
expect(forNode.source.loc.start.offset).toBe(source.indexOf('items') - 1)
expect(forNode.source.loc.start.line).toBe(1)
expect(forNode.source.loc.start.column).toBe(source.indexOf('items'))
expect(forNode.source.loc.end.line).toBe(1)
expect(forNode.source.loc.end.column).toBe(source.indexOf('items') + 5)
})
test('value, key and index', () => {
const node = parse('<span v-for="(value, key, index) in items" />')
test('de-structured value', () => {
const source = '<span v-for="( { id, key })in items" />'
const node = parse(source)
transform(node, { nodeTransforms: [transformFor] })
@@ -96,16 +361,82 @@ describe('v-for', () => {
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).not.toBeUndefined()
expect(forNode.valueAlias!.content).toBe('{ id, key }')
expect(forNode.valueAlias!.loc.start.offset).toBe(
source.indexOf('{ id, key }') - 1
)
expect(forNode.valueAlias!.loc.start.line).toBe(1)
expect(forNode.valueAlias!.loc.start.column).toBe(
source.indexOf('{ id, key }')
)
expect(forNode.valueAlias!.loc.end.line).toBe(1)
expect(forNode.valueAlias!.loc.end.column).toBe(
source.indexOf('{ id, key }') + '{ id, key }'.length
)
expect(forNode.source.content).toBe('items')
expect(forNode.source.loc.start.offset).toBe(source.indexOf('items') - 1)
expect(forNode.source.loc.start.line).toBe(1)
expect(forNode.source.loc.start.column).toBe(source.indexOf('items'))
expect(forNode.source.loc.end.line).toBe(1)
expect(forNode.source.loc.end.column).toBe(source.indexOf('items') + 5)
})
test('bracketed value, key, index', () => {
const source = '<span v-for="( item, key, index ) in items" />'
const node = parse(source)
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.valueAlias!.loc.start.offset).toBe(
source.indexOf('item') - 1
)
expect(forNode.valueAlias!.loc.start.line).toBe(1)
expect(forNode.valueAlias!.loc.start.column).toBe(source.indexOf('item'))
expect(forNode.valueAlias!.loc.end.line).toBe(1)
expect(forNode.valueAlias!.loc.end.column).toBe(
source.indexOf('item') + 4
)
expect(forNode.keyAlias!.content).toBe('key')
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.keyAlias!.loc.start.offset).toBe(source.indexOf('key') - 1)
expect(forNode.keyAlias!.loc.start.line).toBe(1)
expect(forNode.keyAlias!.loc.start.column).toBe(source.indexOf('key'))
expect(forNode.keyAlias!.loc.end.line).toBe(1)
expect(forNode.keyAlias!.loc.end.column).toBe(source.indexOf('key') + 3)
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias!.content).toBe('value')
expect(forNode.objectIndexAlias!.loc.start.offset).toBe(
source.indexOf('index') - 1
)
expect(forNode.objectIndexAlias!.loc.start.line).toBe(1)
expect(forNode.objectIndexAlias!.loc.start.column).toBe(
source.indexOf('index')
)
expect(forNode.objectIndexAlias!.loc.end.line).toBe(1)
expect(forNode.objectIndexAlias!.loc.end.column).toBe(
source.indexOf('index') + 5
)
expect(forNode.source.content).toBe('items')
expect(forNode.source.loc.start.offset).toBe(source.indexOf('items') - 1)
expect(forNode.source.loc.start.line).toBe(1)
expect(forNode.source.loc.start.column).toBe(source.indexOf('items'))
expect(forNode.source.loc.end.line).toBe(1)
expect(forNode.source.loc.end.column).toBe(source.indexOf('items') + 5)
})
test('skipped key', () => {
const node = parse('<span v-for="(value,,index) in items" />')
const source = '<span v-for="( item,, index ) in items" />'
const node = parse(source)
transform(node, { nodeTransforms: [transformFor] })
@@ -114,390 +445,37 @@ describe('v-for', () => {
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias!.content).toBe('value')
expect(forNode.source.content).toBe('items')
})
test('skipped value and key', () => {
const node = parse('<span v-for="(,,index) in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias).toBeUndefined()
expect(forNode.source.content).toBe('items')
})
test('unbracketed value', () => {
const node = parse('<span v-for="item in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.source.content).toBe('items')
})
expect(forNode.valueAlias!.loc.start.offset).toBe(
source.indexOf('item') - 1
)
expect(forNode.valueAlias!.loc.start.line).toBe(1)
expect(forNode.valueAlias!.loc.start.column).toBe(source.indexOf('item'))
expect(forNode.valueAlias!.loc.end.line).toBe(1)
expect(forNode.valueAlias!.loc.end.column).toBe(
source.indexOf('item') + 4
)
test('unbracketed value and key', () => {
const node = parse('<span v-for="item, key in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).not.toBeUndefined()
expect(forNode.keyAlias!.content).toBe('key')
expect(forNode.objectIndexAlias).toBeUndefined()
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.source.content).toBe('items')
})
test('unbracketed value, key and index', () => {
const node = parse('<span v-for="value, key, index in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).not.toBeUndefined()
expect(forNode.keyAlias!.content).toBe('key')
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias!.content).toBe('value')
expect(forNode.objectIndexAlias!.loc.start.offset).toBe(
source.indexOf('index') - 1
)
expect(forNode.objectIndexAlias!.loc.start.line).toBe(1)
expect(forNode.objectIndexAlias!.loc.start.column).toBe(
source.indexOf('index')
)
expect(forNode.objectIndexAlias!.loc.end.line).toBe(1)
expect(forNode.objectIndexAlias!.loc.end.column).toBe(
source.indexOf('index') + 5
)
expect(forNode.source.content).toBe('items')
})
test('unbracketed skipped key', () => {
const node = parse('<span v-for="value, , index in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias!.content).toBe('value')
expect(forNode.source.content).toBe('items')
})
test('unbracketed skipped value and key', () => {
const node = parse('<span v-for=", , index in items" />')
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.keyAlias).toBeUndefined()
expect(forNode.objectIndexAlias).not.toBeUndefined()
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.valueAlias).toBeUndefined()
expect(forNode.source.content).toBe('items')
})
test('missing expression', () => {
const node = parse('<span v-for />')
const onError = jest.fn()
transform(node, { nodeTransforms: [transformFor], onError })
expect(onError).toHaveBeenCalledTimes(1)
expect(onError).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_FOR_NO_EXPRESSION
})
)
})
test('empty expression', () => {
const node = parse('<span v-for="" />')
const onError = jest.fn()
transform(node, { nodeTransforms: [transformFor], onError })
expect(onError).toHaveBeenCalledTimes(1)
expect(onError).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_FOR_MALFORMED_EXPRESSION
})
)
})
test('invalid expression', () => {
const node = parse('<span v-for="items" />')
const onError = jest.fn()
transform(node, { nodeTransforms: [transformFor], onError })
expect(onError).toHaveBeenCalledTimes(1)
expect(onError).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_FOR_MALFORMED_EXPRESSION
})
)
})
test('missing source', () => {
const node = parse('<span v-for="item in" />')
const onError = jest.fn()
transform(node, { nodeTransforms: [transformFor], onError })
expect(onError).toHaveBeenCalledTimes(1)
expect(onError).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_FOR_MALFORMED_EXPRESSION
})
)
})
test('missing value', () => {
const node = parse('<span v-for="in items" />')
const onError = jest.fn()
transform(node, { nodeTransforms: [transformFor], onError })
expect(onError).toHaveBeenCalledTimes(1)
expect(onError).toHaveBeenCalledWith(
expect.objectContaining({
code: ErrorCodes.X_FOR_MALFORMED_EXPRESSION
})
)
})
describe('source location', () => {
test('value & source', () => {
const source = '<span v-for="item in items" />'
const node = parse(source)
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.valueAlias!.loc.start.offset).toBe(
source.indexOf('item') - 1
)
expect(forNode.valueAlias!.loc.start.line).toBe(1)
expect(forNode.valueAlias!.loc.start.column).toBe(
source.indexOf('item')
)
expect(forNode.valueAlias!.loc.end.line).toBe(1)
expect(forNode.valueAlias!.loc.end.column).toBe(
source.indexOf('item') + 4
)
expect(forNode.source.content).toBe('items')
expect(forNode.source.loc.start.offset).toBe(
source.indexOf('items') - 1
)
expect(forNode.source.loc.start.line).toBe(1)
expect(forNode.source.loc.start.column).toBe(source.indexOf('items'))
expect(forNode.source.loc.end.line).toBe(1)
expect(forNode.source.loc.end.column).toBe(source.indexOf('items') + 5)
})
test('bracketed value', () => {
const source = '<span v-for="( item ) in items" />'
const node = parse(source)
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.valueAlias!.loc.start.offset).toBe(
source.indexOf('item') - 1
)
expect(forNode.valueAlias!.loc.start.line).toBe(1)
expect(forNode.valueAlias!.loc.start.column).toBe(
source.indexOf('item')
)
expect(forNode.valueAlias!.loc.end.line).toBe(1)
expect(forNode.valueAlias!.loc.end.column).toBe(
source.indexOf('item') + 4
)
expect(forNode.source.content).toBe('items')
expect(forNode.source.loc.start.offset).toBe(
source.indexOf('items') - 1
)
expect(forNode.source.loc.start.line).toBe(1)
expect(forNode.source.loc.start.column).toBe(source.indexOf('items'))
expect(forNode.source.loc.end.line).toBe(1)
expect(forNode.source.loc.end.column).toBe(source.indexOf('items') + 5)
})
test('de-structured value', () => {
const source = '<span v-for="( { id, key })in items" />'
const node = parse(source)
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.valueAlias!.content).toBe('{ id, key }')
expect(forNode.valueAlias!.loc.start.offset).toBe(
source.indexOf('{ id, key }') - 1
)
expect(forNode.valueAlias!.loc.start.line).toBe(1)
expect(forNode.valueAlias!.loc.start.column).toBe(
source.indexOf('{ id, key }')
)
expect(forNode.valueAlias!.loc.end.line).toBe(1)
expect(forNode.valueAlias!.loc.end.column).toBe(
source.indexOf('{ id, key }') + '{ id, key }'.length
)
expect(forNode.source.content).toBe('items')
expect(forNode.source.loc.start.offset).toBe(
source.indexOf('items') - 1
)
expect(forNode.source.loc.start.line).toBe(1)
expect(forNode.source.loc.start.column).toBe(source.indexOf('items'))
expect(forNode.source.loc.end.line).toBe(1)
expect(forNode.source.loc.end.column).toBe(source.indexOf('items') + 5)
})
test('bracketed value, key, index', () => {
const source = '<span v-for="( item, key, index ) in items" />'
const node = parse(source)
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.valueAlias!.loc.start.offset).toBe(
source.indexOf('item') - 1
)
expect(forNode.valueAlias!.loc.start.line).toBe(1)
expect(forNode.valueAlias!.loc.start.column).toBe(
source.indexOf('item')
)
expect(forNode.valueAlias!.loc.end.line).toBe(1)
expect(forNode.valueAlias!.loc.end.column).toBe(
source.indexOf('item') + 4
)
expect(forNode.keyAlias!.content).toBe('key')
expect(forNode.keyAlias!.loc.start.offset).toBe(
source.indexOf('key') - 1
)
expect(forNode.keyAlias!.loc.start.line).toBe(1)
expect(forNode.keyAlias!.loc.start.column).toBe(source.indexOf('key'))
expect(forNode.keyAlias!.loc.end.line).toBe(1)
expect(forNode.keyAlias!.loc.end.column).toBe(source.indexOf('key') + 3)
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.objectIndexAlias!.loc.start.offset).toBe(
source.indexOf('index') - 1
)
expect(forNode.objectIndexAlias!.loc.start.line).toBe(1)
expect(forNode.objectIndexAlias!.loc.start.column).toBe(
source.indexOf('index')
)
expect(forNode.objectIndexAlias!.loc.end.line).toBe(1)
expect(forNode.objectIndexAlias!.loc.end.column).toBe(
source.indexOf('index') + 5
)
expect(forNode.source.content).toBe('items')
expect(forNode.source.loc.start.offset).toBe(
source.indexOf('items') - 1
)
expect(forNode.source.loc.start.line).toBe(1)
expect(forNode.source.loc.start.column).toBe(source.indexOf('items'))
expect(forNode.source.loc.end.line).toBe(1)
expect(forNode.source.loc.end.column).toBe(source.indexOf('items') + 5)
})
test('skipped key', () => {
const source = '<span v-for="( item,, index ) in items" />'
const node = parse(source)
transform(node, { nodeTransforms: [transformFor] })
expect(node.children.length).toBe(1)
const forNode = node.children[0] as ForNode
expect(forNode.type).toBe(NodeTypes.FOR)
expect(forNode.valueAlias!.content).toBe('item')
expect(forNode.valueAlias!.loc.start.offset).toBe(
source.indexOf('item') - 1
)
expect(forNode.valueAlias!.loc.start.line).toBe(1)
expect(forNode.valueAlias!.loc.start.column).toBe(
source.indexOf('item')
)
expect(forNode.valueAlias!.loc.end.line).toBe(1)
expect(forNode.valueAlias!.loc.end.column).toBe(
source.indexOf('item') + 4
)
expect(forNode.objectIndexAlias!.content).toBe('index')
expect(forNode.objectIndexAlias!.loc.start.offset).toBe(
source.indexOf('index') - 1
)
expect(forNode.objectIndexAlias!.loc.start.line).toBe(1)
expect(forNode.objectIndexAlias!.loc.start.column).toBe(
source.indexOf('index')
)
expect(forNode.objectIndexAlias!.loc.end.line).toBe(1)
expect(forNode.objectIndexAlias!.loc.end.column).toBe(
source.indexOf('index') + 5
)
expect(forNode.source.content).toBe('items')
expect(forNode.source.loc.start.offset).toBe(
source.indexOf('items') - 1
)
expect(forNode.source.loc.start.line).toBe(1)
expect(forNode.source.loc.start.column).toBe(source.indexOf('items'))
expect(forNode.source.loc.end.line).toBe(1)
expect(forNode.source.loc.end.column).toBe(source.indexOf('items') + 5)
})
expect(forNode.source.loc.start.offset).toBe(source.indexOf('items') - 1)
expect(forNode.source.loc.start.line).toBe(1)
expect(forNode.source.loc.start.column).toBe(source.indexOf('items'))
expect(forNode.source.loc.end.line).toBe(1)
expect(forNode.source.loc.end.column).toBe(source.indexOf('items') + 5)
})
})
})

View File

@@ -10,248 +10,242 @@ import {
} from '../../src/ast'
import { ErrorCodes } from '../../src/errors'
describe('compiler: v-if', () => {
describe('transform', () => {
test('basic v-if', () => {
const ast = parse(`<div v-if="ok"/>`)
transform(ast, {
nodeTransforms: [transformIf]
})
const node = ast.children[0] as IfNode
expect(node.type).toBe(NodeTypes.IF)
expect(node.branches.length).toBe(1)
expect(node.branches[0].condition!.content).toBe(`ok`)
expect(node.branches[0].children.length).toBe(1)
expect(node.branches[0].children[0].type).toBe(NodeTypes.ELEMENT)
expect((node.branches[0].children[0] as ElementNode).tag).toBe(`div`)
})
test('template v-if', () => {
const ast = parse(`<template v-if="ok"><div/>hello<p/></template>`)
transform(ast, {
nodeTransforms: [transformIf]
})
const node = ast.children[0] as IfNode
expect(node.type).toBe(NodeTypes.IF)
expect(node.branches.length).toBe(1)
expect(node.branches[0].condition!.content).toBe(`ok`)
expect(node.branches[0].children.length).toBe(3)
expect(node.branches[0].children[0].type).toBe(NodeTypes.ELEMENT)
expect((node.branches[0].children[0] as ElementNode).tag).toBe(`div`)
expect(node.branches[0].children[1].type).toBe(NodeTypes.TEXT)
expect((node.branches[0].children[1] as TextNode).content).toBe(`hello`)
expect(node.branches[0].children[2].type).toBe(NodeTypes.ELEMENT)
expect((node.branches[0].children[2] as ElementNode).tag).toBe(`p`)
})
test('v-if + v-else', () => {
const ast = parse(`<div v-if="ok"/><p v-else/>`)
transform(ast, {
nodeTransforms: [transformIf]
})
// should fold branches
expect(ast.children.length).toBe(1)
const node = ast.children[0] as IfNode
expect(node.type).toBe(NodeTypes.IF)
expect(node.branches.length).toBe(2)
const b1 = node.branches[0]
expect(b1.condition!.content).toBe(`ok`)
expect(b1.children.length).toBe(1)
expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b1.children[0] as ElementNode).tag).toBe(`div`)
const b2 = node.branches[1]
expect(b2.condition).toBeUndefined()
expect(b2.children.length).toBe(1)
expect(b2.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b2.children[0] as ElementNode).tag).toBe(`p`)
})
test('v-if + v-else-if', () => {
const ast = parse(`<div v-if="ok"/><p v-else-if="orNot"/>`)
transform(ast, {
nodeTransforms: [transformIf]
})
// should fold branches
expect(ast.children.length).toBe(1)
const node = ast.children[0] as IfNode
expect(node.type).toBe(NodeTypes.IF)
expect(node.branches.length).toBe(2)
const b1 = node.branches[0]
expect(b1.condition!.content).toBe(`ok`)
expect(b1.children.length).toBe(1)
expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b1.children[0] as ElementNode).tag).toBe(`div`)
const b2 = node.branches[1]
expect(b2.condition!.content).toBe(`orNot`)
expect(b2.children.length).toBe(1)
expect(b2.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b2.children[0] as ElementNode).tag).toBe(`p`)
})
test('v-if + v-else-if + v-else', () => {
const ast = parse(
`<div v-if="ok"/><p v-else-if="orNot"/><template v-else>fine</template>`
)
transform(ast, {
nodeTransforms: [transformIf]
})
// should fold branches
expect(ast.children.length).toBe(1)
const node = ast.children[0] as IfNode
expect(node.type).toBe(NodeTypes.IF)
expect(node.branches.length).toBe(3)
const b1 = node.branches[0]
expect(b1.condition!.content).toBe(`ok`)
expect(b1.children.length).toBe(1)
expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b1.children[0] as ElementNode).tag).toBe(`div`)
const b2 = node.branches[1]
expect(b2.condition!.content).toBe(`orNot`)
expect(b2.children.length).toBe(1)
expect(b2.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b2.children[0] as ElementNode).tag).toBe(`p`)
const b3 = node.branches[2]
expect(b3.condition).toBeUndefined()
expect(b3.children.length).toBe(1)
expect(b3.children[0].type).toBe(NodeTypes.TEXT)
expect((b3.children[0] as TextNode).content).toBe(`fine`)
})
test('comment between branches', () => {
const ast = parse(`
<div v-if="ok"/>
<!--foo-->
<p v-else-if="orNot"/>
<!--bar-->
<template v-else>fine</template>
`)
transform(ast, {
nodeTransforms: [transformIf]
})
// should fold branches
expect(ast.children.length).toBe(1)
const node = ast.children[0] as IfNode
expect(node.type).toBe(NodeTypes.IF)
expect(node.branches.length).toBe(3)
const b1 = node.branches[0]
expect(b1.condition!.content).toBe(`ok`)
expect(b1.children.length).toBe(1)
expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b1.children[0] as ElementNode).tag).toBe(`div`)
const b2 = node.branches[1]
expect(b2.condition!.content).toBe(`orNot`)
expect(b2.children.length).toBe(2)
expect(b2.children[0].type).toBe(NodeTypes.COMMENT)
expect((b2.children[0] as CommentNode).content).toBe(`foo`)
expect(b2.children[1].type).toBe(NodeTypes.ELEMENT)
expect((b2.children[1] as ElementNode).tag).toBe(`p`)
const b3 = node.branches[2]
expect(b3.condition).toBeUndefined()
expect(b3.children.length).toBe(2)
expect(b3.children[0].type).toBe(NodeTypes.COMMENT)
expect((b3.children[0] as CommentNode).content).toBe(`bar`)
expect(b3.children[1].type).toBe(NodeTypes.TEXT)
expect((b3.children[1] as TextNode).content).toBe(`fine`)
})
test('error on v-else missing adjacent v-if', () => {
const ast = parse(`<div v-else/>`)
const spy = jest.fn()
transform(ast, {
nodeTransforms: [transformIf],
onError: spy
})
expect(spy.mock.calls[0]).toMatchObject([
{
code: ErrorCodes.X_ELSE_NO_ADJACENT_IF,
loc: ast.children[0].loc.start
}
])
const ast2 = parse(`<div/><div v-else/>`)
const spy2 = jest.fn()
transform(ast2, {
nodeTransforms: [transformIf],
onError: spy2
})
expect(spy2.mock.calls[0]).toMatchObject([
{
code: ErrorCodes.X_ELSE_NO_ADJACENT_IF,
loc: ast2.children[1].loc.start
}
])
const ast3 = parse(`<div/>foo<div v-else/>`)
const spy3 = jest.fn()
transform(ast3, {
nodeTransforms: [transformIf],
onError: spy3
})
expect(spy3.mock.calls[0]).toMatchObject([
{
code: ErrorCodes.X_ELSE_NO_ADJACENT_IF,
loc: ast3.children[2].loc.start
}
])
})
test('error on v-else-if missing adjacent v-if', () => {
const ast = parse(`<div v-else-if="foo"/>`)
const spy = jest.fn()
transform(ast, {
nodeTransforms: [transformIf],
onError: spy
})
expect(spy.mock.calls[0]).toMatchObject([
{
code: ErrorCodes.X_ELSE_IF_NO_ADJACENT_IF,
loc: ast.children[0].loc.start
}
])
const ast2 = parse(`<div/><div v-else-if="foo"/>`)
const spy2 = jest.fn()
transform(ast2, {
nodeTransforms: [transformIf],
onError: spy2
})
expect(spy2.mock.calls[0]).toMatchObject([
{
code: ErrorCodes.X_ELSE_IF_NO_ADJACENT_IF,
loc: ast2.children[1].loc.start
}
])
const ast3 = parse(`<div/>foo<div v-else-if="foo"/>`)
const spy3 = jest.fn()
transform(ast3, {
nodeTransforms: [transformIf],
onError: spy3
})
expect(spy3.mock.calls[0]).toMatchObject([
{
code: ErrorCodes.X_ELSE_IF_NO_ADJACENT_IF,
loc: ast3.children[2].loc.start
}
])
describe('compiler: transform v-if', () => {
test('basic v-if', () => {
const ast = parse(`<div v-if="ok"/>`)
transform(ast, {
nodeTransforms: [transformIf]
})
const node = ast.children[0] as IfNode
expect(node.type).toBe(NodeTypes.IF)
expect(node.branches.length).toBe(1)
expect(node.branches[0].condition!.content).toBe(`ok`)
expect(node.branches[0].children.length).toBe(1)
expect(node.branches[0].children[0].type).toBe(NodeTypes.ELEMENT)
expect((node.branches[0].children[0] as ElementNode).tag).toBe(`div`)
})
describe('codegen', () => {
// TODO
test('template v-if', () => {
const ast = parse(`<template v-if="ok"><div/>hello<p/></template>`)
transform(ast, {
nodeTransforms: [transformIf]
})
const node = ast.children[0] as IfNode
expect(node.type).toBe(NodeTypes.IF)
expect(node.branches.length).toBe(1)
expect(node.branches[0].condition!.content).toBe(`ok`)
expect(node.branches[0].children.length).toBe(3)
expect(node.branches[0].children[0].type).toBe(NodeTypes.ELEMENT)
expect((node.branches[0].children[0] as ElementNode).tag).toBe(`div`)
expect(node.branches[0].children[1].type).toBe(NodeTypes.TEXT)
expect((node.branches[0].children[1] as TextNode).content).toBe(`hello`)
expect(node.branches[0].children[2].type).toBe(NodeTypes.ELEMENT)
expect((node.branches[0].children[2] as ElementNode).tag).toBe(`p`)
})
test('v-if + v-else', () => {
const ast = parse(`<div v-if="ok"/><p v-else/>`)
transform(ast, {
nodeTransforms: [transformIf]
})
// should fold branches
expect(ast.children.length).toBe(1)
const node = ast.children[0] as IfNode
expect(node.type).toBe(NodeTypes.IF)
expect(node.branches.length).toBe(2)
const b1 = node.branches[0]
expect(b1.condition!.content).toBe(`ok`)
expect(b1.children.length).toBe(1)
expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b1.children[0] as ElementNode).tag).toBe(`div`)
const b2 = node.branches[1]
expect(b2.condition).toBeUndefined()
expect(b2.children.length).toBe(1)
expect(b2.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b2.children[0] as ElementNode).tag).toBe(`p`)
})
test('v-if + v-else-if', () => {
const ast = parse(`<div v-if="ok"/><p v-else-if="orNot"/>`)
transform(ast, {
nodeTransforms: [transformIf]
})
// should fold branches
expect(ast.children.length).toBe(1)
const node = ast.children[0] as IfNode
expect(node.type).toBe(NodeTypes.IF)
expect(node.branches.length).toBe(2)
const b1 = node.branches[0]
expect(b1.condition!.content).toBe(`ok`)
expect(b1.children.length).toBe(1)
expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b1.children[0] as ElementNode).tag).toBe(`div`)
const b2 = node.branches[1]
expect(b2.condition!.content).toBe(`orNot`)
expect(b2.children.length).toBe(1)
expect(b2.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b2.children[0] as ElementNode).tag).toBe(`p`)
})
test('v-if + v-else-if + v-else', () => {
const ast = parse(
`<div v-if="ok"/><p v-else-if="orNot"/><template v-else>fine</template>`
)
transform(ast, {
nodeTransforms: [transformIf]
})
// should fold branches
expect(ast.children.length).toBe(1)
const node = ast.children[0] as IfNode
expect(node.type).toBe(NodeTypes.IF)
expect(node.branches.length).toBe(3)
const b1 = node.branches[0]
expect(b1.condition!.content).toBe(`ok`)
expect(b1.children.length).toBe(1)
expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b1.children[0] as ElementNode).tag).toBe(`div`)
const b2 = node.branches[1]
expect(b2.condition!.content).toBe(`orNot`)
expect(b2.children.length).toBe(1)
expect(b2.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b2.children[0] as ElementNode).tag).toBe(`p`)
const b3 = node.branches[2]
expect(b3.condition).toBeUndefined()
expect(b3.children.length).toBe(1)
expect(b3.children[0].type).toBe(NodeTypes.TEXT)
expect((b3.children[0] as TextNode).content).toBe(`fine`)
})
test('comment between branches', () => {
const ast = parse(`
<div v-if="ok"/>
<!--foo-->
<p v-else-if="orNot"/>
<!--bar-->
<template v-else>fine</template>
`)
transform(ast, {
nodeTransforms: [transformIf]
})
// should fold branches
expect(ast.children.length).toBe(1)
const node = ast.children[0] as IfNode
expect(node.type).toBe(NodeTypes.IF)
expect(node.branches.length).toBe(3)
const b1 = node.branches[0]
expect(b1.condition!.content).toBe(`ok`)
expect(b1.children.length).toBe(1)
expect(b1.children[0].type).toBe(NodeTypes.ELEMENT)
expect((b1.children[0] as ElementNode).tag).toBe(`div`)
const b2 = node.branches[1]
expect(b2.condition!.content).toBe(`orNot`)
expect(b2.children.length).toBe(2)
expect(b2.children[0].type).toBe(NodeTypes.COMMENT)
expect((b2.children[0] as CommentNode).content).toBe(`foo`)
expect(b2.children[1].type).toBe(NodeTypes.ELEMENT)
expect((b2.children[1] as ElementNode).tag).toBe(`p`)
const b3 = node.branches[2]
expect(b3.condition).toBeUndefined()
expect(b3.children.length).toBe(2)
expect(b3.children[0].type).toBe(NodeTypes.COMMENT)
expect((b3.children[0] as CommentNode).content).toBe(`bar`)
expect(b3.children[1].type).toBe(NodeTypes.TEXT)
expect((b3.children[1] as TextNode).content).toBe(`fine`)
})
test('error on v-else missing adjacent v-if', () => {
const ast = parse(`<div v-else/>`)
const spy = jest.fn()
transform(ast, {
nodeTransforms: [transformIf],
onError: spy
})
expect(spy.mock.calls[0]).toMatchObject([
{
code: ErrorCodes.X_ELSE_NO_ADJACENT_IF,
loc: ast.children[0].loc
}
])
const ast2 = parse(`<div/><div v-else/>`)
const spy2 = jest.fn()
transform(ast2, {
nodeTransforms: [transformIf],
onError: spy2
})
expect(spy2.mock.calls[0]).toMatchObject([
{
code: ErrorCodes.X_ELSE_NO_ADJACENT_IF,
loc: ast2.children[1].loc
}
])
const ast3 = parse(`<div/>foo<div v-else/>`)
const spy3 = jest.fn()
transform(ast3, {
nodeTransforms: [transformIf],
onError: spy3
})
expect(spy3.mock.calls[0]).toMatchObject([
{
code: ErrorCodes.X_ELSE_NO_ADJACENT_IF,
loc: ast3.children[2].loc
}
])
})
test('error on v-else-if missing adjacent v-if', () => {
const ast = parse(`<div v-else-if="foo"/>`)
const spy = jest.fn()
transform(ast, {
nodeTransforms: [transformIf],
onError: spy
})
expect(spy.mock.calls[0]).toMatchObject([
{
code: ErrorCodes.X_ELSE_IF_NO_ADJACENT_IF,
loc: ast.children[0].loc
}
])
const ast2 = parse(`<div/><div v-else-if="foo"/>`)
const spy2 = jest.fn()
transform(ast2, {
nodeTransforms: [transformIf],
onError: spy2
})
expect(spy2.mock.calls[0]).toMatchObject([
{
code: ErrorCodes.X_ELSE_IF_NO_ADJACENT_IF,
loc: ast2.children[1].loc
}
])
const ast3 = parse(`<div/>foo<div v-else-if="foo"/>`)
const spy3 = jest.fn()
transform(ast3, {
nodeTransforms: [transformIf],
onError: spy3
})
expect(spy3.mock.calls[0]).toMatchObject([
{
code: ErrorCodes.X_ELSE_IF_NO_ADJACENT_IF,
loc: ast3.children[2].loc
}
])
})
})