Back to Repositories

Testing v-HTML Directive Transformation in uni-app UTS Android Compiler

This test suite validates the v-html directive transformation functionality in the uni-app UTS compiler for Android. It ensures proper handling of HTML content injection through v-html directives while maintaining security and compliance with the Vue compiler core specifications.

Test Coverage Overview

The test suite provides comprehensive coverage of v-html directive transformations:

  • Simple expression handling for basic v-html usage
  • Non-element component validation
  • Error handling for missing expressions
  • Validation of child element restrictions

Implementation Analysis

The testing approach utilizes Jest’s describe/test pattern combined with custom assertion utilities. It implements Vue compiler core transformations through a specialized parseWithVHtml helper that integrates multiple transform phases including vHtml, expression, and element transformations.

The implementation leverages @vue/compiler-core and @vue/shared libraries for AST parsing and transformation.

Technical Details

Testing infrastructure includes:

  • Jest as the primary testing framework
  • Custom assert utility for template transformation validation
  • Mock error handlers for validation testing
  • Integration with Vue compiler core AST parsing
  • Specialized compiler options for prefixIdentifiers and custom transforms

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Isolated test cases for specific functionality
  • Comprehensive error condition coverage
  • Clear test case organization and naming
  • Mock function usage for error validation
  • Modular test helper functions

dcloudio/uni-app

packages/uni-app-uts/__tests__/android/transforms/vHtml.spec.ts

            
import { extend } from '@vue/shared'
import {
  type CompilerOptions,
  baseParse as parse,
  transform,
  transformElement,
} from '@vue/compiler-core'
import { ErrorCodes } from '../../../src/plugins/android/uvue/compiler/errors'
import { transformVHtml } from '../../../src/plugins/android/uvue/compiler/transforms/vHtml'
import { transformExpression } from '../../../src/plugins/android/uvue/compiler/transforms/transformExpression'
import { assert } from '../testUtils'

function parseWithVHtml(template: string, options: CompilerOptions = {}) {
  const ast = parse(template)

  transform(
    ast,
    extend({}, options, {
      prefixIdentifiers: options.prefixIdentifiers,
      nodeTransforms: [transformVHtml, transformExpression, transformElement],
    })
  )

  return ast
}

describe('compiler: transform v-html', () => {
  test('simple expression', () => {
    assert(
      `<view v-html="html" />`,
      `createElementVNode(\"view\", null, [
  createElementVNode(\"rich-text\", utsMapOf({ nodes: _ctx.html }), null, 8 /* PROPS */, [\"nodes\"])
])`
    )
  })

  test('Non-Element should be ignored', () => {
    assert(`<Foo v-html="html" />`, `createVNode(_component_Foo)`)
  })

  test('should throw error when missing expression', () => {
    const onError = jest.fn()
    parseWithVHtml('<view v-html="" />', {
      onError,
      prefixIdentifiers: true,
    })

    expect(onError).toHaveBeenCalledTimes(1)
    expect(onError).toHaveBeenCalledWith(
      expect.objectContaining({
        code: ErrorCodes.X_V_HTML_NO_EXPRESSION,
      })
    )
  })

  test('should throw error when has children', () => {
    const onError = jest.fn()
    parseWithVHtml(
      '<view v-html="html"><text>text child in v-html</text></view>',
      {
        onError,
        prefixIdentifiers: true,
      }
    )

    expect(onError).toHaveBeenCalledTimes(1)
    expect(onError).toHaveBeenCalledWith(
      expect.objectContaining({
        code: ErrorCodes.X_V_HTML_WITH_CHILDREN,
      })
    )
  })
})