/* vim: set ts=2: */ /* eslint-env mocha */ import * as assert_ from 'https://deno.land/std/testing/asserts.ts'; const assert: any = {...assert_}; assert.throws = function(f: () => void) { assert.assertThrows(function() { try { f(); } catch(e) { throw e instanceof Error ? e : new Error(e); }})}; assert.doesNotThrow = function(f: ()=>void) { f(); }; assert.equal = assert.assertEquals; assert.notEqual = assert.assertNotEquals; assert.deepEqual = (x: any,y: any, z?: string) => assert.equal(JSON.stringify(x), JSON.stringify(y), z); // @deno-types="./types/index.d.ts" import * as X from "./printj.mjs"; var sprintf = X.sprintf; var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ !\"#$%&'()*+,-./0123456789:;<=>?@[\\]^_~{|}`".split(""); var convs = "aAbBcCdDeEfFgGiJmnoOpsSTuUVxXyY%".split(""); var flags = " #'+-0".split(""); var digits = "0123456789".split(""); var lens = "hIjlLqtwzZ".split(""); lens.push("hh"); lens.push("ll"); var other = "$*.".split(""); var unused: string[] = []; chars.forEach(function(c) { if(convs.indexOf(c) == -1 && flags.indexOf(c) == -1 && digits.indexOf(c) == -1 && lens.indexOf(c) == -1 && other.indexOf(c) == -1 ) unused.push(c); }); Deno.test('special cases', async function(t) { await t.step('fails on unrecognized format chars: ' + unused.join(""), function() { unused.forEach(function(c) { assert.throws(function() { sprintf("%" + c, 0); }, "Should fail on %" +c); }); }); await t.step('accepts all expected conversions: ' + convs.join(""), function() { convs.forEach(function(c) { assert.doesNotThrow(function() { sprintf("%" + c, 0); }, "Should pass on %" +c); }); }); await t.step('accepts all expected lengths: ' + lens.join(""), function() { lens.forEach(function(l) { var fmt = "%" + l + "X"; assert.doesNotThrow(function() { sprintf(fmt, 0); }, "Should pass on "+fmt); }); }); await t.step('accepts all expected flags: ' + flags.join(""), function() { flags.forEach(function(l) { var fmt = "%" + l + "X"; assert.doesNotThrow(function() { sprintf(fmt, 0); }, "Should pass on "+fmt); }); }); await t.step('correctly handles character conversions: cC', function() { assert.equal(sprintf("|%c %c|", "69", 69), "|6 E|"); assert.equal(sprintf("|%c|", {toString:function() { return "69"; }, valueOf: function() { return 69; }} ), "|6|"); }); await t.step('correctly handles error conversion: m', function() { var x = new Error("sheetjs"); (x as any).errno = 69; x.toString = function() { return "SHEETJS"; }; assert.equal(sprintf("|%#m|", x), "|sheetjs|"); delete (x as any).message; assert.equal(sprintf("|%#m|", x), "|Error number 69|"); delete (x as any).errno; assert.equal(sprintf("|%#m|", x), "|Error SHEETJS|"); }); await t.step('correctly handles typeof and valueOf conversions: TV', function() { assert.equal(sprintf("%1$T %1$#T", 1), 'number Number'); assert.equal(sprintf("%1$T %1$#T", 'foo'), 'string String'); assert.equal(sprintf("%1$T %1$#T", [1,2,3]), 'object Array'); assert.equal(sprintf("%1$T %1$#T", null).replace(/Object|global/, "Null"), 'object Null'); assert.equal(sprintf("%1$T %1$#T", undefined).replace(/Object|global/, "Undefined"), 'undefined Undefined'); var _f = function() { return "f"; }; var _3 = function() { return 3; }; assert.equal(sprintf("%1$d %1$s %1$V", {toString:_f}), '0 f f'); assert.equal(sprintf("%1$d %1$s %1$V", {valueOf:_3}), '3 [object Object] 3'); assert.equal(sprintf("%1$d %1$s %1$V", {valueOf:_3, toString:_f}), '3 f 3'); }); await t.step('correctly handles standard integer conversions: diouxXDUO', function() { assert.equal(sprintf("%02hhx %02hhX", 1, 1234321), "01 91"); assert.equal(sprintf("%02hhx %-02hhX", -1, -253), "ff 3 "); assert.equal(sprintf("%#02llx", -3), "0xfffffffffffffffd"); assert.equal(sprintf("%#02llX", -3), "0XFFFFFFFFFFFFFFFD"); assert.equal(sprintf("%#02llo", -3), "01777777777777777777775"); assert.equal(sprintf("%#02llu", -3), "18446744073709551613"); assert.equal(sprintf("%#03lld", -3), "-03"); assert.equal(sprintf("%.9d %.9d", 123456, -123456), "000123456 -000123456"); }); await t.step('correctly handles new binary conversions: bB', function() { assert.equal(sprintf("%#b", -3), "0b11111111111111111111111111111101"); assert.equal(sprintf("%#5B", 3), " 0b11"); }); await t.step('recognizes IEEE754 special values', function() { assert.equal(sprintf("%a", Infinity), "inf"); assert.equal(sprintf("%e", -Infinity), "-inf"); assert.equal(sprintf("%f", 0/0), "nan"); assert.equal(sprintf("%g", 1/-Infinity), "-0"); }); await t.step('correctly handles floating point conversions: aAeEfFgG', function() { assert.equal(sprintf("%1$g %1$#g", 1e5), "100000 100000."); assert.equal(sprintf("%.3g %.3g", 1.2345e-4, 1.2345e-5), "0.000123 1.23e-05"); assert.equal(sprintf("%f", 1.23e22).replace("10486","00000"), "12300000000000000000000.000000"); assert.equal(sprintf("|%1$4.1f|%1$04.1f|%1$-4.1f", 1.2), "| 1.2|01.2|1.2 "); assert.equal(sprintf("%1$.1a|%1$04.0f", -128), "-0x1.0p+7|-128"); assert.equal(sprintf("%1$.1a|%1$04.0f", -6.9e-11), "-0x1.3p-34|-000"); assert.equal(sprintf("%a %A %a %A", 1, .2, .69, 6e20), "0x1p+0 0X1.999999999999AP-3 0x1.6147ae147ae14p-1 0X1.043561A88293P+69"); assert.equal(sprintf("%La %LA %La %LA", 1, .2, .69, 6e20), "0x8p-3 0XC.CCCCCCCCCCCDP-6 0xb.0a3d70a3d70ap-4 0X8.21AB0D441498P+66"); assert.equal(sprintf("%010.1a", 1.), "0x001.0p+0"); assert.equal(sprintf("%.7a %.7a", 129, -129), "0x1.0200000p+7 -0x1.0200000p+7"); assert.equal(sprintf("%.7a", -3.1), "-0x1.8cccccdp+1"); }); await t.step('consistently handles null and undefined', function() { assert.equal(sprintf("|%1$a|%1$A|%1$e|%1$E|%1$f|%1$F|%1$g|%1$G|", undefined), "|nan|NAN|nan|NAN|nan|NAN|nan|NAN|"); assert.equal(sprintf("|%1$a|%1$A|%1$e|%1$E|%1$f|%1$F|%1$g|%1$G|", null), "|nan|NAN|nan|NAN|nan|NAN|nan|NAN|"); assert.equal(sprintf("|%1$b|%1$B|%1$d|%1$D|%1$i|%1$o|%1$O|%1$u|%1$U|%1$x|%1$X|", undefined), "|0|0|0|0|0|0|0|0|0|0|0|"); assert.equal(sprintf("|%1$b|%1$B|%1$d|%1$D|%1$i|%1$o|%1$O|%1$u|%1$U|%1$x|%1$X|", null), "|0|0|0|0|0|0|0|0|0|0|0|"); }); await t.step('correctly handles JSON conversion: J', function() { var data = ({a:1}); assert.equal(sprintf("%J", data), JSON.stringify(data)); X.set_inspect(function(data: any) { return "|" + JSON.stringify(data) + "|"; }); assert.equal(sprintf("%J", data), JSON.stringify(data)); assert.equal(sprintf("%#J", data), "|" + JSON.stringify(data) + "|"); }); await t.step('handles dynamic specifiers', function() { assert.equal(sprintf("|%5s|", "sheetjs"), "|sheetjs|"); assert.equal(sprintf("|%*s|", 5, "sheetjs"), "|sheetjs|"); assert.equal(sprintf("|%2$*1$s|", 5, "sheetjs", 10), "|sheetjs|"); assert.equal(sprintf("|%10s|", "sheetjs"), "| sheetjs|"); assert.equal(sprintf("|%2$*3$s|", 5, "sheetjs", 10), "| sheetjs|"); assert.equal(sprintf("|%0*.*d|", 4, 2, 1), "| 01|"); assert.equal(sprintf("|%1$0*3$.*2$d|", 1, 2, 4), "| 01|"); assert.equal(sprintf("|%*.*d|", 4, 2, 1), "| 01|"); assert.equal(sprintf("|%-*.*d|", 4, 2, 1), "|01 |"); assert.equal(sprintf("|%*.*d|", -4, 2, 1), "|01 |"); assert.equal(sprintf("|%-*.*d|", -4, 2, 1), "|01 |"); assert.equal(sprintf("|%*s|", 4, "sheetjs"), "|sheetjs|"); assert.equal(sprintf("|%*.*s|", 4, 3, "sheetjs"), "| she|"); assert.equal(sprintf("|%*.*s|", 4, 2, "sheetjs"), "| sh|"); assert.equal(sprintf("|%*.*s|", 4, 1, "sheetjs"), "| s|"); assert.equal(sprintf("|%*.*s|", 4, 0, "sheetjs"), "| |"); assert.equal(sprintf("|%*.*s|", 4, -1, "sheetjs"), "|sheetjs|"); }); await t.step('handles long strings', function() { for(var i = 10; i <= 1000; i+= 10) assert.equal(sprintf("%" + i + "s", "abc").length, i); }); });