Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Big ass rename: buster-assertions -> referee

  - Switch out test framework (use Buster)
  • Loading branch information...
commit 1e586a011320916f1761c689e5ad31befde29613 1 parent af35309
Christian Johansen cjohansen authored
1  .gitignore
... ... @@ -1,4 +1,3 @@
1 1 *.log
2   -doc/*.html
3 2 node_modules
4 3 test/test.html
9 .gitmodules
... ... @@ -1,9 +0,0 @@
1   -[submodule "vendor/buster-util"]
2   - path = vendor/buster-util
3   - url = https://gitorious.org/buster/buster-util.git
4   -[submodule "vendor/buster-core"]
5   - path = vendor/buster-core
6   - url = https://gitorious.org/buster/buster-core.git
7   -[submodule "vendor/sinon"]
8   - path = vendor/sinon
9   - url = https://github.com/cjohansen/Sinon.JS.git
1  .npmignore
... ... @@ -1,4 +1,3 @@
1 1 vendor
2 2 .gitignore
3   -.gitmodules
4 3 .npmignore
2  LICENSE
... ... @@ -1,6 +1,6 @@
1 1 (The BSD License)
2 2
3   -Copyright (c) 2010-2011, Christian Johansen, christian@cjohansen.no and
  3 +Copyright (c) 2010-2012, Christian Johansen, christian@cjohansen.no and
4 4 August Lilleaas, august.lilleaas@gmail.com. All rights reserved.
5 5
6 6 Redistribution and use in source and binary forms, with or without modification,
16 Readme.md
Source Rendered
... ... @@ -1,16 +0,0 @@
1   -# buster-assertions
2   -
3   -[![Build status](https://secure.travis-ci.org/busterjs/buster-assertions.png?branch=master)](http://travis-ci.org/busterjs/buster-assertions)
4   -
5   -Test-framework agnostic assertions and expectations. Features an API for
6   -adding custom assertions.
7   -
8   -# Running tests
9   -
10   -To run tests in the browser:
11   -
12   - vendor/buster-util/jstdhtml
13   -
14   -Open test/test.html in a browser
15   -
16   -You can also run JsTestDriver from the root directory.
24 Readme.rst
Source Rendered
... ... @@ -0,0 +1,24 @@
  1 +# referee
  2 +
  3 + Referee is in you unit tests, deciding who passes and who fails
  4 +
  5 +[![Build status](https://secure.travis-ci.org/busterjs/referee.png?branch=master)](http://travis-ci.org/busterjs/referee)
  6 +
  7 +``referee`` is a test-framework agnostic assertion and expectation library.
  8 +Some highlights:
  9 +
  10 +- Rich library of assertions
  11 +- Symmetric assert/refute (refute is ``referee``'s "assert.not*")
  12 +- Evented: Emits success and failure events
  13 +- Failing assertions throw exceptions by default, but can be configured to not
  14 +- API to add custom assertions that provides quite a bit of plumbing for free
  15 +
  16 +Developers - Running tests
  17 +==========================
  18 +
  19 +::
  20 +
  21 + npm install
  22 + ./node_modules/.bin/buster-test --node
  23 + ./node_modules/.bin/buster-server
  24 + ./node_modules/.bin/buster-test --browser
21 autolint.js
... ... @@ -0,0 +1,21 @@
  1 +module.exports = {
  2 + paths: [
  3 + "lib/*.js",
  4 + "test/*.js"
  5 + ],
  6 + linterOptions: {
  7 + node: true,
  8 + browser: true,
  9 + plusplus: true,
  10 + sloppy: true,
  11 + vars: true,
  12 + nomen: true,
  13 + regexp: true,
  14 + predef: [
  15 + "define",
  16 + "assert",
  17 + "refute",
  18 + "buster"
  19 + ]
  20 + }
  21 +};
18 buster.js
... ... @@ -0,0 +1,18 @@
  1 +exports["Browser"] = {
  2 + libs: [
  3 + "node_modules/lodash/lodash.js",
  4 + "node_modules/samsam/lib/samsam.js",
  5 + "node_modules/bane/lib/bane.js"
  6 + ],
  7 + sources: [
  8 + "lib/referee.js",
  9 + "lib/expect.js"
  10 + ],
  11 + testHelpers: ["test/test-helper.js"],
  12 + tests: ["test/*-test.js"]
  13 +};
  14 +
  15 +exports["Node"] = {
  16 + extends: "Browser",
  17 + environment: "node"
  18 +};
22 jsTestDriver.conf
... ... @@ -1,22 +0,0 @@
1   -server: http://localhost:4224
2   -
3   -load:
4   - - vendor/buster-util/lib/buster-util/jstestdriver-shim.js
5   - - vendor/buster-core/lib/buster-core.js
6   - - vendor/buster-core/lib/buster-event-emitter.js
7   - - vendor/sinon/lib/sinon.js
8   - - vendor/sinon/lib/sinon/spy.js
9   - - vendor/sinon/lib/sinon/stub.js
10   - - vendor/sinon/lib/sinon/mock.js
11   - - vendor/sinon/lib/sinon/collection.js
12   - - vendor/sinon/lib/sinon/util/fake_timers.js
13   - - vendor/sinon/lib/sinon/util/timers_ie.js
14   - - vendor/sinon/lib/sinon/sandbox.js
15   - - vendor/sinon/lib/sinon/test.js
16   - - vendor/sinon/lib/sinon/test_case.js
17   - - vendor/sinon/lib/sinon/assert.js
18   - - lib/*.js
19   - - lib/buster-assertions/*.js
20   - - test/test-helper.js
21   - - test/*.js
22   - - test/buster-assertions/*.js
4 jsl.conf
... ... @@ -1,4 +0,0 @@
1   -+output-format __FILENAME__(__LINE__): __ERROR__
2   -
3   -+define module
4   -+define require
797 lib/buster-assertions.js
... ... @@ -1,797 +0,0 @@
1   -/*jslint eqeqeq: false, onevar: false, plusplus: false*/
2   -/*global buster, require, module*/
3   -(function () {
4   - var isCommonJS = typeof require == "function" && typeof module == "object";
5   - if (isCommonJS) buster = require("buster-core");
6   - var toString = Object.prototype.toString;
7   - var slice = Array.prototype.slice;
8   - var assert, refute, ba = buster.assertions = buster.eventEmitter.create();
9   -
10   - if (isCommonJS) {
11   - module.exports = buster.assertions;
12   - }
13   -
14   - function countAssertion() {
15   - if (typeof ba.count != "number") {
16   - ba.count = 0;
17   - }
18   -
19   - ba.count += 1;
20   - }
21   -
22   - ba.count = countAssertion;
23   -
24   - function assertEnoughArguments(name, args, num) {
25   - if (args.length < num) {
26   - ba.fail("[" + name + "] Expected to receive at least " +
27   - num + " argument" + (num > 1 ? "s" : ""));
28   - return false;
29   - }
30   -
31   - return true;
32   - }
33   -
34   - function defineAssertion(type, name, func, fl, messageValues) {
35   - ba[type][name] = function () {
36   - var fullName = type + "." + name;
37   - countAssertion();
38   - if (!assertEnoughArguments(fullName, arguments, fl || func.length)) return;
39   -
40   - var failed = false;
41   -
42   - var ctx = {
43   - fail: function () {
44   - failed = true;
45   - var failArgs = [type, name].concat(slice.call(arguments));
46   - fail.apply(this, failArgs);
47   - return true;
48   - }
49   - };
50   -
51   - var args = slice.call(arguments, 0);
52   -
53   - if (typeof messageValues == "function") {
54   - args = messageValues.apply(this, args);
55   - }
56   -
57   - if (!func.apply(ctx, arguments)) {
58   - return fail.apply(ctx, [type, name, "message"].concat(args));
59   - }
60   -
61   - if (!failed) {
62   - ba.emit.apply(ba, ["pass", fullName].concat(args));
63   - }
64   - };
65   - }
66   -
67   - ba.add = function (name, options) {
68   - var refuteArgs;
69   -
70   - if (options.refute) {
71   - refuteArgs = options.refute.length;
72   - } else {
73   - refuteArgs = options.assert.length;
74   - options.refute = function () {
75   - return !options.assert.apply(this, arguments);
76   - };
77   - }
78   -
79   - var values = options && options.values; // TODO: Remove
80   - defineAssertion("assert", name, options.assert, options.assert.length, values);
81   - defineAssertion("refute", name, options.refute, refuteArgs, values);
82   -
83   - assert[name].message = options.assertMessage;
84   - refute[name].message = options.refuteMessage;
85   -
86   - if (options.expectation) {
87   - if (ba.expect && ba.expect.wrapAssertion) {
88   - ba.expect.wrapAssertion(name, options.expectation);
89   - } else {
90   - assert[name].expectationName = options.expectation;
91   - refute[name].expectationName = options.expectation;
92   - }
93   - }
94   - };
95   -
96   - function interpolate(string, property, value) {
97   - return string.replace(new RegExp("\\$\\{" + property + "\\}", "g"), value);
98   - }
99   -
100   - function interpolatePosArg(message, values) {
101   - var value;
102   - values = values || [];
103   -
104   - for (var i = 0, l = values.length; i < l; i++) {
105   - message = interpolate(message, i, ba.format(values[i]));
106   - }
107   -
108   - return message;
109   - }
110   -
111   - function interpolateProperties(msg, properties) {
112   - for (var prop in properties) {
113   - msg = interpolate(msg, prop, ba.format(properties[prop]));
114   - }
115   -
116   - return msg || "";
117   - }
118   -
119   - function fail(type, assertion, msg) {
120   - delete this.fail;
121   - var message = interpolateProperties(
122   - interpolatePosArg(ba[type][assertion][msg] || msg,
123   - [].slice.call(arguments, 3)), this);
124   - ba.fail("[" + type + "." + assertion + "] " + message);
125   - }
126   -
127   - function isDate(value) {
128   - // Duck typed dates, allows objects to take on the role of dates
129   - // without actually being dates
130   - return typeof value.getTime == "function" &&
131   - value.getTime() == value.valueOf();
132   - }
133   -
134   - ba.isDate = isDate;
135   -
136   - // Fixes NaN === NaN (should be true) and
137   - // -0 === +0 (should be false)
138   - // http://wiki.ecmascript.org/doku.php?id=harmony:egal
139   - function egal(x, y) {
140   - if (x === y) {
141   - // 0 === -0, but they are not identical
142   - return x !== 0 || 1 / x === 1 / y;
143   - }
144   -
145   - // NaN !== NaN, but they are identical.
146   - // NaNs are the only non-reflexive value, i.e., if x !== x,
147   - // then x is a NaN.
148   - // isNaN is broken: it converts its argument to number, so
149   - // isNaN("foo") => true
150   - return x !== x && y !== y;
151   - }
152   -
153   - function areEqual(expected, actual) {
154   - if (egal(expected, actual)) {
155   - return true;
156   - }
157   -
158   - // Elements are only equal if expected === actual
159   - if (buster.isElement(expected) || buster.isElement(actual)) {
160   - return false;
161   - }
162   -
163   - // null and undefined only pass for null === null and
164   - // undefined === undefined
165   - /*jsl: ignore*/
166   - if (expected == null || actual == null) {
167   - return actual === expected;
168   - }
169   - /*jsl: end*/
170   -
171   - if (isDate(expected) || isDate(actual)) {
172   - return isDate(expected) && isDate(actual) &&
173   - expected.getTime() == actual.getTime();
174   - }
175   -
176   - var useCoercingEquality = typeof expected != "object" || typeof actual != "object";
177   -
178   - if (expected instanceof RegExp && actual instanceof RegExp) {
179   - if (expected.toString() != actual.toString()) {
180   - return false;
181   - }
182   -
183   - useCoercingEquality = false;
184   - }
185   -
186   - // Arrays can only be equal to arrays
187   - var expectedStr = toString.call(expected);
188   - var actualStr = toString.call(actual);
189   -
190   - // Coerce and compare when primitives are involved
191   - if (useCoercingEquality) {
192   - return expectedStr != "[object Array]" && actualStr != "[object Array]" &&
193   - expected == actual;
194   - }
195   -
196   - var expectedKeys = ba.keys(expected);
197   - var actualKeys = ba.keys(actual);
198   -
199   - if (isArguments(expected) || isArguments(actual)) {
200   - if (expected.length != actual.length) {
201   - return false;
202   - }
203   - } else {
204   - if (typeof expected != typeof actual || expectedStr != actualStr ||
205   - expectedKeys.length != actualKeys.length) {
206   - return false;
207   - }
208   - }
209   -
210   - var key;
211   -
212   - for (var i = 0, l = expectedKeys.length; i < l; i++) {
213   - key = expectedKeys[i];
214   - if (!Object.prototype.hasOwnProperty.call(actual, key) ||
215   - !areEqual(expected[key], actual[key])) {
216   - return false;
217   - }
218   - }
219   -
220   - return true;
221   - }
222   -
223   - ba.deepEqual = areEqual;
224   -
225   - assert = ba.assert = function assert(actual, message) {
226   - countAssertion();
227   - if (!assertEnoughArguments("assert", arguments, 1)) return;
228   -
229   - if (!actual) {
230   - var val = ba.format(actual);
231   - ba.fail(message || "[assert] Expected " + val + " to be truthy");
232   - } else {
233   - ba.emit("pass", "assert", message || "", actual);
234   - }
235   - };
236   -
237   - assert.toString = function () {
238   - return "buster.assert";
239   - };
240   -
241   - refute = ba.refute = function (actual, message) {
242   - countAssertion();
243   - if (!assertEnoughArguments("refute", arguments, 1)) return;
244   -
245   - if (actual) {
246   - var val = ba.format(actual);
247   - ba.fail(message || "[refute] Expected " + val + " to be falsy");
248   - } else {
249   - ba.emit("pass", "refute", message || "", actual);
250   - }
251   - };
252   -
253   - assert.message = "[assert] Expected ${0} to be truthy";
254   - ba.count = 0;
255   -
256   - ba.fail = function (message) {
257   - var exception = new Error(message);
258   - exception.name = "AssertionError";
259   -
260   - try {
261   - throw exception;
262   - } catch (e) {
263   - ba.emit("failure", e);
264   - }
265   -
266   - if (typeof ba.throwOnFailure != "boolean" || ba.throwOnFailure) {
267   - throw exception;
268   - }
269   - };
270   -
271   - ba.format = function (object) {
272   - return "" + object;
273   - };
274   -
275   - function msg(message) {
276   - if (!message) { return ""; }
277   - return message + (/[.:!?]$/.test(message) ? " " : ": ");
278   - }
279   -
280   - function actualAndExpectedMessageValues(actual, expected, message) {
281   - return [actual, expected, msg(message)]
282   - }
283   -
284   - function actualMessageValues(actual) {
285   - return [actual, msg(arguments[1])];
286   - }
287   -
288   - function actualAndTypeOfMessageValues(actual) {
289   - return [actual, typeof actual, msg(arguments[1])];
290   - }
291   -
292   - ba.add("same", {
293   - assert: function (actual, expected) {
294   - return egal(actual, expected);
295   - },
296   - refute: function (actual, expected) {
297   - return !egal(actual, expected);
298   - },
299   - assertMessage: "${2}${0} expected to be the same object as ${1}",
300   - refuteMessage: "${2}${0} expected not to be the same object as ${1}",
301   - expectation: "toBe",
302   - values: actualAndExpectedMessageValues
303   - });
304   -
305   - function multiLineStringDiff(actual, expected, message) {
306   - if (actual == expected) return true;
307   -
308   - var message = interpolatePosArg(assert.equals.multiLineStringHeading, [message]),
309   - actualLines = actual.split("\n"),
310   - expectedLines = expected.split("\n"),
311   - lineCount = Math.max(expectedLines.length, actualLines.length),
312   - lines = [];
313   -
314   - for (var i = 0; i < lineCount; ++i) {
315   - if (expectedLines[i] != actualLines[i]) {
316   - lines.push("line " + (i + 1) + ": " + (expectedLines[i] || "") +
317   - "\nwas: " + (actualLines[i] || ""));
318   - }
319   - }
320   -
321   - ba.fail("[assert.equals] " + message + lines.join("\n\n"));
322   - return false;
323   - }
324   -
325   - ba.add("equals", {
326   - assert: function (actual, expected) {
327   - if (typeof actual == "string" && typeof expected == "string" &&
328   - (actual.indexOf("\n") >= 0 || expected.indexOf("\n") >= 0)) {
329   - var message = msg(arguments[2]);
330   - return multiLineStringDiff.call(this, actual, expected, message);
331   - }
332   -
333   - return areEqual(actual, expected);
334   - },
335   -
336   - refute: function (actual, expected) {
337   - return !areEqual(actual, expected);
338   - },
339   -
340   - assertMessage: "${2}${0} expected to be equal to ${1}",
341   - refuteMessage: "${2}${0} expected not to be equal to ${1}",
342   - expectation: "toEqual",
343   - values: actualAndExpectedMessageValues
344   - });
345   -
346   - assert.equals.multiLineStringHeading = "${0}Expected multi-line strings to be equal:\n";
347   -
348   - ba.add("greater", {
349   - assert: function (actual, expected) {
350   - return actual > expected;
351   - },
352   -
353   - assertMessage: "${2}Expected ${0} to be greater than ${1}",
354   - refuteMessage: "${2}Expected ${0} to be less than or equal to ${1}",
355   - expectation: "toBeGreaterThan",
356   - values: actualAndExpectedMessageValues
357   - });
358   -
359   - ba.add("less", {
360   - assert: function (actual, expected) {
361   - return actual < expected;
362   - },
363   -
364   - assertMessage: "${2}Expected ${0} to be less than ${1}",
365   - refuteMessage: "${2}Expected ${0} to be greater than or equal to ${1}",
366   - expectation: "toBeLessThan",
367   - values: actualAndExpectedMessageValues
368   - });
369   -
370   - ba.add("defined", {
371   - assert: function (actual) {
372   - return typeof actual != "undefined";
373   - },
374   - assertMessage: "${2}Expected to be defined",
375   - refuteMessage: "${2}Expected ${0} (${1}) not to be defined",
376   - expectation: "toBeDefined",
377   - values: actualAndTypeOfMessageValues
378   - });
379   -
380   - ba.add("isNull", {
381   - assert: function (actual) {
382   - return actual === null;
383   - },
384   - assertMessage: "${1}Expected ${0} to be null",
385   - refuteMessage: "${1}Expected not to be null",
386   - expectation: "toBeNull",
387   - values: actualMessageValues
388   - });
389   -
390   - function arrayContains(array, subset) {
391   - var i, l, j, k;
392   - for (i = 0, l = array.length; i < l; ++i) {
393   - if (match(array[i], subset[0])) {
394   - for (j = 0, k = subset.length; j < k; ++j) {
395   - if (!match(array[i + j], subset[j])) { return false; }
396   - }
397   - return true;
398   - }
399   - }
400   - return false;
401   - }
402   -
403   - function match(object, matcher) {
404   - if (matcher && typeof matcher.test == "function") {
405   - return matcher.test(object);
406   - }
407   -
408   - if (typeof matcher == "function") {
409   - return matcher(object) === true;
410   - }
411   -
412   - if (typeof matcher == "string") {
413   - matcher = matcher.toLowerCase();
414   - var notNull = typeof object === "string" || !!object;
415   - return notNull && ("" + object).toLowerCase().indexOf(matcher) >= 0;
416   - }
417   -
418   - if (typeof matcher == "number") {
419   - return matcher == object;
420   - }
421   -
422   - if (typeof matcher == "boolean") {
423   - return matcher === object;
424   - }
425   -
426   - if (toString.call(object) == "[object Array]" &&
427   - toString.call(matcher) == "[object Array]") {
428   - return arrayContains(object, matcher);
429   - }
430   -
431   - if (matcher && typeof matcher == "object") {
432   - for (var prop in matcher) {
433   - if (!match(object[prop], matcher[prop])) {
434   - return false;
435   - }
436   - }
437   -
438   - return true;
439   - }
440   -
441   - throw new Error("Matcher (" + ba.format(matcher) + ") was not a " +
442   - "string, a number, a function, a boolean or an object");
443   - }
444   -
445   - ba.match = match;
446   -
447   - ba.add("match", {
448   - assert: function (actual, matcher) {
449   - var passed;
450   -
451   - try {
452   - passed = match(actual, matcher);
453   - } catch (e) {
454   - return this.fail("exceptionMessage", e.message, msg(arguments[2]));
455   - }
456   -
457   - return passed;
458   - },
459   -
460   - refute: function (actual, matcher) {
461   - var passed;
462   -
463   - try {
464   - passed = match(actual, matcher);
465   - } catch (e) {
466   - return this.fail("exceptionMessage", e.message);
467   - }
468   -
469   - return !passed;
470   - },
471   -
472   - assertMessage: "${2}${0} expected to match ${1}",
473   - refuteMessage: "${2}${0} expected not to match ${1}",
474   - expectation: "toMatch",
475   - values: actualAndExpectedMessageValues
476   - });
477   -
478   - assert.match.exceptionMessage = "${1}${0}";
479   - refute.match.exceptionMessage = "${1}${0}";
480   -
481   - ba.add("isObject", {
482   - assert: function (actual) {
483   - return typeof actual == "object" && !!actual;
484   - },
485   - assertMessage: "${2}${0} (${1}) expected to be object and not null",
486   - refuteMessage: "${2}${0} expected to be null or not an object",
487   - expectation: "toBeObject",
488   - values: actualAndTypeOfMessageValues
489   - });
490   -
491   - ba.add("isFunction", {
492   - assert: function (actual) {
493   - return typeof actual == "function";
494   - },
495   - assertMessage: "${2}${0} (${1}) expected to be function",
496   - refuteMessage: "${2}${0} expected not to be function",
497   - expectation: "toBeFunction",
498   - values: function (actual) {
499   - return [("" + actual).replace("\n", ""), typeof actual, msg(arguments[1])];
500   - }
501   - });
502   -
503   - ba.add("isTrue", {
504   - assert: function (actual) {
505   - return actual === true;
506   - },
507   - assertMessage: "${1}Expected ${0} to be true",
508   - refuteMessage: "${1}Expected ${0} to not be true",
509   - expectation: "toBeTrue",
510   - values: actualMessageValues
511   - });
512   -
513   - ba.add("isFalse", {
514   - assert: function (actual) {
515   - return actual === false;
516   - },
517   - assertMessage: "${1}Expected ${0} to be false",
518   - refuteMessage: "${1}Expected ${0} to not be false",
519   - expectation: "toBeFalse",
520   - values: actualMessageValues
521   - });
522   -
523   - ba.add("isString", {
524   - assert: function (actual) {
525   - return typeof actual == "string";
526   - },
527   - assertMessage: "${2}Expected ${0} (${1}) to be string",
528   - refuteMessage: "${2}Expected ${0} not to be string",
529   - expectation: "toBeString",
530   - values: actualAndTypeOfMessageValues
531   - });
532   -
533   - ba.add("isBoolean", {
534   - assert: function (actual) {
535   - return typeof actual == "boolean";
536   - },
537   - assertMessage: "${2}Expected ${0} (${1}) to be boolean",
538   - refuteMessage: "${2}Expected ${0} not to be boolean",
539   - expectation: "toBeBoolean",
540   - values: actualAndTypeOfMessageValues
541   - });
542   -
543   - ba.add("isNumber", {
544   - assert: function (actual) {
545   - return typeof actual == "number" && !isNaN(actual);
546   - },
547   - assertMessage: "${2}Expected ${0} (${1}) to be a non-NaN number",
548   - refuteMessage: "${2}Expected ${0} to be NaN or another non-number value",
549   - expectation: "toBeNumber",
550   - values: actualAndTypeOfMessageValues
551   - });
552   -
553   - ba.add("isNaN", {
554   - assert: function (actual) {
555   - return typeof actual == "number" && isNaN(actual);
556   - },
557   - assertMessage: "${2}Expected ${0} to be NaN",
558   - refuteMessage: "${2}Expected not to be NaN",
559   - expectation: "toBeNaN",
560   - values: actualAndTypeOfMessageValues
561   - });
562   -
563   - ba.add("isArray", {
564   - assert: function (actual) {
565   - return toString.call(actual) == "[object Array]";
566   - },
567   - assertMessage: "${2}Expected ${0} to be array",
568   - refuteMessage: "${2}Expected ${0} not to be array",
569   - expectation: "toBeArray",
570   - values: actualAndTypeOfMessageValues
571   - });
572   -
573   - function isArrayLike(object) {
574   - return toString.call(object) == "[object Array]" ||
575   - (!!object && typeof object.length == "number" &&
576   - typeof object.splice == "function") ||
577   - ba.isArguments(object);
578   - }
579   -
580   - ba.isArrayLike = isArrayLike;
581   -
582   - ba.add("isArrayLike", {
583   - assert: function (actual) {
584   - return isArrayLike(actual);
585   - },
586   - assertMessage: "${2}Expected ${0} to be array like",
587   - refuteMessage: "${2}Expected ${0} not to be array like",
588   - expectation: "toBeArrayLike",
589   - values: actualAndTypeOfMessageValues
590   - });
591   -
592   - function captureException(callback) {
593   - try {
594   - callback();
595   - } catch (e) {
596   - return e;
597   - }
598   -
599   - return null;
600   - }
601   -
602   - ba.captureException = captureException;
603   -
604   - assert.exception = function (callback, matcher, message) {
605   - countAssertion();
606   - if (!assertEnoughArguments("assert.exception", arguments, 1)) { return; }
607   - if (!callback) { return; }
608   -
609   - if (typeof matcher === "string") {
610   - message = matcher;
611   - matcher = undefined;
612   - }
613   -
614   - var err = captureException(callback);
615   - message = msg(message);
616   -
617   - if (!err) {
618   - if (typeof matcher === "object") {
619   - return fail.call({}, "assert", "exception", "typeNoExceptionMessage",
620   - message, ba.format(matcher));
621   - } else {
622   - return fail.call({}, "assert", "exception", "message", message);
623   - }
624   - }
625   -
626   - if (typeof matcher === "object" && !match(err, matcher)) {
627   - return fail.call({}, "assert", "exception", "typeFailMessage",
628   - message, ba.format(matcher), err.name, err.message);
629   - }
630   -
631   - if (typeof matcher === "function" && matcher(err) !== true) {
632   - return fail.call({}, "assert", "exception", "matchFailMessage",
633   - message, err.name, err.message);
634   - }
635   -
636   - ba.emit("pass", "assert.exception", message, callback, matcher);
637   - };
638   -
639   - assert.exception.typeNoExceptionMessage = "${0}Expected ${1} but no exception was thrown";
640   - assert.exception.message = "${0}Expected exception";
641   - assert.exception.typeFailMessage = "${0}Expected ${1} but threw ${2} (${3})";
642   - assert.exception.matchFailMessage = "${0}Expected thrown ${1} (${2}) to pass matcher function";
643   - assert.exception.expectationName = "toThrow";
644   -
645   - refute.exception = function (callback) {
646   - countAssertion();
647   - if (!assertEnoughArguments("refute.exception", arguments, 1)) return;
648   -
649   - var err = captureException(callback);
650   -
651   - if (err) {
652   - fail.call({}, "refute", "exception", "message",
653   - msg(arguments[1]), err.name, err.message, callback);
654   - } else {
655   - ba.emit("pass", "refute.exception", callback);
656   - }
657   - };
658   -
659   - refute.exception.message = "${0}Expected not to throw but threw ${1} (${2})";
660   - refute.exception.expectationName = "toThrow";
661   -
662   - ba.add("near", {
663   - assert: function (actual, expected, delta) {
664   - return Math.abs(actual - expected) <= delta;
665   - },
666   - assertMessage: "${3}Expected ${0} to be equal to ${1} +/- ${2}",
667   - refuteMessage: "${3}Expected ${0} not to be equal to ${1} +/- ${2}",
668   - expectation: "toBeNear",
669   - values: function (actual, expected, delta, message) {
670   - return [actual, expected, delta, msg(message)];
671   - }
672   - });
673   -
674   - ba.add("hasPrototype", {
675   - assert: function (actual, protoObj) {
676   - return protoObj.isPrototypeOf(actual);
677   - },
678   - assertMessage: "${2}Expected ${0} to have ${1} on its prototype chain",
679   - refuteMessage: "${2}Expected ${0} not to have ${1} on its prototype chain",
680   - expectation: "toHavePrototype",
681   - values: actualAndExpectedMessageValues
682   - });
683   -
684   - ba.add("contains", {
685   - assert: function (haystack, needle) {
686   - for (var i = 0; i < haystack.length; i++) {
687   - if (haystack[i] === needle) {
688   - return true;
689   - }
690   - }
691   - return false;
692   - },
693   - assertMessage: "${2}Expected [${0}] to contain ${1}",
694   - refuteMessage: "${2}Expected [${0}] not to contain ${1}",
695   - expectation: "toContain",
696   - values: actualAndExpectedMessageValues
697   - });
698   -
699   - ba.add("tagName", {
700   - assert: function (element, tagName) {
701   - if (!element.tagName) {
702   - return this.fail("noTagNameMessage", tagName, element, msg(arguments[2]));
703   - }
704   -
705   - return tagName.toLowerCase &&
706   - tagName.toLowerCase() == element.tagName.toLowerCase();
707   - },
708   - assertMessage: "${2}Expected tagName to be ${0} but was ${1}",
709   - refuteMessage: "${2}Expected tagName not to be ${0}",
710   - expectation: "toHaveTagName",
711   - values: function (element, tagName, message) {
712   - return [tagName, element.tagName, msg(message)];
713   - }
714   - });
715   -
716   - assert.tagName.noTagNameMessage = "${2}Expected ${1} to have tagName property";
717   - refute.tagName.noTagNameMessage = "${2}Expected ${1} to have tagName property";
718   -
719   - function indexOf(arr, item) {
720   - for (var i = 0, l = arr.length; i < l; i++) {
721   - if (arr[i] == item) {
722   - return i;
723   - }
724   - }
725   -
726   - return -1;
727   - }
728   -
729   - ba.add("className", {
730   - assert: function (element, className) {
731   - if (typeof element.className == "undefined") {
732   - return this.fail("noClassNameMessage", className, element, msg(arguments[2]));
733   - }
734   -
735   - var expected = typeof className == "string" ? className.split(" ") : className;
736   - var actual = element.className.split(" ");
737   -
738   - for (var i = 0, l = expected.length; i < l; i++) {
739   - if (indexOf(actual, expected[i]) < 0) {
740   - return false;
741   - }
742   - }
743   -
744   - return true;
745   - },
746   - assertMessage: "${2}Expected object's className to include ${0} but was ${1}",
747   - refuteMessage: "${2}Expected object's className not to include ${0}",
748   - expectation: "toHaveClassName",
749   - values: function (element, className, message) {
750   - return [className, element.className, msg(message)];
751   - }
752   - });
753   -
754   - assert.className.noClassNameMessage = "${2}Expected object to have className property";
755   - refute.className.noClassNameMessage = "${2}Expected object to have className property";
756   -
757   - if (typeof module != "undefined") {
758   - ba.expect = function () {
759   - ba.expect = require("./buster-assertions/expect");
760   - return ba.expect.apply(exports, arguments);
761   - };
762   - }
763   -
764   - function isArguments(obj) {
765   - if (typeof obj != "object" || typeof obj.length != "number" ||
766   - toString.call(obj) == "[object Array]") {
767   - return false;
768   - }
769   -
770   - if (typeof obj.callee == "function") {
771   - return true;
772   - }
773   -
774   - try {
775   - obj[obj.length] = 6;
776   - delete obj[obj.length];
777   - } catch (e) {
778   - return true;
779   - }
780   -
781   - return false;
782   - }
783   -
784   - ba.isArguments = isArguments;
785   -
786   - ba.keys = function (object) {
787   - var keys = [];
788   -
789   - for (var prop in object) {
790   - if (Object.prototype.hasOwnProperty.call(object, prop)) {
791   - keys.push(prop);
792   - }
793   - }
794   -
795   - return keys;
796   - };
797   -}());
63 lib/buster-assertions/expect.js
... ... @@ -1,63 +0,0 @@
1   -if (typeof module == "object" && typeof require == "function") {
2   - var buster = require("buster-core");
3   - buster.assertions = require("../buster-assertions");
4   -}
5   -
6   -(function (ba) {
7   - ba.expectation = {};
8   -
9   - ba.expect = function (actual) {
10   - var expectation = buster.extend(buster.create(ba.expectation), {
11   - actual: actual,
12   - assertMode: true
13   - });
14   - expectation.not = buster.create(expectation);
15   - expectation.not.assertMode = false;
16   - return expectation;
17   - };
18   -
19   - ba.expect.wrapAssertion = function (assertion, expectation) {
20   - ba.expectation[expectation] = function () {
21   - var args = [this.actual].concat(Array.prototype.slice.call(arguments));
22   - var type = this.assertMode ? "assert" : "refute";
23   - var callFunc;
24   -
25   - if (assertion === "assert") {
26   - callFunc = this.assertMode ? ba.assert : ba.refute;
27   - } else if (assertion === "refute") {
28   - callFunc = this.assertMode ? ba.refute : ba.assert;
29   - } else {
30   - callFunc = ba[type][assertion];
31   - }
32   -
33   - try {
34   - return callFunc.apply(ba.expect, args);
35   - } catch (e) {
36   - e.message = (e.message || "").replace(
37   - "[" + type + "." + assertion + "]",
38   - "[expect." + (this.assertMode ? "" : "not.") + expectation + "]");
39   - throw e;
40   - }
41   - };
42   - };
43   -
44   - var prop, expectationName;
45   -
46   - for (prop in ba.assert) {
47   - if (ba.assert[prop].expectationName) {
48   - expectationName = ba.assert[prop].expectationName;
49   - ba.expect.wrapAssertion(prop, expectationName);
50   - }
51   - }
52   -
53   - ba.expect.wrapAssertion("assert", "toBeTruthy");
54   - ba.expect.wrapAssertion("refute", "toBeFalsy");
55   -
56   - if (ba.expectation.toBeNear) {
57   - ba.expectation.toBeCloseTo = ba.expectation.toBeNear;
58   - }
59   -
60   - if (typeof module == "object") {
61   - module.exports = ba.expect;
62   - }
63   -}(buster.assertions));
65 lib/expect.js
... ... @@ -0,0 +1,65 @@
  1 +((typeof define === "function" && define.amd && function (m) {
  2 + define(["lodash", "referee"], m);
  3 +}) || (typeof module === "object" && function (m) {
  4 + module.exports = m(require("lodash"), require("./referee"));
  5 +}) || function (m) { this.referee.expect = m(this._, this.referee); }
  6 +)(function (_, referee) {
  7 + var expectation = {};
  8 + function F() {}
  9 + var create = function (object) { F.prototype = object; return new F(); };
  10 +
  11 + var expect = function (actual) {
  12 + var expectation = _.extend(create(expect.expectation), {
  13 + actual: actual,
  14 + assertMode: true
  15 + });
  16 + expectation.not = create(expectation);
  17 + expectation.not.assertMode = false;
  18 + return expectation;
  19 + };
  20 +
  21 + expect.expectation = expectation;
  22 +
  23 + expect.wrapAssertion = function (assertion, expectation) {
  24 + expect.expectation[expectation] = function () {
  25 + var args = [this.actual].concat(_.toArray(arguments));
  26 + var type = this.assertMode ? "assert" : "refute";
  27 + var callFunc;
  28 +
  29 + if (assertion === "assert") {
  30 + callFunc = this.assertMode ? referee.assert : referee.refute;
  31 + } else if (assertion === "refute") {
  32 + callFunc = this.assertMode ? referee.refute : referee.assert;
  33 + } else {
  34 + callFunc = referee[type][assertion];
  35 + }
  36 +
  37 + try {
  38 + return callFunc.apply(referee.expect, args);
  39 + } catch (e) {
  40 + e.message = (e.message || "").replace(
  41 + "[" + type + "." + assertion + "]",
  42 + "[expect." + (this.assertMode ? "" : "not.") +
  43 + expectation + "]"
  44 + );
  45 + throw e;
  46 + }
  47 + };
  48 + };
  49 +
  50 + _.each(_.keys(referee.assert), function (name) {
  51 + var expectationName = referee.assert[name].expectationName;
  52 + if (expectationName) {
  53 + expect.wrapAssertion(name, expectationName);
  54 + }
  55 + });
  56 +
  57 + expect.wrapAssertion("assert", "toBeTruthy");
  58 + expect.wrapAssertion("refute", "toBeFalsy");
  59 +
  60 + if (expect.expectation.toBeNear) {
  61 + expect.expectation.toBeCloseTo = expect.expectation.toBeNear;
  62 + }
  63 +
  64 + return expect;
  65 +});
