Back to Repositories

Testing Vue Template Compilation and Virtual DOM Implementation in dcloudio/uni-app

This test suite validates the Vue template compilation and virtual DOM functionality in uni-app, focusing on component rendering and event handling. It ensures proper template compilation, event modifier handling, and reactive state management within the uni-app framework.

Test Coverage Overview

The test suite provides comprehensive coverage of Vue template compilation and virtual DOM operations in uni-app.

  • Tests template compilation with event modifiers and conditional rendering
  • Verifies proper handling of ref-based reactivity
  • Validates component lifecycle and DOM updates
  • Tests integration between Vue runtime and uni-app page nodes

Implementation Analysis

The testing approach utilizes Jest’s describe/test structure to validate Vue template compilation and runtime behavior. The implementation leverages Vue’s compiler-sfc and runtime APIs to test template compilation, event handling with modifiers, and reactive state management using ref.

  • Uses compile function to test template transformation
  • Implements virtual DOM testing with createBlock and openBlock
  • Tests reactive state updates with nextTick

Technical Details

  • Testing Framework: Jest
  • Vue Compiler: @vue/compiler-sfc
  • Runtime Libraries: uni-app-vue service runtime
  • Test Utilities: createPageNode, nextTick
  • Environment Configuration: UNI_INPUT_DIR

Best Practices Demonstrated

The test suite exemplifies high-quality testing practices by isolating component functionality and ensuring comprehensive coverage of Vue template features.

  • Proper setup and teardown of test environment
  • Isolation of template compilation and runtime behavior
  • Comprehensive testing of event modifiers and conditional rendering
  • Clear separation of concerns between compilation and runtime tests

dcloudio/uni-app

packages/uni-app-plus/__tests__/service/index.spec.ts

            
import { compileTemplate } from '@vue/compiler-sfc'

import { uniAppPlugin } from '../../../uni-app-vite/src/plugin'
import {
  createBlock as _createBlock,
  createCommentVNode as _createCommentVNode,
  createVNode as _createVNode,
  openBlock as _openBlock,
  withModifiers as _withModifiers,
  createApp,
  nextTick,
  ref,
} from '../../../uni-app-vue/lib/service.runtime.esm'

import { createPageNode } from '../../src/service/framework/dom/Page'

process.env.UNI_INPUT_DIR = __dirname

const defaultPageNodeOptions = {
  css: true,
  route: 'pages/index/index',
  version: 1,
  locale: 'zh_CN',
  platform: 'ios',
  pixelRatio: 1,
  windowWidth: 375,
  disableScroll: false,
  onPageScroll: false,
  onPageReachBottom: false,
  onReachBottomDistance: 50,
  statusbarHeight: 24,
  windowTop: 0,
  windowBottom: 0,
}

const { uni } = uniAppPlugin()

function compile(source: string) {
  return compileTemplate({
    source,
    filename: 'demo',
    id: 'test',
    compilerOptions: { mode: 'module', ...uni!.compilerOptions },
  }).code
}

console.log(
  compile(
    `<view class="a" @click.stop="handleClick"><view v-if="show" style="color:red">123</view></view>`
  )
)

describe('vue', () => {
  test('vdom', () => {
    const show = ref(true)
    let handleClick: Function | null = _withModifiers(() => {}, [
      'stop',
      'self',
    ])
    const Page = {
      setup() {
        return () => {
          return (
            _openBlock(),
            _createBlock(
              'view',
              {
                class: 'a',
                onClickPassiveCaptureOnce: handleClick,
              },
              [
                show.value
                  ? (_openBlock(),
                    _createBlock(
                      'view',
                      {
                        key: 0,
                        style: { color: 'red' },
                      },
                      '123'
                    ))
                  : _createCommentVNode('v-if', true),
              ],
              8 /* PROPS */,
              ['onClickPassiveCaptureOnce']
            )
          )
        }
      },
    }
    const pageNode = createPageNode(1, defaultPageNodeOptions, true)
    createApp(Page).mount(pageNode as unknown as Element)
    show.value = false
    handleClick = null
    nextTick(() => {
      pageNode.update()
    })
  })
})