[
{ "name": "a card number shows its last four", "args": ["4242424242424242", 4, "*", false], "expect": "************4242" },
{ "name": "separators kept: the grouping survives and still four digits show", "args": ["4242 4242 4242 4242", 4, "*", true], "expect": "**** **** **** 4242" },
{ "name": "separators not kept: spaces are masked and count as characters", "args": ["4242 4242 4242 4242", 4, "*", false], "expect": "***************4242" },
{ "name": "separators kept, the visible count skips over a separator", "args": ["1234 5678", 5, "*", true], "expect": "***4 5678" },
{ "name": "a hyphenated sort code with a different mask character", "args": ["12-34-56", 2, "#", true], "expect": "##-##-56" },
{ "name": "zero visible masks everything", "args": ["12345678", 0, "*", false], "expect": "********" },
{ "name": "visible equal to the length leaves the value alone", "args": ["1234", 4, "*", false], "expect": "1234" },
{ "name": "visible past the length leaves the value alone, unpadded", "args": ["12", 4, "*", false], "expect": "12" },
{ "name": "the empty string stays empty", "args": ["", 4, "*", true], "expect": "" },
{ "name": "dots are not separators: they are masked", "args": ["a.b.c", 1, "*", true], "expect": "****c" },
{ "name": "accented letters count as one character each", "args": ["ÄÖÜß", 1, "•", false], "expect": "•••ß" },
{ "name": "an emoji is one character, not two UTF-16 units", "args": ["a😀b", 1, "*", false], "expect": "**b" },
{ "name": "an emoji is masked as a single mask character", "args": ["😀😀x", 2, "*", false], "expect": "*😀x" },
{ "name": "a negative visible count is an error", "args": ["1234", -1, "*", false], "expectError": "visible must be 0 or greater" },
{ "name": "an empty mask character is an error", "args": ["1234", 2, "", false], "expectError": "maskChar must be exactly one character" },
{ "name": "a two-character mask would change the length, so it is an error", "args": ["1234", 2, "**", false], "expectError": "maskChar must be exactly one character" }
]