vitest의 format 유틸이 %s를 처리하는 방식이 NodeJS Spec이랑 다름.
(커스텀 toString 메서드 있을 때, node inspect말고 커스텀 toString 사용해야함.)
%s: String will be used to convert all values except BigInt, Object and -0.
BigInt values will be represented with an n and Objects
that have no user defined toString function are inspected using util.inspect()
with options { depth: 0, colors: false, compact: 3 }.
switch (x) {
case '%s': {
const value = args[i++]
if (typeof value === 'bigint') {
return `${value.toString()}n`
}
if (typeof value === 'number' && value === 0 && 1 / value < 0) {
return '-0'
}
if (typeof value === 'object' && value !== null) {
// 🎯 inspect만 사용. toString 검증 로직 추가해야함.
return inspect(value, { depth: 0, colors: false })
}
return String(value)
기존 테스트에 추가해주기
import util from 'node:util'
import { format } from '@vitest/utils'
import { describe, expect, test } from 'vitest'
describe('format', () => {
const obj = {} as any
obj.obj = obj
test.each([
// ...cases
[
'%s',
new (class {
constructor(public value: string) {}
toString() {
return this.value
}
})('string value'),
],
// ...cases
])('format(%s)', (formatString, ...args) => {
expect(format(formatString, ...args), `failed ${formatString}`).toBe(util.format(formatString, ...args))
})
새로 정의된 toString 메서드가 있는지 확인하고 분기처리하면 끝난다.
switch (x) {
case '%s': {
const value = args[i++]
if (typeof value === 'bigint') {
return `${value.toString()}n`
}
if (typeof value === 'number' && value === 0 && 1 / value < 0) {
return '-0'
}
if (typeof value === 'object' && value !== null) {
// 🎯 함수면서 && toString이 오버라이딩 되었니? > 그렇다면 toString 호출
if (typeof value.toString === 'function' && value.toString !== Object.prototype.toString) {
return value.toString()
}
return inspect(value, { depth: 0, colors: false })
}
return String(value)
별 다른 피드백 없이 merged