useFieldDependencies.test.js 4.07 KB
/**
 * useFieldDependencies 单元测试
 *
 * @description 测试字段关联系统的显示/隐藏逻辑
 * @module composables/__tests__/useFieldDependencies.test
 */

import { describe, it, expect, beforeEach, vi } from 'vitest'
import { reactive } from 'vue'
import { useFieldDependencies } from '../useFieldDependencies'
import { PLAN_FIELD_DEFINITIONS } from '@/config/plan-fields'

describe('useFieldDependencies', () => {
  let formData, deps

  beforeEach(() => {
    formData = reactive({
      withdrawal_enabled: false,
      withdrawal_mode: '',
      withdrawal_start_age: null
    })
    deps = useFieldDependencies(formData)
  })

  it('should initialize field states', () => {
    expect(deps.fieldVisibility.withdrawal_enabled).toBe(true)
    expect(deps.fieldVisibility.withdrawal_mode).toBe(false) // 受影响,默认隐藏
  })

  it('should hide fields when dependency is false', () => {
    // withdrawal_enabled = false,withdrawal_mode 应该隐藏
    expect(deps.isFieldVisible('withdrawal_mode')).toBe(false)
    expect(deps.isFieldEnabled('withdrawal_mode')).toBe(false)
  })

  it('should show fields when dependency becomes true', () => {
    // 启用提取
    deps.updateFieldValue('withdrawal_enabled', true)

    // withdrawal_mode 应该显示
    expect(deps.isFieldVisible('withdrawal_mode')).toBe(true)
    expect(deps.isFieldEnabled('withdrawal_mode')).toBe(true)
    expect(deps.fieldVisibility.withdrawal_mode).toBe(true)
  })

  it('should update affected fields when dependency changes', () => {
    // 初始状态
    expect(deps.fieldVisibility.withdrawal_mode).toBe(false)

    // 启用提取
    deps.updateFieldValue('withdrawal_enabled', true)

    // 检查状态已更新
    expect(deps.fieldVisibility.withdrawal_mode).toBe(true)

    // 禁用提取
    deps.updateFieldValue('withdrawal_enabled', false)

    // 状态应该隐藏
    expect(deps.fieldVisibility.withdrawal_mode).toBe(false)
  })

  it('should handle show_when conditions', () => {
    // 测试 show_when 条件
    const definition = PLAN_FIELD_DEFINITIONS.withdrawal_mode
    expect(definition.show_when).toEqual({ withdrawal_enabled: true })

    // 当条件不满足时
    expect(deps.isFieldVisible('withdrawal_mode')).toBe(false)

    // 满足条件
    deps.updateFieldValue('withdrawal_enabled', true)
    expect(deps.isFieldVisible('withdrawal_mode')).toBe(true)
  })

  it('should return list of visible fields', () => {
    // 初始状态(withdrawal_enabled = false)
    expect(deps.visibleFields.value).toContain('withdrawal_enabled')
    expect(deps.visibleFields.value).not.toContain('withdrawal_mode')

    // 启用后
    deps.updateFieldValue('withdrawal_enabled', true)
    expect(deps.visibleFields.value).toContain('withdrawal_mode')
  })

  it('should handle multiple affected fields', () => {
    // withdrawal_enabled affects multiple fields
    const affectedFields = PLAN_FIELD_DEFINITIONS.withdrawal_enabled.affects
    expect(affectedFields.length).toBeGreaterThan(0)

    // 启用后,所有受影响字段应该可见
    deps.updateFieldValue('withdrawal_enabled', true)

    for (const field of affectedFields) {
      expect(deps.isFieldVisible(field)).toBe(true)
    }
  })

  it('should handle fields without dependencies', () => {
    // customer_name 没有依赖,应该始终显示
    expect(deps.isFieldVisible('customer_name')).toBe(true)
    expect(deps.isFieldEnabled('customer_name')).toBe(true)
  })

  it('should detect circular dependencies in development', () => {
    const originalEnv = process.env.NODE_ENV
    process.env.NODE_ENV = 'development'
    const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {})

    PLAN_FIELD_DEFINITIONS.circular_a = {
      affects: ['circular_b']
    }
    PLAN_FIELD_DEFINITIONS.circular_b = {
      affects: ['circular_a']
    }

    const localFormData = reactive({})
    useFieldDependencies(localFormData)

    expect(consoleSpy).toHaveBeenCalled()

    delete PLAN_FIELD_DEFINITIONS.circular_a
    delete PLAN_FIELD_DEFINITIONS.circular_b
    consoleSpy.mockRestore()
    process.env.NODE_ENV = originalEnv
  })
})