serialize.test.js 1.86 KB
import { describe, it, expect } from 'vitest'
import { serializeLine } from '../src/serialize.js'

describe('serializeLine', () => {
  it('produces a single-line valid JSON string', () => {
    const line = serializeLine({ trace_id: 't1', msg: 'hi' })
    expect(line).not.toContain('\n')
    expect(JSON.parse(line)).toEqual({ trace_id: 't1', msg: 'hi' })
  })

  it('serializes Error with name/message/stack instead of {}', () => {
    const err = new TypeError('boom')
    const out = JSON.parse(serializeLine({ trace_id: 't2', err }))
    expect(out.err.name).toBe('TypeError')
    expect(out.err.message).toBe('boom')
    expect(typeof out.err.stack).toBe('string')
  })

  it('does not throw on circular references and keeps trace_id', () => {
    const a = { trace_id: 't3' }
    a.self = a
    const out = JSON.parse(serializeLine(a))
    expect(out.trace_id).toBe('t3')
    expect(out.self).toBe('[Circular]')
  })

  it('drops undefined fields, keeps null', () => {
    const out = JSON.parse(serializeLine({ trace_id: 't4', a: undefined, b: null }))
    expect('a' in out).toBe(false)
    expect(out.b).toBe(null)
    expect(out.trace_id).toBe('t4')
  })

  it('downgrades bigint/function/symbol without throwing', () => {
    const out = JSON.parse(
      serializeLine({ trace_id: 't5', big: 10n, fn: function named() {}, sym: Symbol('x') }),
    )
    expect(out.big).toBe('10')
    expect(out.fn).toBe('[Function: named]')
    expect(out.sym).toBe('Symbol(x)')
  })

  it('never throws and still carries trace_id on total failure', () => {
    // 用一个会让 toJSON 抛错的对象逼出兜底分支。
    const evil = {
      trace_id: 't6',
      bad: {
        toJSON() {
          throw new Error('nope')
        },
      },
    }
    const out = JSON.parse(serializeLine(evil))
    expect(out.trace_id).toBe('t6')
    expect(out.msg).toBe('log serialization failed')
  })
})