base.js 2.2 KB
/**
 * Vitest 预设的「默认值」与共享工具 —— 共享 coverage 门槛 / include / reporter + 深合并。
 *
 * `index.js` 持有 node/vue 两个工厂,本文件持有跨工厂共享的默认数据与无副作用 `deepMerge`。
 * coverage 门槛是「单一来源」:全仓收紧门槛改这一处,所有消费包下次跑即生效(§2 验收 5)。
 * 预设为纯配置:不读 env、不建连接。
 */

/**
 * @param {unknown} v
 * @returns {boolean}
 */
function isPlainObject(v) {
  if (v === null || typeof v !== 'object' || Array.isArray(v)) return false
  const proto = Object.getPrototypeOf(v)
  return proto === Object.prototype || proto === null
}

/**
 * 递归深合并(嵌套对象逐层合并、数组与标量整体替换)。
 * 保证 app 传 `test.coverage.thresholds` 只覆盖门槛字段,不抹掉其余默认。
 * @template T
 * @param {T} base
 * @param {Record<string, unknown>} override
 * @returns {T}
 */
export function deepMerge(base, override) {
  if (!isPlainObject(override)) return /** @type {T} */ (override ?? base)
  const out = isPlainObject(base) ? { ...base } : {}
  for (const key of Object.keys(override)) {
    const o = override[key]
    const b = /** @type {Record<string, unknown>} */ (out)[key]
    if (isPlainObject(b) && isPlainObject(o)) {
      /** @type {Record<string, unknown>} */ (out)[key] = deepMerge(b, o)
    } else {
      /** @type {Record<string, unknown>} */ (out)[key] = o
    }
  }
  return /** @type {T} */ (out)
}

/** 全仓统一的覆盖率门槛(单一来源)。改这里 = 全仓消费包门槛同步变化。 */
export const COVERAGE_THRESHOLDS = Object.freeze({
  lines: 80,
  functions: 80,
  branches: 75,
  statements: 80,
})

/** 全仓统一的 test 匹配 / 排除 / reporter / coverage 约定。 */
export function buildSharedTestConfig() {
  return {
    globals: true,
    include: ['test/**/*.test.js', 'src/**/*.test.js'],
    exclude: ['**/node_modules/**', '**/dist/**', '**/coverage/**'],
    reporters: ['default'],
    coverage: {
      provider: 'v8',
      reporter: ['text', 'lcov'],
      include: ['src/**/*.js'],
      exclude: ['**/*.test.js', '**/test/**'],
      thresholds: { ...COVERAGE_THRESHOLDS },
    },
  }
}