@paydirt/fmt
Version:
String formating using commonly used standards
413 lines (363 loc) • 21.2 kB
text/typescript
const fmt = require('./lib/umd')
interface result {
total:number;
passed:number;
}
let total:number = 0
let passed:number = 0
function expect (method:Function, description:string, result:string, ...a:Array<any>):boolean {
const r:string = method.apply(this, a)
if (r !== result) {
console.log('\033[30;41m FAIL \033[0m\t\033[31m' + description + '\033[0m')
console.log('\t\t' + a.join(', '))
console.log(`\t\tExpected: ${result} Received: ${r}`)
return false
}
console.log('\033[30;42m PASS \033[0m\t' + description)
return true
}
function batch (list:Array<Array<any>>):result {
return {
total: list.length,
passed: list.reduce((acc:number, test:Array<any>):number => (
(expect.apply(this, test) ? 1 : 0) + acc
), 0)
}
}
function segment (label:string, list:Array<Array<any>>):void {
console.log(label.toUpperCase())
const r:result = batch(list)
console.log(`\n\tPassed: ${r.passed} Failed: ${r.total - r.passed}`)
total += r.total
passed += r.passed
if (r.total !== r.passed) {
console.log('\t\033[31mFAILED\033[0m\n')
} else {
console.log('\t\033[32mPASSED\033[0m\n')
}
}
function report ():void {
if (0 === total - passed) {
console.error('\033[32mPASSED\033[0m')
console.error(`${passed} / ${total} tests passed`)
} else {
console.error('\033[31mFAILED\033[0m')
console.error(`${passed} / ${total} tests passed`)
}
}
segment('sprintf - objects', [
[ fmt.sprintf, 'single', '{"foo":"bar","baz":true}', '%v', { foo: 'bar', baz: true } ],
[ fmt.sprintf, 'values', '["bar",true]', '%-v', { foo: 'bar', baz: true } ],
[ fmt.sprintf, 'string', 'hello world', '%v', 'hello world' ],
[ fmt.sprintf, 'boolean', 'false', '%v', false ],
[ fmt.sprintf, 'number', '1.23', '%v', 1.23 ]
])
segment('sprintf - types', [
[ fmt.sprintf, 'string', 'string', '%T', 'hello' ],
[ fmt.sprintf, 'number', 'number', '%T', 1 ],
[ fmt.sprintf, 'object', 'object', '%T', {} ],
[ fmt.sprintf, 'array', 'array', '%T', [] ],
[ fmt.sprintf, 'boolean', 'boolean', '%T', false ],
[ fmt.sprintf, 'padding left', ' array', '%8T', [] ],
[ fmt.sprintf, 'padding right', 'array ', '%-8T', [] ]
])
segment('sprintf - booleans', [
[ fmt.sprintf, 'single (true)', 'true', '%t', true ],
[ fmt.sprintf, 'single (false)', 'false', '%t', false ],
[ fmt.sprintf, 'single (1)', 'true', '%t', 1 ],
[ fmt.sprintf, 'single (0)', 'false', '%t', 0 ],
[ fmt.sprintf, 'padding left', ' true', '%6t', true ],
[ fmt.sprintf, 'padding right', 'true ', '%-6t', true ]
])
segment('sprintf - integers', [
[ fmt.sprintf, 'single', '123', '%d', 123 ],
[ fmt.sprintf, 'decimal', '123', '%d', 123.45 ],
[ fmt.sprintf, 'sign negative', '-123', '%+d', -123 ],
[ fmt.sprintf, 'sign positive', '+123', '%+d', 123 ],
[ fmt.sprintf, 'padding left', ' 123', '%6d', 123 ],
[ fmt.sprintf, 'padding right', '123 ', '%-6d', 123 ]
])
segment('sprintf - binary', [
[ fmt.sprintf, 'single', '01111011', '%b', 123 ],
[ fmt.sprintf, 'negative', '11111111111111111111111110000101', '%b', -123 ],
[ fmt.sprintf, 'string', '01101000 01100101 01101100 01101100', '%b', 'hell' ],
[ fmt.sprintf, 'padding left', ' 01111011', '%9b', 123 ],
[ fmt.sprintf, 'padding right', '01111011 ', '%-9b', 123 ]
])
segment('sprintf - characters', [
[ fmt.sprintf, 'single', 'A', '%c', 65 ],
[ fmt.sprintf, 'multiple', 'ABC', '%c%c%c', 65, 66, 67 ],
[ fmt.sprintf, 'padding left', ' A', '%2c', 65 ],
[ fmt.sprintf, 'padding right', 'A ', '%-2c', 65 ]
])
segment('sprintf - hexadecimal', [
[ fmt.sprintf, 'single', 'a2', '%x', 162 ],
[ fmt.sprintf, 'multiple', 'a2 a3 a4', '%x %x %x', 162, 163, 164 ],
[ fmt.sprintf, 'single uppercase', 'A2', '%X', 162 ],
[ fmt.sprintf, 'multiple uppercase', 'A2 A3 A4', '%X %X %X', 162, 163, 164 ],
[ fmt.sprintf, 'padding left', ' a2', '%3x', 162 ],
[ fmt.sprintf, 'padding right', 'a2 ', '%-3x', 162 ],
[ fmt.sprintf, 'string', '00680065006c006c006f00200077006f0072006c00640021', '%x', 'hello world!' ],
[ fmt.sprintf, 'string uppercase', '00680065006C006C006F00200077006F0072006C00640021', '%X', 'hello world!' ],
[ fmt.sprintf, 'katana', '52000020006f00720020304b305f306a', '%x', '刀 or かたな' ],
[ fmt.sprintf, 'object', '007b002200610022003a0031002c002200620022003a0074007200750065007d', '%x', { a: 1, b: true } ],
[ fmt.sprintf, 'array', '005B002200610022002C0031002C002200620022002C0074007200750065005D', '%X', [ 'a', 1, 'b', true ] ],
[ fmt.sprintf, 'boolean', '0074007200750065', '%x', true ],
[ fmt.sprintf, 'number', '7B', '%X', 123 ]
])
segment('sprintf - strings', [
[ fmt.sprintf, 'single', 'abc', '%s', 'abc' ],
[ fmt.sprintf, 'quotes', '"abc"', '%q', 'abc' ],
[ fmt.sprintf, 'padding left', ' abc', '%6s', 'abc' ],
[ fmt.sprintf, 'padding right', 'abc ', '%-6s', 'abc' ],
[ fmt.sprintf, 'insert', 'aBcdEfgHi', 'aBc%sgHi', 'dEf' ],
[ fmt.sprintf, 'lowercase', 'abcdefghi', 'abc%_sghi', 'DEF' ],
[ fmt.sprintf, 'lowercase quotes', 'abc"def"ghi', 'abc%_qghi', 'DEF' ],
[ fmt.sprintf, 'whitespace', 'abc def ghi', 'abc %s ghi', 'def' ],
[ fmt.sprintf, 'uppercase (%S)', 'abcDEFghi', 'abc%Sghi', 'def' ],
[ fmt.sprintf, 'uppercase (%Q)', 'abc"DEF"ghi', 'abc%Qghi', 'def' ],
[ fmt.sprintf, 'uppercase (%^s)', 'abcDEFghi', 'abc%^sghi', 'def' ],
[ fmt.sprintf, 'uppercase (%^q)', 'abc"DEF"ghi', 'abc%^qghi', 'def' ],
[ fmt.sprintf, 'multiple', 'hello!', '%s%s', 'hel', 'lo!' ]
])
segment('sprintf - floats', [
[ fmt.sprintf, 'single', '1.2', '%f', 1.2 ],
[ fmt.sprintf, 'decimals', '1.23', '%.2f', 1.2345 ],
[ fmt.sprintf, 'sign negative', '-1.23', '%+.2f', -1.234 ],
[ fmt.sprintf, 'sign positive', '+1.23', '%+.2f', 1.2345 ],
[ fmt.sprintf, 'padding left', ' 1.23', '%6.2f', 1.2345 ],
[ fmt.sprintf, 'padding right', '1.23 ', '%-6.2f', 1.2345 ]
])
segment('sprintf - literal', [
[ fmt.sprintf, '100%', '100%', '%d%%', 100 ],
[ fmt.sprintf, '60% + 40%', '60% + 40%', '%d%% + %d%%', 60, 40 ],
])
segment('sprintf - mixed', [
[ fmt.sprintf, '%s %d %t', 'foo 1 true', '%s %d %t', 'foo', 1.2, true ],
[ fmt.sprintf, '%S %.2f %T', 'FOO 1.24 boolean', '%S %.2f %T', 'foo', 1.235, true ]
])
// Tables
const labels:object = {
'name': { label: 'Movie Name' },
'release': { label: 'Release' },
'director': { label: 'Director' }
}
const rows:Array<object> = [
{ name: 'Toy Story', release: 1995, director: 'John Lasseter' },
{ name: 'Monsters, Inc', release: 2001, director: 'Pete Docter' },
{ name: 'Finding Nemo', release: 2003, director: 'Andrew Stanton' }
]
const expectedDefault:string = [
'┏━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━┓',
'┃ Movie Name ┃ Release ┃ Director ┃',
'┡━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━┩',
'│ Toy Story │ 1995 │ John Lasseter │',
'│ Monsters, Inc │ 2001 │ Pete Docter │',
'│ Finding Nemo │ 2003 │ Andrew Stanton │',
'└───────────────┴─────────┴────────────────┘'
].join('\n')
const expectedHeavy:string = [
'┏━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━┓',
'┃ Movie Name ┃ Release ┃ Director ┃',
'┣━━━━━━━━━━━━━━━╋━━━━━━━━━╋━━━━━━━━━━━━━━━━┫',
'┃ Toy Story ┃ 1995 ┃ John Lasseter ┃',
'┃ Monsters, Inc ┃ 2001 ┃ Pete Docter ┃',
'┃ Finding Nemo ┃ 2003 ┃ Andrew Stanton ┃',
'┗━━━━━━━━━━━━━━━┻━━━━━━━━━┻━━━━━━━━━━━━━━━━┛'
].join('\n')
const expectedThin:string = [
'┌───────────────┬─────────┬────────────────┐',
'│ Movie Name │ Release │ Director │',
'├───────────────┼─────────┼────────────────┤',
'│ Toy Story │ 1995 │ John Lasseter │',
'│ Monsters, Inc │ 2001 │ Pete Docter │',
'│ Finding Nemo │ 2003 │ Andrew Stanton │',
'└───────────────┴─────────┴────────────────┘'
].join('\n')
const expectedRounded:string = [
'╭───────────────┬─────────┬────────────────╮',
'│ Movie Name │ Release │ Director │',
'├───────────────┼─────────┼────────────────┤',
'│ Toy Story │ 1995 │ John Lasseter │',
'│ Monsters, Inc │ 2001 │ Pete Docter │',
'│ Finding Nemo │ 2003 │ Andrew Stanton │',
'╰───────────────┴─────────┴────────────────╯'
].join('\n')
const expectedSemiRounded:string = [
'┏━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━┓',
'┃ Movie Name ┃ Release ┃ Director ┃',
'┡━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━┩',
'│ Toy Story │ 1995 │ John Lasseter │',
'│ Monsters, Inc │ 2001 │ Pete Docter │',
'│ Finding Nemo │ 2003 │ Andrew Stanton │',
'╰───────────────┴─────────┴────────────────╯'
].join('\n')
const expectedAscii:string = [
'+---------------+---------+----------------+',
'| Movie Name | Release | Director |',
'+---------------+---------+----------------+',
'| Toy Story | 1995 | John Lasseter |',
'| Monsters, Inc | 2001 | Pete Docter |',
'| Finding Nemo | 2003 | Andrew Stanton |',
'+---------------+---------+----------------+'
].join('\n')
const expectedPadding:string = [
'┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓',
'┃ Movie Name ┃ Release ┃ Director ┃',
'┡━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩',
'│ Toy Story │ 1995 │ John Lasseter │',
'│ Monsters, Inc │ 2001 │ Pete Docter │',
'│ Finding Nemo │ 2003 │ Andrew Stanton │',
'└───────────────────┴─────────────┴────────────────────┘'
].join('\n')
const expectedNoPadding:string = [
'┏━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━┓',
'┃Movie Name ┃Release┃Director ┃',
'┡━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━┩',
'│Toy Story │1995 │John Lasseter │',
'│Monsters, Inc│2001 │Pete Docter │',
'│Finding Nemo │2003 │Andrew Stanton│',
'└─────────────┴───────┴──────────────┘'
].join('\n')
segment('table - palettes', [
[ fmt.table, 'default', expectedDefault, labels, rows, { silent: true }],
[ fmt.table, 'heavy', expectedHeavy, labels, rows, { silent: true, palette: fmt.TABLE_PALETTE_HEAVY }],
[ fmt.table, 'thin', expectedThin, labels, rows, { silent: true, palette: fmt.TABLE_PALETTE_THIN }],
[ fmt.table, 'rounded', expectedRounded, labels, rows, { silent: true, palette: fmt.TABLE_PALETTE_ROUNDED }],
[ fmt.table, 'semi rounded', expectedSemiRounded, labels, rows, { silent: true, palette: fmt.TABLE_PALETTE_SEMI_ROUNDED }],
[ fmt.table, 'ascii', expectedAscii, labels, rows, { silent: true, palette: fmt.TABLE_PALETTE_ASCII }],
[ fmt.table, 'padding (3)', expectedPadding, labels, rows, { silent: true, padding: 3 }],
[ fmt.table, 'padding (0)', expectedNoPadding, labels, rows, { silent: true, padding: 0 }]
])
const formattingLabels:object = {
'name': { label: 'Name', format: v => v.toUpperCase() },
'value': { label: 'Value', format: Math.round }
}
const formattingLabelsArray:Array<object> = [
{ key: 'name', label: 'Name', format: v => v.toUpperCase() },
{ key: 'value', label: 'Value', format: Math.round }
]
const formattingRows:Array<object> = [
{ name: 'First', value: 123.4 },
{ name: 'Second', value: 455.6 }
]
const expectedFormatting = [
'┏━━━━━━━━┳━━━━━━━┓',
'┃ Name ┃ Value ┃',
'┡━━━━━━━━╇━━━━━━━┩',
'│ FIRST │ 123 │',
'│ SECOND │ 456 │',
'└────────┴───────┘'
].join('\n')
segment('table - formatting', [
[ fmt.table, 'generic', expectedFormatting, formattingLabels, formattingRows, { silent: true }],
[ fmt.table, 'label array', expectedFormatting, formattingLabelsArray, formattingRows, { silent: true }],
])
const orderLabelsObjectStrings = {
"a": { label: 'A' },
"b": { label: 'B' },
"c": { label: 'C' }
}
const orderRowsStrings = [
{ a: 'A1', b: 'B1', c: 'C1' },
{ a: 'A2', b: 'B2', c: 'C2' },
{ a: 'A3', b: 'B3', c: 'C3' }
]
const orderLabelsObjectNumbers = {
2: { label: '2' },
1: { label: '1' },
3: { label: '3' }
}
const orderRowsNumbers = [
{ 1: '11', 2: '21', 3: '31' },
{ 1: '12', 2: '22', 3: '32' },
{ 1: '13', 2: '23', 3: '33' }
]
const orderLabelsObjectStringsAndNumbers = {
"b": { label: 'B' },
2: { label: '2' },
"a": { label: 'A' },
1: { label: '1' },
3: { label: '3' },
"c": { label: 'C' }
}
const orderLabelsArray = [
{ key: 'b', label: 'B'},
{ key: 2, label: '2' },
{ key: 'a', label: 'A'},
{ key: 1, label: '1' },
{ key: 3, label: '3' },
{ key: 'c', label: 'C'},
]
const orderRowsStringsAndNumbers = [...orderRowsStrings, ...orderRowsNumbers]
const expectedOrderObjectStrings = [
'┏━━━━┳━━━━┳━━━━┓',
'┃ A ┃ B ┃ C ┃',
'┡━━━━╇━━━━╇━━━━┩',
'│ A1 │ B1 │ C1 │',
'│ A2 │ B2 │ C2 │',
'│ A3 │ B3 │ C3 │',
'└────┴────┴────┘'
].join('\n')
const expectedOrderObjectNumbers = [
'┏━━━━┳━━━━┳━━━━┓',
'┃ 1 ┃ 2 ┃ 3 ┃',
'┡━━━━╇━━━━╇━━━━┩',
'│ 11 │ 21 │ 31 │',
'│ 12 │ 22 │ 32 │',
'│ 13 │ 23 │ 33 │',
'└────┴────┴────┘'
].join('\n')
const expectedOrderObjectStringsAndNumbers = [
'┏━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┓',
'┃ 1 ┃ 2 ┃ 3 ┃ B ┃ A ┃ C ┃',
'┡━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━┩',
'│ undefined │ undefined │ undefined │ B1 │ A1 │ C1 │',
'│ undefined │ undefined │ undefined │ B2 │ A2 │ C2 │',
'│ undefined │ undefined │ undefined │ B3 │ A3 │ C3 │',
'│ 11 │ 21 │ 31 │ undefined │ undefined │ undefined │',
'│ 12 │ 22 │ 32 │ undefined │ undefined │ undefined │',
'│ 13 │ 23 │ 33 │ undefined │ undefined │ undefined │',
'└───────────┴───────────┴───────────┴───────────┴───────────┴───────────┘'
].join('\n')
const expectedOrderArray = [
'┏━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┓',
'┃ B ┃ 2 ┃ A ┃ 1 ┃ 3 ┃ C ┃',
'┡━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━┩',
'│ B1 │ undefined │ A1 │ undefined │ undefined │ C1 │',
'│ B2 │ undefined │ A2 │ undefined │ undefined │ C2 │',
'│ B3 │ undefined │ A3 │ undefined │ undefined │ C3 │',
'│ undefined │ 21 │ undefined │ 11 │ 31 │ undefined │',
'│ undefined │ 22 │ undefined │ 12 │ 32 │ undefined │',
'│ undefined │ 23 │ undefined │ 13 │ 33 │ undefined │',
'└───────────┴───────────┴───────────┴───────────┴───────────┴───────────┘'
].join('\n')
segment('table - key order', [
[ fmt.table, 'object strings', expectedOrderObjectStrings, orderLabelsObjectStrings, orderRowsStrings, { silent: true }],
[ fmt.table, 'object numbers', expectedOrderObjectNumbers, orderLabelsObjectNumbers, orderRowsNumbers, { silent: true }],
[ fmt.table, 'object strings and numbers', expectedOrderObjectStringsAndNumbers, orderLabelsObjectStringsAndNumbers, orderRowsStringsAndNumbers, { silent: true }],
[ fmt.table, 'array', expectedOrderArray, orderLabelsArray, orderRowsStringsAndNumbers, { silent: true }],
])
const orderLabelsLimited = [
{ key: 'a', label: 'A'},
{ key: 2, label: '2' },
{ key: 1, label: '1' },
{ key: 'b', label: 'B'},
]
const expectedOrderLimited = [
'┏━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┓',
'┃ A ┃ 2 ┃ 1 ┃ B ┃',
'┡━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━┩',
'│ A1 │ undefined │ undefined │ B1 │',
'│ A2 │ undefined │ undefined │ B2 │',
'│ A3 │ undefined │ undefined │ B3 │',
'│ undefined │ 21 │ 11 │ undefined │',
'│ undefined │ 22 │ 12 │ undefined │',
'│ undefined │ 23 │ 13 │ undefined │',
'└───────────┴───────────┴───────────┴───────────┘'
].join('\n')
segment('table - limited keys', [
[ fmt.table, 'limited', expectedOrderLimited, orderLabelsLimited, orderRowsStringsAndNumbers, { silent: true }]
])
report()
process.exit(Math.min(total - passed, 1))