Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

A spyOn implementation for whiskey. (in progress) #35

Merged
merged 5 commits into from

2 participants

@btipling

No description provided.

lib/common.js
@@ -544,3 +545,73 @@ 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_ = {};
@Kami Owner
Kami added a note

Minor style issue - we prefix 'private' attributes with _ (_callCount) instead of suffix them.

Fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/common.js
((32 lines not shown))
+ this.reset(funcName);
+ var 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} opt_func The optional function to reapply to the context.
+ */
+SpyOn.prototype.clear = function (funcName, context, opt_func) {
@Kami Owner
Kami added a note

Another minor style issue: opt_func -> optFunc.

Fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@Kami Kami merged commit 0a801c3 into master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 11, 2012
  1. Stubbed out a spyOn implementation for whiskey.

    Bjorn Tipling authored
  2. Add tests for spyOn and fix issues.

    Bjorn Tipling authored
  3. Add spyon to test/run.sh

    Bjorn Tipling authored
This page is out of date. Refresh to see the latest.
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
Something went wrong with that request. Please try again.