diff --git a/packages/css/src/options.test.ts b/packages/css/src/options.test.ts index f6ba6cbf6..bea36ddaa 100644 --- a/packages/css/src/options.test.ts +++ b/packages/css/src/options.test.ts @@ -43,11 +43,6 @@ describe('resolveCssOptions', () => { expect(result.target).toBeUndefined() }) - test('modules defaults to empty object', () => { - const result = resolveCssOptions() - expect(result.modules).toEqual({}) - }) - test('modules=false disables CSS modules', () => { const result = resolveCssOptions({ modules: false }) expect(result.modules).toBe(false) diff --git a/src/utils/fs.test.ts b/src/utils/fs.test.ts index 86030be29..61b0c65e2 100644 --- a/src/utils/fs.test.ts +++ b/src/utils/fs.test.ts @@ -12,74 +12,53 @@ import { } from './fs.ts' describe('lowestCommonAncestor', () => { - test('returns empty string for no paths', () => { - expect(lowestCommonAncestor()).toBe('') - }) - - test('returns dirname for single path', () => { - expect(lowestCommonAncestor('/foo/bar/baz.ts')).toBe( + test.each<[string, string[], string]>([ + ['returns empty string for no paths', [], ''], + [ + 'returns dirname for single path', + ['/foo/bar/baz.ts'], path.dirname('/foo/bar/baz.ts'), - ) - }) - - test('finds common ancestor of sibling files', () => { - expect(lowestCommonAncestor('/src/a.ts', '/src/b.ts')).toBe( + ], + [ + 'finds common ancestor of sibling files', + ['/src/a.ts', '/src/b.ts'], path.normalize('/src'), - ) - }) - - test('finds common ancestor of nested paths', () => { - expect(lowestCommonAncestor('/src/utils/a.ts', '/src/config/b.ts')).toBe( + ], + [ + 'finds common ancestor of nested paths', + ['/src/utils/a.ts', '/src/config/b.ts'], path.normalize('/src'), - ) - }) - - test('handles paths with no common ancestor beyond root', () => { - expect(lowestCommonAncestor('/foo/a.ts', '/bar/b.ts')).toBe( + ], + [ + 'handles paths with no common ancestor beyond root', + ['/foo/a.ts', '/bar/b.ts'], path.normalize('/'), - ) - }) - - test('handles multiple paths', () => { - expect( - lowestCommonAncestor( - '/project/src/a.ts', - '/project/src/b.ts', - '/project/src/c.ts', - ), - ).toBe(path.normalize('/project/src')) - }) - - test('handles paths at different depths', () => { - expect( - lowestCommonAncestor('/project/src/a.ts', '/project/lib/deep/b.ts'), - ).toBe(path.normalize('/project')) + ], + [ + 'handles multiple paths', + ['/project/src/a.ts', '/project/src/b.ts', '/project/src/c.ts'], + path.normalize('/project/src'), + ], + [ + 'handles paths at different depths', + ['/project/src/a.ts', '/project/lib/deep/b.ts'], + path.normalize('/project'), + ], + ])('%s', (_, paths, expected) => { + expect(lowestCommonAncestor(...paths)).toBe(expected) }) }) describe('stripExtname', () => { - test('strips .ts extension', () => { - expect(stripExtname('index.ts')).toBe('index') - }) - - test('strips .js extension', () => { - expect(stripExtname('file.js')).toBe('file') - }) - - test('strips only last extension', () => { - expect(stripExtname('file.test.ts')).toBe('file.test') - }) - - test('returns path unchanged if no extension', () => { - expect(stripExtname('Makefile')).toBe('Makefile') - }) - - test('handles path with directory', () => { - expect(stripExtname('src/utils/index.ts')).toBe('src/utils/index') - }) - - test('handles dotfile', () => { - expect(stripExtname('.gitignore')).toBe('.gitignore') + test.each([ + ['strips .ts extension', 'index.ts', 'index'], + ['strips .js extension', 'file.js', 'file'], + ['strips only last extension', 'file.test.ts', 'file.test'], + ['returns path unchanged if no extension', 'Makefile', 'Makefile'], + ['handles path with directory', 'src/utils/index.ts', 'src/utils/index'], + ['handles dotfile', '.gitignore', '.gitignore'], + ])('%s', (_, input, expected) => { + expect(stripExtname(input)).toBe(expected) }) }) diff --git a/src/utils/general.test.ts b/src/utils/general.test.ts index 43897b0df..b41070402 100644 --- a/src/utils/general.test.ts +++ b/src/utils/general.test.ts @@ -10,54 +10,38 @@ import { } from './general.ts' describe('toArray', () => { - test('wraps single value in array', () => { - expect(toArray('foo')).toEqual(['foo']) - }) - - test('returns array as-is', () => { - expect(toArray(['a', 'b'])).toEqual(['a', 'b']) - }) - - test('returns empty array for null', () => { - expect(toArray(null)).toEqual([]) - }) - - test('returns empty array for undefined', () => { - expect(toArray(undefined)).toEqual([]) - }) - - test('returns default value array for null with default', () => { - expect(toArray(null, 'default')).toEqual(['default']) - }) - - test('returns default value array for undefined with default', () => { - expect(toArray(undefined, 'default')).toEqual(['default']) - }) - - test('wraps number in array', () => { - expect(toArray(42)).toEqual([42]) - }) - - test('wraps false in array', () => { - expect(toArray(false)).toEqual([false]) + test.each<[string, unknown, unknown, unknown[]]>([ + ['wraps single value in array', 'foo', undefined, ['foo']], + ['returns array as-is', ['a', 'b'], undefined, ['a', 'b']], + ['returns empty array for null', null, undefined, []], + ['returns empty array for undefined', undefined, undefined, []], + [ + 'returns default value array for null with default', + null, + 'default', + ['default'], + ], + [ + 'returns default value array for undefined with default', + undefined, + 'default', + ['default'], + ], + ['wraps number in array', 42, undefined, [42]], + ['wraps false in array', false, undefined, [false]], + ])('%s', (_, val, defaultValue, expected) => { + expect(toArray(val, defaultValue)).toEqual(expected) }) }) describe('resolveComma', () => { - test('splits comma-separated values', () => { - expect(resolveComma(['esm,cjs'])).toEqual(['esm', 'cjs']) - }) - - test('handles values without commas', () => { - expect(resolveComma(['esm', 'cjs'])).toEqual(['esm', 'cjs']) - }) - - test('handles mixed values', () => { - expect(resolveComma(['esm,cjs', 'iife'])).toEqual(['esm', 'cjs', 'iife']) - }) - - test('handles empty array', () => { - expect(resolveComma([])).toEqual([]) + test.each<[string, string[], string[]]>([ + ['splits comma-separated values', ['esm,cjs'], ['esm', 'cjs']], + ['handles values without commas', ['esm', 'cjs'], ['esm', 'cjs']], + ['handles mixed values', ['esm,cjs', 'iife'], ['esm', 'cjs', 'iife']], + ['handles empty array', [], []], + ])('%s', (_, input, expected) => { + expect(resolveComma(input)).toEqual(expected) }) }) @@ -87,20 +71,17 @@ describe('resolveRegex', () => { }) describe('slash', () => { - test('replaces backslashes with forward slashes', () => { - expect(slash(String.raw`foo\bar\baz`)).toBe('foo/bar/baz') - }) - - test('leaves forward slashes unchanged', () => { - expect(slash('foo/bar/baz')).toBe('foo/bar/baz') - }) - - test('handles empty string', () => { - expect(slash('')).toBe('') - }) - - test('handles mixed slashes', () => { - expect(slash(String.raw`foo\bar/baz`)).toBe('foo/bar/baz') + test.each([ + [ + 'replaces backslashes with forward slashes', + String.raw`foo\bar\baz`, + 'foo/bar/baz', + ], + ['leaves forward slashes unchanged', 'foo/bar/baz', 'foo/bar/baz'], + ['handles empty string', '', ''], + ['handles mixed slashes', String.raw`foo\bar/baz`, 'foo/bar/baz'], + ])('%s', (_, input, expected) => { + expect(slash(input)).toBe(expected) }) }) @@ -215,17 +196,3 @@ describe('createConcurrencyExecutor', () => { expect(order).toEqual([1, 2]) }) }) - -describe('promiseWithResolvers', () => { - test('returns a promise that resolves', async () => { - const { promise, resolve } = Promise.withResolvers() - resolve('hello') - expect(await promise).toBe('hello') - }) - - test('resolve is callable before awaiting', async () => { - const { promise, resolve } = Promise.withResolvers() - resolve(42) - await expect(promise).resolves.toBe(42) - }) -}) diff --git a/src/utils/json.test.ts b/src/utils/json.test.ts index a4ac5503f..20114400a 100644 --- a/src/utils/json.test.ts +++ b/src/utils/json.test.ts @@ -75,20 +75,14 @@ describe('writeJsonFile', () => { }) describe('detectIndent', () => { - test('two spaces', ({ expect }) => { - expect(detectIndentation(stringifyJson(2))).toBe(2) - }) - test('four spaces', ({ expect }) => { - expect(detectIndentation(stringifyJson(4))).toBe(4) - }) - test('tab', ({ expect }) => { - expect(detectIndentation(stringifyJson('\t'))).toBe('\t') - }) - test('empty', ({ expect }) => { - expect(detectIndentation('')).toBe(2) - }) - test('empty line', ({ expect }) => { - expect(detectIndentation('{\n\n "foo": 42 }')).toBe(2) + test.each([ + ['two spaces', stringifyJson(2), 2], + ['four spaces', stringifyJson(4), 4], + ['tab', stringifyJson('\t'), '\t'], + ['empty', '', 2], + ['empty line', '{\n\n "foo": 42 }', 2], + ])('%s', (_, contents, expected) => { + expect(detectIndentation(contents)).toBe(expected) }) }) diff --git a/src/utils/logger.test.ts b/src/utils/logger.test.ts index 2c46b940d..0a0c96c24 100644 --- a/src/utils/logger.test.ts +++ b/src/utils/logger.test.ts @@ -13,12 +13,6 @@ describe('LogLevels', () => { expect(LogLevels.warn).toBe(2) expect(LogLevels.info).toBe(3) }) - - test('silent < error < warn < info', () => { - expect(LogLevels.silent).toBeLessThan(LogLevels.error) - expect(LogLevels.error).toBeLessThan(LogLevels.warn) - expect(LogLevels.warn).toBeLessThan(LogLevels.info) - }) }) describe('createLogger', () => { @@ -247,17 +241,6 @@ describe('suppressWarnings', () => { expect(mockConsole.error).toHaveBeenCalledOnce() }) - - test('warns normally when suppressWarnings is not set', () => { - const mockConsole = { log: vi.fn(), warn: vi.fn(), error: vi.fn() } - const logger = createLogger('info', { - console: mockConsole as unknown as Console, - }) - - logger.warn('a normal warning') - - expect(mockConsole.warn).toHaveBeenCalledOnce() - }) }) describe('getNameLabel', () => { @@ -274,18 +257,11 @@ describe('getNameLabel', () => { }) describe('prettyFormat', () => { - test('formats es as ESM', () => { - const result = prettyFormat('es') - expect(result).toContain('ESM') - }) - - test('formats cjs as CJS', () => { - const result = prettyFormat('cjs') - expect(result).toContain('CJS') - }) - - test('formats iife as IIFE', () => { - const result = prettyFormat('iife') - expect(result).toContain('IIFE') + test.each([ + ['formats es as ESM', 'es', 'ESM'], + ['formats cjs as CJS', 'cjs', 'CJS'], + ['formats iife as IIFE', 'iife', 'IIFE'], + ] as const)('%s', (_, format, expected) => { + expect(prettyFormat(format)).toContain(expected) }) }) diff --git a/src/utils/package.test.ts b/src/utils/package.test.ts index 08d251933..85b373af0 100644 --- a/src/utils/package.test.ts +++ b/src/utils/package.test.ts @@ -1,23 +1,23 @@ import path from 'node:path' import { describe, expect, test } from 'vitest' import { writeFixtures } from '../../tests/utils.ts' -import { getPackageType, normalizeFormat, readPackageJson } from './package.ts' +import { + getPackageType, + normalizeFormat, + readPackageJson, + type PackageType, +} from './package.ts' +import type { Format, NormalizedFormat } from '../config/index.ts' +import type { PackageJson } from 'pkg-types' describe('getPackageType', () => { - test('returns "module" for module type', () => { - expect(getPackageType({ type: 'module' })).toBe('module') - }) - - test('returns "commonjs" for commonjs type', () => { - expect(getPackageType({ type: 'commonjs' })).toBe('commonjs') - }) - - test('returns undefined when no type field', () => { - expect(getPackageType({})).toBeUndefined() - }) - - test('returns undefined for undefined pkg', () => { - expect(getPackageType(undefined)).toBeUndefined() + test.each<[string, PackageJson | undefined, PackageType]>([ + ['returns "module" for module type', { type: 'module' }, 'module'], + ['returns "commonjs" for commonjs type', { type: 'commonjs' }, 'commonjs'], + ['returns undefined when no type field', {}, undefined], + ['returns undefined for undefined pkg', undefined, undefined], + ])('%s', (_, pkg, expected) => { + expect(getPackageType(pkg)).toBe(expected) }) test('throws for invalid type value', () => { @@ -29,28 +29,15 @@ describe('getPackageType', () => { }) describe('normalizeFormat', () => { - test('normalizes "es" to "es"', () => { - expect(normalizeFormat('es')).toBe('es') - }) - - test('normalizes "esm" to "es"', () => { - expect(normalizeFormat('esm')).toBe('es') - }) - - test('normalizes "module" to "es"', () => { - expect(normalizeFormat('module')).toBe('es') - }) - - test('normalizes "cjs" to "cjs"', () => { - expect(normalizeFormat('cjs')).toBe('cjs') - }) - - test('normalizes "commonjs" to "cjs"', () => { - expect(normalizeFormat('commonjs')).toBe('cjs') - }) - - test('returns iife as-is', () => { - expect(normalizeFormat('iife')).toBe('iife') + test.each<[string, Format, NormalizedFormat]>([ + ['normalizes "es" to "es"', 'es', 'es'], + ['normalizes "esm" to "es"', 'esm', 'es'], + ['normalizes "module" to "es"', 'module', 'es'], + ['normalizes "cjs" to "cjs"', 'cjs', 'cjs'], + ['normalizes "commonjs" to "cjs"', 'commonjs', 'cjs'], + ['returns iife as-is', 'iife', 'iife'], + ])('%s', (_, format, expected) => { + expect(normalizeFormat(format)).toBe(expected) }) }) @@ -58,22 +45,17 @@ describe('readPackageJson', () => { test('reads package.json from directory', async (context) => { const { testDir } = await writeFixtures(context, { 'package.json': JSON.stringify({ name: 'test-pkg', version: '1.0.0' }), + 'src/nested/index.ts': '', }) const result = await readPackageJson(testDir) expect(result).toBeDefined() expect(result!.name).toBe('test-pkg') expect(result!.version).toBe('1.0.0') expect(result!.packageJsonPath).toBe(path.join(testDir, 'package.json')) - }) - test('returns result with packageJsonPath property', async (context) => { - const { testDir } = await writeFixtures(context, { - 'index.ts': '', - }) - const result = await readPackageJson(testDir) - if (result) { - expect(result.packageJsonPath).toContain('package.json') - } + // looks up the nearest package.json from a nested directory + const nested = await readPackageJson(path.join(testDir, 'src/nested')) + expect(nested!.packageJsonPath).toBe(path.join(testDir, 'package.json')) }) test('reads package.json with type field', async (context) => {