647 lib/referee.js
... ... @@ -0,0 +1,647 @@
  1 +((typeof define === "function" && define.amd && function (m) {
  2 + define(["lodash", "samsam", "bane"], m);
  3 +}) || (typeof module === "object" && function (m) {
  4 + module.exports = m(require("lodash"), require("samsam"), require("bane"));
  5 +}) || function (m) { this.referee = m(this._, this.samsam, this.bane); }
  6 +)(function (_, samsam, bane) {
  7 + "use strict";
  8 +
  9 + var toString = Object.prototype.toString;
  10 + var slice = Array.prototype.slice;
  11 + var assert, refute, referee = bane.createEventEmitter();
  12 +
  13 + referee.countAssertion = function countAssertion() {
  14 + if (typeof referee.count !== "number") { referee.count = 0; }
  15 + referee.count += 1;
  16 + };
  17 +
  18 + function interpolate(string, prop, value) {
  19 + return string.replace(new RegExp("\\$\\{" + prop + "\\}", "g"), value);
  20 + }
  21 +
  22 + // Interpolate positional arguments. Replaces occurences of ${<index>} in
  23 + // the string with the corresponding entry in values[<index>]
  24 + function interpolatePosArg(message, values) {
  25 + return _.reduce(values, function (msg, value, index) {
  26 + return interpolate(msg, index, referee.format(value));
  27 + }, message);
  28 + }
  29 +
  30 + function interpolateProperties(message, properties) {
  31 + return _.reduce(_.keys(properties), function (msg, name) {
  32 + return interpolate(msg, name, referee.format(properties[name]));
  33 + }, message || "");
  34 + }
  35 +
  36 + // Fail an assertion. Interpolates message before calling referee.fail
  37 + function fail(type, assertion, msg) {
  38 + delete this.fail;
  39 + var message = interpolateProperties(interpolatePosArg(
  40 + referee[type][assertion][msg] || msg,
  41 + [].slice.call(arguments, 3)
  42 + ), this);
  43 + referee.fail("[" + type + "." + assertion + "] " + message);
  44 + }
  45 +
  46 + // Internal helper. Used throughout to fail assertions if they receive
  47 + // too few arguments. The name is provided for a helpful error message.
  48 + function assertArgNum(name, args, num) {
  49 + if (args.length < num) {
  50 + referee.fail("[" + name + "] Expected to receive at least " +
  51 + num + " argument" + (num > 1 ? "s" : ""));
  52 + return false;
  53 + }
  54 + return true;
  55 + }
  56 +
  57 + // Internal helper. Not the most elegant of functions, but it takes
  58 + // care of all the nitty-gritty of assertion functions: counting,
  59 + // verifying parameter count, interpolating messages with actual
  60 + // values and so on.
  61 + function defineAssertion(type, name, func, minArgs, messageValues) {
  62 + referee[type][name] = function () {
  63 + referee.countAssertion();
  64 + var fullName = type + "." + name, failed = false;
  65 +
  66 + if (!assertArgNum(fullName, arguments, minArgs || func.length)) {
  67 + return;
  68 + }
  69 +
  70 + var ctx = {
  71 + fail: function () {
  72 + failed = true;
  73 + var failArgs = [type, name].concat(slice.call(arguments));
  74 + fail.apply(this, failArgs);
  75 + return true;
  76 + }
  77 + };
  78 +
  79 + var args = slice.call(arguments, 0);
  80 +
  81 + if (typeof messageValues === "function") {
  82 + args = messageValues.apply(this, args);
  83 + }
  84 +
  85 + if (!func.apply(ctx, arguments)) {
  86 + return fail.apply(ctx, [type, name, "message"].concat(args));
  87 + }
  88 +
  89 + if (!failed) {
  90 + referee.emit.apply(referee, ["pass", fullName].concat(args));
  91 + }
  92 + };
  93 + }
  94 +
  95 + referee.add = function (name, opt) {
  96 + var refuteArgs;
  97 +
  98 + if (opt.refute) {
  99 + refuteArgs = opt.refute.length;
  100 + } else {
  101 + refuteArgs = opt.assert.length;
  102 + opt.refute = function () {
  103 + return !opt.assert.apply(this, arguments);
  104 + };
  105 + }
  106 +
  107 + var values = opt.values;
  108 + defineAssertion("assert", name, opt.assert, opt.assert.length, values);
  109 + defineAssertion("refute", name, opt.refute, refuteArgs, values);
  110 +
  111 + assert[name].message = opt.assertMessage;
  112 + refute[name].message = opt.refuteMessage;
  113 +
  114 + if (opt.expectation) {
  115 + if (referee.expect && referee.expect.wrapAssertion) {
  116 + referee.expect.wrapAssertion(name, opt.expectation);
  117 + } else {
  118 + assert[name].expectationName = opt.expectation;
  119 + refute[name].expectationName = opt.expectation;
  120 + }
  121