diff --git a/packages/compiler-core/__tests__/directives/vIf.spec.ts b/packages/compiler-core/__tests__/directives/vIf.spec.ts new file mode 100644 index 000000000..503901014 --- /dev/null +++ b/packages/compiler-core/__tests__/directives/vIf.spec.ts @@ -0,0 +1,257 @@ +import { parse } from '../../src/parse' +import { transform } from '../../src/transform' +import { transformIf } from '../../src/directives/vIf' +import { + IfNode, + NodeTypes, + ElementNode, + TextNode, + CommentNode +} from '../../src/ast' +import { ErrorCodes } from '../../src/errors' + +describe('compiler: v-if', () => { + describe('transform', () => { + test('basic v-if', () => { + const ast = parse(`
`) + transform(ast, { + transforms: [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(`hello`) + transform(ast, { + transforms: [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(``) + transform(ast, { + transforms: [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(``) + transform(ast, { + transforms: [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( + `fine` + ) + transform(ast, { + transforms: [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(` + + + + + fine + `) + transform(ast, { + transforms: [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(``) + const spy = jest.fn() + transform(ast, { + transforms: [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(``) + const spy2 = jest.fn() + transform(ast2, { + transforms: [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(`foo`) + const spy3 = jest.fn() + transform(ast3, { + transforms: [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(``) + const spy = jest.fn() + transform(ast, { + transforms: [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(``) + const spy2 = jest.fn() + transform(ast2, { + transforms: [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(`foo`) + const spy3 = jest.fn() + transform(ast3, { + transforms: [transformIf], + onError: spy3 + }) + expect(spy3.mock.calls[0]).toMatchObject([ + { + code: ErrorCodes.X_ELSE_IF_NO_ADJACENT_IF, + loc: ast3.children[2].loc.start + } + ]) + }) + }) + + describe('codegen', () => { + // TODO + }) +}) diff --git a/packages/compiler-core/__tests__/transform.spec.ts b/packages/compiler-core/__tests__/transform.spec.ts index 2875e0956..87cb9326a 100644 --- a/packages/compiler-core/__tests__/transform.spec.ts +++ b/packages/compiler-core/__tests__/transform.spec.ts @@ -25,7 +25,7 @@ describe('compiler: transform', () => { { parent: ast, ancestors: [ast], - childIndex: 0 + currentNode: div } ]) expect(calls[1]).toMatchObject([ @@ -33,7 +33,7 @@ describe('compiler: transform', () => { { parent: div, ancestors: [ast, div], - childIndex: 0 + currentNode: div.children[0] } ]) expect(calls[2]).toMatchObject([ @@ -41,7 +41,7 @@ describe('compiler: transform', () => { { parent: div, ancestors: [ast, div], - childIndex: 1 + currentNode: div.children[1] } ]) }) @@ -81,7 +81,7 @@ describe('compiler: transform', () => { }) test('context.removeNode', () => { - const ast = parse(``) + const ast = parse(`