require('../common');
var Gently = require('gently')
, gently;
function test(test) {
process.removeAllListeners('exit');
gently = new Gently();
test();
}
test(function constructor() {
assert.deepEqual(gently.expectations, []);
assert.deepEqual(gently.hijacked, {});
assert.equal(gently.constructor.name, 'Gently');
});
test(function expectBadArgs() {
var BAD_ARG = 'oh no';
try {
gently.expect(BAD_ARG);
assert.ok(false, 'throw needs to happen');
} catch (e) {
assert.equal(e.message, 'Bad 1st argument for gently.expect(), object, function, or number expected, got: '+(typeof BAD_ARG));
}
});
test(function expectObjMethod() {
var OBJ = {}, NAME = 'foobar';
OBJ.foo = function(x) {
return x;
};
gently._name = function() {
return NAME;
};
var original = OBJ.foo
, stubFn = function() {};
(function testAddOne() {
assert.strictEqual(gently.expect(OBJ, 'foo', stubFn), original);
assert.equal(gently.expectations.length, 1);
var expectation = gently.expectations[0];
assert.strictEqual(expectation.obj, OBJ);
assert.strictEqual(expectation.method, 'foo');
assert.strictEqual(expectation.stubFn, stubFn);
assert.strictEqual(expectation.name, NAME);
assert.strictEqual(OBJ.foo._original, original);
})();
(function testAddTwo() {
gently.expect(OBJ, 'foo', 2, stubFn);
assert.equal(gently.expectations.length, 2);
assert.strictEqual(OBJ.foo._original, original);
})();
(function testAddOneWithoutMock() {
gently.expect(OBJ, 'foo');
assert.equal(gently.expectations.length, 3);
})();
var stubFnCalled = 0, SELF = {};
gently._stubFn = function(self, obj, method, name, args) {
stubFnCalled++;
assert.strictEqual(self, SELF);
assert.strictEqual(obj, OBJ);
assert.strictEqual(method, 'foo');
assert.strictEqual(name, NAME);
assert.deepEqual(args, [1, 2]);
return 23;
};
assert.equal(OBJ.foo.apply(SELF, [1, 2]), 23);
assert.equal(stubFnCalled, 1);
});
test(function expectClosure() {
var NAME = 'MY CLOSURE';
function closureFn() {};
gently._name = function() {
return NAME;
};
var fn = gently.expect(closureFn);
assert.equal(gently.expectations.length, 1);
var expectation = gently.expectations[0];
assert.strictEqual(expectation.obj, null);
assert.strictEqual(expectation.method, null);
assert.strictEqual(expectation.stubFn, closureFn);
assert.strictEqual(expectation.name, NAME);
var stubFnCalled = 0, SELF = {};
gently._stubFn = function(self, obj, method, name, args) {
stubFnCalled++;
assert.strictEqual(self, SELF);
assert.strictEqual(obj, null);
assert.strictEqual(method, null);
assert.strictEqual(name, NAME);
assert.deepEqual(args, [1, 2]);
return 23;
};
assert.equal(fn.apply(SELF, [1, 2]), 23);
assert.equal(stubFnCalled, 1);
});
test(function expectClosureCount() {
var stubFnCalled = 0;
function closureFn() {stubFnCalled++};
var fn = gently.expect(2, closureFn);
assert.equal(gently.expectations.length, 1);
fn();
assert.equal(gently.expectations.length, 1);
fn();
assert.equal(stubFnCalled, 2);
});
test(function restore() {
var OBJ = {}, NAME = '[my object].myFn()';
OBJ.foo = function(x) {
return x;
};
gently._name = function() {
return NAME;
};
var original = OBJ.foo;
gently.expect(OBJ, 'foo');
gently.restore(OBJ, 'foo');
assert.strictEqual(OBJ.foo, original);
(function testError() {
try {
gently.restore(OBJ, 'foo');
assert.ok(false, 'throw needs to happen');
} catch (e) {
assert.equal(e.message, NAME+' is not gently stubbed');
}
})();
});
test(function _stubFn() {
var OBJ1 = {toString: function() {return '[OBJ 1]'}}
, OBJ2 = {toString: function() {return '[OBJ 2]'}, foo: function () {return 'bar';}}
, SELF = {};
gently.expect(OBJ1, 'foo', function(x) {
assert.strictEqual(this, SELF);
return x * 2;
});
assert.equal(gently._stubFn(SELF, OBJ1, 'foo', 'dummy_name', [5]), 10);
(function testAutorestore() {
assert.equal(OBJ2.foo(), 'bar');
gently.expect(OBJ2, 'foo', function() {
return 'stubbed foo';
});
gently.expect(OBJ2, 'foo', function() {
return "didn't restore yet";
});
assert.equal(gently._stubFn(SELF, OBJ2, 'foo', 'dummy_name', []), 'stubbed foo');
assert.equal(gently._stubFn(SELF, OBJ2, 'foo', 'dummy_name', []), "didn't restore yet");
assert.equal(OBJ2.foo(), 'bar');
assert.deepEqual(gently.expectations, []);
})();
(function testNoMoreCallExpected() {
try {
gently._stubFn(SELF, OBJ1, 'foo', 'dummy_name', [5]);
assert.ok(false, 'throw needs to happen');
} catch (e) {
assert.equal(e.message, 'Unexpected call to dummy_name, no call was expected');
}
})();
(function testDifferentCallExpected() {
gently.expect(OBJ2, 'bar');
try {
gently._stubFn(SELF, OBJ1, 'foo', 'dummy_name', [5]);
assert.ok(false, 'throw needs to happen');
} catch (e) {
assert.equal(e.message, 'Unexpected call to dummy_name, expected call to '+gently._name(OBJ2, 'bar'));
}
assert.equal(gently.expectations.length, 1);
})();
(function testNoMockCallback() {
OBJ2.bar();
assert.equal(gently.expectations.length, 0);
})();
});
test(function stub() {
var LOCATION = './my_class';
(function testRegular() {
var Stub = gently.stub(LOCATION);
assert.ok(Stub instanceof Function);
assert.strictEqual(gently.hijacked[LOCATION], Stub);
assert.ok(Stub['new'] instanceof Function);
assert.equal(Stub.toString(), 'require('+JSON.stringify(LOCATION)+')');
(function testConstructor() {
var newCalled = 0
, STUB
, ARGS = ['foo', 'bar'];
Stub['new'] = function(a, b) {
assert.equal(a, ARGS[0]);
assert.equal(b, ARGS[1]);
newCalled++;
STUB = this;
};
var stub = new Stub(ARGS[0], ARGS[1]);
assert.strictEqual(stub, STUB);
assert.equal(newCalled, 1);
assert.equal(stub.toString(), 'require('+JSON.stringify(LOCATION)+')');
})();
(function testUseReturnValueAsInstance() {
var R = {};
Stub['new'] = function() {
return R;
};
var stub = new Stub();
assert.strictEqual(stub, R);
})();
})();
var EXPORTS_NAME = 'MyClass';
test(function testExportsName() {
var Stub = gently.stub(LOCATION, EXPORTS_NAME);
assert.strictEqual(gently.hijacked[LOCATION][EXPORTS_NAME], Stub);
assert.equal(Stub.toString(), 'require('+JSON.stringify(LOCATION)+').'+EXPORTS_NAME);
(function testConstructor() {
var stub = new Stub();
assert.equal(Stub.toString(), 'require('+JSON.stringify(LOCATION)+').'+EXPORTS_NAME);
})();
});
});
test(function hijack() {
var LOCATION = './foo'
, REQUIRE_CALLS = 0
, EXPORTS = {}
, REQUIRE = function() {
REQUIRE_CALLS++;
return EXPORTS;
};
var hijackedRequire = gently.hijack(REQUIRE);
hijackedRequire(LOCATION);
assert.strictEqual(gently.hijacked[LOCATION], EXPORTS);
assert.equal(REQUIRE_CALLS, 1);
// make sure we are caching the hijacked module
hijackedRequire(LOCATION);
assert.equal(REQUIRE_CALLS, 1);
});
test(function verify() {
var OBJ = {toString: function() {return '[OBJ]'}};
gently.verify();
gently.expect(OBJ, 'foo');
try {
gently.verify();
assert.ok(false, 'throw needs to happen');
} catch (e) {
assert.equal(e.message, 'Expected call to [OBJ].foo() did not happen');
}
try {
gently.verify('foo');
assert.ok(false, 'throw needs to happen');
} catch (e) {
assert.equal(e.message, 'Expected call to [OBJ].foo() did not happen (foo)');
}
});
test(function processExit() {
var verifyCalled = 0;
gently.verify = function(msg) {
verifyCalled++;
assert.equal(msg, 'process exit');
};
process.emit('exit');
assert.equal(verifyCalled, 1);
});
test(function _name() {
(function testNamedClass() {
function Foo() {};
var foo = new Foo();
assert.equal(gently._name(foo, 'bar'), '[Foo].bar()');
})();
(function testToStringPreference() {
function Foo() {};
Foo.prototype.toString = function() {
return '[Superman 123]';
};
var foo = new Foo();
assert.equal(gently._name(foo, 'bar'), '[Superman 123].bar()');
})();
(function testUnamedClass() {
var Foo = function() {};
var foo = new Foo();
assert.equal(gently._name(foo, 'bar'), foo.toString()+'.bar()');
})();
(function testNamedClosure() {
function myClosure() {};
assert.equal(gently._name(null, null, myClosure), myClosure.name+'()');
})();
(function testUnamedClosure() {
var myClosure = function() {2+2 == 5};
assert.equal(gently._name(null, null, myClosure), '>> '+myClosure.toString()+' <<');
})();
});
test(function verifyExpectNone() {
var OBJ = {toString: function() {return '[OBJ]'}};
gently.verify();
gently.expect(OBJ, 'foo', 0);
try {
gently.verify();
} catch (e) {
assert.fail('Exception should not have been thrown');
}
});
|