Skip to content
This repository
Browse code

basic stub test works emitting json events

  • Loading branch information...
commit 6c78e602f3b8d5893b71c7025e5d1c0edfac0781 1 parent 1cc80b7
James Halliday authored

Showing 3 changed files with 329 additions and 0 deletions. Show diff stats Hide diff stats

  1. +6 0 example/test.js
  2. +237 0 index.js
  3. +86 0 lib/deep_equal.js
6 example/test.js
... ... @@ -0,0 +1,6 @@
  1 +var test = require('testling');
  2 +
  3 +test('json parse', function (t) {
  4 + t.deepEqual(JSON.parse('[1,2]'), [1,2]);
  5 + t.end();
  6 +});
237 index.js
... ... @@ -0,0 +1,237 @@
  1 +var EventEmitter = require('events').EventEmitter;
  2 +var deepEqual = require('./lib/deep_equal');
  3 +var pending = 0;
  4 +
  5 +function push (name, res) {
  6 + console.log(name + ': ' + JSON.stringify(res));
  7 +}
  8 +
  9 +module.exports = function (name, cb) {
  10 + if (typeof name === 'function') {
  11 + cb = name;
  12 + name = undefined;
  13 + }
  14 +
  15 + var t = new Test(name);
  16 + pending ++;
  17 +
  18 + t.on('testEnd', function () {
  19 + pending --;
  20 + process.nextTick(function () {
  21 + if (pending <= 0) push('end', {});
  22 + });
  23 + });
  24 +
  25 + cb(t);
  26 +};
  27 +
  28 +var testId = 0;
  29 +function Test (name, cb) {
  30 + this.id = testId ++;
  31 + push('testBegin', { name : name, testId : this.id });
  32 +
  33 + this.counts = {
  34 + plan : undefined,
  35 + pass : 0,
  36 + fail : 0
  37 + };
  38 + this.windows = [];
  39 +}
  40 +
  41 +Test.prototype = new EventEmitter;
  42 +
  43 +Test.prototype.assert = function (res) {
  44 + if (res.ok) this.counts.pass ++
  45 + else this.counts.fail ++
  46 +
  47 + if (this.counts.plan !== undefined
  48 + && this.counts.pass + this.counts.fail > this.counts.plan) {
  49 + push('fail', {
  50 + type : 'fail',
  51 + ok : false,
  52 + found : this.counts.fail + this.counts.pass,
  53 + wanted : this.counts.plan,
  54 + name : 'more tests run than planned',
  55 + testId : this.id
  56 + });
  57 + }
  58 +
  59 + res.testId = this.id;
  60 + push('assert', res);
  61 +
  62 + if (this.counts.plan !== undefined
  63 + && this.counts.plan === this.counts.pass + this.counts.fail) {
  64 + this.end();
  65 + }
  66 +};
  67 +
  68 +Test.prototype.ok = function (value, name) {
  69 + this.assert({
  70 + type : 'ok',
  71 + ok : !!value,
  72 + name : name,
  73 + found : Boolean(value),
  74 + wanted : true
  75 + });
  76 +};
  77 +
  78 +Test.prototype.notOk = function (value, name) {
  79 + this.assert({
  80 + type : 'ok',
  81 + ok : !!!value,
  82 + name : name,
  83 + found : Boolean(value),
  84 + wanted : false
  85 + });
  86 +};
  87 +
  88 +Test.prototype.fail = function (value, name) {
  89 + this.assert({
  90 + type : 'fail',
  91 + ok : false,
  92 + name : name,
  93 + found : value,
  94 + wanted : undefined
  95 + });
  96 +};
  97 +
  98 +Test.prototype.equal = function (found, wanted, name) {
  99 + this.assert({
  100 + type : 'equal',
  101 + ok : found == wanted,
  102 + name : name,
  103 + found : found,
  104 + wanted : wanted
  105 + });
  106 +};
  107 +
  108 +Test.prototype.notEqual = function (found, wanted, name) {
  109 + this.assert({
  110 + type : 'notEqual',
  111 + ok : found != wanted,
  112 + name : name,
  113 + found : found,
  114 + wanted : wanted
  115 + });
  116 +};
  117 +
  118 +Test.prototype.deepEqual = function (found, wanted, name) {
  119 + this.assert({
  120 + type : 'deepEqual',
  121 + ok : deepEqual(found, wanted),
  122 + name : name,
  123 + found : found,
  124 + wanted : wanted
  125 + });
  126 +};
  127 +
  128 +Test.prototype.notDeepEqual = function (found, wanted, name) {
  129 + this.assert({
  130 + type : 'notDeepEqual',
  131 + ok : !deepEqual(found, wanted),
  132 + name : name,
  133 + found : found,
  134 + wanted : wanted
  135 + });
  136 +};
  137 +
  138 +Test.prototype.strictEqual = function (found, wanted, name) {
  139 + this.assert({
  140 + type : 'strictEqual',
  141 + ok : found === wanted,
  142 + name : name,
  143 + found : found,
  144 + wanted : wanted
  145 + });
  146 +};
  147 +
  148 +Test.prototype.notStrictEqual = function (found, wanted, name) {
  149 + this.assert({
  150 + type : 'strictEqual',
  151 + ok : found !== wanted,
  152 + name : name,
  153 + found : found,
  154 + wanted : wanted
  155 + });
  156 +};
  157 +
  158 +function checkThrows (shouldThrow, fn, expected, name) {
  159 + if (typeof expected === 'string') {
  160 + name = expected;
  161 + expected = null;
  162 + }
  163 + var ok = !shouldThrow, err = undefined;
  164 +
  165 + try { fn() }
  166 + catch (e) {
  167 + ok = !ok;
  168 + err = e;
  169 + }
  170 +
  171 + this.assert({
  172 + type : shouldThrow ? 'throws' : 'doesNotThrow',
  173 + ok : ok,
  174 + found : err,
  175 + expected : expected
  176 + });
  177 +}
  178 +
  179 +Test.prototype['throws'] = function (fn, expected, name) {
  180 + checkThrows.call(this, true, fn, expected, name);
  181 +};
  182 +
  183 +Test.prototype.doesNotThrow = function (fn, expected, name) {
  184 + checkThrows.call(this, false, fn, expected, name);
  185 +};
  186 +
  187 +Test.prototype.ifError = function (err, name) {
  188 + this.assert({
  189 + type : 'ifError',
  190 + ok : !!!err,
  191 + name : name,
  192 + found : err,
  193 + wanted : undefined
  194 + });
  195 +};
  196 +
  197 +Test.prototype.plan = function (n) {
  198 + if (this.counts.plan === undefined) {
  199 + this.counts.plan = n;
  200 + }
  201 + else {
  202 + this.counts.plan += n;
  203 + }
  204 + push('plan', { testId : this.id, n : n });
  205 +};
  206 +
  207 +Test.prototype.log = function (msg) {
  208 + push('log', { testId : this.id, message : msg });
  209 +};
  210 +
  211 +Test.prototype.end = function () {
  212 + if (this.counts.plan !== undefined
  213 + && this.counts.plan > this.counts.fail + this.counts.pass) {
  214 + push('planFail', {
  215 + type : 'fail',
  216 + ok : false,
  217 + found : this.counts.fail + this.counts.pass,
  218 + wanted : this.counts.plan,
  219 + name : 'more tests planned than run',
  220 + testId : this.id
  221 + });
  222 + }
  223 +
  224 + if (!this.ended) {
  225 + this.ended = true;
  226 + push('testEnd', { testId : this.id });
  227 + this.emit('testEnd');
  228 + }
  229 +};
  230 +
  231 +Test.prototype.createWindow = function (opts, cb) {
  232 + // ...
  233 +};
  234 +
  235 +Test.prototype.submitForm = function (form, opts, cb) {
  236 + // ...
  237 +};
