- Auto-convert on image load (0ms) and flag change (400ms debounce) - SizeControl: linked width/height sliders with aspect-ratio lock and 0.5 font correction factor - Full flag exposure for all 4 tools (chafa, jp2a, ascii-image-converter, img2txt) - ChafaOptions: symbols/fill dropdowns, dither controls, work/threshold/font-ratio sliders, format select, toggles - Jp2aOptions: color-depth, RGB weight sliders, edge controls, 8 toggles - ImgTxtOptions: dither select with valid libcaca values, gamma slider - OutputDisplay: ansi-to-html rendering for colored chafa output - ShellBridge: abort-previous pattern, conversion-start/end lifecycle events - Test API (ENABLE_TEST_API=true): /test/health, /test/convert, /test/flags/:tool, /test/imagemagick - buildArgs: space-separated args (not = format); full schemas in SCHEMAS export - runChafa: width/height destructured and combined into --size WxH - Port changed to 3050; Vite on 0.0.0.0 with allowedHosts for production domain - 98 unit tests passing across 12 test files Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
121 lines
4.7 KiB
JavaScript
121 lines
4.7 KiB
JavaScript
import { describe, it, expect } from 'vitest'
|
|
import { buildArgs } from '../lib/converters.js'
|
|
|
|
describe('buildArgs', () => {
|
|
it('returns empty array for empty flags', () => {
|
|
expect(buildArgs('chafa', {})).toEqual([])
|
|
})
|
|
|
|
it('maps value flags to --key value pairs', () => {
|
|
expect(buildArgs('chafa', { size: '80x40' })).toEqual(['--size', '80x40'])
|
|
})
|
|
|
|
it('includes bool flag only when true', () => {
|
|
expect(buildArgs('ascii-image-converter', { color: true })).toContain('--color')
|
|
expect(buildArgs('ascii-image-converter', { color: false })).not.toContain('--color')
|
|
})
|
|
|
|
it('rejects unknown flags', () => {
|
|
expect(() => buildArgs('chafa', { evil: 'value' })).toThrow('Unknown flag')
|
|
})
|
|
|
|
it('rejects invalid enum values', () => {
|
|
expect(() => buildArgs('chafa', { colors: 'invalid' })).toThrow('Invalid value')
|
|
})
|
|
|
|
it('throws on unknown tool', () => {
|
|
expect(() => buildArgs('malicious-tool', {})).toThrow('Unknown tool')
|
|
})
|
|
|
|
it('stringifies numeric values', () => {
|
|
expect(buildArgs('chafa', { size: 80 })).toEqual(['--size', '80'])
|
|
})
|
|
|
|
it('handles hyphenated keys', () => {
|
|
expect(buildArgs('chafa', { 'font-ratio': '0.5' })).toEqual(['--font-ratio', '0.5'])
|
|
expect(buildArgs('chafa', { 'dither-grain': '4x4' })).toEqual(['--dither-grain', '4x4'])
|
|
expect(buildArgs('chafa', { 'dither-intensity': '1.5' })).toEqual(['--dither-intensity', '1.5'])
|
|
expect(buildArgs('chafa', { 'color-extractor': 'median' })).toEqual(['--color-extractor', 'median'])
|
|
expect(buildArgs('chafa', { 'color-space': 'din99d' })).toEqual(['--color-space', 'din99d'])
|
|
expect(buildArgs('chafa', { 'fg-only': true })).toContain('--fg-only')
|
|
})
|
|
|
|
it('accepts all valid chafa color depths', () => {
|
|
for (const v of ['none', '2', '8', '16/8', '16', '240', '256', 'full']) {
|
|
expect(() => buildArgs('chafa', { colors: v })).not.toThrow()
|
|
}
|
|
})
|
|
|
|
it('accepts all valid chafa dither modes', () => {
|
|
for (const v of ['none', 'ordered', 'diffusion', 'noise']) {
|
|
expect(() => buildArgs('chafa', { dither: v })).not.toThrow()
|
|
}
|
|
})
|
|
|
|
it('accepts all valid chafa dither grains', () => {
|
|
for (const v of ['1x1', '2x2', '4x4', '8x8']) {
|
|
expect(() => buildArgs('chafa', { 'dither-grain': v })).not.toThrow()
|
|
}
|
|
})
|
|
|
|
it('accepts chafa bool flags', () => {
|
|
expect(buildArgs('chafa', { zoom: true })).toContain('--zoom')
|
|
expect(buildArgs('chafa', { stretch: true })).toContain('--stretch')
|
|
expect(buildArgs('chafa', { 'fg-only': true })).toContain('--fg-only')
|
|
expect(buildArgs('chafa', { zoom: false })).not.toContain('--zoom')
|
|
})
|
|
|
|
it('accepts chafa work quality value', () => {
|
|
expect(buildArgs('chafa', { work: 9 })).toEqual(['--work', '9'])
|
|
})
|
|
|
|
it('accepts chafa format values', () => {
|
|
expect(buildArgs('chafa', { format: 'symbols' })).toEqual(['--format', 'symbols'])
|
|
expect(buildArgs('chafa', { format: 'utf8' })).toEqual(['--format', 'utf8'])
|
|
expect(() => buildArgs('chafa', { format: 'sixel' })).toThrow('Invalid value')
|
|
})
|
|
|
|
it('accepts valid jp2a background values', () => {
|
|
expect(() => buildArgs('jp2a', { background: 'dark' })).not.toThrow()
|
|
expect(() => buildArgs('jp2a', { background: 'light' })).not.toThrow()
|
|
expect(() => buildArgs('jp2a', { background: 'invalid' })).toThrow('Invalid value')
|
|
})
|
|
|
|
it('accepts valid jp2a color-depth values', () => {
|
|
for (const v of ['4', '8', '24']) {
|
|
expect(() => buildArgs('jp2a', { 'color-depth': v })).not.toThrow()
|
|
}
|
|
expect(() => buildArgs('jp2a', { 'color-depth': '16' })).toThrow('Invalid value')
|
|
})
|
|
|
|
it('accepts jp2a bool flags', () => {
|
|
for (const flag of ['colors', 'fill', 'grayscale', 'invert', 'border', 'flipx', 'flipy', 'edges-only']) {
|
|
expect(buildArgs('jp2a', { [flag]: true })).toContain(`--${flag}`)
|
|
expect(buildArgs('jp2a', { [flag]: false })).not.toContain(`--${flag}`)
|
|
}
|
|
})
|
|
|
|
it('accepts jp2a RGB weight values', () => {
|
|
expect(buildArgs('jp2a', { red: '0.5', green: '0.3', blue: '0.2' })).toEqual([
|
|
'--red', '0.5', '--green', '0.3', '--blue', '0.2',
|
|
])
|
|
})
|
|
|
|
it('accepts jp2a edge-threshold', () => {
|
|
expect(buildArgs('jp2a', { 'edge-threshold': '0.4' })).toEqual(['--edge-threshold', '0.4'])
|
|
})
|
|
|
|
it('accepts valid img2txt format values', () => {
|
|
for (const v of ['ansi', 'utf8', 'html']) {
|
|
expect(() => buildArgs('img2txt', { format: v })).not.toThrow()
|
|
}
|
|
})
|
|
|
|
it('accepts valid img2txt dither values', () => {
|
|
for (const v of ['none', 'ordered2', 'ordered4', 'ordered8', 'random', 'fstein']) {
|
|
expect(() => buildArgs('img2txt', { dither: v })).not.toThrow()
|
|
}
|
|
expect(() => buildArgs('img2txt', { dither: 'invalid' })).toThrow('Invalid value')
|
|
})
|
|
})
|