Skip to content

Commit

Permalink
Updated README and unit tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
clintandrewhall committed Jun 20, 2011
1 parent 6ea6413 commit da6de56
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 32 deletions.
14 changes: 13 additions & 1 deletion lib/config-default.js
Expand Up @@ -3,10 +3,22 @@ module.exports = {
"accessTokenUrl" : "https://foursquare.com/oauth2/access_token",
"authenticateUrl" : "https://foursquare.com/oauth2/authenticate",
"apiUrl" : "https://api.foursquare.com/v2"
/*
This field will indicate which version of the Foursquare API you wish to call. If not specified or set to "LATEST",
it will use the latest version by setting the version number to today's date.
*/
//"version" : "LATEST",
/*
This field determines how this library handles endpoints that return results along with an error, (e.g. deprecations).
- If set to "WARN" (default), log4js will write a warning to the log, (NOTE: You must raise the
"node-foursquare.core" log4js level to WARN or lower in order to see these warnings.
- If set to "ERROR", the library will behave as though it encountered an ERROR and not return results.
*/
//"warnings" : "WARN"
},
"log4js" : {
"levels" : {
"node-foursquare" : "OFF",
"node-foursquare" : "INFO",
"node-foursquare.core" : "OFF",
"node-foursquare.Users" : "OFF",
"node-foursquare.Venues" : "OFF",
Expand Down
26 changes: 24 additions & 2 deletions lib/core.js
Expand Up @@ -64,6 +64,11 @@ module.exports = function(config) {
else {
parsedUrl.query.oauth_token = accessToken;
}

if(config.foursquare.version) {
parsedUrl.query.v = config.foursquare.version;
}

parsedUrl.search = "?" + qs.stringify(parsedUrl.query);
url = urlParser.format(parsedUrl);

Expand All @@ -79,7 +84,7 @@ module.exports = function(config) {
});
}

function extractData(status, result, callback) {
function extractData(url, status, result, callback) {
var json;
callback = callback || emptyCallback;

Expand All @@ -93,6 +98,19 @@ module.exports = function(config) {
}

if(json.meta && json.meta.code === 200) {
if(json.meta.errorType) {
var parsedUrl = urlParser.parse(url),
message = parsedUrl.pathname + " (" + json.meta.errorType + "): " + json.meta.errorDetail || "No detail provided.";
logger.debug("Warning level set to: " + config.foursquare.warnings);
if(config.foursquare.warnings === "ERROR") {
logger.error(message);
callback(new Error(message));
return;
}
else {
logger.warn(message);
}
}
if(json.response !== undefined) {
callback(null, json.response);
}
Expand All @@ -109,6 +127,10 @@ module.exports = function(config) {
callback(new Error("Response had no code: " + sys.inspect(json)));
}
}
else {
logger.error("There was an unexpected, fatal error calling Foursquare: the response was undefined or had no status code.");
callback(new Error("Foursquare had no response or status code."));
}
}

function callApi(path, accessToken, params, callback) {
Expand All @@ -131,7 +153,7 @@ module.exports = function(config) {
logger.trace("URL: " + url);
}
invokeApi(url, accessToken, function(error, status, result) {
extractData(status, result, callback);
extractData(url, status, result, callback);
});
}

Expand Down
51 changes: 33 additions & 18 deletions lib/node-foursquare.js
Expand Up @@ -8,7 +8,8 @@
*/
var qs = require('querystring'),
sys = require("sys"),
defaultConfig = require("./config-default");
defaultConfig = require("./config-default"),
log4js = require("log4js")();

function mergeDefaults(o1, o2) {
for(var p in o2) {
Expand All @@ -26,31 +27,45 @@ function mergeDefaults(o1, o2) {
return o1;
}

function configure(config) {
config = config || {};
mergeDefaults(config, defaultConfig);
return config;
}

module.exports = function(config) {
config = configure(config);

if(!config.foursquare.accessTokenUrl || !config.foursquare.apiUrl) {
throw new TypeError("Supplied configuration is invalid.");
function getLogger(config) {
log4js.configure(config.log4js);
return log4js.getLogger("node-foursquare");
}

var core = require("./core")(config),
log4js = require("log4js")();
log4js.configure(config.log4js);
function configure(config) {
config = config || {};
mergeDefaults(config, defaultConfig);

var logger = getLogger(config);

if(!config.secrets || !config.secrets.clientId || !config.secrets.clientSecret || !config.secrets.redirectUrl) {
logger.error("Client configuration not supplied; add config.secrets information, (clientId, clientSecret, redirectUrl).");
throw new Error("Configuration Error: Client information not supplied.");
}

var logger = log4js.getLogger("node-foursquare");
logger.trace("Configuration: " + sys.inspect(config));
if(!config.foursquare.accessTokenUrl || !config.foursquare.apiUrl) {
logger.error("Foursquare configuration not supplied; add config.foursquare information, (accessTokenUrl, apiUrl)");
throw new TypeError("Configuration Error: Foursquare information not supplied.");
}

if(!config.foursquare.version || config.foursquare.version === "LATEST") {
var d = new Date(), month = d.getMonth() + 1, date = d.getDate();
config.foursquare.version = d.getFullYear() + ((month < 10 ? "0" : "") + month) + ((date < 10 ? "0" : "") + date);
logger.warn("Foursquare API version not defined in configuration; defaulting to latest: " + config.foursquare.version);
}

if(!config.secrets || !config.secrets.clientId || !config.secrets.clientSecret || !config.secrets.redirectUrl) {
logger.fatal("Client configuration not supplied; add config.secrets information, (client_id, client_secret, redirect_uri).");
throw new Error("Client information not supplied.");
return config;
}

config = configure(config);

var logger = getLogger(config),
core = require("./core")(config);

logger.debug("Configuration: " + sys.inspect(config));

/**
* Exchange a user authorization code for an access token.
* @memberof module:node-foursquare
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,7 +1,7 @@
{
"name": "node-foursquare",
"description": "Fault-tolerant Foursquare API v2 wrapper for Node JS.",
"version": "0.1.0",
"version": "0.1.1",
"main": "index.js",
"keywords": [
"node-foursquare",
Expand Down
45 changes: 40 additions & 5 deletions readme.md
Expand Up @@ -20,6 +20,7 @@ Version History
* Ability to load single portions of the library, (e.g. only import Venues).
* Users - Leaderboard, Requests
* Venues - Categories, Explore
* v0.1.1 - Support for Foursquare API Version + Deprecation Warnings (via configuration).


Use
Expand Down Expand Up @@ -62,6 +63,41 @@ in Foursquare. Using Express, for example:
});
});

Foursquare API Version and Deprecation Warnings
-----------------------------------------------

Foursquare allows consumers to specify a "version" of their API to invoke, based on the date that version became active.
For example, passing a version string of "20110101" uses the API as of Jan 1, 2011. By default, this library will pass
a version of today's date.

To enable a different version of the API, add the following to configuration.

var config = {
...
"foursquare" : {
...
"version" : "20110101",
...
}
...
}

When using an older API, Foursquare will provide deprecation warnings if applicable. By default, this library will log
warnings to the log, (which will only be visible if logging for "node-foursquare" is turned on, see below).

You can configure this library to throw an error instead:

var config = {
...
"foursquare" : {
...
"warnings" : "ERROR",
...
}
...
}


Logging
-------

Expand All @@ -77,12 +113,8 @@ INFO (and higher) messages in Venues:
"levels" : {
"node-foursquare.Venues" : "INFO"
}
},
"secrets" : {
"clientId" : "CLIENT_ID",
"clientSecret" : "CLIENT_SECRET",
"redirectUrl" : "REDIRECT_URL"
}
...
}

var foursquare = require("node-foursquare")(config);
Expand Down Expand Up @@ -113,6 +145,9 @@ errors for protected endpoints.

If you hit [http://localhost:3000](http://localhost:3000), you'll be redirected for an authentication token.

If you hit [http://localhost:3000/deprecations](http://localhost:3000/deprecations), you'll test an endpoint with older versions and
errors vs. warnings.

Testing results will be logged to the console.

Documentation
Expand Down
2 changes: 1 addition & 1 deletion test.js
@@ -1,2 +1,2 @@
require("./test/node-foursquare-test");
console.log("Authenticated tests: http://localhost:3000/\nNon-authenticated tests: http://localhost:3000/test");
console.log("Authenticated tests: http://localhost:3000/\nNon-authenticated tests: http://localhost:3000/test\nDeprecation + Version tests: http://localhost:3000/deprecated");
50 changes: 46 additions & 4 deletions test/node-foursquare-test.js
Expand Up @@ -8,7 +8,6 @@ log4js.configure(config.log4js);

var logger = log4js.getLogger("node-foursquare-test"),
Foursquare = require('./../lib/node-foursquare')(config);
core = require("./../lib/core")(config);

function reportError(test, message) {
logger.error(test + " : \033[22;31mERROR: " + message + "\x1B[0m");
Expand Down Expand Up @@ -253,7 +252,7 @@ function TestSuite(accessToken) {
else {
try {
logger.trace(sys.inspect(data));
assert.ok(data.groups);
assert.ok(data.venues);
ok(test);
} catch (error) {
reportError(test, error);
Expand Down Expand Up @@ -586,6 +585,42 @@ function TestSuite(accessToken) {
}
}

function testDeprecated() {
var depConfig = require("./config").config;

depConfig.foursquare.version = "20110101";
depConfig.log4js.levels["node-foursquare"] = "INFO";
depConfig.log4js.levels["node-foursquare.core"] = "WARN";
depConfig.foursquare.warnings = "WARN";

var depFoursquare = Foursquare = require('./../lib/node-foursquare')(depConfig),
test = "(Version 20110101, WARN) Foursquare.Venues.search(40.7, -74)";

function run(error, data) {
if(error) {
reportError(test, error);
}
else {
try {
logger.trace(sys.inspect(data));
assert.ok(data.groups);
ok(test);
} catch (error) {
reportError(test, error);
}
}
}

depFoursquare.Venues.search("40.7", "-74", {}, null, function(error, data) {
run(error, data);
test = "(Version 20110101, ERROR) Foursquare.Venues.search(40.7, -74)",
depConfig.foursquare.warnings = "ERROR";
depFoursquare.Venues.search("40.7", "-74", {}, null, function(error, data) {
run(error, data);
});
});
}

// Using express was just faster... *sigh*
var app = express.createServer();

Expand All @@ -610,10 +645,17 @@ app.get('/callback', function (req, res) {
});
});

app.get("/deprecated", function(req, res) {
logger.info("\n\nTesting Version + Deprecations...\n");
testDeprecated();
res.send('<html></html><title>Refer to Console</title><body>Testing Version + Deprecations...</body></html>');
});

app.get("/test", function(req, res) {
var accessToken = req.query.token || null;
var accessToken = req.query.token || null, type = "Testing with" + (accessToken ? "" : "out") + " Authorization";
logger.info("\n\n" + type + "\n");
TestSuite(accessToken).execute();
res.send('<html></html><title>Testing...</title><body>Please check the console.</body></html>');
res.send('<html></html><title>Refer to Console</title><body>' + type + '...</body></html>');
});

app.listen(3000);

0 comments on commit da6de56

Please sign in to comment.