Skip to content

Commit 26cb099

Browse files
committed
Merge pull request #8 from qubyte/feature/return-promise
Return promises from requireWithStubs and reset.
2 parents fce46ad + 363d13b commit 26cb099

File tree

3 files changed

+121
-23
lines changed

3 files changed

+121
-23
lines changed

README.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ define('Car', ['SteeringWheel'], function(SteeringWheel){
4242

4343
Car.prototype.getSteeringWheelColor = function getSteeringWheelColor(){
4444
return this.steeringWheel.color;
45-
}
45+
};
4646

4747
return Car;
4848
});
@@ -73,7 +73,7 @@ define([
7373

7474
afterEach(function(done){
7575
bogus.reset(done);
76-
})
76+
});
7777

7878
describe('Car', function(){
7979
describe('getSteeringWheelColor method', function(){
@@ -88,6 +88,29 @@ define([
8888
});
8989
```
9090

91+
### Promises
92+
93+
Both `bogus.require` and `bogus.reset` return promises. The `beforeEach` and
94+
`afterEach` in the example above can be written as:
95+
96+
```javascript
97+
beforeEach(function(){
98+
var fakeSteeringWheel = function(){
99+
this.color = 'blue';
100+
};
101+
102+
bogus.stub('SteeringWheel', fakeSteeringWheel);
103+
104+
return bogus.require('Car').then(function(module){
105+
Car = module;
106+
});
107+
});
108+
109+
afterEach(function(){
110+
return bogus.reset();
111+
});
112+
```
113+
91114
### Stub multiple dependencies
92115

93116
If you're stubbing several dependencies, you can pass a map of them to `stub`

bogus.js

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@ define(['require'], function(require){
22

33
'use strict';
44

5+
// Modified (not to use global) and minified from https://github.com/timjansen/PinkySwear.js
6+
/* jshint ignore:start */
7+
var pinkySwear = (function(){function n(n){return"function"==typeof n}function t(n){return"object"==typeof n}function e(n){"undefined"!=typeof setImmediate?setImmediate(n):"undefined"!=typeof process&&process.nextTick?process.nextTick(n):setTimeout(n,0)}function r(o){var c,i=[],f=[],a=function(n,t){return null==c&&null!=n&&(c=n,i=t,f.length&&e(function(){for(var n=0;n<f.length;n++)f[n]()})),c};return a.then=function(a,p){var l=r(o),s=function(){function e(r){var o,c=0;try{if(r&&(t(r)||n(r))&&n(o=r.then)){if(r===l)throw new TypeError;o.call(r,function(){c++||e.apply(u,arguments)},function(n){c++||l(!1,[n])})}else l(!0,arguments)}catch(i){c++||l(!1,[i])}}try{var r=c?a:p;n(r)?e(r.apply(u,i||[])):l(c,i)}catch(o){l(!1,[o])}};return null!=c?e(s):f.push(s),l},o&&(a=o(a)),a}var u;return r}());
8+
/* jshint ignore:end */
9+
10+
// PinkySwear is A+ only and lacks .catch, which is a part of ES2015 promises. This function is
11+
// used as an argument to pinkySwear to bridge the gap (just in case).
12+
function addCatch(p){
13+
p.catch = function(cb){
14+
p.then(undefined, cb);
15+
};
16+
return p;
17+
}
18+
519
function isObject(value){
620
return Object.prototype.toString.call(value) === '[object Object]';
721
}
@@ -61,18 +75,39 @@ define(['require'], function(require){
6175
function requireWithStubs(name, callback, errback){
6276
// Cache the current index of the module in the array.
6377
var moduleIndex = stubbed.push(name) - 1;
78+
var promise = pinkySwear(addCatch);
6479

6580
preserveDefinition(name);
6681
requirejs.undef(name);
6782

83+
84+
function resolve(mod){
85+
promise(true, [mod]);
86+
87+
if (callback) {
88+
callback(mod);
89+
}
90+
}
91+
92+
function reject(err){
93+
promise(false, [err]);
94+
95+
if (errback) {
96+
errback(err);
97+
}
98+
}
99+
68100
// Require all the dependencies to ensure that they're registered.
69-
require(stubbed, function () {
70-
callback(arguments[moduleIndex]); // Return the required module.
71-
}, errback);
101+
require(stubbed, function(){
102+
resolve(arguments[moduleIndex]); // Return the required module.
103+
}, reject);
104+
105+
return promise;
72106
}
73107

74108
function reset(callback){
75109
var originalsToRestore = [];
110+
var promise = pinkySwear(addCatch);
76111

77112
if (stubbed.length === 0) {
78113
callback();
@@ -93,8 +128,15 @@ define(['require'], function(require){
93128
// require the module in order to trigger requirejs to commit to defining it
94129
require(originalsToRestore, function(){
95130
stubbed = [];
96-
callback();
131+
132+
if (callback) {
133+
callback();
134+
}
135+
136+
promise(true, []);
97137
});
138+
139+
return promise;
98140
}
99141

100142
return {

test/test.js

Lines changed: 50 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@
111111
it('should be a function', function(){
112112
assert(typeof bogus.requireWithStubs === 'function');
113113
});
114+
115+
it('should return a promise', function(){
116+
var p = bogus.requireWithStubs('blah', function(){}, function(){});
117+
118+
assert.equal(typeof p.then, 'function');
119+
assert.equal(typeof p.catch, 'function');
120+
});
114121
});
115122

116123
describe('require method', function(){
@@ -120,18 +127,22 @@
120127
});
121128

122129
describe('reset method', function(){
123-
it('should return all original implementations to their names', function(done){
124-
var define = requirejs.define,
125-
modules = [],
126-
moduleNames = [],
127-
i, j, module,
128-
defineStub;
130+
var modules;
131+
var defineStub;
132+
133+
beforeEach(function(done){
134+
var define = requirejs.define;
135+
var i;
136+
var moduleNames = [];
137+
var module;
138+
139+
modules = [];
129140

130141
sandbox.stub(requirejs, 'defined', function(){
131142
return true;
132143
});
133144

134-
for (i = 0; i < 10; i++){
145+
for (i = 0; i < 10; i++) {
135146
module = {
136147
name : getUniqueModuleName(),
137148
originalImplementation : {name: 'original'},
@@ -146,19 +157,41 @@
146157
}
147158

148159
defineStub = sandbox.spy(requirejs, 'define');
149-
requirejs(moduleNames, function () {
150-
bogus.reset(function(){
151-
j = 0;
152-
modules.forEach(function(module, index){
153-
var call = defineStub.getCall(index);
154160

155-
assert.equal(call.args[0], module.name);
156-
j++;
157-
});
161+
requirejs(moduleNames, function(){
162+
done();
163+
});
164+
});
165+
166+
it('is a function', function(){
167+
assert.equal(typeof bogus.reset, 'function');
168+
});
169+
170+
it('returns a promise', function(){
171+
var p = bogus.reset();
172+
173+
assert.equal(typeof p.then, 'function');
174+
assert.equal(typeof p.catch, 'function');
175+
});
176+
177+
it('returns all original implementations to their names and call a callback', function(done){
178+
bogus.reset(function(){
179+
modules.forEach(function(module, index){
180+
var call = defineStub.getCall(index);
181+
182+
assert.equal(call.args[0], module.name);
183+
});
184+
185+
done();
186+
});
187+
});
158188

159-
assert.equal(j, modules.length);
189+
it('returns all original implementations to their names and resolves a returned promise', function(){
190+
return bogus.reset().then(function(){
191+
modules.forEach(function(module, index){
192+
var call = defineStub.getCall(index);
160193

161-
done();
194+
assert.equal(call.args[0], module.name);
162195
});
163196
});
164197
});

0 commit comments

Comments
 (0)