Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

phpunit tests converted to mocha/chai #140

Open
wants to merge 33 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
cfc8228
phpunit test v1 and v2 converted to mocha/chai
abaevbog May 19, 2023
d58206e
helper functions for api v3, annotation, atom and creator tests for v3
abaevbog May 22, 2023
0244f16
v3 collection, group, fullText and note test
abaevbog May 22, 2023
f4dfc10
v3 object test
abaevbog May 22, 2023
b30737f
leftover object tests, mappings, params tests
abaevbog May 23, 2023
aae33b1
previously skipped tests requiring citation or translation server
abaevbog May 23, 2023
878afef
file tests v2 and half of v3
abaevbog May 24, 2023
e8449db
the rest of file tests
abaevbog May 25, 2023
8b7804b
publication tests
abaevbog May 25, 2023
bf083e1
minor adjustments to prevent random 500 errors
abaevbog May 26, 2023
6af7367
more v3 tests
abaevbog May 26, 2023
9e746e0
removing work dir, removed unneeded data/ files
abaevbog May 26, 2023
339d923
notification, tag and version tests
abaevbog May 29, 2023
2f5ccd0
v3 itemTest
abaevbog May 30, 2023
755e133
some cleanup, proper retry logic when socket hangs
abaevbog May 30, 2023
319ce22
using node-config
abaevbog May 30, 2023
1ee44b1
removed inheritance from between api files and helpers
abaevbog May 30, 2023
41d5981
package.json
abaevbog May 30, 2023
4d7632c
changed 'Setup' for 'Before' and 'Wrapup' for 'After' in shared.js, g…
abaevbog May 30, 2023
e150cd1
removing retries, using 0-second delay instead
abaevbog May 31, 2023
ae270e5
minor cleanup, added missing comments, some tweaking with socker hanging
abaevbog Jun 1, 2023
0d653ed
using helper functions for statusForObject + removed unnecessary part…
abaevbog Jun 2, 2023
5e21351
initial pdf text extraction setup
abaevbog Jun 9, 2023
8e0936b
pdf text extraction test
abaevbog Jun 9, 2023
1976445
full-text tests with indexing function invoked locally
abaevbog Jun 12, 2023
d8f3427
items/unfiled and items/unfiled/tags tests
abaevbog Jun 23, 2023
2e7a853
?sort=editBy for group libraries
abaevbog Jun 23, 2023
d4465f2
test to rename tag for PR #150
abaevbog Jun 23, 2023
e7518c2
test for literal || escaping for tags PR #143
abaevbog Jun 23, 2023
c5b1a93
new annotation types test
abaevbog Jun 28, 2023
640caf4
minor cleanup, skip tests for PRs, missing tests
abaevbog Aug 21, 2023
8253f4d
skip annotation tags test for collections
abaevbog Aug 21, 2023
b2b562a
should_add_zero_integer_value_for_lastPageIndex
abaevbog Sep 22, 2023
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
765 changes: 765 additions & 0 deletions tests/remote_js/api2.js

Large diffs are not rendered by default.

933 changes: 933 additions & 0 deletions tests/remote_js/api3.js

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions tests/remote_js/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const fs = require('fs');

var config = {};

const data = fs.readFileSync('config.json');
config = JSON.parse(data);
config.timeout = 60000;
config.numOwnedGroups = 3;
config.numPublicGroups = 2;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the logic for why these are in here and not in config.json?

In any case, we should use the npm config package and move everything into a default.json5 file in config (like translation-server).

And then we could either do a find-and-replace to switch to the recommended access method or we could just stick to direct property access. get() would let us set values (e.g., rootUsername/rootPassword) to undefined in default.json to force them to be populated in a local.json, but since these are tests anyway, they'll just fail if something isn't configured properly, so maybe it's not worth the extra noise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing specific here. I think the config.ini used in phpunit did not have those fields, and they were set in some of the other php files. I was converting files one by one, so it just turned out that way.
Anyways, after my cleanup, I removed it all and setup the node-config with default.json5

module.exports = config;
35 changes: 35 additions & 0 deletions tests/remote_js/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"verbose": 1,
"syncURLPrefix": "http://dataserver/",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need this

"apiURLPrefix": "http://localhost/",
"rootUsername": "YtTnrHcWUC0FqP27xuaa",
"rootPassword": "esFEIngwxnyp1kuTrUpKpH72gEftHbkiWneoeimV",
"awsRegion": "us-east-1",
"s3Bucket": "zotero",
"awsAccessKey": "",
"awsSecretKey": "",
"filesystemStorage": 1,
"syncVersion": 9,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need this



"userID": 1,
"libraryID": 1,
"username": "testuser",
"password": "letmein",
"displayName": "testuser",
"emailPrimary": "test@test.com",
"emailSecondary": "test@test.com",
"ownedPrivateGroupID": 1,
"ownedPrivateGroupLibraryID": 1,
"ownedPrivateGroupName": "Test Group",


