pax_global_header00006660000000000000000000000064126610160640014514gustar00rootroot0000000000000052 comment=055a641371fc47b59804fd1d96a1dc2b364e9bf1 formatio-1.2.0/000077500000000000000000000000001266101606400133345ustar00rootroot00000000000000formatio-1.2.0/.gitignore000066400000000000000000000000311266101606400153160ustar00rootroot00000000000000*.log node_modules .idea formatio-1.2.0/.travis.yml000066400000000000000000000001561266101606400154470ustar00rootroot00000000000000language: node_js sudo: false node_js: - "0.10" - "0.12" - "4" - "5" before_install: - npm i -g npm formatio-1.2.0/AUTHORS000066400000000000000000000003431266101606400144040ustar00rootroot00000000000000Buster.JS Format was written by Christian Johansen, christian@cjohansen.no August Lilleaas, august.lilleaas@gmail.com Dave Geddes, davidcgeddes@gmail.com Stein Magnus Jodal, stein.magnus@jodal.no Tek Nynja, github@teknynja.com formatio-1.2.0/LICENSE000066400000000000000000000031261266101606400143430ustar00rootroot00000000000000(The BSD License) Copyright (c) 2010-2012, Christian Johansen (christian@cjohansen.no) and August Lilleaas (august.lilleaas@gmail.com). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Christian Johansen nor the names of his contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. formatio-1.2.0/Readme.md000066400000000000000000000156201266101606400150570ustar00rootroot00000000000000# formatio [![Build status](https://secure.travis-ci.org/busterjs/formatio.png?branch=master)](http://travis-ci.org/busterjs/formatio) > The cheesy object formatter Pretty formatting of arbitrary JavaScript values. Currently only supports ascii formatting, suitable for command-line utilities. Like `JSON.stringify`, it formats objects recursively, but unlike `JSON.stringify`, it can handle regular expressions, functions, circular objects and more. `formatio` is a general-purpose library. It works in browsers (including old and rowdy ones, like IE6) and Node. It will define itself as an AMD module if you want it to (i.e. if there's a `define` function available). ## Running tests ``` npm test ``` Or use Buster.JS manually: ``` node_modules/buster/bin/buster-test --help ``` ## `formatio.ascii` API `formatio.ascii` can take any JavaScript object and format it nicely as plain text. It uses the helper functions described below to format different types of objects. ### `formatio.ascii(object)` `object` can be any kind of object, including DOM elements. **Simple object** ```javascript var formatio = require("formatio"); var object = { name: "Christian" }; console.log(formatio.ascii(object)); // Outputs: // { name: "Christian" } ``` **Complex object** ```javascript var formatio = require("formatio"); var developer = { name: "Christian", interests: ["Programming", "Guitar", "TV"], location: { language: "Norway", city: "Oslo", getLatLon: function getLatLon(callback) { // ... }, distanceTo: function distanceTo(location) { } }, speak: function () { return "Oh hi!"; } }; console.log(formatio.ascii(developer)); // Outputs: // { // interests: ["Programming", "Guitar", "TV"], // location: { // city: "Oslo", // distanceTo: function distanceTo() {}, // getLatLon: function getLatLon() {}, // language: "Norway" // }, // name: "Christian", // speak: function () {} // } ``` **Custom constructor** If the object to format is not a generic `Object` object, **formatio** displays the type of object (i.e. name of constructor). Set the `excludeConstructors` (see below) property to control what constructors to include in formatted output. ```javascript var formatio = require("formatio"); function Person(name) { this.name = name; } var dude = new Person("Dude"); console.log(format.ascii(dude)); // Outputs: // [Person] { name: "Dude" } ``` **DOM elements** DOM elements are formatted as abbreviated HTML source. 20 characters of `innerHTML` is included, and if the content is longer, it is truncated with `"[...]"`. Future editions will add the possibility to format nested markup structures. ```javascript var p = document.createElement("p"); p.id = "sample"; p.className = "notice"; p.setAttribute("data-custom", "42"); p.innerHTML = "Hey there, here's some text for ya there buddy"; console.log(formatio.ascii(p)); // Outputs // <p id="sample" class="notice" data-custom="42">Hey there, here's so[...]</p> ``` ### `formatio.ascii.func(func)` Formats a function like `"function [name]() {}"`. The name is retrieved from `formatio.functionName`. ### `formatio.ascii.array(array)` Formats an array as `"[item1, item2, item3]"` where each item is formatted with `formatio.ascii`. Circular references are represented in the resulting string as `"[Circular]"`. ### `formatio.ascii.object(object)` Formats all properties of the object with `formatio.ascii`. If the object can be fully represented in 80 characters, it's formatted in one line. Otherwise, it's nicely indented over as many lines as necessary. Circular references are represented by `"[Circular]"`. Objects created with custom constructors will be formatted as `"[ConstructorName] { ... }"`. Set the `excludeConstructors` property to control what constructors are included in the output like this. ### `formatio.ascii.element(element)` Formats a DOM element as HTML source. The tag name is represented in lower-case and all attributes and their values are included. The element's content is included, up to 20 characters. If the length exceeds 20 characters, it's truncated with a `"[...]"`. ### `formatio.functionName(func)` Guesses a function's name. If the function defines the `displayName` property (used by `some debugging tools `_) it is preferred. If it is not found, the `name` property is tried. If no name can be found this way, an attempt is made to find the function name by looking at the function's `toString()` representation. ### `formatio.constructorName(object)` Attempts to guess the name of the constructor that created the object. It does so by getting the name of `object.constructor` using `functionName`. If a name is found, `excludeConstructors` is consulted. If the constructor name matches any of these elements, an empty string is returned, otherwise the name is returned. ## `formatio.ascii` properties ### `quoteStrings(true)` Whether or not to quote simple strings. When set to `false`, simple strings are not quoted. Strings in arrays and objects will still be quoted, but `ascii("Some string")` will not gain additional quotes. ### `limitChildrenCount(number)` This property allows to limit the number of printed array elements or object properties. When set to 0, all elements will be included in output, any number greater than zero will set the limit to that number. ### `excludeConstructors (["Object", /^.$/])` An array of strings and/or regular expressions naming constructors that should be stripped from the formatted output. The default value skips objects created by `Object` and constructors that have one character names (which are typically used in `Object.create` shims). While you can set this property directly on `formatio.ascii`, it is recommended to create an instance of `formatio.ascii` and override the property on that object. **Strings** represent constructor names that should not be represented in the formatted output. **Regular expressions** are tested against constructor names when formatting. If the expression is a match, the constructor name is not included in the formatted output. ```javascript function Person(name) { this.name = name; } var person = new Person("Chris"); console.log(formatio.ascii(person)); // Outputs // [Person] { name: "Chris" } var formatter = Object.create(formatio); formatter.excludeConstructors = ["Object", /^.$/, "Person"]; console.log(formatter.ascii(person)); // Outputs // { name: "Chris" } // Global overwrite, generally not recommended formatio.excludeConstructors = ["Object", /^.$/, "Person"]; console.log(formatio.ascii(person)); // Outputs // { name: "Chris" } ``` ## Changelog **1.1.2** (12.12.2014) * [Safe-guard innerHTML which may be empty (SVG elements)](https://github.com/busterjs/formatio/commit/ff623a6) * [Format empty strings as (empty string)](https://github.com/busterjs/formatio/commit/116d0ac) formatio-1.2.0/appveyor.yml000066400000000000000000000004531266101606400157260ustar00rootroot00000000000000environment: matrix: - nodejs_version: "0.10" - nodejs_version: "0.12" - nodejs_version: "4" - nodejs_version: "5" install: - ps: Install-Product node $env:nodejs_version - npm install -g npm - npm install test_script: - node --version - npm --version - npm test build: off formatio-1.2.0/autolint.js000066400000000000000000000006431266101606400155340ustar00rootroot00000000000000module.exports = { paths: [ "lib/*.js", "test/*.js" ], linterOptions: { node: true, browser: true, plusplus: true, vars: true, nomen: true, forin: true, sloppy: true, regexp: true, predef: [ "samsam", "define", "assert", "refute", "buster" ] } }; formatio-1.2.0/buster.js000066400000000000000000000004201266101606400151720ustar00rootroot00000000000000exports["Browser"] = { // TODO: Needs fixing environment: "browser", libs: [ "node_modules/samsam/lib/samsam.js" ], sources: ["lib/*.js"], tests: ["test/*-test.js"] }; exports["Node"] = { extends: "Browser", environment: "node" }; formatio-1.2.0/lib/000077500000000000000000000000001266101606400141025ustar00rootroot00000000000000formatio-1.2.0/lib/formatio.js000066400000000000000000000162141266101606400162640ustar00rootroot00000000000000((typeof define === "function" && define.amd && function (m) { define("formatio", ["samsam"], m); }) || (typeof module === "object" && function (m) { module.exports = m(require("samsam")); }) || function (m) { this.formatio = m(this.samsam); } )(function (samsam) { "use strict"; var formatio = { excludeConstructors: ["Object", /^.$/], quoteStrings: true, limitChildrenCount: 0 }; var hasOwn = Object.prototype.hasOwnProperty; var specialObjects = []; if (typeof global !== "undefined") { specialObjects.push({ object: global, value: "[object global]" }); } if (typeof document !== "undefined") { specialObjects.push({ object: document, value: "[object HTMLDocument]" }); } if (typeof window !== "undefined") { specialObjects.push({ object: window, value: "[object Window]" }); } function functionName(func) { if (!func) { return ""; } if (func.displayName) { return func.displayName; } if (func.name) { return func.name; } var matches = func.toString().match(/function\s+([^\(]+)/m); return (matches && matches[1]) || ""; } function constructorName(f, object) { var name = functionName(object && object.constructor); var excludes = f.excludeConstructors || formatio.excludeConstructors || []; var i, l; for (i = 0, l = excludes.length; i < l; ++i) { if (typeof excludes[i] === "string" && excludes[i] === name) { return ""; } else if (excludes[i].test && excludes[i].test(name)) { return ""; } } return name; } function isCircular(object, objects) { if (typeof object !== "object") { return false; } var i, l; for (i = 0, l = objects.length; i < l; ++i) { if (objects[i] === object) { return true; } } return false; } function ascii(f, object, processed, indent) { if (typeof object === "string") { if (object.length === 0) { return "(empty string)"; } var qs = f.quoteStrings; var quote = typeof qs !== "boolean" || qs; return processed || quote ? '"' + object + '"' : object; } if (typeof object === "function" && !(object instanceof RegExp)) { return ascii.func(object); } processed = processed || []; if (isCircular(object, processed)) { return "[Circular]"; } if (Object.prototype.toString.call(object) === "[object Array]") { return ascii.array.call(f, object, processed); } if (!object) { return String((1/object) === -Infinity ? "-0" : object); } if (samsam.isElement(object)) { return ascii.element(object); } if (typeof object.toString === "function" && object.toString !== Object.prototype.toString) { return object.toString(); } var i, l; for (i = 0, l = specialObjects.length; i < l; i++) { if (object === specialObjects[i].object) { return specialObjects[i].value; } } if (typeof Set !== 'undefined' && object instanceof Set) { return ascii.set.call(f, object, processed); } return ascii.object.call(f, object, processed, indent); } ascii.func = function (func) { return "function " + functionName(func) + "() {}"; }; function delimit(str, delimiters) { delimiters = delimiters || ["[", "]"]; return delimiters[0] + str + delimiters[1]; } ascii.array = function (array, processed, delimiters) { processed = processed || []; processed.push(array); var pieces = []; var i, l; l = (this.limitChildrenCount > 0) ? Math.min(this.limitChildrenCount, array.length) : array.length; for (i = 0; i < l; ++i) { pieces.push(ascii(this, array[i], processed)); } if (l < array.length) { pieces.push("[... " + (array.length - l) + " more elements]"); } return delimit(pieces.join(", "), delimiters); }; ascii.set = function (set, processed) { return ascii.array.call(this, Array.from(set), processed, ['Set {', '}']); }; ascii.object = function (object, processed, indent) { processed = processed || []; processed.push(object); indent = indent || 0; var pieces = [], properties = samsam.keys(object).sort(); var length = 3; var prop, str, obj, i, k, l; l = (this.limitChildrenCount > 0) ? Math.min(this.limitChildrenCount, properties.length) : properties.length; for (i = 0; i < l; ++i) { prop = properties[i]; obj = object[prop]; if (isCircular(obj, processed)) { str = "[Circular]"; } else { str = ascii(this, obj, processed, indent + 2); } str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str; length += str.length; pieces.push(str); } var cons = constructorName(this, object); var prefix = cons ? "[" + cons + "] " : ""; var is = ""; for (i = 0, k = indent; i < k; ++i) { is += " "; } if(l < properties.length) pieces.push("[... " + (properties.length - l) + " more elements]"); if (length + indent > 80) { return prefix + "{\n " + is + pieces.join(",\n " + is) + "\n" + is + "}"; } return prefix + "{ " + pieces.join(", ") + " }"; }; ascii.element = function (element) { var tagName = element.tagName.toLowerCase(); var attrs = element.attributes, attr, pairs = [], attrName, i, l, val; for (i = 0, l = attrs.length; i < l; ++i) { attr = attrs.item(i); attrName = attr.nodeName.toLowerCase().replace("html:", ""); val = attr.nodeValue; if (attrName !== "contenteditable" || val !== "inherit") { if (!!val) { pairs.push(attrName + "=\"" + val + "\""); } } } var formatted = "<" + tagName + (pairs.length > 0 ? " " : ""); // SVG elements have undefined innerHTML var content = element.innerHTML || ''; if (content.length > 20) { content = content.substr(0, 20) + "[...]"; } var res = formatted + pairs.join(" ") + ">" + content + ""; return res.replace(/ contentEditable="inherit"/, ""); }; function Formatio(options) { for (var opt in options) { this[opt] = options[opt]; } } Formatio.prototype = { functionName: functionName, configure: function (options) { return new Formatio(options); }, constructorName: function (object) { return constructorName(this, object); }, ascii: function (object, processed, indent) { return ascii(this, object, processed, indent); } }; return Formatio.prototype; }); formatio-1.2.0/package.json000066400000000000000000000021351266101606400156230ustar00rootroot00000000000000{ "name": "formatio", "version": "1.2.0", "description": "Human-readable object formatting", "homepage": "http://busterjs.org/docs/formatio/", "author": "Christian Johansen", "contributors": [ { "name": "Christian Johansen", "email": "christian@cjohansen.no", "url": "http://cjohansen.no" }, { "name": "August Lilleaas", "email": "august.lilleaas@gmail.com", "url": "http://augustl.com" }, { "name": "Dave Geddes", "email": "davidcgeddes@gmail.com" }, { "name": "Stein Magnus Jodal", "email": "stein.magnus@jodal.no" }, { "name": "Tek Nynja", "email": "github@teknynja.com" } ], "license": "BSD-3-Clause", "main": "./lib/formatio", "repository": { "type": "git", "url": "https://github.com/busterjs/formatio.git" }, "scripts": { "test": "node node_modules/buster/bin/buster-test --node", "test-debug": "node --debug-brk node_modules/buster/bin/buster-test --node" }, "dependencies": { "samsam": "1.x" }, "devDependencies": { "buster": "0.7.x" } } formatio-1.2.0/test/000077500000000000000000000000001266101606400143135ustar00rootroot00000000000000formatio-1.2.0/test/formatio-test.js000066400000000000000000000410211266101606400174440ustar00rootroot00000000000000/*global formatio*/ ((typeof module === "object" && typeof require === "function" && function (t) { t(require("buster"), require("../lib/formatio")); }) || function (t) { t(buster, formatio); })(function (buster, formatio) { var assert = buster.referee.assert; var refute = buster.referee.refute; function range(size){ var array = []; for (var i = 0; i < size; i++){ array[i] = i; } return array; } function getObjectWithManyProperties(size){ var object = {}; for (var i = 0; i < size; i++) { object[i.toString()] = i; } return object; } buster.testCase("formatio.ascii", { "formats strings with quotes": function () { assert.equals(formatio.ascii("A string"), '"A string"'); }, "formats 0-length strings in a special way": function () { assert.equals(formatio.ascii(""), "(empty string)"); }, "formats booleans without quotes": function () { assert.equals(formatio.ascii(true), "true"); assert.equals(formatio.ascii(false), "false"); }, "formats null and undefined without quotes": function () { assert.equals(formatio.ascii(null), "null"); assert.equals(formatio.ascii(undefined), "undefined"); }, "formats numbers without quotes": function () { assert.equals(formatio.ascii(3), "3"); assert.equals(formatio.ascii(3987.56), "3987.56"); assert.equals(formatio.ascii(-980.0), "-980"); assert.equals(formatio.ascii(NaN), "NaN"); assert.equals(formatio.ascii(Infinity), "Infinity"); assert.equals(formatio.ascii(-Infinity), "-Infinity"); assert.equals(formatio.ascii(-0), "-0"); }, "formats regexp using toString": function () { assert.equals(formatio.ascii(/[a-zA-Z0-9]+\.?/), "/[a-zA-Z0-9]+\\.?/"); }, "formats functions with name": function () { var fn = function doIt() {}; assert.equals(formatio.ascii(fn), "function doIt() {}"); }, "formats functions without name": function () { assert.equals(formatio.ascii(function () {}), "function () {}"); }, "formats functions with display name": function () { function doIt() {} doIt.displayName = "ohHai"; assert.equals(formatio.ascii(doIt), "function ohHai() {}"); }, "shortens functions with long bodies": function () { function doIt() { var i; function hey() {} for (i = 0; i < 10; i++) { console.log(i); } } assert.equals(formatio.ascii(doIt), "function doIt() {}"); }, "formats functions with no name or display name": function () { function doIt() {} doIt.name = ""; assert.equals(formatio.ascii(doIt), "function doIt() {}"); }, "formats arrays": function () { function ohNo() { return "Oh yes!"; } var array = ["String", 123, /a-z/, null]; var str = formatio.ascii(array); assert.equals(str, '["String", 123, /a-z/, null]'); str = formatio.ascii([ohNo, array]); assert.equals(str, '[function ohNo() {}, ["String", 123, /a-z/, null]]'); }, "does not trip on circular arrays": function () { var array = ["String", 123, /a-z/]; array.push(array); var str = formatio.ascii(array); assert.equals(str, '["String", 123, /a-z/, [Circular]]'); }, "limit formatted array length": { "should stop at given limit" : function () { var configuredFormatio = formatio.configure({ limitChildrenCount : 30 }); var str = configuredFormatio.ascii(range(300)); refute.contains(str, "30"); assert.contains(str, "29"); assert.contains(str, "[... 270 more elements]"); }, "should only format as many elements as exists" : function(){ var configuredFormatio = formatio.configure({ limitChildrenCount : 30 }); var str = configuredFormatio.ascii(range(10)); refute.contains(str, "10"); assert.contains(str, "9"); refute.contains(str, "undefined"); refute.contains(str, "[..."); }, "should format all array elements if no config is used" : function () { var str = formatio.ascii(range(300)); assert.contains(str, "100"); assert.contains(str, "299]"); refute.contains(str, "[..."); } }, "limit count of formated object properties": { "should stop at given limit" : function () { var configured = formatio.configure({ limitChildrenCount: 30 }); var str = configured.ascii(getObjectWithManyProperties(300)); // returned formation may not be in the original order assert.equals(30 + 3, str.split("\n").length); assert.contains(str, "[... 270 more elements]"); }, "should only format as many properties as exists" : function(){ var configured = formatio.configure({ limitChildrenCount : 30 }); var str = configured.ascii(getObjectWithManyProperties(10)); refute.contains(str, "10"); assert.contains(str, "9"); refute.contains(str, "undefined"); refute.contains(str, "[..."); }, "should format all properties if no config is used" : function () { var str = formatio.ascii(getObjectWithManyProperties(300)); assert.equals(300 + 2, str.split("\n").length); } }, "formats object": function () { var object = { id: 42, hello: function () {}, prop: "Some", more: "properties", please: "Gimme some more", "oh hi": 42, seriously: "many properties" }; var expected = "{\n hello: function () {},\n id: 42,\n " + "more: \"properties\",\n \"oh hi\": 42,\n please: " + "\"Gimme some more\",\n prop: \"Some\"," + "\n seriously: \"many properties\"\n}"; assert.equals(formatio.ascii(object), expected); }, "formats short object on one line": function () { var object = { id: 42, hello: function () {}, prop: "Some" }; var expected = "{ hello: function () {}, id: 42, prop: \"Some\" }"; assert.equals(formatio.ascii(object), expected); }, "formats object with a non-function toString": function () { var object = { toString: 42 }; assert.equals(formatio.ascii(object), "{ toString: 42 }"); }, "formats nested object": function () { var object = { id: 42, hello: function () {}, prop: "Some", obj: { num: 23, string: "Here you go you little mister" } }; var expected = "{\n hello: function () {},\n id: 42,\n obj" + ": { num: 23, string: \"Here you go you little mister\"" + " },\n prop: \"Some\"\n}"; assert.equals(formatio.ascii(object), expected); }, "includes constructor if known and not Object": function () { function Person(name) { this.name = name; } var person = new Person("Christian"); assert.equals(formatio.ascii(person), "[Person] { name: \"Christian\" }"); }, "does not include one letter constructors": function () { function F(name) { this.name = name; } var person = new F("Christian"); assert.equals(formatio.ascii(person), "{ name: \"Christian\" }"); }, "includes one letter constructors when configured so": function () { function C(name) { this.name = name; } var person = new C("Christian"); var formatter = formatio.configure({ excludeConstructors: [] }); assert.equals(formatter.ascii(person), "[C] { name: \"Christian\" }"); }, "excludes constructors when configured to do so": function () { function Person(name) { this.name = name; } var person = new Person("Christian"); var formatter = formatio.configure({ excludeConstructors: ["Person"] }); assert.equals(formatter.ascii(person), "{ name: \"Christian\" }"); }, "excludes constructors by pattern when configured so": function () { function Person(name) { this.name = name; } function Ninja(name) { this.name = name; } function Pervert(name) { this.name = name; } var person = new Person("Christian"); var ninja = new Ninja("Haruhachi"); var pervert = new Pervert("Mr. Garrison"); var formatter = formatio.configure({ excludeConstructors: [/^Per/] }); assert.equals(formatter.ascii(person), "{ name: \"Christian\" }"); assert.equals(formatter.ascii(ninja), "[Ninja] { name: \"Haruhachi\" }"); assert.equals(formatter.ascii(pervert), "{ name: \"Mr. Garrison\" }"); }, "excludes constructors when run on other objects": function () { function Person(name) { this.name = name; } var person = new Person("Christian"); var formatter = { ascii: formatio.ascii }; formatter.excludeConstructors = ["Person"]; assert.equals(formatter.ascii(person), "{ name: \"Christian\" }"); }, "excludes default constructors when run on other objects": function () { var person = { name: "Christian" }; var formatter = { ascii: formatio.ascii }; assert.equals(formatter.ascii(person), "{ name: \"Christian\" }"); }, "does not trip on circular formatting": function () { var object = {}; object.foo = object; assert.equals(formatio.ascii(object), "{ foo: [Circular] }"); }, "does not trip on indirect circular formatting": function () { var object = { someProp: {} }; object.someProp.foo = object; assert.equals(formatio.ascii(object), "{ someProp: { foo: [Circular] } }"); }, "formats nested array nicely": function () { var object = { people: ["Chris", "August"] }; assert.equals(formatio.ascii(object), "{ people: [\"Chris\", \"August\"] }"); }, "does not rely on object's hasOwnProperty": function () { // Create object with no "own" properties to get past // Object.keys test and no .hasOwnProperty() function var Obj = function () {}; Obj.prototype = { hasOwnProperty: undefined }; var object = new Obj(); assert.equals(formatio.ascii(object), "{ }"); }, "handles cyclic structures": function () { var obj = {}; obj.list1 = [obj]; obj.list2 = [obj]; obj.list3 = [{ prop: obj }]; refute.exception(function () { formatio.ascii(obj); }); }, "sets": { "formats sets": function () { var set = new Set([2, { id: 42, prop: "Some" }]); var expected = "Set {2, { id: 42, prop: \"Some\" }}"; assert.equals(formatio.ascii(set), expected); }, "limits the number of set members": function () { var fmt = formatio.configure({limitChildrenCount: 30}); var str = fmt.ascii(new Set(range(300))); refute.contains(str, "30"); assert.contains(str, "29"); assert.contains(str, "[... 270 more elements]"); } }, "unquoted strings": { setUp: function () { this.formatter = formatio.configure({ quoteStrings: false }); }, "does not quote strings": function () { assert.equals(this.formatter.ascii("Hey there"), "Hey there"); }, "quotes string properties": function () { var obj = { hey: "Mister" }; assert.equals(this.formatter.ascii(obj), "{ hey: \"Mister\" }"); } }, "numbers": { "formats object with 0": function () { var str = formatio.ascii({ me: 0 }); refute.match(str, "-0"); }, "formats object with -0": function () { var str = formatio.ascii({ me: -0 }); assert.match(str, "-0"); } }, "DOM elements": { requiresSupportFor: { "DOM": typeof document !== "undefined" }, "formats dom element": function () { var element = document.createElement("div"); assert.equals(formatio.ascii(element), "
"); }, "formats dom element with attributes": function () { var element = document.createElement("div"); element.className = "hey there"; element.id = "ohyeah"; var str = formatio.ascii(element); assert.match(str, /
<\/div>/); assert.match(str, /class="hey there"/); assert.match(str, /id="ohyeah"/); }, "formats dom element with content": function () { var element = document.createElement("div"); element.innerHTML = "Oh hi!"; assert.equals(formatio.ascii(element), "
Oh hi!
"); }, "truncates dom element content": function () { var element = document.createElement("div"); element.innerHTML = "Oh hi! I'm Christian, and this " + "is a lot of content"; assert.equals(formatio.ascii(element), "
Oh hi! I'm Christian[...]
"); }, "includes attributes and truncated content": function () { var element = document.createElement("div"); element.id = "anid"; element.lang = "en"; element.innerHTML = "Oh hi! I'm Christian, and this " + "is a lot of content"; var str = formatio.ascii(element); assert.match(str, /
Oh hi! I'm Christian\[\.\.\.\]<\/div>/); assert.match(str, /lang="en"/); assert.match(str, /id="anid"/); }, "formats document object as toString": function () { var str; buster.referee.refute.exception(function () { str = formatio.ascii(document); }); assert.equals(str, "[object HTMLDocument]"); }, "formats window object as toString": function () { var str; buster.referee.refute.exception(function () { str = formatio.ascii(window); }); assert.equals(str, "[object Window]"); } }, "global object": { requiresSupportFor: { "global": typeof global !== "undefined" }, "formats global object as toString": function () { var str; buster.referee.refute.exception(function () { str = formatio.ascii(global); }); assert.equals(str, "[object global]"); } } }); });