Merge pull request #2527 from ldidry/issue-1870-get-saved-revisions-count

Fixes #1870
This commit is contained in:
John McLear 2015-02-27 12:03:03 +00:00
commit 152f51aeab
5 changed files with 271 additions and 30 deletions

View File

@ -61,7 +61,7 @@ Portal submits content into new blog post
## Usage ## Usage
### API version ### API version
The latest version is `1.2.10` The latest version is `1.2.11`
The current version can be queried via /api. The current version can be queried via /api.
@ -402,6 +402,33 @@ returns the number of revisions of this pad
* `{code: 0, message:"ok", data: {revisions: 56}}` * `{code: 0, message:"ok", data: {revisions: 56}}`
* `{code: 1, message:"padID does not exist", data: null}` * `{code: 1, message:"padID does not exist", data: null}`
#### getSavedRevisionsCount(padID)
* API >= 1.2.11
returns the number of saved revisions of this pad
*Example returns:*
* `{code: 0, message:"ok", data: {savedRevisions: 42}}`
* `{code: 1, message:"padID does not exist", data: null}`
#### listSavedRevisions(padID)
* API >= 1.2.11
returns the list of saved revisions of this pad
*Example returns:*
* `{code: 0, message:"ok", data: {savedRevisions: [2, 42, 1337]}}`
* `{code: 1, message:"padID does not exist", data: null}`
#### saveRevision(padID [, rev])
* API >= 1.2.11
saves a revision
*Example returns:*
* `{code: 0, message:"ok", data: null}`
* `{code: 1, message:"padID does not exist", data: null}`
#### padUsersCount(padID) #### padUsersCount(padID)
* API >= 1 * API >= 1

View File

