# 11. [Vitest] fix: support custom toString method in %s format

pengooseDev·약 18시간 전
0

PR
Issue

1. Issue

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 }.


2. Context 파악

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)

3. 회귀 테스트

기존 테스트에 추가해주기

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

4. 해결

새로 정의된 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

별 다른 피드백 없이 merged

0개의 댓글

관련 채용 정보