86 lib/deep_equal.js
... ... @@ -0,0 +1,86 @@
  1 +// ripped from node's deepEqual implementation in assert
  2 +
  3 +var pSlice = Array.prototype.slice;
  4 +var Object_keys = typeof Object.keys === 'function'
  5 + ? Object.keys
  6 + : function (obj) {
  7 + var keys = [];
  8 + for (var key in obj) keys.push(key);
  9 + return keys;
  10 + }
  11 +;
  12 +
  13 +var deepEqual = module.exports = function (actual, expected) {
  14 + // 7.1. All identical values are equivalent, as determined by ===.
  15 + if (actual === expected) {
  16 + return true;
  17 +
  18 + } else if (actual instanceof Date && expected instanceof Date) {
  19 + return actual.getTime() === expected.getTime();
  20 +
  21 + // 7.3. Other pairs that do not both pass typeof value == 'object',
  22 + // equivalence is determined by ==.
  23 + } else if (typeof actual != 'object' && typeof expected != 'object') {
  24 + return actual == expected;
  25 +
  26 + // 7.4. For all other Object pairs, including Array objects, equivalence is
  27 + // determined by having the same number of owned properties (as verified
  28 + // with Object.prototype.hasOwnProperty.call), the same set of keys
  29 + // (although not necessarily the same order), equivalent values for every
  30 + // corresponding key, and an identical 'prototype' property. Note: this
  31 + // accounts for both named and indexed properties on Arrays.
  32 + } else {
  33 + return objEquiv(actual, expected);
  34 + }
  35 +}
  36 +
  37 +function isUndefinedOrNull(value) {
  38 + return value === null || value === undefined;
  39 +}
  40 +
  41 +function isArguments(object) {
  42 + return Object.prototype.toString.call(object) == '[object Arguments]';
  43 +}
  44 +
  45 +function objEquiv(a, b) {
  46 + if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
  47 + return false;
  48 + // an identical 'prototype' property.
  49 + if (a.prototype !== b.prototype) return false;
  50 + //~~~I've managed to break Object.keys through screwy arguments passing.
  51 + // Converting to array solves the problem.
  52 + if (isArguments(a)) {
  53 + if (!isArguments(b)) {
  54 + return false;
  55 + }
  56 + a = pSlice.call(a);
  57 + b = pSlice.call(b);
  58 + return deepEqual(a, b);
  59 + }
  60 + try {
  61 + var ka = Object_keys(a),
  62 + kb = Object_keys(b),
  63 + key, i;
  64 + } catch (e) {//happens when one is a string literal and the other isn't
  65 + return false;
  66 + }
  67 + // having the same number of owned properties (keys incorporates
  68 + // hasOwnProperty)
  69 + if (ka.length != kb.length)
  70 + return false;
  71 + //the same set of keys (although not necessarily the same order),
  72 + ka.sort();
  73 + kb.sort();
  74 + //~~~cheap key test
  75 + for (i = ka.length - 1; i >= 0; i--) {
  76 + if (ka[i] != kb[i])
  77 + return false;
  78 + }
  79 + //equivalent values for every corresponding key, and
  80 + //~~~possibly expensive deep test
  81 + for (i = ka.length - 1; i >= 0; i--) {
  82 + key = ka[i];
  83 + if (!deepEqual(a[key], b[key])) return false;
  84 + }
  85 + return true;
  86 +}

0 comments on commit 6c78e60

Please sign in to comment.
Something went wrong with that request. Please try again.