Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #35 from cloudkick/spyon

A spyOn implementation for whiskey. (in progress)
  • Loading branch information...
commit 0a801c3a081d81280dfa482777c071a8f89a7223 2 parents 5ec13a7 + d559765
@Kami Kami authored
View
129 example/test-spyon.js
@@ -0,0 +1,129 @@
+/*
+ * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * Cloudkick licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @constructor
+ */
+function Foo () {
+ /**
+ * @param {bool}
+ */
+ this.fooCalled = false;
+ /**
+ * @param {string}
+ */
+ this.bar = "";
+ /**
+ * @param {string}
+ */
+ this.postFix = 'postFix';
+}
+
+Foo.prototype.setFoo = function () {
+ this.fooCalled = true;
+};
+
+/**
+ * @param {string} bar
+ */
+Foo.prototype.setBar = function (bar) {
+ this.bar = bar;
+ return bar + this.postFix;
+};
+
+exports['test_spyon_calls_method'] = function(test, assert) {
+ var foo = new Foo();
+ test.spy.on('setFoo', foo);
+ foo.setFoo();
+ assert.equal(foo.fooCalled, true);
+ test.spy.clear('setFoo', foo);
+ test.finish();
+};
+
+exports['test_spyon_returns_right'] = function(test, assert) {
+ var foo, str;
+ foo = new Foo();
+ str = 'foo';
+ test.spy.on('setBar', foo);
+ assert.equal(foo.setBar(str), str + foo.postFix);
+ test.spy.clear('setBar', foo);
+ test.finish();
+};
+
+exports['test_spyon_count_correct'] = function (test, assert) {
+ var foo = new Foo();
+ test.spy.on('setFoo', foo);
+ foo.setFoo();
+ foo.setFoo();
+ foo.setFoo();
+ foo.setFoo();
+ foo.setFoo();
+ foo.setFoo();
+ foo.setFoo();
+ assert.equal(test.spy.called('setFoo'), 7);
+ test.spy.clear('setFoo', foo);
+ test.finish();
+};
+
+
+exports['test_spyon_accepts_function'] = function (test, assert) {
+ var foo, func, set;
+ foo = new Foo();
+ set = false;
+ func = function () {
+ set = true;
+ }
+ test.spy.on('setFoo', foo, func);
+ foo.setFoo();
+ assert.equal(set, true);
+ test.spy.clear('setFoo', foo);
+ test.finish();
+};
+
+exports['test_spyon_reapplies_original_function'] = function (test, assert) {
+ var foo, func;
+ foo = new Foo();
+ func = foo.setFoo;
+ test.spy.on('setFoo', foo);
+ test.spy.clear('setFoo', foo);
+ assert.equal(foo.setFoo, func);
+ test.finish();
+};
+
+exports['test_spyon_reapplies_given_function'] = function (test, assert) {
+ var foo, func, set;
+ foo = new Foo();
+ set = false;
+ func = function () {
+ set = true;
+ };
+ test.spy.on('setFoo', foo);
+ test.spy.clear('setFoo', foo, func);
+ assert.equal(foo.setFoo, func);
+ test.finish();
+};
+
+exports['test_spyon_reset'] = function(test, assert) {
+ var foo = new Foo();
+ test.spy.on('setFoo', foo);
+ foo.setFoo();
+ test.spy.reset('setFoo');
+ assert.equal(test.spy.called('setFoo'), 0);
+ test.spy.clear('setFoo', foo);
+ test.finish();
+};
+
View
78 lib/common.js
@@ -199,6 +199,7 @@ Test.prototype._getTestObject = function(finishFunc) {
testObj.finish = finishFunc;
testObj.skip = skipFunc;
+ testObj.spy = new SpyOn();
return testObj;
};
@@ -544,3 +545,80 @@ exports.TestFile = TestFile;
exports.getTestFilePathAndPattern = getTestFilePathAndPattern;
exports.registerCustomAssertionFunctions = registerCustomAssertionFunctions;
+
+/**
+ * @constructor
+ */
+function SpyOn (){
+ /**
+ * This tracks the number of times a function has been fired.
+ * @param {Object.<number>}
+ * @private
+ */
+ this._callCount = {};
+ /**
+ * This tracks the function to call
+ * @param {Object.<Function>}
+ * @private
+ */
+ this._funcMap = {};
+};
+
+/**
+ * @param {string} funcName The key to use for tracking call counts.
+ * @param {Object} context The context in which the function should execute.
+ * @param {Function} optFunc The optional function to call in wrapper. If not
+ * provided, original function will be called.
+ */
+SpyOn.prototype.on = function (funcName, context, optFunc) {
+ var wrapper, func;
+ if (optFunc) {
+ func = optFunc;
+ } else {
+ func = context[funcName];
+ }
+ if (this._callCount.hasOwnProperty(funcName)) {
+ throw "Function already being tracked.";
+ }
+ this.reset(funcName);
+ wrapper = (function () {
+ this._callCount[funcName] += 1;
+ return func.apply(context, arguments);
+ }).bind(this);
+ context[funcName] = wrapper;
+ this._funcMap[funcName] = func;
+ return this;
+};
+
+/**
+ * @param {string} funcName The key to clear.
+ * @param {Object} context The context in which the function should execute.
+ * @param {Function} optFunc The optional function to reapply to the context.
+ */
+SpyOn.prototype.clear = function (funcName, context, optFunc) {
+ if (optFunc) {
+ context[funcName] = optFunc
+ } else {
+ context[funcName] = this._funcMap[funcName];
+ }
+ delete this._callCount[funcName];
+ delete this._funcMap[funcName];
+ return this;
+};
+
+/**
+ * Reset a call count.
+ * @param {string} funcName The name of the function.
+ */
+SpyOn.prototype.reset = function (funcName) {
+ this._callCount[funcName] = 0;
+};
+
+/**
+ * Get the call count for a spied on function.
+ * @param {string} funcName
+ */
+SpyOn.prototype.called = function (funcName) {
+ return this._callCount[funcName];
+};
+
View
2  package.json
@@ -1,7 +1,7 @@
{
"name": "whiskey",
"description": "A simple test runner for NodeJS applications.",
- "version": "0.6.9",
+ "version": "0.6.10",
"author": "Cloudkick, Inc. <tomaz+npm@cloudkick.com> http://www.cloudkick.com",
"keywords": [ "whiskey", "tests", "test runner", "testing", "tdd", "coverage", "test coverage"],
"homepage": "https://github.com/cloudkick/whiskey",
View
8 test/run.sh
@@ -260,6 +260,14 @@ if [ $? -ne 0 ]; then
exit 1
fi
+"${CWD}/bin/whiskey" --timeout 1000 \
+ --tests "${CWD}/example/test-spyon.js"
+
+if [ $? -ne 0 ]; then
+ echo "Test didn't exit with zero exit code."
+ exit 1
+fi
+
echo ""
echo "* * * Whiskey test suite PASSED. * * *"
exit 0
Please sign in to comment.
Something went wrong with that request. Please try again.