* Convert a value to a nice, human-readable string * * When many JavaScript Object values are coerced to a String, the * resulting value will be ``"[object Object]"``. This obscures * helpful information, making the coerced value unsuitable for * use in assertion messages, t
(val, seen)
| 1414 | * @returns {string} - A string representation of ``val``, optimised for human readability. |
| 1415 | */ |
| 1416 | function format_value(val, seen) |
| 1417 | { |
| 1418 | if (!seen) { |
| 1419 | seen = []; |
| 1420 | } |
| 1421 | if (typeof val === "object" && val !== null) { |
| 1422 | if (seen.indexOf(val) >= 0) { |
| 1423 | return "[...]"; |
| 1424 | } |
| 1425 | seen.push(val); |
| 1426 | } |
| 1427 | if (Array.isArray(val)) { |
| 1428 | let output = "["; |
| 1429 | if (val.beginEllipsis !== undefined) { |
| 1430 | output += "…, "; |
| 1431 | } |
| 1432 | output += val.map(function(x) {return format_value(x, seen);}).join(", "); |
| 1433 | if (val.endEllipsis !== undefined) { |
| 1434 | output += ", …"; |
| 1435 | } |
| 1436 | return output + "]"; |
| 1437 | } |
| 1438 | |
| 1439 | switch (typeof val) { |
| 1440 | case "string": |
| 1441 | return '"' + val.replace(formatEscapePattern, match => formatEscapeMap[match]) + '"'; |
| 1442 | case "boolean": |
| 1443 | case "undefined": |
| 1444 | return String(val); |
| 1445 | case "number": |
| 1446 | // In JavaScript, -0 === 0 and String(-0) == "0", so we have to |
| 1447 | // special-case. |
| 1448 | if (val === -0 && 1/val === -Infinity) { |
| 1449 | return "-0"; |
| 1450 | } |
| 1451 | return String(val); |
| 1452 | case "bigint": |
| 1453 | return String(val) + 'n'; |
| 1454 | case "object": |
| 1455 | if (val === null) { |
| 1456 | return "null"; |
| 1457 | } |
| 1458 | |
| 1459 | // Special-case Node objects, since those come up a lot in my tests. I |
| 1460 | // ignore namespaces. |
| 1461 | if (is_node(val)) { |
| 1462 | switch (val.nodeType) { |
| 1463 | case Node.ELEMENT_NODE: |
| 1464 | var ret = "<" + val.localName; |
| 1465 | for (var i = 0; i < val.attributes.length; i++) { |
| 1466 | ret += " " + val.attributes[i].name + '="' + val.attributes[i].value + '"'; |
| 1467 | } |
| 1468 | ret += ">" + val.innerHTML + "</" + val.localName + ">"; |
| 1469 | return "Element node " + truncate(ret, 60); |
| 1470 | case Node.TEXT_NODE: |
| 1471 | return 'Text node "' + truncate(val.data, 60) + '"'; |
| 1472 | case Node.PROCESSING_INSTRUCTION_NODE: |
| 1473 | return "ProcessingInstruction node with target " + format_value(truncate(val.target, 60)) + " and data " + format_value(truncate(val.data, 60)); |
no test coverage detected
searching dependent graphs…