"userID2": 2,
"username2": "testuser2",
"password2": "letmein2",
"displayName2": "testuser2",
"ownedPrivateGroupID2": 0,
"ownedPrivateGroupLibraryID2": 0


}
6 changes: 6 additions & 0 deletions tests/remote_js/data/bad_string.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<p> </p>
<p style="margin-top: 0.18cm; margin-bottom: 0.18cm; line-height: 100%;" lang="es-ES"><br /><br /></p>
<p style="margin-top: 0.18cm; margin-bottom: 0.18cm; line-height: 100%;" lang="es-ES"><br /><br /></p>
<table border="1" cellspacing="0" cellpadding="7" width="614">
<colgroup><col width="598"></col> </colgroup>
<p style="margin-top: 0.18cm; margin-bottom: 0.18cm;" lang="en-US"><span style="font-family: Times New Roman,serif;"><span style="font-size: x-large;"><strong>test</strong></span></span></p>
Binary file added tests/remote_js/data/test.html.zip
Binary file not shown.
Binary file added tests/remote_js/data/test.pdf
Binary file not shown.
103 changes: 103 additions & 0 deletions tests/remote_js/groupsSetup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@

const config = require('./config');
const API3 = require('./api3.js');

const resetGroups = async () => {
let resetGroups = true;

let response = await API3.superGet(
`users/${config.userID}/groups`
);
let groups = await API3.getJSONFromResponse(response);
config.ownedPublicGroupID = null;
config.ownedPublicNoAnonymousGroupID = null;
config.ownedPrivateGroupID = null;
config.ownedPrivateGroupName = 'Private Test Group';
config.ownedPrivateGroupID2 = null;
let toDelete = [];
for (let group of groups) {
let data = group.data;
let id = data.id;
let type = data.type;
let owner = data.owner;
let libraryReading = data.libraryReading;

if (resetGroups) {
toDelete.push(id);
continue;
}

if (!config.ownedPublicGroupID
&& type == 'PublicOpen'
&& owner == config.userID
&& libraryReading == 'all') {
config.ownedPublicGroupID = id;
}
else if (!config.ownedPublicNoAnonymousGroupID
&& type == 'PublicClosed'
&& owner == config.userID
&& libraryReading == 'members') {
config.ownedPublicNoAnonymousGroupID = id;
}
else if (type == 'Private' && owner == config.userID && data.name == config.ownedPrivateGroupName) {
config.ownedPrivateGroupID = id;
}
else if (type == 'Private' && owner == config.userID2) {
config.ownedPrivateGroupID2 = id;
}
else {
toDelete.push(id);
}
}

if (!config.ownedPublicGroupID) {
config.ownedPublicGroupID = await API3.createGroup({
owner: config.userID,
type: 'PublicOpen',
libraryReading: 'all'
});
}
if (!config.ownedPublicNoAnonymousGroupID) {
config.ownedPublicNoAnonymousGroupID = await API3.createGroup({
owner: config.userID,
type: 'PublicClosed',
libraryReading: 'members'
});
}
if (!config.ownedPrivateGroupID) {
config.ownedPrivateGroupID = await API3.createGroup({
owner: config.userID,
name: "Private Test Group",
type: 'Private',
libraryReading: 'members',
fileEditing: 'members',
members: [
config.userID2
]
});
}
if (!config.ownedPrivateGroupID2) {
config.ownedPrivateGroupID2 = await API3.createGroup({
owner: config.userID2,
type: 'Private',
libraryReading: 'members',
fileEditing: 'members'
});
}
for (let groupID of toDelete) {
await API3.deleteGroup(groupID);
}

config.numOwnedGroups = 3;
config.numPublicGroups = 2;

for (let group of groups) {
if (!toDelete.includes(group.id)) {
await API3.groupClear(group.id);
}
}
};

module.exports = {
resetGroups
};
226 changes: 226 additions & 0 deletions tests/remote_js/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
const { JSDOM } = require("jsdom");
const chai = require('chai');
const assert = chai.assert;
const crypto = require('crypto');

