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') }) })