@ -517,6 +517,117 @@ exports.getRevisionsCount = function(padID, callback)
}); });
} }
/**
getSavedRevisionsCount(padID) returns the number of saved revisions of this pad
Example returns:
{code: 0, message:"ok", data: {savedRevisions: 42}}
{code: 1, message:"padID does not exist", data: null}
*/
exports.getSavedRevisionsCount = function(padID, callback)
{
//get the pad
getPadSafe(padID, true, function(err, pad)
{
if(ERR(err, callback)) return;
callback(null, {savedRevisions: pad.getSavedRevisionsNumber()});
});
}
/**
listSavedRevisions(padID) returns the list of saved revisions of this pad
Example returns:
{code: 0, message:"ok", data: {savedRevisions: [2, 42, 1337]}}
{code: 1, message:"padID does not exist", data: null}
*/
exports.listSavedRevisions = function(padID, callback)
{
//get the pad
getPadSafe(padID, true, function(err, pad)
{
if(ERR(err, callback)) return;
callback(null, {savedRevisions: pad.getSavedRevisionsList()});
});
}
/**
saveRevision(padID) returns the list of saved revisions of this pad
Example returns:
{code: 0, message:"ok", data: null}
{code: 1, message:"padID does not exist", data: null}
*/
exports.saveRevision = function(padID, rev, callback)
{
//check if rev is set
if(typeof rev == "function")
{
callback = rev;
rev = undefined;
}
//check if rev is a number
if(rev !== undefined && typeof rev != "number")
{
//try to parse the number
if(!isNaN(parseInt(rev)))
{
rev = parseInt(rev);
}
else
{
callback(new customError("rev is not a number", "apierror"));
return;
}
}
//ensure this is not a negativ number
if(rev !== undefined && rev < 0)
{
callback(new customError("rev is a negativ number","apierror"));
return;
}
//ensure this is not a float value
if(rev !== undefined && !is_int(rev))
{
callback(new customError("rev is a float value","apierror"));
return;
}
//get the pad
getPadSafe(padID, true, function(err, pad)
{
if(ERR(err, callback)) return;
//the client asked for a special revision
if(rev !== undefined)
{
//check if this is a valid revision
if(rev > pad.getHeadRevisionNumber())
{
callback(new customError("rev is higher than the head revision of the pad","apierror"));
return;
}
} else {
rev = pad.getHeadRevisionNumber();
}
authorManager.createAuthor('API', function(err, author) {
if(ERR(err, callback)) return;
pad.addSavedRevision(rev, author.authorID, 'Saved through API call');
callback();
});
});
}
/** /**
getLastEdited(padID) returns the timestamp of the last revision of the pad getLastEdited(padID) returns the timestamp of the last revision of the pad

View File

@ -54,6 +54,21 @@ Pad.prototype.getHeadRevisionNumber = function getHeadRevisionNumber() {
return this.head; return this.head;
}; };
Pad.prototype.getSavedRevisionsNumber = function getSavedRevisionsNumber() {
return this.savedRevisions.length;
};
Pad.prototype.getSavedRevisionsList = function getSavedRevisionsList() {
var savedRev = new Array();
for(var rev in this.savedRevisions){
savedRev.push(this.savedRevisions[rev].revNum);
}
savedRev.sort(function(a, b) {
return a - b;
});
return savedRev;
};
Pad.prototype.getPublicStatus = function getPublicStatus() { Pad.prototype.getPublicStatus = function getPublicStatus() {
return this.publicStatus; return this.publicStatus;
}; };

View File

@ -368,6 +368,9 @@ var version =
, "setHTML" : ["padID", "html"] , "setHTML" : ["padID", "html"]
, "getAttributePool" : ["padID"] , "getAttributePool" : ["padID"]
, "getRevisionsCount" : ["padID"] , "getRevisionsCount" : ["padID"]
, "getSavedRevisionsCount" : ["padID"]
, "listSavedRevisions" : ["padID"]
, "saveRevision" : ["padID", "rev"]
, "getRevisionChangeset" : ["padID", "rev"] , "getRevisionChangeset" : ["padID", "rev"]
, "getLastEdited" : ["padID"] , "getLastEdited" : ["padID"]
, "deletePad" : ["padID"] , "deletePad" : ["padID"]

View File

@ -48,33 +48,38 @@ describe('Permission', function(){
-> deletePad -- This gives us a guaranteed clear environment -> deletePad -- This gives us a guaranteed clear environment
-> createPad -> createPad
-> getRevisions -- Should be 0 -> getRevisions -- Should be 0
-> getHTML -- Should be the default pad text in HTML format -> getSavedRevisionsCount(padID) -- Should be 0
-> deletePad -- Should just delete a pad -> listSavedRevisions(padID) -- Should be an empty array
-> getHTML -- Should return an error -> getHTML -- Should be the default pad text in HTML format
-> createPad(withText) -> deletePad -- Should just delete a pad
-> getText -- Should have the text specified above as the pad text -> getHTML -- Should return an error
-> setText -> createPad(withText)
-> getText -- Should be the text set before -> getText -- Should have the text specified above as the pad text
-> getRevisions -- Should be 0 still? -> setText
-> padUsersCount -- Should be 0 -> getText -- Should be the text set before
-> getReadOnlyId -- Should be a value -> getRevisions -- Should be 0 still?
-> listAuthorsOfPad(padID) -- should be empty array? -> saveRevision
-> getLastEdited(padID) -- Should be when pad was made -> getSavedRevisionsCount(padID) -- Should be 0 still?
-> setText(padId) -> listSavedRevisions(padID) -- Should be an empty array still ?
-> getLastEdited(padID) -- Should be when setText was performed -> padUsersCount -- Should be 0
-> padUsers(padID) -- Should be when setText was performed -> getReadOnlyId -- Should be a value
-> listAuthorsOfPad(padID) -- should be empty array?
-> setText(padId, "hello world")
-> getLastEdited(padID) -- Should be when pad was made -> getLastEdited(padID) -- Should be when pad was made
-> getText(padId) -- Should be "hello world" -> setText(padId)
-> movePad(padID, newPadId) -- Should provide consistant pad data -> getLastEdited(padID) -- Should be when setText was performed
-> getText(newPadId) -- Should be "hello world" -> padUsers(padID) -- Should be when setText was performed
-> movePad(newPadID, originalPadId) -- Should provide consistant pad data
-> getText(originalPadId) -- Should be "hello world" -> setText(padId, "hello world")
-> getLastEdited(padID) -- Should not be 0 -> getLastEdited(padID) -- Should be when pad was made
-> setHTML(padID) -- Should fail on invalid HTML -> getText(padId) -- Should be "hello world"
-> setHTML(padID) *3 -- Should fail on invalid HTML -> movePad(padID, newPadId) -- Should provide consistant pad data
-> getHTML(padID) -- Should return HTML close to posted HTML -> getText(newPadId) -- Should be "hello world"
-> movePad(newPadID, originalPadId) -- Should provide consistant pad data
-> getText(originalPadId) -- Should be "hello world"
-> getLastEdited(padID) -- Should not be 0
-> setHTML(padID) -- Should fail on invalid HTML
-> setHTML(padID) *3 -- Should fail on invalid HTML
-> getHTML(padID) -- Should return HTML close to posted HTML
*/ */
@ -109,11 +114,35 @@ describe('getRevisionsCount', function(){
}); });
}) })
describe('getSavedRevisionsCount', function(){
it('gets saved revisions count of Pad', function(done) {
api.get(endPoint('getSavedRevisionsCount')+"&padID="+testPadId)
.expect(function(res){
if(res.body.code !== 0) throw new Error("Unable to get Saved Revisions Count");
if(res.body.data.savedRevisions !== 0) throw new Error("Incorrect Saved Revisions Count");
})
.expect('Content-Type', /json/)
.expect(200, done)
});
})
describe('listSavedRevisions', function(){
it('gets saved revision list of Pad', function(done) {
api.get(endPoint('listSavedRevisions')+"&padID="+testPadId)
.expect(function(res){
if(res.body.code !== 0) throw new Error("Unable to get Saved Revisions List");
if(!res.body.data.savedRevisions.equals([])) throw new Error("Incorrect Saved Revisions List");
})
.expect('Content-Type', /json/)
.expect(200, done)
});
})
describe('getHTML', function(){ describe('getHTML', function(){
it('get the HTML of Pad', function(done) { it('get the HTML of Pad', function(done) {
api.get(endPoint('getHTML')+"&padID="+testPadId) api.get(endPoint('getHTML')+"&padID="+testPadId)
.expect(function(res){ .expect(function(res){
if(res.body.data.html.length <= 1) throw new Error("Unable to get Revision Count"); if(res.body.data.html.length <= 1) throw new Error("Unable to get the HTML");
}) })
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
.expect(200, done) .expect(200, done)
@ -187,16 +216,50 @@ describe('getText', function(){
}) })
describe('getRevisionsCount', function(){ describe('getRevisionsCount', function(){
it('gets Revision Coutn of a Pad', function(done) { it('gets Revision Count of a Pad', function(done) {
api.get(endPoint('getRevisionsCount')+"&padID="+testPadId) api.get(endPoint('getRevisionsCount')+"&padID="+testPadId)
.expect(function(res){ .expect(function(res){
if(res.body.data.revisions !== 1) throw new Error("Unable to set text revision count") if(res.body.data.revisions !== 1) throw new Error("Unable to get text revision count")
}) })
.expect('Content-Type', /json/) .expect('Content-Type', /json/)
.expect(200, done) .expect(200, done)
}); });
}) })
describe('saveRevision', function(){
it('saves Revision', function(done) {
api.get(endPoint('saveRevision')+"&padID="+testPadId)
.expect(function(res){
if(res.body.code !== 0) throw new Error("Unable to save Revision");
})
.expect('Content-Type', /json/)
.expect(200, done)
});
})
describe('getSavedRevisionsCount', function(){
it('gets saved revisions count of Pad', function(done) {
api.get(endPoint('getSavedRevisionsCount')+"&padID="+testPadId)
.expect(function(res){
if(res.body.code !== 0) throw new Error("Unable to get Saved Revisions Count");
if(res.body.data.savedRevisions !== 1) throw new Error("Incorrect Saved Revisions Count");
})
.expect('Content-Type', /json/)
.expect(200, done)
});
})
describe('listSavedRevisions', function(){
it('gets saved revision list of Pad', function(done) {
api.get(endPoint('listSavedRevisions')+"&padID="+testPadId)
.expect(function(res){
if(res.body.code !== 0) throw new Error("Unable to get Saved Revisions List");
if(!res.body.data.savedRevisions.equals([1])) throw new Error("Incorrect Saved Revisions List");
})
.expect('Content-Type', /json/)
.expect(200, done)
});
})
describe('padUsersCount', function(){ describe('padUsersCount', function(){
it('gets User Count of a Pad', function(done) { it('gets User Count of a Pad', function(done) {
api.get(endPoint('padUsersCount')+"&padID="+testPadId) api.get(endPoint('padUsersCount')+"&padID="+testPadId)
@ -461,3 +524,25 @@ function generateLongText(){
} }
return text; return text;
} }
// Need this to compare arrays (listSavedRevisions test)
Array.prototype.equals = function (array) {
// if the other array is a falsy value, return
if (!array)
return false;
// compare lengths - can save a lot of time
if (this.length != array.length)
return false;
for (var i = 0, l=this.length; i < l; i++) {
// Check if we have nested arrays
if (this[i] instanceof Array && array[i] instanceof Array) {
// recurse into the nested arrays
if (!this[i].equals(array[i]))
return false;
} else if (this[i] != array[i]) {
// Warning - two different object instances will never be equal: {x:20} != {x:20}
return false;
}
}
return true;
}