Browse Source

adds API tests

master
Christian Müller 9 years ago
parent
commit
7078589d7c
  1. 234
      api_spec.js
  2. 3
      package.json
  3. 6
      server.js
  4. 4
      storage.js

234
api_spec.js

@ -0,0 +1,234 @@
var frisby = require('frisby');
var md5 = require('md5');
frisby.create('Landing page')
.get('http://localhost:3000/')
.expectStatus(200)
.expectHeaderContains('content-type', 'text/html; charset=utf-8')
.expectBodyContains('Hassle-free')
.toss();
frisby.create('Open note page')
.get('http://localhost:3000/new')
.expectStatus(200)
.expectHeaderContains('content-type', 'text/html; charset=utf-8')
.expectBodyContains('Terms of Service')
.toss();
frisby.create('Open TOS')
.get('http://localhost:3000/TOS')
.expectStatus(200)
.expectHeaderContains('content-type', 'text/html; charset=utf-8')
.expectBodyContains('Site Terms of Use Modifications')
.toss();
frisby.create('Incurrect URL')
.get('http://localhost:3000/abcdef')
.expectStatus(404)
.expectBodyContains('Not found')
.toss();
frisby.create('Invalid posting')
.post('http://localhost:3000/note')
.expectStatus(400)
.expectHeaderContains('content-type', 'text/html; charset=utf-8')
.expectBodyContains('Bad request')
.toss();
let testNote = 'This is a test note';
frisby.create('Invalid posting 2')
.post('http://localhost:3000/note', {
action: 'POST',
note: testNote
})
.expectStatus(400)
.expectHeaderContains('content-type', 'text/html; charset=utf-8')
.expectBodyContains('Bad request')
.toss();
frisby.create('Invalid posting 3')
.post('http://localhost:3000/note', {
action: 'POST',
session: md5("new"),
signature: "assdss",
note: testNote
})
.expectStatus(400)
.expectHeaderContains('content-type', 'text/html; charset=utf-8')
.expectBodyContains('Signature mismatch')
.toss();
frisby.create('Valid posting')
.post('http://localhost:3000/note', {
action: 'POST',
session: md5("new"),
signature: md5(md5("new") + testNote),
password: '',
note: testNote
})
.expectStatus(302)
.expectBodyContains('Found. Redirecting to')
.expectHeaderContains('content-type', 'text/plain; charset=utf-8')
.after(function(err, res, body) {
let noteId = body.replace('Found. Redirecting to /', '');
frisby.create('Read posted note')
.get('http://localhost:3000/' + noteId)
.expectStatus(200)
.expectBodyContains(testNote)
.after((err, res, body) => {
frisby.create('Illegal note editing attempt with empty password')
.post('http://localhost:3000/note', {
id: noteId,
action: 'UPDATE',
session: md5("new"),
signature: md5(md5("new") + testNote+'!!!'),
note: testNote + '!!!',
password: ''
})
.expectStatus(400)
.expectBodyContains('Password is wrong')
.toss()
})
.after((err, res, body) => {
frisby.create('Illegal note editing attempt')
.post('http://localhost:3000/note', {
id: noteId,
action: 'UPDATE',
session: md5("new"),
signature: md5(md5("new") + testNote+'!!!'),
note: testNote + '!!!',
password: "aaabbb"
})
.expectStatus(400)
.expectBodyContains('Password is wrong')
.toss()
})
.toss()
})
.toss();
frisby.create('Valid posting, editing and removal')
.post('http://localhost:3000/note', {
action: 'POST',
session: md5("new"),
signature: md5(md5("new") + testNote),
password: 'aabbcc',
note: testNote
})
.expectStatus(302)
.expectBodyContains('Found. Redirecting to')
.expectHeaderContains('content-type', 'text/plain; charset=utf-8')
.after(function(err, res, body) {
var noteId = body.replace('Found. Redirecting to /', '');
frisby.create('Export posted note')
.get('http://localhost:3000/' + noteId + "/export")
.expectStatus(200)
.expectHeaderContains('content-type', 'text/plain; charset=utf-8')
.expectBodyContains(testNote)
.toss();
frisby.create('Read posted note')
.get('http://localhost:3000/' + noteId)
.expectStatus(200)
.expectBodyContains(testNote)
.expectHeaderContains('content-type', 'text/html; charset=utf-8')
.after((err, res, body) => {
frisby.create('Unauthorized note editing attempt')
.post('http://localhost:3000/note', {
id: noteId,
action: 'UPDATE',
session: md5("new"),
signature: md5(md5("new") + testNote+'!!!'),
note: testNote + '!!!',
password: "abbcc"
})
.expectStatus(400)
.expectBodyContains('Password is wrong')
.toss()
})
.after((err, res, body) => {
frisby.create('Valid note editing attempt')
.post('http://localhost:3000/note', {
id: noteId,
action: 'UPDATE',
session: md5("new"),
signature: md5(md5("new") + 'Changed!'),
note: 'Changed!',
password: "aabbcc"
})
.expectStatus(302)
.after((err, res, body) => {
frisby.create('Read changed note')
.get('http://localhost:3000/' + noteId)
.expectStatus(200)
.expectBodyContains('Changed!')
.toss();
})
.after((err, res, body) => {
frisby.create('Delete posted note')
.post('http://localhost:3000/note',{
id: noteId,
button: 'Delete',
action: 'UPDATE',
session: md5("new"),
signature: md5(md5("new") + 'Changed!'),
note: 'Changed!',
password: "aabbcc"
})
.expectStatus(200)
.expectBodyContains('Note deleted')
.toss();
})
.toss()
})
.toss()
frisby.create('Read stats of posted note')
.expectStatus(200)
.get('http://localhost:3000/' + noteId).toss()
frisby.create('Read stats of posted note')
.expectStatus(200)
.get('http://localhost:3000/' + noteId).toss()
frisby.create('Read stats of posted note')
.expectStatus(200)
.get('http://localhost:3000/' + noteId).toss()
frisby.create('Read stats of posted note')
.get('http://localhost:3000/' + noteId + '/stats')
.expectHeaderContains('content-type', 'text/html; charset=utf-8')
.expectStatus(200)
.expectBodyContains('Statistics')
.expectBodyContains('<tr><td>Views</td><td>4</td></tr>')
.toss();
})
.toss();
var tooLongNote = 'ABCD';
while (tooLongNote.length < 1024*200) tooLongNote += tooLongNote;
frisby.create('Invalid posting of too long note')
.post('http://localhost:3000/note', {
action: 'POST',
session: md5("new"),
signature: md5(md5("new") + testNote),
password: 'aabbcc',
note: tooLongNote
})
.expectStatus(400)
.expectHeaderContains('content-type', 'text/html; charset=utf-8')
.expectBodyContains('too large')
.toss();
frisby.create('Invalid update without id')
.post('http://localhost:3000/note', {
action: 'UPDATE',
session: md5("new"),
signature: md5(md5("new") + 'Any note'),
password: 'aabbcc',
note: 'Any note'
})
.expectStatus(400)
.expectHeaderContains('content-type', 'text/html; charset=utf-8')
.expectBodyContains('Wrong note ID')
.toss();