class Helpers {
static isV3 = false;

static useV3 = () => {
this.isV3 = true;
};

static uniqueToken = () => {
const id = crypto.randomBytes(16).toString("hex");
const hash = crypto.createHash('md5').update(id).digest('hex');
return hash;
};

static uniqueID = (count = 8) => {
const chars = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Z'];
let result = "";
for (let i = 0; i < count; i++) {
result += chars[crypto.randomInt(chars.length)];
}
return result;
};

static namespaceResolver = (prefix) => {
let ns = {
atom: 'http://www.w3.org/2005/Atom',
zapi: 'http://zotero.org/ns/api',
zxfer: 'http://zotero.org/ns/transfer',
html: 'http://www.w3.org/1999/xhtml'
};
return ns[prefix] || null;
};

static xpathEval = (document, xpath, returnHtml = false, multiple = false, element = null) => {
const xpathData = document.evaluate(xpath, (element || document), this.namespaceResolver, 5, null);
if (!multiple && xpathData.snapshotLength != 1) {
throw new Error("No single xpath value fetched");
}
var node;
var result = [];
do {
node = xpathData.iterateNext();
if (node) {
result.push(node);
}
} while (node);

if (returnHtml) {
return multiple ? result : result[0];
}

return multiple ? result.map(el => el.innerHTML) : result[0].innerHTML;
};

static assertRegExp(exp, val) {
if (typeof exp == "string") {
exp = new RegExp(exp);
}
if (!exp.test(val)) {
throw new Error(`${val} does not match regular expression`);
}
}

static assertXMLEqual = (one, two) => {
const contentDom = new JSDOM(one);
const expectedDom = new JSDOM(two);
assert.equal(contentDom.window.document.innerHTML, expectedDom.window.document.innerHTML);
};

static assertStatusCode = (response, expectedCode, message) => {
try {
assert.equal(response.status, expectedCode);
if (message) {
assert.equal(response.data, message);
}
}
catch (e) {
console.log(response.data);
throw e;
}
};

static assertStatusForObject = (response, status, recordId, httpCode, message) => {
let body = response;
if (response.data) {
body = response.data;
}
try {
body = JSON.parse(body);
}
catch (e) { }
assert.include(['unchanged', 'failed', 'success'], status);

try {
//Make sure the recordId is in the right category - unchanged, failed, success
assert.property(body[status], recordId);
if (httpCode) {
assert.equal(body[status][recordId].code, httpCode);
}
if (message) {
assert.equal(body[status][recordId].message, message);
}
}
catch (e) {
console.log(response.data);
throw e;
}
};

static assertNumResults = (response, expectedResults) => {
const doc = new JSDOM(response.data, { url: "http://localhost/" });
const entries = this.xpathEval(doc.window.document, "//entry", false, true);
assert.equal(entries.length, expectedResults);
};

static assertTotalResults = (response, expectedResults) => {
const doc = new JSDOM(response.data, { url: "http://localhost/" });
const totalResults = this.xpathEval(doc.window.document, "//zapi:totalResults", false, true);
assert.equal(parseInt(totalResults[0]), expectedResults);
};

static assertContentType = (response, contentType) => {
assert.include(response?.headers['content-type'], contentType.toLowerCase());
};


//Assert codes
static assert200 = (response) => {
this.assertStatusCode(response, 200);
};

static assert201 = (response) => {
this.assertStatusCode(response, 201);
};

static assert204 = (response) => {
this.assertStatusCode(response, 204);
};

static assert300 = (response) => {
this.assertStatusCode(response, 300);
};

static assert302 = (response) => {
this.assertStatusCode(response, 302);
};

static assert400 = (response, message) => {
this.assertStatusCode(response, 400, message);
};

static assert401 = (response) => {
this.assertStatusCode(response, 401);
};

static assert403 = (response) => {
this.assertStatusCode(response, 403);
};

static assert412 = (response) => {
this.assertStatusCode(response, 412);
};

static assert428 = (response) => {
this.assertStatusCode(response, 428);
};

static assert404 = (response) => {
this.assertStatusCode(response, 404);
};

static assert405 = (response) => {
this.assertStatusCode(response, 405);
};

static assert500 = (response) => {
this.assertStatusCode(response, 500);
};

static assert400ForObject = (response, { index = 0, message = null } = {}) => {
this.assertStatusForObject(response, 'failed', index, 400, message);
};

static assert200ForObject = (response, { index = 0, message = null } = {}) => {
this.assertStatusForObject(response, 'success', index, message);
};

static assert404ForObject = (response, { index = 0, message = null } = {}) => {
this.assertStatusForObject(response, 'failed', index, 404, message);
};

static assert409ForObject = (response, { index = 0, message = null } = {}) => {
this.assertStatusForObject(response, 'failed', index, 409, message);
};

static assert412ForObject = (response, { index = 0, message = null } = {}) => {
this.assertStatusForObject(response, 'failed', index, 412, message);
};

static assert413ForObject = (response, { index = 0, message = null } = {}) => {
this.assertStatusForObject(response, 'failed', index, 413, message);
};

static assert428ForObject = (response, { index = 0, message = null } = {}) => {
this.assertStatusForObject(response, 'failed', index, 428, message);
};

static assertUnchangedForObject = (response, { index = 0, message = null } = {}) => {
this.assertStatusForObject(response, 'unchanged', index, null, message);
};

// Methods to help during conversion
static assertEquals = (one, two) => {
assert.equal(two, one);
};

static assertCount = (count, object) => {
assert.lengthOf(Object.keys(object), count);
};
}

module.exports = Helpers;
Loading