Skip to content

Commit bd4e370

Browse files
Merge pull request #4 from christianbundy/euankdev
Escape args, add some tests
2 parents f001a2a + 871deb2 commit bd4e370

File tree

5 files changed

+162
-31
lines changed

5 files changed

+162
-31
lines changed

index.js

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,30 @@
33
var querystring = require('querystring');
44
var request = require('request');
55

6+
function encodeURIComponentArray(arr) {
7+
return arr.map(function(component) {
8+
return encodeURIComponent(component);
9+
});
10+
}
11+
612
var hn = {
7-
// make a request to the specified endpoint
8-
call: function (endpoint, cb) {
9-
var query = 'https://hn.algolia.com/api/v1/' + endpoint;
13+
// Make a request with the spicified uri component array
14+
// and query argument object. If the queryObj is omitted,
15+
// it will be assumed to be empty and the callback may be
16+
// there instead
17+
call: function (components, queryObj, cb) {
18+
if(!Array.isArray(components)) components = [components];
19+
if(typeof queryObj === 'function') {
20+
cb = queryObj;
21+
queryObj = {};
22+
}
23+
24+
var endpoint_parts = encodeURIComponentArray(components);
25+
var query = 'https://hn.algolia.com/api/v1/' + endpoint_parts.join('/');
26+
27+
var query_args = querystring.stringify(queryObj);
28+
if(query_args.length > 0) query += '?' + query_args;
29+
1030
request(query, function (error, response, body) {
1131
if (!error && response.statusCode != 200)
1232
error = response.statusCode;
@@ -23,93 +43,93 @@ var hn = {
2343

2444
// get popular/recent comments
2545
getComments: function (cb) {
26-
hn.call('search?tags=comment', cb);
46+
hn.call('search', {tags: 'comment'}, cb);
2747
},
2848
getLastComments: function (cb) {
29-
hn.call('search_by_date?tags=comment', cb);
49+
hn.call('search_by_date', {tags: 'comment'}, cb);
3050
},
3151

3252
// get popular/recent polls
3353
getPolls: function (cb) {
34-
hn.call('search?tags=poll', cb);
54+
hn.call('search', {tags: 'poll'}, cb);
3555
},
3656
getLastPolls: function (cb) {
37-
hn.call('search_by_date?tags=poll', cb);
57+
hn.call('search_by_date', {tags: 'poll'}, cb);
3858
},
3959

4060
// get popular/recent posts
4161
getPosts: function (cb) {
42-
hn.call('search?tags=(story,poll)', cb);
62+
hn.call('search', {tags: '(story,poll)'}, cb);
4363
},
4464
getLastPosts: function (cb) {
45-
hn.call('search_by_date?tags=(story,poll)', cb);
65+
hn.call('search_by_date', {tags: '(story,poll)'}, cb);
4666
},
4767

4868
// get popular/recent stories
4969
getStories: function (cb) {
50-
hn.call('search?tags=story', cb);
70+
hn.call('search', {tags: 'story'}, cb);
5171
},
5272
getLastStories: function (cb) {
53-
hn.call('search_by_date?tags=story', cb);
73+
hn.call('search_by_date', {tags: 'story'}, cb);
5474
},
5575

5676
// get unique post/comment
5777
getItem: function (id, cb) {
58-
hn.call('items/' + id, cb);
78+
hn.call(['items', id], cb);
5979
},
6080

6181
// get unique user
6282
getUser: function (username, cb) {
63-
hn.call('users/' + username, cb);
83+
hn.call(['users', username], cb);
6484
},
6585

6686
// get popular/recent user comments
6787
getUserComments: function (username, cb) {
68-
hn.call('search?tags=comment,author_' + username, cb);
88+
hn.call('search', {tags: 'comment,author_' + username}, cb);
6989
},
7090
getLastUserComments: function (username, cb) {
71-
hn.call('search_by_date?tags=comment,author_' + username, cb);
91+
hn.call('search_by_date', {tags: 'comment,author_' + username}, cb);
7292
},
7393

7494
// get popular/recent user polls
7595
getUserPolls: function (username, cb) {
76-
hn.call('search?tags=poll,author_' + username, cb);
96+
hn.call('search', {tags: 'poll,author_' + username}, cb);
7797
},
7898
getLastUserPolls: function (username, cb) {
79-
hn.call('search_by_date?tags=poll,author_' + username, cb);
99+
hn.call('search_by_date', {tags: 'poll,author_' + username}, cb);
80100
},
81101

82102
// get popular/recent user posts
83103
getUserPosts: function (username, cb) {
84-
hn.call('search?tags=(story,poll),author_' + username, cb);
104+
hn.call('search', {tags: '(story,poll),author_' + username}, cb);
85105
},
86106
getLastUserPosts: function (username, cb) {
87-
hn.call('search_by_date?tags=(story,poll),author_' + username, cb);
107+
hn.call('search_by_date', {tags: '(story,poll),author_' + username}, cb);
88108
},
89109

90110
// get popular/recent user stories
91111
getUserStories: function (username, cb) {
92-
hn.call('search?tags=story,author_' + username, cb);
112+
hn.call('search', {tags: 'story,author_' + username}, cb);
93113
},
94114
getLastUserStories: function (username, cb) {
95-
hn.call('search_by_date?tags=story,author_' + username, cb);
115+
hn.call('search_by_date', {tags: 'story,author_' + username}, cb);
96116
},
97117

98118

99119
// search popular/recent comments
100120
searchComments: function (query, cb) {
101-
hn.call('search?query=' + query + '&tags=comment', cb);
121+
hn.call('search', {query: query, tags: 'comment'}, cb);
102122
},
103123
searchLastComments: function (query, cb) {
104-
hn.call('search_by_date?query=' + query + '&tags=comment', cb);
124+
hn.call('search_by_date', {query: query, tags: 'comment'}, cb);
105125
},
106126

107127
// search popular/recent polls
108128
searchPolls: function (query, cb) {
109-
hn.call('search?query=' + query + '&tags=poll', cb);
129+
hn.call('search', {query: query, tags: 'poll'}, cb);
110130
},
111131
searchLastPolls: function (query, cb) {
112-
hn.call('search_by_date?query=' + query + '&tags=poll', cb);
132+
hn.call('search_by_date', {query: query, tags: 'poll'}, cb);
113133
},
114134

115135
// search popular/recent posts
@@ -122,21 +142,19 @@ var hn = {
122142

123143
// search popular/recent stories
124144
searchStories: function (query, cb) {
125-
hn.call('search?query=' + query + '&tags=story', cb);
145+
hn.call('search', {query: query, tags: 'story'}, cb);
126146
},
127147
searchLastStories: function (query, cb) {
128-
hn.call('search_by_date?query=' + query + '&tags=story', cb);
148+
hn.call('search_by_date', {query: query, tags: 'story'}, cb);
129149
},
130150

131151

132152
// search popular/recent
133153
search: function (obj, cb) {
134-
var params = querystring.stringify(obj);
135-
hn.call('search?' + params, cb);
154+
hn.call('search', obj, cb);
136155
},
137156
searchLast: function (obj, cb) {
138-
var params = querystring.stringify(obj);
139-
hn.call('search_by_date?' + params, cb);
157+
hn.call('search_by_date', obj, cb);
140158
}
141159
};
142160

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,10 @@
2626
"homepage": "https://github.com/christianbundy/node-hacker-news-api",
2727
"dependencies": {
2828
"request": "~2.34.0"
29+
},
30+
"devDependencies": {
31+
"chai": "*",
32+
"nock": "*",
33+
"mocha": "*"
2934
}
3035
}

test/fixtures/fixtures.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

test/fixtures/generate_fixtures.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
var https = require('https');
2+
var async = require('async');
3+
var request = require('request');
4+
var fs = require('fs');
5+
6+
var urls = [
7+
'/api/v1/search?tags=comment',
8+
'/api/v1/search_by_date?tags=comment',
9+
'/api/v1/search?tags=poll',
10+
'/api/v1/search_by_date?tags=poll',
11+
'/api/v1/search?tags=(story%2Cpoll)',
12+
'/api/v1/search_by_date?tags=(story%2Cpoll)',
13+
'/api/v1/search?tags=story',
14+
'/api/v1/search_by_date?tags=story',
15+
];
16+
17+
async.mapSeries(urls, function(item, next) {
18+
request.get('https://hn.algolia.com' + item, function(err, response, body) {
19+
next(err, {
20+
url: item,
21+
reply: JSON.parse(body)
22+
});
23+
});
24+
}, function(err, results) {
25+
if(err) {
26+
console.err("Bad news: " + err);
27+
process.exit();
28+
}
29+
fs.writeFileSync("./fixtures.json", JSON.stringify(results));
30+
console.log("Wrote fixtures.json!");
31+
});

test/test.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
var hn = require("./../index.js");
2+
var fs = require('fs');
3+
var expect = require('chai').expect;
4+
var nock = require('nock');
5+
6+
var fixtures = JSON.parse(fs.readFileSync(__dirname + "/fixtures/fixtures.json"));
7+
8+
var api = nock('https://hn.algolia.com').persist();
9+
fixtures.forEach(function(f) {
10+
console.log(f.url);
11+
api.get(f.url).reply(200, f.reply);
12+
});
13+
14+
15+
var slice = function(arr){ return Array.prototype.slice.call(arr); };
16+
17+
function crazy_curry(args, fn) {
18+
args = slice(arguments);
19+
fn = args.pop();
20+
21+
return function(innerArgs) {
22+
console.log(arguments[0]);
23+
innerArgs = slice(arguments);
24+
Array.prototype.push.apply(innerArgs, args);
25+
fn.apply(this, innerArgs);
26+
};
27+
}
28+
29+
30+
31+
describe('hn', function(){
32+
function verifyDataHasOneOfTags(err, data, tags, done) {
33+
if(err) {
34+
return done("Error");
35+
}
36+
expect(data).to.have.property('hits');
37+
data.hits.map(function(comment) {
38+
var intersection = tags.filter(function(n) {
39+
return comment._tags.indexOf(n) != -1;
40+
});
41+
expect(intersection).not.to.be.empty;
42+
});
43+
done();
44+
}
45+
46+
it('should get comments', function(done) {
47+
hn.getComments(crazy_curry(['comment'], done, verifyDataHasOneOfTags));
48+
});
49+
it('should get latest comments', function(done) {
50+
hn.getLastComments(crazy_curry(['comment'], done, verifyDataHasOneOfTags));
51+
});
52+
53+
54+
it('should get polls', function(done) {
55+
hn.getPolls(crazy_curry(['poll'], done, verifyDataHasOneOfTags));
56+
});
57+
it('should get latest polls', function(done) {
58+
hn.getLastPolls(crazy_curry(['poll'], done, verifyDataHasOneOfTags));
59+
});
60+
61+
62+
it('should get posts', function(done) {
63+
hn.getPosts(crazy_curry(['story', 'poll'], done, verifyDataHasOneOfTags));
64+
});
65+
it('should get latest posts', function(done) {
66+
hn.getLastPosts(crazy_curry(['story', 'poll'], done, verifyDataHasOneOfTags));
67+
});
68+
69+
70+
it('should get stories', function(done) {
71+
hn.getStories(crazy_curry(['story'], done, verifyDataHasOneOfTags));
72+
});
73+
it('should get latest stories', function(done) {
74+
hn.getLastStories(crazy_curry(['story'], done, verifyDataHasOneOfTags));
75+
});
76+
});

0 commit comments

Comments
 (0)