3
package.json

@ -6,7 +6,7 @@
"scripts": { "scripts": {
"start": "node server.js", "start": "node server.js",
"dev": "./node_modules/nodemon/bin/nodemon.js server.js", "dev": "./node_modules/nodemon/bin/nodemon.js server.js",
"test": "echo \"Error: no test specified\" && exit 1" "test": "jasmine-node ."
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -33,6 +33,7 @@
"sqlite3": "*" "sqlite3": "*"
}, },
"devDependencies": { "devDependencies": {
"frisby": "^0.8.5",
"nodemon": "^1.9.1" "nodemon": "^1.9.1"
} }
} }

6
server.js

@ -57,13 +57,14 @@ app.post('/note', (req, res) => {
id = body.id; id = body.id;
log(req.ip, "calls /note to", action, id); log(req.ip, "calls /note to", action, id);
var goToNote = note => res.redirect("/" + note.id); var goToNote = note => res.redirect("/" + note.id);
if (!note || session.indexOf(md5('edit/' + id)) != 0 && session.indexOf(md5('new')) != 0) if (!note || !session || session.indexOf(md5('edit/' + id)) != 0 && session.indexOf(md5('new')) != 0)
return sendResponse(res, 400, "Invalid session"); return sendResponse(res, 400, 'Bad request');
if (body.signature != md5(session + note.replace(/[\n\r]/g, ""))) if (body.signature != md5(session + note.replace(/[\n\r]/g, "")))
return sendResponse(res, 400, "Signature mismatch"); return sendResponse(res, 400, "Signature mismatch");
if (action == "POST") if (action == "POST")
storage.addNote(note, password).then(goToNote); storage.addNote(note, password).then(goToNote);
else { else {
if (!id) return sendResponse(res, 400, "Wrong note ID");
CACHE.del(id); CACHE.del(id);
if (body.button == "Delete") { if (body.button == "Delete") {
log("deleting note", id); log("deleting note", id);
@ -177,3 +178,4 @@ var updateBlackList = () => {
setInterval(updateBlackList, 60 * 60 * 1000) setInterval(updateBlackList, 60 * 60 * 1000)
updateBlackList(); updateBlackList();

4
storage.js

@ -45,7 +45,8 @@ module.exports.addNote = (note, password) => getFreeId().then(id => Note.create(
password: password password: password
})); }));
var passwordCheck = (note, password, callback) => (!note || note.password !== password) var passwordCheck = (note, password, callback) =>
(!note || note.password.length == 0 || note.password !== password)
? new Promise((resolve, reject) => reject({ message: "Password is wrong" })) ? new Promise((resolve, reject) => reject({ message: "Password is wrong" }))
: callback(); : callback();
@ -60,3 +61,4 @@ module.exports.updateNote = (id, password, text) =>
module.exports.deleteNote = (id, password) => module.exports.deleteNote = (id, password) =>
Note.findById(id).then(note => Note.findById(id).then(note =>
passwordCheck(note, password, () => note.destroy())); passwordCheck(note, password, () => note.destroy()));

Loading…
Cancel
Save