mirror of
https://github.com/voson-wang/toon.git
synced 2026-01-29 15:24:10 +08:00
test(cli): add tests for invalid values
This commit is contained in:
@@ -5,8 +5,8 @@ import * as path from 'node:path'
|
|||||||
import process from 'node:process'
|
import process from 'node:process'
|
||||||
import { defineCommand } from 'citty'
|
import { defineCommand } from 'citty'
|
||||||
import { consola } from 'consola'
|
import { consola } from 'consola'
|
||||||
import { name, version } from '../../toon/package.json' with { type: 'json' }
|
|
||||||
import { DEFAULT_DELIMITER, DELIMITERS } from '../../toon/src'
|
import { DEFAULT_DELIMITER, DELIMITERS } from '../../toon/src'
|
||||||
|
import { name, version } from '../package.json' with { type: 'json' }
|
||||||
import { decodeToJson, encodeToToon } from './conversion'
|
import { decodeToJson, encodeToToon } from './conversion'
|
||||||
import { detectMode } from './utils'
|
import { detectMode } from './utils'
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import process from 'node:process'
|
import process from 'node:process'
|
||||||
import { consola } from 'consola'
|
import { consola } from 'consola'
|
||||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||||
import { version } from '../../toon/package.json' with { type: 'json' }
|
|
||||||
import { DEFAULT_DELIMITER, encode } from '../../toon/src'
|
import { DEFAULT_DELIMITER, encode } from '../../toon/src'
|
||||||
|
import { version } from '../package.json' with { type: 'json' }
|
||||||
import { createCliTestContext, runCli } from './utils'
|
import { createCliTestContext, runCli } from './utils'
|
||||||
|
|
||||||
describe('toon CLI', () => {
|
describe('toon CLI', () => {
|
||||||
@@ -14,113 +14,161 @@ describe('toon CLI', () => {
|
|||||||
vi.restoreAllMocks()
|
vi.restoreAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('prints the version when using --version', async () => {
|
describe('version', () => {
|
||||||
const consolaLog = vi.spyOn(consola, 'log').mockImplementation(() => undefined)
|
it('prints the version when using --version', async () => {
|
||||||
const consolaError = vi.spyOn(consola, 'error').mockImplementation(() => undefined)
|
const consolaLog = vi.spyOn(consola, 'log').mockImplementation(() => undefined)
|
||||||
|
|
||||||
await runCli({ rawArgs: ['--version'] })
|
await runCli({ rawArgs: ['--version'] })
|
||||||
|
|
||||||
expect(consolaLog).toHaveBeenCalledWith(version)
|
expect(consolaLog).toHaveBeenCalledWith(version)
|
||||||
expect(consolaError).not.toHaveBeenCalled()
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('encodes a JSON file into a TOON file', async () => {
|
describe('encode (JSON → TOON)', () => {
|
||||||
const data = {
|
it('encodes a JSON file into a TOON file', async () => {
|
||||||
title: 'TOON test',
|
const data = {
|
||||||
count: 3,
|
title: 'TOON test',
|
||||||
nested: { ok: true },
|
count: 3,
|
||||||
}
|
nested: { ok: true },
|
||||||
const context = await createCliTestContext({
|
}
|
||||||
'input.json': JSON.stringify(data, undefined, 2),
|
const context = await createCliTestContext({
|
||||||
})
|
'input.json': JSON.stringify(data, undefined, 2),
|
||||||
|
|
||||||
const consolaSuccess = vi.spyOn(consola, 'success').mockImplementation(() => undefined)
|
|
||||||
|
|
||||||
try {
|
|
||||||
await context.run(['input.json', '--output', 'output.toon'])
|
|
||||||
|
|
||||||
const output = await context.read('output.toon')
|
|
||||||
const expected = encode(data, {
|
|
||||||
delimiter: DEFAULT_DELIMITER,
|
|
||||||
indent: 2,
|
|
||||||
lengthMarker: false,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(output).toBe(expected)
|
const consolaSuccess = vi.spyOn(consola, 'success').mockImplementation(() => undefined)
|
||||||
expect(consolaSuccess).toHaveBeenCalledWith('Encoded `input.json` → `output.toon`')
|
|
||||||
}
|
try {
|
||||||
finally {
|
await context.run(['input.json', '--output', 'output.toon'])
|
||||||
await context.cleanup()
|
|
||||||
}
|
const output = await context.read('output.toon')
|
||||||
|
const expected = encode(data, {
|
||||||
|
delimiter: DEFAULT_DELIMITER,
|
||||||
|
indent: 2,
|
||||||
|
lengthMarker: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(output).toBe(expected)
|
||||||
|
expect(consolaSuccess).toHaveBeenCalledWith(expect.stringMatching(/Encoded .* → .*/))
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
await context.cleanup()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('writes to stdout when output not specified', async () => {
|
||||||
|
const data = { ok: true }
|
||||||
|
const context = await createCliTestContext({
|
||||||
|
'input.json': JSON.stringify(data),
|
||||||
|
})
|
||||||
|
|
||||||
|
const stdout: string[] = []
|
||||||
|
const logSpy = vi.spyOn(console, 'log').mockImplementation((message?: unknown) => {
|
||||||
|
stdout.push(String(message ?? ''))
|
||||||
|
})
|
||||||
|
|
||||||
|
try {
|
||||||
|
await context.run(['input.json'])
|
||||||
|
|
||||||
|
expect(stdout).toHaveLength(1)
|
||||||
|
expect(stdout[0]).toBe(encode(data))
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
logSpy.mockRestore()
|
||||||
|
await context.cleanup()
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('decodes a TOON file into a JSON file', async () => {
|
describe('decode (TOON → JSON)', () => {
|
||||||
const data = {
|
it('decodes a TOON file into a JSON file', async () => {
|
||||||
items: ['alpha', 'beta'],
|
const data = {
|
||||||
meta: { done: false },
|
items: ['alpha', 'beta'],
|
||||||
}
|
meta: { done: false },
|
||||||
const toonInput = encode(data)
|
}
|
||||||
const context = await createCliTestContext({
|
const toonInput = encode(data)
|
||||||
'input.toon': toonInput,
|
const context = await createCliTestContext({
|
||||||
|
'input.toon': toonInput,
|
||||||
|
})
|
||||||
|
|
||||||
|
const consolaSuccess = vi.spyOn(consola, 'success').mockImplementation(() => undefined)
|
||||||
|
|
||||||
|
try {
|
||||||
|
await context.run(['input.toon', '--output', 'output.json'])
|
||||||
|
|
||||||
|
const output = await context.read('output.json')
|
||||||
|
expect(JSON.parse(output)).toEqual(data)
|
||||||
|
expect(consolaSuccess).toHaveBeenCalledWith(expect.stringMatching(/Decoded .* → .*/))
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
await context.cleanup()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const consolaSuccess = vi.spyOn(consola, 'success').mockImplementation(() => undefined)
|
|
||||||
|
|
||||||
try {
|
|
||||||
await context.run(['input.toon', '--output', 'output.json'])
|
|
||||||
|
|
||||||
const output = await context.read('output.json')
|
|
||||||
expect(JSON.parse(output)).toEqual(data)
|
|
||||||
expect(consolaSuccess).toHaveBeenCalledWith('Decoded `input.toon` → `output.json`')
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
await context.cleanup()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('writes encoded TOON to stdout when no output file is provided', async () => {
|
describe('error handling', () => {
|
||||||
const data = { ok: true }
|
it('rejects invalid delimiter', async () => {
|
||||||
const context = await createCliTestContext({
|
const context = await createCliTestContext({
|
||||||
'input.json': JSON.stringify(data),
|
'input.json': JSON.stringify({ value: 1 }),
|
||||||
|
})
|
||||||
|
|
||||||
|
const consolaError = vi.spyOn(consola, 'error').mockImplementation(() => undefined)
|
||||||
|
const exitSpy = vi.mocked(process.exit)
|
||||||
|
|
||||||
|
try {
|
||||||
|
await context.run(['input.json', '--delimiter', ';'])
|
||||||
|
|
||||||
|
expect(exitSpy).toHaveBeenCalledWith(1)
|
||||||
|
|
||||||
|
const errorCall = consolaError.mock.calls.at(0)
|
||||||
|
expect(errorCall).toBeDefined()
|
||||||
|
const [error] = errorCall!
|
||||||
|
expect(error).toBeInstanceOf(Error)
|
||||||
|
expect(error.message).toContain('Invalid delimiter')
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
await context.cleanup()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const stdout: string[] = []
|
it('rejects invalid indent value', async () => {
|
||||||
const logSpy = vi.spyOn(console, 'log').mockImplementation((message?: unknown) => {
|
const context = await createCliTestContext({
|
||||||
stdout.push(String(message ?? ''))
|
'input.json': JSON.stringify({ value: 1 }),
|
||||||
|
})
|
||||||
|
|
||||||
|
const consolaError = vi.spyOn(consola, 'error').mockImplementation(() => undefined)
|
||||||
|
const exitSpy = vi.mocked(process.exit)
|
||||||
|
|
||||||
|
try {
|
||||||
|
await context.run(['input.json', '--indent', 'abc'])
|
||||||
|
|
||||||
|
expect(exitSpy).toHaveBeenCalledWith(1)
|
||||||
|
|
||||||
|
const errorCall = consolaError.mock.calls.at(0)
|
||||||
|
expect(errorCall).toBeDefined()
|
||||||
|
const [error] = errorCall!
|
||||||
|
expect(error).toBeInstanceOf(Error)
|
||||||
|
expect(error.message).toContain('Invalid indent value')
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
await context.cleanup()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
try {
|
it('handles missing input file', async () => {
|
||||||
await context.run(['input.json'])
|
const context = await createCliTestContext({})
|
||||||
|
|
||||||
expect(stdout).toHaveLength(1)
|
const consolaError = vi.spyOn(consola, 'error').mockImplementation(() => undefined)
|
||||||
expect(stdout[0]).toBe(encode(data))
|
const exitSpy = vi.mocked(process.exit)
|
||||||
}
|
|
||||||
finally {
|
|
||||||
logSpy.mockRestore()
|
|
||||||
await context.cleanup()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
it('throws on an invalid delimiter argument', async () => {
|
try {
|
||||||
const context = await createCliTestContext({
|
await context.run(['nonexistent.json'])
|
||||||
'input.json': JSON.stringify({ value: 1 }),
|
|
||||||
|
expect(exitSpy).toHaveBeenCalledWith(1)
|
||||||
|
expect(consolaError).toHaveBeenCalled()
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
await context.cleanup()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const consolaError = vi.spyOn(consola, 'error').mockImplementation(() => undefined)
|
|
||||||
|
|
||||||
try {
|
|
||||||
await expect(context.run(['input.json', '--delimiter', ';'])).resolves.toBeUndefined()
|
|
||||||
|
|
||||||
const exitMock = vi.mocked(process.exit)
|
|
||||||
expect(exitMock).toHaveBeenCalledWith(1)
|
|
||||||
|
|
||||||
const errorCall = consolaError.mock.calls.at(0)
|
|
||||||
expect(errorCall).toBeDefined()
|
|
||||||
const [error] = errorCall!
|
|
||||||
expect(error.message).toContain('Invalid delimiter')
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
await context.cleanup()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user