Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion pinboard/locales/en-US/pinboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
"error": {
"no-url": "url must be provided in msg.payload",
"no-title": "msg.title must be provided",
"no-apitoken": "missing api token"
"no-apitoken": "missing api token",
"server-error": "server returned error response",
"invalid-json": "server returned invalid json"
}
}
}
44 changes: 31 additions & 13 deletions pinboard/pinboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ module.exports = function(RED) {
token: { type:"password" }
}
});


function PinboardOutNode(n) {
RED.nodes.createNode(this,n);
var node = this;
this.tags = n.tags;
this.toread = n.toread;
this.private = n.private;

this.user = RED.nodes.getNode(n.user);
if (this.user) {
this.on("input", function(msg) {
Expand All @@ -47,6 +47,8 @@ module.exports = function(RED) {
return;
}
var options = {
method: 'GET',
protocol: "https:",
hostname: "api.pinboard.in",
path: "/v1/posts/add?"+
"url="+encodeURIComponent(msg.payload)+
Expand All @@ -59,40 +61,56 @@ module.exports = function(RED) {
"Accept":"application/json"
}
}
// TODO: allow tags to be added by the message
// TODO: allow tags to be added by the message
if (node.tags) {
options.path += "&tags="+encodeURIComponent(node.tags)
options.path += "&tags="+encodeURIComponent(node.tags);
}
if (msg.description) {
options.path += "&extended="+encodeURIComponent(msg.description)
options.path += "&extended="+encodeURIComponent(msg.description);
}

node.status({fill:"blue",shape:"dot",text:"pinboard.status.saving"});

https.get(options, function(res) {
var req = https.request(options, function(res) {
var m = "";
res.on('data',function(chunk) {
m += chunk;
});
res.on('end',function() {
var result = JSON.parse(m);
var httpStatusMessage, result;
if (res.statusCode < 200 || res.statusCode > 299) {
httpStatusMessage = res.statusMessage || ('Server Error, Status ' + res.statusCode );
node.error(httpStatusMessage);
node.status({fill:"red",shape:"ring",text:RED._("pinboard.error.server-error")});
return;
}
try {
result = JSON.parse(m);
} catch (e) {
node.error(e.message, msg);
node.status({fill:"red",shape:"ring",text:RED._("pinboard.error.invalid.json")});
return;
}

if (result.result_code == "done") {
node.status({});
} else {
node.error(result.result_code,msg);
node.status({fill:"red",shape:"ring",text:result.result_code});
}
});
}).on('error',function(err) {
});
req.on('error',function(err) {
node.error(err,msg);
node.status({fill:"red",shape:"ring",text:err.code});
});

req.end();

});
} else {
this.error(RED._("pinboard.error.no-apitoken"));
}

}
RED.nodes.registerType("pinboard out",PinboardOutNode);
}
};
193 changes: 159 additions & 34 deletions test/pinboard/pinboard_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
**/

var should = require("should");
var sinon = require('sinon');
var pinboardNode = require("../../pinboard/pinboard.js");
var helper = require('../helper.js');
var nock = helper.nock;

