From 1868f1c4ba4ce610ebe758d95d192be249aa1e23 Mon Sep 17 00:00:00 2001 From: scarf Date: Mon, 5 Dec 2022 23:26:04 +0900 Subject: [PATCH] feat: format test objects in `each` title (fix #2420) (#2421) * test: add test for objectAttr * feat: pretty print test title objects * style: apply lint * refactor(dev): add return type for formatObject * feat(dev): use maxWidth specify maximum printed width for properties such as arrays and sets * refactor: use `chaiUtil.objDisplay` instead --- packages/vitest/src/runtime/suite.ts | 8 +++++--- test/core/test/utils.spec.ts | 27 ++++++++++++++++++++++++++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/packages/vitest/src/runtime/suite.ts b/packages/vitest/src/runtime/suite.ts index 1f217fbdc3d2..8a69f6bc05e1 100644 --- a/packages/vitest/src/runtime/suite.ts +++ b/packages/vitest/src/runtime/suite.ts @@ -1,4 +1,5 @@ import util from 'util' +import { util as chaiUtil } from 'chai' import type { BenchFunction, BenchOptions, Benchmark, BenchmarkAPI, File, RunMode, Suite, SuiteAPI, SuiteCollector, SuiteFactory, SuiteHooks, Task, Test, TestAPI, TestFunction, TestOptions } from '../types' import { getWorkerState, isObject, isRunningInBenchmark, isRunningInTest, noop, objectAttr } from '../utils' import { createChainable } from './chain' @@ -273,9 +274,10 @@ function formatTitle(template: string, items: any[], idx: number) { const count = template.split('%').length - 1 let formatted = util.format(template, ...items.slice(0, count)) if (isObject(items[0])) { - formatted = formatted.replace(/\$([$\w_.]+)/g, (_, key) => { - return objectAttr(items[0], key) - }) + formatted = formatted.replace(/\$([$\w_.]+)/g, + (_, key) => chaiUtil.objDisplay(objectAttr(items[0], key)) as unknown as string, + // https://github.com/chaijs/chai/pull/1490 + ) } return formatted } diff --git a/test/core/test/utils.spec.ts b/test/core/test/utils.spec.ts index 5525adae7a3b..7ebfda54a73d 100644 --- a/test/core/test/utils.spec.ts +++ b/test/core/test/utils.spec.ts @@ -1,5 +1,5 @@ import { describe, expect, test } from 'vitest' -import { assertTypes, deepClone, deepMerge, resetModules, toArray } from '../../../packages/vitest/src/utils' +import { assertTypes, deepClone, deepMerge, objectAttr, resetModules, toArray } from '../../../packages/vitest/src/utils' import { deepMergeSnapshot } from '../../../packages/vitest/src/integrations/snapshot/port/utils' import type { ModuleCacheMap } from '../../../packages/vite-node/src/types' @@ -182,3 +182,28 @@ describe('resetModules doesn\'t resets only user modules', () => { expect(moduleCache.size).toBe(2) }) }) + +describe('objectAttr', () => { + const arrow = (a: number) => a * 3 + const func = function (a: number) { + return a * 3 + } + + test.each` + value | path | expected + ${{ foo: 'bar' }} | ${'foo'} | ${'bar'} + ${{ foo: { bar: 'baz' } }} | ${'foo'} | ${{ bar: 'baz' }} + ${{ foo: { bar: 'baz' } }} | ${'foo.bar'} | ${'baz'} + ${{ foo: [{ bar: 'baz' }] }} | ${'foo.0.bar'} | ${'baz'} + ${{ foo: [1, 2, ['a']] }} | ${'foo'} | ${[1, 2, ['a']]} + ${{ foo: [1, 2, ['a']] }} | ${'foo.2'} | ${['a']} + ${{ foo: [1, 2, ['a']] }} | ${'foo.2.0'} | ${'a'} + ${{ foo: [[1]] }} | ${'foo.0.0'} | ${1} + ${{ deep: [[[1]]] }} | ${'deep.0.0.0'} | ${1} + ${{ a: 1, b: 2, c: 3, d: 4 }} | ${'a'} | ${1} + ${{ arrow }} | ${'arrow'} | ${arrow} + ${{ func }} | ${'func'} | ${func} + `('objectAttr($value, $path) -> $expected', ({ value, path, expected }) => { + expect(objectAttr(value, path)).toEqual(expected) + }) +})