This repository has been archived by the owner on Sep 23, 2021. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit a813d18
Showing
11 changed files
with
362 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
Copyrights for code authored by Yahoo! Inc. is licensed under the following | ||
terms: | ||
|
||
MIT License | ||
|
||
Copyright (c) 2011 Yahoo! Inc. All Rights Reserved. | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to | ||
deal in the Software without restriction, including without limitation the | ||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | ||
sell copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# Sidedoor - Exposing a secondary API for your Node.js modules | ||
|
||
As you've written unit tests for your Node.js modules, you've almost certainly | ||
been forced to think about exposing some internal methods for the sole purpose | ||
of enabling more comprehensive tests or verifying such tests. You've wrestled | ||
with polluting the public API of your module with functions you really don't | ||
want people to see, let alone depend on. | ||
|
||
What if, instead, you could expose a secondary API for your module, such that | ||
the additional methods are available to your tests, but without polluting the | ||
public API? | ||
|
||
This is just what Sidedoor enables. In your module, a simple call to Sidedoor | ||
exposes whatever secondary API you need, while a similarly simple call from a | ||
client module provides access to that secondary API. | ||
|
||
## Installation | ||
|
||
Just use npm: | ||
|
||
npm install sidedoor | ||
|
||
## Exposing an API | ||
|
||
You expose your secondary API by telling Sidedoor which functions to expose, | ||
and, optionally, the name under which you want to expose them. For example: | ||
|
||
function doSomethingImportant() { | ||
... | ||
} | ||
|
||
function doSomethingTestRelated() { | ||
... | ||
} | ||
|
||
// Expose the primary API | ||
module.exports = { | ||
doSomething: doSomethingImportant | ||
}; | ||
|
||
// Expose the secondary API | ||
sidedoor.expose(module, 'test', { | ||
testHelper: doSomethingTestRelated | ||
}); | ||
|
||
Here, in addition to our module's primary API, we've exposed a secondary API | ||
named 'test' that contains the single function `doSomethingTestRelated` exposed | ||
under the name `testHelper`. | ||
|
||
The arguments to `expose` are as follows: | ||
|
||
* _module_, the module from which you are exposing the secondary API. This will | ||
almost always be just 'module'. | ||
* _name_, the name of the secondary API you are exposing. If omitted, a default | ||
unnamed API is exposed. | ||
* _exports_, the equivalent of the `exports` object, being the API that is to | ||
be exposed. | ||
|
||
Note that, because a secondary API may be named, it is possible to expose any | ||
number of such APIs from any module. | ||
|
||
## Accessing an API | ||
|
||
You access a secondary API by asking Sidedoor to obtain it for you, optionally | ||
providing the name of the API you want, and then simply calling it as you would | ||
a regularly exported API. For example, : | ||
|
||
var public_api = require('my_module'), | ||
test_api = sidedoor.get('my_module', 'test'); | ||
|
||
// Call the public API as normal | ||
public_api.doSomething(); | ||
|
||
// Call the secondary API obtained via Sidedoor | ||
test_api.testHelper(); | ||
|
||
The arguments to `get` are as follows: | ||
|
||
* _modpath_, the name or path of the module for which you want to access the API. | ||
This is the same as what you would pass to `require` to obtain the primary API. | ||
* _name_, the name of the secondary API you are accessing. If omitted, the default | ||
unnamed API is obtained. | ||
|
||
## License | ||
|
||
Sidedoor is licensed under the [MIT License](http://github.com/mfncooper/sidedoor/raw/master/LICENSE). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* Copyright (c) 2011 Yahoo! Inc. All rights reserved. | ||
*/ | ||
|
||
/* | ||
* A library that allows the controlled exposure of functions from a module | ||
* without polluting the primary exports mechanism. This is useful mainly | ||
* when exposing test-only functions, since those functions are made available | ||
* to tests while being withheld from the public module API. (The functions are | ||
* still available to any client, but an explicit effort must be made to obtain | ||
* them.) | ||
*/ | ||
|
||
var SIDEDOOR_KEY = "sidedoor", | ||
DEFAULT_GROUP = "default"; | ||
|
||
/* | ||
* Expose a set of functions from a module as a group. The group name may be | ||
* elided, in which case the functions are considered to be within a default | ||
* group. | ||
*/ | ||
function expose(mod, group, fns) { | ||
// Check for a defaulted group | ||
if (typeof group !== "string") { | ||
fns = group; | ||
group = DEFAULT_GROUP; | ||
} | ||
|
||
if (!mod.hasOwnProperty(SIDEDOOR_KEY)) { | ||
mod[SIDEDOOR_KEY] = {}; | ||
} | ||
mod[SIDEDOOR_KEY][group] = fns; | ||
} | ||
|
||
/* | ||
* Retrieve a set of functions from a module as a group. If the group name is | ||
* not specified, the default group is retrieved. If the group of functions | ||
* does not exist, undefined is returned. | ||
*/ | ||
function get(modname, group) { | ||
var mod = require.cache[require.resolve(modname)], | ||
fns = null; | ||
|
||
if (!mod) { | ||
require(modname); | ||
mod = require.cache[require.resolve(modname)]; | ||
} | ||
if (!mod) { | ||
throw new Error("bad stuff"); | ||
} | ||
|
||
if (mod.hasOwnProperty(SIDEDOOR_KEY)) { | ||
fns = mod[SIDEDOOR_KEY][group || DEFAULT_GROUP]; | ||
} | ||
|
||
return fns; | ||
} | ||
|
||
exports.expose = expose; | ||
exports.get = get; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"author": "Martin Cooper <mfncooper@gmail.com>", | ||
"name": "sidedoor", | ||
"description": "Exposing a secondary API for your Node.js modules", | ||
"version": "0.1.0", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/mfncooper/sidedoor.git" | ||
}, | ||
"bugs": { | ||
"url" : "http://github.com/mfncooper/sidedoor/issues" | ||
}, | ||
"main": "lib/sidedoor.js", | ||
"engines": { | ||
"node": ">=0.4.5" | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"nodeunit" : "0.6.x" | ||
}, | ||
"scripts": { | ||
"test": "test/run.js" | ||
}, | ||
"licenses" : [ | ||
{ | ||
"type" : "MIT", | ||
"url" : "http://github.com/mfncooper/mockery/raw/master/LICENSE" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
var sidedoor = require("../../lib/sidedoor.js"); | ||
|
||
function exposee() { | ||
return "-exposed-"; | ||
} | ||
|
||
sidedoor.expose(module, { | ||
exposee: exposee | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
var sidedoor = require("../../lib/sidedoor.js"); | ||
|
||
function group1fn() { | ||
return "-group1fn-exposed-"; | ||
} | ||
|
||
function group2fn() { | ||
return "-group2fn-exposed-"; | ||
} | ||
|
||
sidedoor.expose(module, "mygroup1", { | ||
group1fn: group1fn | ||
}); | ||
|
||
sidedoor.expose(module, "mygroup2", { | ||
group2fn: group2fn | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
var sidedoor = require("../../lib/sidedoor.js"); | ||
|
||
function exposee() { | ||
return "-exposed-"; | ||
} | ||
|
||
sidedoor.expose(module, "mygroup", { | ||
exposee: exposee | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
var sidedoor = require("../../lib/sidedoor.js"); | ||
|
||
function group1fn() { | ||
return "-group1fn-exposed-"; | ||
} | ||
|
||
function group2fn() { | ||
return "-group2fn-exposed-"; | ||
} | ||
|
||
sidedoor.expose(module, "mygroup1", { | ||
group1fn: group1fn | ||
}); | ||
|
||
sidedoor.expose(module, "mygroup2", { | ||
group2fn: group2fn | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/usr/bin/env node | ||
var test_reporter = require('nodeunit').reporters.nested; | ||
test_reporter.run(['./test/test-sidedoor.js']); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* | ||
* Copyright (c) 2011 Yahoo! Inc. All rights reserved. | ||
*/ | ||
|
||
var testCase = require('nodeunit').testCase, | ||
sidedoor = require('../lib/sidedoor'); | ||
|
||
function fixtureMod(name) { | ||
return "../test/fixtures/" + name; | ||
} | ||
|
||
module.exports = testCase({ | ||
|
||
"when nothing is exposed": testCase({ | ||
"getting the default group returns undefined": function (test) { | ||
var sd = sidedoor.get(fixtureMod("exposeNone")); | ||
test.strictEqual(sd, undefined); | ||
test.done(); | ||
}, | ||
"getting a named group returns undefined": function (test) { | ||
var sd = sidedoor.get(fixtureMod("exposeNone"), "mygroup"); | ||
test.strictEqual(sd, undefined); | ||
test.done(); | ||
} | ||
}), | ||
|
||
"when the default group is exposed": testCase({ | ||
"getting the default group returns the functions": function (test) { | ||
var sd = sidedoor.get(fixtureMod("exposeDefault")); | ||
test.notEqual(sd, undefined); | ||
test.equal(typeof sd, "object"); | ||
test.equal(typeof sd.exposee, "function"); | ||
test.equal(sd.exposee(), "-exposed-"); | ||
test.done(); | ||
}, | ||
"getting a named group returns undefined": function (test) { | ||
var sd = sidedoor.get(fixtureMod("exposeDefault"), "mygroup"); | ||
test.strictEqual(sd, undefined); | ||
test.done(); | ||
} | ||
}), | ||
|
||
"when a named group is exposed": testCase({ | ||
"getting the default group returns undefined": function (test) { | ||
var sd = sidedoor.get(fixtureMod("exposeNamed")); | ||
test.strictEqual(sd, undefined); | ||
test.done(); | ||
}, | ||
"getting the exposed group returns the functions": function (test) { | ||
var sd = sidedoor.get(fixtureMod("exposeNamed"), "mygroup"); | ||
test.notEqual(sd, null); | ||
test.equal(typeof sd, "object"); | ||
test.equal(typeof sd.exposee, "function"); | ||
test.equal(sd.exposee(), "-exposed-"); | ||
test.done(); | ||
}, | ||
"getting another named group returns undefined": function (test) { | ||
var sd = sidedoor.get(fixtureMod("exposeNamed"), "another"); | ||
test.strictEqual(sd, undefined); | ||
test.done(); | ||
} | ||
}), | ||
|
||
"when multiple groups are exposed": testCase({ | ||
"getting the default group returns undefined": function (test) { | ||
var sd = sidedoor.get(fixtureMod("exposeMultiple")); | ||
test.strictEqual(sd, undefined); | ||
test.done(); | ||
}, | ||
"getting an exposed group returns the functions": function (test) { | ||
var sd = sidedoor.get(fixtureMod("exposeMultiple"), "mygroup1"); | ||
test.notEqual(sd, null); | ||
test.equal(typeof sd, "object"); | ||
test.equal(typeof sd.group1fn, "function"); | ||
test.equal(sd.group1fn(), "-group1fn-exposed-"); | ||
test.done(); | ||
}, | ||
"getting another exposed group returns the functions": function (test) { | ||
var sd = sidedoor.get(fixtureMod("exposeMultiple"), "mygroup2"); | ||
test.notEqual(sd, null); | ||
test.equal(typeof sd, "object"); | ||
test.equal(typeof sd.group2fn, "function"); | ||
test.equal(sd.group2fn(), "-group2fn-exposed-"); | ||
test.done(); | ||
}, | ||
"getting another named group returns undefined": function (test) { | ||
var sd = sidedoor.get(fixtureMod("exposeMultiple"), "another"); | ||
test.strictEqual(sd, undefined); | ||
test.done(); | ||
}, | ||
"functions are exposed only in their assigned groups": function (test) { | ||
var sd1 = sidedoor.get(fixtureMod("exposeMultiple"), "mygroup1"), | ||
sd2 = sidedoor.get(fixtureMod("exposeMultiple"), "mygroup2"); | ||
test.notEqual(sd1, null); | ||
test.notEqual(sd2, null); | ||
test.equal(typeof sd1, "object"); | ||
test.equal(typeof sd2, "object"); | ||
test.equal(typeof sd1.group1fn, "function"); | ||
test.equal(typeof sd2.group2fn, "function"); | ||
test.equal(typeof sd1.group2fn, "undefined"); | ||
test.equal(typeof sd2.group1fn, "undefined"); | ||
test.done(); | ||
} | ||
}) | ||
|
||
}); |