describe('pinboard nodes', function() {

Expand All @@ -30,10 +32,10 @@ describe('pinboard nodes', function() {

describe('out node', function() {
it(' logs a warning if msg.payload is not set', function(done) {
helper.load(pinboardNode,
helper.load(pinboardNode,
[ {id:"inject", type:"helper", wires:[["pinboard"]]},
{id:"del-user", type:"pinboard-user", username:"Bob Jones"},
{id:"pinboard", type:"pinboard out", user:"del-user", private:true, tags:"testtag"}],
{id:"pinboard", type:"pinboard out", user:"del-user", private:true, tags:"testtag"}],
{
"del-user": {
password:"abcd1234"
Expand All @@ -43,30 +45,23 @@ describe('pinboard nodes', function() {
var inject = helper.getNode("inject");
var pinboard = helper.getNode("pinboard");
pinboard.should.have.property('id','pinboard');

var stub = sinon.stub(pinboard, 'error').callsFake(function(msg){
var expected = 'pinboard.error.no-url';
should.deepEqual(msg, expected);
stub.restore();
done();
});

inject.send({title:"test",description:"testdesc"});
setTimeout(function() {
try {
helper.log().called.should.be.true;
var logEvents = helper.log().args.filter(function(evt) {
return evt[0].type == "pinboard out";
});
logEvents.should.have.length(1);
logEvents[0][0].should.have.a.property("id",pinboard.id);
logEvents[0][0].should.have.a.property("type",pinboard.type);
logEvents[0][0].should.have.a.property("msg","pinboard.error.no-url");
done();
} catch(err) {
done(err);
}
},200);
});
});

it(' logs a warning if msg.title is not set', function(done) {
helper.load(pinboardNode,
helper.load(pinboardNode,
[ {id:"inject", type:"helper", wires:[["pinboard"]]},
{id:"del-user", type:"pinboard-user", username:"Bob Jones"},
{id:"pinboard", type:"pinboard out", user:"del-user", private:true, tags:"testtag"}],
{id:"pinboard", type:"pinboard out", user:"del-user", private:true, tags:"testtag"}],
{
"del-user": {
password:"abcd1234"
Expand All @@ -76,23 +71,153 @@ describe('pinboard nodes', function() {
var inject = helper.getNode("inject");
var pinboard = helper.getNode("pinboard");
pinboard.should.have.property('id','pinboard');

var stub = sinon.stub(pinboard, 'error').callsFake(function(msg){
var expected = 'pinboard.error.no-title';
should.deepEqual(msg, expected);
stub.restore();
done();
});

inject.send({payload:"foobar",description:"testdesc"});
setTimeout(function() {
try {
helper.log().called.should.be.true;
var logEvents = helper.log().args.filter(function(evt) {
return evt[0].type == "pinboard out";
});
logEvents.should.have.length(1);
logEvents[0][0].should.have.a.property("id",pinboard.id);
logEvents[0][0].should.have.a.property("type",pinboard.type);
logEvents[0][0].should.have.a.property("msg","pinboard.error.no-title");
done();
} catch(err) {
done(err);
});
});

it(' logs a warning if server status is not ok', function(done) {
if (!nock) { return; }
helper.load(pinboardNode,
[ {id:"inject", type:"helper", wires:[["pinboard"]]},
{id:"del-user", type:"pinboard-user", username:"Bob Jones"},
{id:"pinboard", type:"pinboard out", user:"del-user", private:true, tags:"testtag"}],
{
"del-user": {
token:"bob:abcd1234"
},
},
function() {

var scope = nock('https://api.pinboard.in:443')
.get('/v1/posts/add?url=http%3A%2F%2Fexample.com%2F&description=test%20link&auth_token=bob:abcd1234&format=json&shared=no&toread=no&tags=testtag')
.reply(401)

var inject = helper.getNode("inject");
var pinboard = helper.getNode("pinboard");
pinboard.should.have.property('id','pinboard');

var stub = sinon.stub(pinboard, 'error').callsFake(function(msg){
var expected = 'Server Error, Status 401';
should.deepEqual(msg, expected);
stub.restore();
done();
});

inject.send({payload:"http://example.com/",title:"test link"});

});
});

it(' logs a warning if server returns broken JSON', function(done) {
if (!nock) { return; }
helper.load(pinboardNode,
[ {id:"inject", type:"helper", wires:[["pinboard"]]},
{id:"del-user", type:"pinboard-user", username:"Bob Jones"},
{id:"pinboard", type:"pinboard out", user:"del-user", private:true, tags:"testtag"}],
{
"del-user": {
token:"bob:abcd1234"
},
},
function() {

var scope = nock('https://api.pinboard.in:443')
.get('/v1/posts/add?url=http%3A%2F%2Fexample.com%2F&description=test%20link&auth_token=bob:abcd1234&format=json&shared=no&toread=no&tags=testtag')
.reply(200, "}This is not Json{")

var inject = helper.getNode("inject");
var pinboard = helper.getNode("pinboard");
pinboard.should.have.property('id','pinboard');

var stub = sinon.stub(pinboard, 'error').callsFake(function(msg){
msg.should.containEql('Unexpected token }');
stub.restore();
done();
});

inject.send({payload:"http://example.com/",title:"test link"});

});
});

it(' logs a warning if server returns an error code', function(done) {
if (!nock) { return; }
helper.load(pinboardNode,
[ {id:"inject", type:"helper", wires:[["pinboard"]]},
{id:"del-user", type:"pinboard-user", username:"Bob Jones"},
{id:"pinboard", type:"pinboard out", user:"del-user", private:true, tags:"testtag"}],
{
"del-user": {
token:"bob:abcd1234"
},
},
function() {

var scope = nock('https://api.pinboard.in:443')
.get('/v1/posts/add?url=http%3A%2F%2Fexample.com%2F&description=test%20link&auth_token=bob:abcd1234&format=json&shared=no&toread=no&tags=testtag')
.reply(200, {result_code: 'internal error (testing)'})

var inject = helper.getNode("inject");
var pinboard = helper.getNode("pinboard");
pinboard.should.have.property('id','pinboard');

var stub = sinon.stub(pinboard, 'error').callsFake(function(msg){
var expected = 'internal error (testing)';
should.deepEqual(msg, expected);
stub.restore();
done();
});

inject.send({payload:"http://example.com/",title:"test link"});

});
});

it(' changes the status on successful request', function(done) {
if (!nock) { return; }
helper.load(pinboardNode,
[ {id:"inject", type:"helper", wires:[["pinboard"]]},
{id:"del-user", type:"pinboard-user", username:"Bob Jones"},
{id:"pinboard", type:"pinboard out", user:"del-user", private:true, tags:"testtag"}],
{
"del-user": {
token:"bob:abcd1234"
},
},
function() {

var scope = nock('https://api.pinboard.in:443')
.get('/v1/posts/add?url=http%3A%2F%2Fexample.com%2F&description=test%20link&auth_token=bob:abcd1234&format=json&shared=no&toread=no&tags=testtag')
.reply(200, {result_code: 'done'})

var inject = helper.getNode("inject");
var pinboard = helper.getNode("pinboard");
pinboard.should.have.property('id','pinboard');

var stub = sinon.stub(pinboard, 'status').callsFake(function(status){
switch (stub.callCount) {
case 1:
should.deepEqual(status, {fill:"blue",shape:"dot",text:"pinboard.status.saving"});
break;
case 2:
should.deepEqual(status, {});
stub.restore();
done();
}
},200);
});

inject.send({payload:"http://example.com/",title:"test link"});

});
});

});
});