mirror of
https://github.com/ajayyy/SponsorBlockServer.git
synced 2025-12-25 00:48:22 +03:00
Merge branch 'master' of https://github.com/ajayyy/SponsorBlockServer into fullVideoLabels
This commit is contained in:
141
test/cases/addUserAsVIP.ts
Normal file
141
test/cases/addUserAsVIP.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import { HashedUserID } from "../../src/types/user.model";
|
||||
import { client } from "../utils/httpClient";
|
||||
import { db } from "../../src/databases/databases";
|
||||
import assert from "assert";
|
||||
|
||||
// helpers
|
||||
const checkUserVIP = (publicID: string) => db.prepare("get", `SELECT "userID" FROM "vipUsers" WHERE "userID" = ?`, [publicID]);
|
||||
|
||||
const adminPrivateUserID = "testUserId";
|
||||
const permVIP1 = "addVIP_permaVIPOne";
|
||||
const publicPermVIP1 = getHash(permVIP1) as HashedUserID;
|
||||
const permVIP2 = "addVIP_permaVIPTwo";
|
||||
const publicPermVIP2 = getHash(permVIP2) as HashedUserID;
|
||||
const permVIP3 = "addVIP_permaVIPThree";
|
||||
const publicPermVIP3 = getHash(permVIP3) as HashedUserID;
|
||||
|
||||
const endpoint = "/api/addUserAsVIP";
|
||||
const addUserAsVIP = (userID: string, enabled: boolean, adminUserID = adminPrivateUserID) => client({
|
||||
method: "POST",
|
||||
url: endpoint,
|
||||
params: {
|
||||
userID,
|
||||
adminUserID,
|
||||
enabled: String(enabled)
|
||||
}
|
||||
});
|
||||
|
||||
describe("addVIP test", function() {
|
||||
it("User should not already be VIP", (done) => {
|
||||
checkUserVIP(publicPermVIP1)
|
||||
.then(result => {
|
||||
assert.ok(!result);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should be able to add user as VIP", (done) => {
|
||||
addUserAsVIP(publicPermVIP1, true)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await checkUserVIP(publicPermVIP1);
|
||||
assert.ok(row);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should be able to add second user as VIP", (done) => {
|
||||
addUserAsVIP(publicPermVIP2, true)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await checkUserVIP(publicPermVIP2);
|
||||
assert.ok(row);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should return 403 with invalid adminID", (done) => {
|
||||
addUserAsVIP(publicPermVIP1, true, "Invalid_Admin_User_ID")
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should return 400 with missing adminID", (done) => {
|
||||
client({
|
||||
method: "POST",
|
||||
url: endpoint,
|
||||
params: {
|
||||
userID: publicPermVIP1,
|
||||
enabled: String(true)
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should return 400 with missing userID", (done) => {
|
||||
client({
|
||||
method: "POST",
|
||||
url: endpoint,
|
||||
params: {
|
||||
enabled: String(true),
|
||||
adminUserID: adminPrivateUserID
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should be able to remove VIP", (done) => {
|
||||
addUserAsVIP(publicPermVIP1, false)
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await checkUserVIP(publicPermVIP1);
|
||||
assert.ok(!row);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should remove VIP if enabled is false", (done) => {
|
||||
client({
|
||||
method: "POST",
|
||||
url: endpoint,
|
||||
params: {
|
||||
userID: publicPermVIP2,
|
||||
adminUserID: adminPrivateUserID,
|
||||
enabled: "invalid-text"
|
||||
}
|
||||
})
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await checkUserVIP(publicPermVIP2);
|
||||
assert.ok(!row);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should remove VIP if enabled is missing", (done) => {
|
||||
client({
|
||||
method: "POST",
|
||||
url: endpoint,
|
||||
params: {
|
||||
userID: publicPermVIP3,
|
||||
adminUserID: adminPrivateUserID
|
||||
}
|
||||
})
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const row = await checkUserVIP(publicPermVIP3);
|
||||
assert.ok(!row);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
189
test/cases/generateVerifyToken.ts
Normal file
189
test/cases/generateVerifyToken.ts
Normal file
@@ -0,0 +1,189 @@
|
||||
import assert from "assert";
|
||||
import { config } from "../../src/config";
|
||||
import axios from "axios";
|
||||
import { createAndSaveToken, TokenType } from "../../src/utils/tokenUtils";
|
||||
import MockAdapter from "axios-mock-adapter";
|
||||
let mock: MockAdapter;
|
||||
import * as patreon from "../mocks/patreonMock";
|
||||
import * as gumroad from "../mocks/gumroadMock";
|
||||
import { client } from "../utils/httpClient";
|
||||
import { validatelicenseKeyRegex } from "../../src/routes/verifyToken";
|
||||
|
||||
const generateEndpoint = "/api/generateToken";
|
||||
const getGenerateToken = (type: string, code: string | null, adminUserID: string | null) => client({
|
||||
url: `${generateEndpoint}/${type}`,
|
||||
params: { code, adminUserID }
|
||||
});
|
||||
|
||||
const verifyEndpoint = "/api/verifyToken";
|
||||
const getVerifyToken = (licenseKey: string | null) => client({
|
||||
url: verifyEndpoint,
|
||||
params: { licenseKey }
|
||||
});
|
||||
|
||||
let patreonLicense: string;
|
||||
let localLicense: string;
|
||||
const gumroadLicense = gumroad.generateLicense();
|
||||
|
||||
const extractLicenseKey = (data: string) => {
|
||||
const regex = /([A-Za-z0-9]{40})/;
|
||||
const match = data.match(regex);
|
||||
if (!match) throw new Error("Failed to extract license key");
|
||||
return match[1];
|
||||
};
|
||||
|
||||
describe("generateToken test", function() {
|
||||
|
||||
before(function() {
|
||||
mock = new MockAdapter(axios, { onNoMatch: "throwException" });
|
||||
mock.onPost("https://www.patreon.com/api/oauth2/token").reply(200, patreon.fakeOauth);
|
||||
});
|
||||
|
||||
after(function () {
|
||||
mock.restore();
|
||||
});
|
||||
|
||||
it("Should be able to create patreon token for active patron", function (done) {
|
||||
mock.onGet(/identity/).reply(200, patreon.activeIdentity);
|
||||
if (!config?.patreon) this.skip();
|
||||
getGenerateToken("patreon", "patreon_code", "").then(res => {
|
||||
patreonLicense = extractLicenseKey(res.data);
|
||||
assert.ok(validatelicenseKeyRegex(patreonLicense));
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should create patreon token for invalid patron", function (done) {
|
||||
mock.onGet(/identity/).reply(200, patreon.formerIdentityFail);
|
||||
if (!config?.patreon) this.skip();
|
||||
getGenerateToken("patreon", "patreon_code", "").then(res => {
|
||||
patreonLicense = extractLicenseKey(res.data);
|
||||
assert.ok(validatelicenseKeyRegex(patreonLicense));
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to create new local token", function (done) {
|
||||
createAndSaveToken(TokenType.local).then((licenseKey) => {
|
||||
assert.ok(validatelicenseKeyRegex(licenseKey));
|
||||
localLicense = licenseKey;
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 if missing code parameter", function (done) {
|
||||
getGenerateToken("patreon", null, "").then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 403 if missing adminuserID parameter", function (done) {
|
||||
getGenerateToken("local", "fake-code", null).then(res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 403 for invalid adminuserID parameter", function (done) {
|
||||
getGenerateToken("local", "fake-code", "fakeAdminID").then(res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
describe("verifyToken static tests", function() {
|
||||
it("Should fast reject invalid token", function (done) {
|
||||
getVerifyToken("00000").then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.ok(!res.data.allowed);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 if missing code token", function (done) {
|
||||
getVerifyToken(null).then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
describe("verifyToken mock tests", function() {
|
||||
|
||||
beforeEach(function() {
|
||||
mock = new MockAdapter(axios, { onNoMatch: "throwException" });
|
||||
mock.onPost("https://www.patreon.com/api/oauth2/token").reply(200, patreon.fakeOauth);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
mock.restore();
|
||||
});
|
||||
|
||||
it("Should accept current patron", function (done) {
|
||||
if (!config?.patreon) this.skip();
|
||||
mock.onGet(/identity/).reply(200, patreon.activeIdentity);
|
||||
getVerifyToken(patreonLicense).then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.ok(res.data.allowed);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should reject nonexistent patron", function (done) {
|
||||
if (!config?.patreon) this.skip();
|
||||
mock.onGet(/identity/).reply(200, patreon.invalidIdentity);
|
||||
getVerifyToken(patreonLicense).then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.ok(!res.data.allowed);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should accept qualitying former patron", function (done) {
|
||||
if (!config?.patreon) this.skip();
|
||||
mock.onGet(/identity/).reply(200, patreon.formerIdentitySucceed);
|
||||
getVerifyToken(patreonLicense).then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.ok(res.data.allowed);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should reject unqualitifed former patron", function (done) {
|
||||
if (!config?.patreon) this.skip();
|
||||
mock.onGet(/identity/).reply(200, patreon.formerIdentityFail);
|
||||
getVerifyToken(patreonLicense).then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.ok(!res.data.allowed);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should accept real gumroad key", function (done) {
|
||||
mock.onPost("https://api.gumroad.com/v2/licenses/verify").reply(200, gumroad.licenseSuccess);
|
||||
getVerifyToken(gumroadLicense).then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.ok(res.data.allowed);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should reject fake gumroad key", function (done) {
|
||||
mock.onPost("https://api.gumroad.com/v2/licenses/verify").reply(200, gumroad.licenseFail);
|
||||
getVerifyToken(gumroadLicense).then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.ok(!res.data.allowed);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should validate local license", function (done) {
|
||||
getVerifyToken(localLicense).then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.ok(res.data.allowed);
|
||||
done();
|
||||
}).catch(err => done(err));
|
||||
});
|
||||
});
|
||||
27
test/cases/getDaysSavedFormatted.ts
Normal file
27
test/cases/getDaysSavedFormatted.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import assert from "assert";
|
||||
import { client } from "../utils/httpClient";
|
||||
import sinon from "sinon";
|
||||
import { db } from "../../src/databases/databases";
|
||||
|
||||
const endpoint = "/api/getDaysSavedFormatted";
|
||||
|
||||
describe("getDaysSavedFormatted", () => {
|
||||
it("can get days saved", async () => {
|
||||
const result = await client({ url: endpoint });
|
||||
assert.ok(result.data.daysSaved >= 0);
|
||||
});
|
||||
|
||||
it("returns 0 days saved if no segments", async () => {
|
||||
const stub = sinon.stub(db, "prepare").resolves(undefined);
|
||||
const result = await client({ url: endpoint });
|
||||
assert.ok(result.data.daysSaved >= 0);
|
||||
stub.restore();
|
||||
});
|
||||
|
||||
it("returns days saved to 2 fixed points", async () => {
|
||||
const stub = sinon.stub(db, "prepare").resolves({ daysSaved: 1.23456789 });
|
||||
const result = await client({ url: endpoint });
|
||||
assert.strictEqual(result.data.daysSaved, "1.23");
|
||||
stub.restore();
|
||||
});
|
||||
});
|
||||
109
test/cases/getIP.ts
Normal file
109
test/cases/getIP.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
import sinon from "sinon";
|
||||
import { config } from "../../src/config";
|
||||
import assert from "assert";
|
||||
const mode = "production";
|
||||
let stub: sinon.SinonStub;
|
||||
let stub2: sinon.SinonStub;
|
||||
import { createRequest } from "../mocks/mockExpressRequest";
|
||||
import { getIP } from "../../src/utils/getIP";
|
||||
|
||||
const v4RequestOptions = {
|
||||
headers: {
|
||||
"x-forwarded-for": "127.0.1.1",
|
||||
"cf-connecting-ip": "127.0.1.2",
|
||||
"x-real-ip": "127.0.1.3",
|
||||
},
|
||||
ip: "127.0.1.5",
|
||||
socket: {
|
||||
remoteAddress: "127.0.1.4"
|
||||
}
|
||||
};
|
||||
const v6RequestOptions = {
|
||||
headers: {
|
||||
"x-forwarded-for": "[100::1]",
|
||||
"cf-connecting-ip": "[100::2]",
|
||||
"x-real-ip": "[100::3]",
|
||||
},
|
||||
ip: "[100::5]",
|
||||
socket: {
|
||||
remoteAddress: "[100::4]"
|
||||
}
|
||||
};
|
||||
const v4MockRequest = createRequest(v4RequestOptions);
|
||||
const v6MockRequest = createRequest(v6RequestOptions);
|
||||
|
||||
const expectedIP4 = {
|
||||
"X-Forwarded-For": "127.0.1.1",
|
||||
"Cloudflare": "127.0.1.2",
|
||||
"X-Real-IP": "127.0.1.3",
|
||||
"default": "127.0.1.4",
|
||||
};
|
||||
|
||||
const expectedIP6 = {
|
||||
"X-Forwarded-For": "[100::1]",
|
||||
"Cloudflare": "[100::2]",
|
||||
"X-Real-IP": "[100::3]",
|
||||
"default": "[100::4]",
|
||||
};
|
||||
|
||||
describe("getIP stubs", () => {
|
||||
before(() => stub = sinon.stub(config, "mode").value(mode));
|
||||
after(() => stub.restore());
|
||||
|
||||
it("Should return production mode if stub worked", (done) => {
|
||||
assert.strictEqual(config.mode, mode);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe("getIP array tests", () => {
|
||||
beforeEach(() => stub = sinon.stub(config, "mode").value(mode));
|
||||
afterEach(() => {
|
||||
stub.restore();
|
||||
stub2.restore();
|
||||
});
|
||||
|
||||
for (const [key, value] of Object.entries(expectedIP4)) {
|
||||
it(`Should return correct IPv4 from ${key}`, (done) => {
|
||||
stub2 = sinon.stub(config, "behindProxy").value(key);
|
||||
const ip = getIP(v4MockRequest);
|
||||
assert.strictEqual(config.behindProxy, key);
|
||||
assert.strictEqual(ip, value);
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(expectedIP6)) {
|
||||
it(`Should return correct IPv6 from ${key}`, (done) => {
|
||||
stub2 = sinon.stub(config, "behindProxy").value(key);
|
||||
const ip = getIP(v6MockRequest);
|
||||
assert.strictEqual(config.behindProxy, key);
|
||||
assert.strictEqual(ip, value);
|
||||
done();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe("getIP true tests", () => {
|
||||
before(() => stub = sinon.stub(config, "mode").value(mode));
|
||||
after(() => {
|
||||
stub.restore();
|
||||
stub2.restore();
|
||||
});
|
||||
|
||||
it(`Should return correct IPv4 from with bool true`, (done) => {
|
||||
stub2 = sinon.stub(config, "behindProxy").value(true);
|
||||
const ip = getIP(v4MockRequest);
|
||||
assert.strictEqual(config.behindProxy, "X-Forwarded-For");
|
||||
assert.strictEqual(ip, expectedIP4["X-Forwarded-For"]);
|
||||
done();
|
||||
});
|
||||
|
||||
it(`Should return correct IPv4 from with string true`, (done) => {
|
||||
stub2 = sinon.stub(config, "behindProxy").value("true");
|
||||
const ip = getIP(v4MockRequest);
|
||||
assert.strictEqual(config.behindProxy, "X-Forwarded-For");
|
||||
assert.strictEqual(ip, expectedIP4["X-Forwarded-For"]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -166,17 +166,77 @@ describe("getLockCategoriesByHash", () => {
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to get by actionType", (done) => {
|
||||
getLockCategories(fakeHash.substring(0,5), [ActionType.Full])
|
||||
it("should return 400 if invalid actionTypes", (done) => {
|
||||
client.get(`${endpoint}/aaaa`, { params: { actionTypes: 3 } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("should return 400 if invalid actionTypes JSON", (done) => {
|
||||
client.get(`${endpoint}/aaaa`, { params: { actionTypes: "{3}" } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to get single lock", (done) => {
|
||||
const videoID = "getLockHash2";
|
||||
const hash = getHash(videoID, 1);
|
||||
getLockCategories(hash.substring(0,6))
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const expected = [{
|
||||
videoID: "fakehash-2",
|
||||
hash: fakeHash,
|
||||
videoID,
|
||||
hash,
|
||||
categories: [
|
||||
"sponsor"
|
||||
"preview"
|
||||
],
|
||||
reason: "fake2-notshown"
|
||||
reason: "2-reason"
|
||||
}];
|
||||
assert.deepStrictEqual(res.data, expected);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to get by actionType not in array", (done) => {
|
||||
const videoID = "getLockHash2";
|
||||
const hash = getHash(videoID, 1);
|
||||
client.get(`${endpoint}/${hash.substring(0,6)}`, { params: { actionType: ActionType.Skip } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const expected = [{
|
||||
videoID,
|
||||
hash,
|
||||
categories: [
|
||||
"preview"
|
||||
],
|
||||
reason: "2-reason"
|
||||
}];
|
||||
assert.deepStrictEqual(res.data, expected);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to get by no actionType", (done) => {
|
||||
const videoID = "getLockHash2";
|
||||
const hash = getHash(videoID, 1);
|
||||
client.get(`${endpoint}/${hash.substring(0,6)}`)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const expected = [{
|
||||
videoID,
|
||||
hash,
|
||||
categories: [
|
||||
"preview"
|
||||
],
|
||||
reason: "2-reason"
|
||||
}];
|
||||
assert.deepStrictEqual(res.data, expected);
|
||||
done();
|
||||
|
||||
@@ -55,6 +55,45 @@ describe("getLockReason", () => {
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to get with actionTypes array", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "getLockReason", category: "selfpromo", actionTypes: '["full"]' } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const expected = [
|
||||
{ category: "selfpromo", locked: 1, reason: "selfpromo-reason", userID: vipUserID2, userName: vipUserName2 }
|
||||
];
|
||||
assert.deepStrictEqual(res.data, expected);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to get with actionType", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "getLockReason", category: "selfpromo", actionType: "full" } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const expected = [
|
||||
{ category: "selfpromo", locked: 1, reason: "selfpromo-reason", userID: vipUserID2, userName: vipUserName2 }
|
||||
];
|
||||
assert.deepStrictEqual(res.data, expected);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to get with actionType array", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "getLockReason", category: "selfpromo", actionType: ["full"] } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const expected = [
|
||||
{ category: "selfpromo", locked: 1, reason: "selfpromo-reason", userID: vipUserID2, userName: vipUserName2 }
|
||||
];
|
||||
assert.deepStrictEqual(res.data, expected);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to get empty locks", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "getLockReason", category: "intro" } })
|
||||
.then(res => {
|
||||
@@ -118,8 +157,10 @@ describe("getLockReason", () => {
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
it("should return 400 if no videoID specified", (done) => {
|
||||
describe("getLockReason 400", () => {
|
||||
it("Should return 400 with missing videoID", (done) => {
|
||||
client.get(endpoint)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
@@ -128,15 +169,37 @@ describe("getLockReason", () => {
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("should be able to get by actionType", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "getLockReason", actionType: "full" } })
|
||||
it("Should return 400 with invalid actionTypes ", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "valid-videoid", actionTypes: 3 } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const expected = [
|
||||
{ category: "selfpromo", locked: 1, reason: "sponsor-reason", userID: vipUserID2, userName: vipUserName2 },
|
||||
{ category: "sponsor", locked: 0, reason: "", userID: "", userName: "" }
|
||||
];
|
||||
partialDeepEquals(res.data, expected);
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 with invalid actionTypes JSON ", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "valid-videoid", actionTypes: "{3}" } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 with invalid categories", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "valid-videoid", categories: 3 } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 with invalid categories JSON", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "valid-videoid", categories: "{3}" } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
|
||||
@@ -2,22 +2,31 @@ import { db } from "../../src/databases/databases";
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import { deepStrictEqual } from "assert";
|
||||
import { client } from "../utils/httpClient";
|
||||
import assert from "assert";
|
||||
|
||||
// helpers
|
||||
const endpoint = "/api/getSavedTimeForUser";
|
||||
const getSavedTimeForUser = (userID: string) => client({
|
||||
url: endpoint,
|
||||
params: { userID }
|
||||
});
|
||||
|
||||
describe("getSavedTimeForUser", () => {
|
||||
const user1 = "getSavedTimeForUserUser";
|
||||
const user1 = "getSavedTimeForUser1";
|
||||
const user2 = "getSavedTimeforUser2";
|
||||
const [ start, end, views ] = [1, 11, 50];
|
||||
|
||||
before(async () => {
|
||||
const startOfQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", "views", "shadowHidden") VALUES';
|
||||
await db.prepare("run", `${startOfQuery}(?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
["getSavedTimeForUser", 1, 11, 2, "gstfu0", getHash(user1), 0, 50, 0]);
|
||||
["getSavedTimeForUser", start, end, 2, "getSavedTimeUUID0", getHash(user1), 0, views, 0]);
|
||||
return;
|
||||
});
|
||||
|
||||
it("Should be able to get a 200", (done) => {
|
||||
client.get(endpoint, { params: { userID: user1 } })
|
||||
it("Should be able to get a saved time", (done) => {
|
||||
getSavedTimeForUser(user1)
|
||||
.then(res => {
|
||||
// (end-start)*minute * views
|
||||
const savedMinutes = ((11-1)/60) * 50;
|
||||
const savedMinutes = ((end-start)/60) * views;
|
||||
const expected = {
|
||||
timeSaved: savedMinutes
|
||||
};
|
||||
@@ -26,4 +35,20 @@ describe("getSavedTimeForUser", () => {
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
it("Should return 404 if no submissions", (done) => {
|
||||
getSavedTimeForUser(user2)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 404);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
it("Should return 400 if no userID", (done) => {
|
||||
client({ url: endpoint })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch((err) => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -80,6 +80,67 @@ describe("getSearchSegments", () => {
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to filter by category with categories string", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "searchTest0", categories: `["selfpromo"]` } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const data = res.data;
|
||||
const segments = data.segments;
|
||||
assert.strictEqual(data.segmentCount, 1);
|
||||
assert.strictEqual(data.page, 0);
|
||||
assert.strictEqual(segments[0].UUID, "search-downvote");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to filter by category with categories array", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "searchTest0", category: ["selfpromo"] } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const data = res.data;
|
||||
const segments = data.segments;
|
||||
assert.strictEqual(data.segmentCount, 1);
|
||||
assert.strictEqual(data.page, 0);
|
||||
assert.strictEqual(segments[0].UUID, "search-downvote");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to filter by category with actionTypes JSON", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "searchTest5", actionTypes: `["mute"]` } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const data = res.data;
|
||||
assert.strictEqual(data.segmentCount, 1);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to filter by category with actionType array", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "searchTest5", actionType: ["mute"] } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const data = res.data;
|
||||
assert.strictEqual(data.segmentCount, 1);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to filter by category with actionType string", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "searchTest5", actionType: "mute" } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const data = res.data;
|
||||
assert.strictEqual(data.segmentCount, 1);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to filter by lock status", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "searchTest0", locked: false } })
|
||||
.then(res => {
|
||||
@@ -274,7 +335,8 @@ describe("getSearchSegments", () => {
|
||||
locked: 1,
|
||||
hidden: 0,
|
||||
shadowHidden: 0,
|
||||
userID: "searchTestUser"
|
||||
userID: "searchTestUser",
|
||||
description: ""
|
||||
};
|
||||
assert.deepStrictEqual(segment0, expected);
|
||||
done();
|
||||
|
||||
48
test/cases/getSearchSegments4xx.ts
Normal file
48
test/cases/getSearchSegments4xx.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { client } from "../utils/httpClient";
|
||||
import assert from "assert";
|
||||
|
||||
describe("getSearchSegments 4xx", () => {
|
||||
const endpoint = "/api/searchSegments";
|
||||
|
||||
it("Should return 400 if no videoID", (done) => {
|
||||
client.get(endpoint, { params: {} })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
const data = res.data;
|
||||
assert.strictEqual(data, "videoID not specified");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 if invalid categories", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "nullVideo", categories: 3 } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
const data = res.data;
|
||||
assert.strictEqual(data, "Categories parameter does not match format requirements.");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 if invalid actionTypes", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "nullVideo", actionTypes: 3 } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
const data = res.data;
|
||||
assert.strictEqual(data, "actionTypes parameter does not match format requirements.");
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 404 if no segments", (done) => {
|
||||
client.get(endpoint, { params: { videoID: "nullVideo", actionType: "chapter" } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 404);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
@@ -3,7 +3,7 @@ import { partialDeepEquals, arrayPartialDeepEquals } from "../utils/partialDeepE
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import { ImportMock, } from "ts-mock-imports";
|
||||
import * as YouTubeAPIModule from "../../src/utils/youtubeApi";
|
||||
import { YouTubeApiMock } from "../youtubeMock";
|
||||
import { YouTubeApiMock } from "../mocks/youtubeMock";
|
||||
import assert from "assert";
|
||||
import { client } from "../utils/httpClient";
|
||||
|
||||
@@ -581,4 +581,78 @@ describe("getSkipSegmentsByHash", () => {
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to get single segment with requiredSegments", (done) => {
|
||||
const requiredSegment1 = "fbf0af454059733c8822f6a4ac8ec568e0787f8c0a5ee915dd5b05e0d7a9a388";
|
||||
client.get(`${endpoint}/17bf?requiredSegment=${requiredSegment1}`)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const data = (res.data as Array<any>).sort((a, b) => a.videoID.localeCompare(b.videoID));
|
||||
assert.strictEqual(data.length, 1);
|
||||
const expected = [{
|
||||
segments: [{
|
||||
UUID: requiredSegment1
|
||||
}]
|
||||
}];
|
||||
assert.ok(partialDeepEquals(data, expected));
|
||||
assert.strictEqual(data[0].segments.length, 1);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 if categories are is number", (done) => {
|
||||
client.get(`${endpoint}/17bf?categories=3`)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 if actionTypes is number", (done) => {
|
||||
client.get(`${endpoint}/17bf?actionTypes=3`)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 if actionTypes are invalid json", (done) => {
|
||||
client.get(`${endpoint}/17bf?actionTypes={test}`)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 if requiredSegments is number", (done) => {
|
||||
client.get(`${endpoint}/17bf?requiredSegments=3`)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
|
||||
it("Should return 404 if requiredSegments is invalid json", (done) => {
|
||||
client.get(`${endpoint}/17bf?requiredSegments={test}`)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 if requiredSegments is not present", (done) => {
|
||||
client.get(`${endpoint}/17bf?requiredSegment=${fullCategoryVidHash}`)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 404);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ import assert from "assert";
|
||||
import { db } from "../../src/databases/databases";
|
||||
import { client } from "../utils/httpClient";
|
||||
import { config } from "../../src/config";
|
||||
import sinon from "sinon";
|
||||
let dbVersion: number;
|
||||
|
||||
describe("getStatus", () => {
|
||||
@@ -122,4 +123,16 @@ describe("getStatus", () => {
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return commit unkown if not present", (done) => {
|
||||
sinon.stub((global as any), "HEADCOMMIT").value(undefined);
|
||||
client.get(`${endpoint}/commit`)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(res.data, "test"); // commit should be test
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
sinon.restore();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -38,6 +38,15 @@ describe("getTopUsers", () => {
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 if undefined sortType provided", (done) => {
|
||||
client.get(endpoint)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to get by all sortTypes", (done) => {
|
||||
client.get(endpoint, { params: { sortType: 0 } })// minutesSaved
|
||||
.then(res => {
|
||||
|
||||
17
test/cases/getTotalStats.ts
Normal file
17
test/cases/getTotalStats.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import assert from "assert";
|
||||
import { client } from "../utils/httpClient";
|
||||
|
||||
const endpoint = "/api/getTotalStats";
|
||||
|
||||
describe("getTotalStats", () => {
|
||||
it("Can get total stats", async () => {
|
||||
const result = await client({ url: endpoint });
|
||||
const data = result.data;
|
||||
assert.ok(data?.userCount ?? true);
|
||||
assert.ok(data.activeUsers >= 0);
|
||||
assert.ok(data.apiUsers >= 0);
|
||||
assert.ok(data.viewCount >= 0);
|
||||
assert.ok(data.totalSubmissions >= 0);
|
||||
assert.ok(data.minutesSaved >= 0);
|
||||
});
|
||||
});
|
||||
@@ -21,6 +21,7 @@ describe("getUserInfo", () => {
|
||||
await db.prepare("run", sponsorTimesQuery, ["getUserInfo0", 0, 36000, 2,"uuid000009", getHash("getuserinfo_user_03"), 8, 10, "sponsor", "skip", 0]);
|
||||
await db.prepare("run", sponsorTimesQuery, ["getUserInfo3", 1, 11, 2, "uuid000006", getHash("getuserinfo_user_02"), 6, 10, "sponsor", "skip", 0]);
|
||||
await db.prepare("run", sponsorTimesQuery, ["getUserInfo4", 1, 11, 2, "uuid000010", getHash("getuserinfo_user_04"), 9, 10, "chapter", "chapter", 0]);
|
||||
await db.prepare("run", sponsorTimesQuery, ["getUserInfo5", 1, 11, 2, "uuid000011", getHash("getuserinfo_user_05"), 9, 10, "sponsor", "skip", 0]);
|
||||
|
||||
|
||||
const insertWarningQuery = 'INSERT INTO warnings ("userID", "issueTime", "issuerUserID", "enabled", "reason") VALUES (?, ?, ?, ?, ?)';
|
||||
@@ -264,6 +265,15 @@ describe("getUserInfo", () => {
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should throw 400 with invalid array", (done) => {
|
||||
client.get(endpoint, { params: { userID: "x", values: 123 } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done(); // pass
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 200 on userID not found", (done) => {
|
||||
client.get(endpoint, { params: { userID: "notused-userid" } })
|
||||
.then(res => {
|
||||
@@ -309,6 +319,30 @@ describe("getUserInfo", () => {
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to get permissions", (done) => {
|
||||
client.get(endpoint, { params: { userID: "getuserinfo_user_01", value: "permissions" } })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const expected = {
|
||||
permissions: {
|
||||
sponsor: true,
|
||||
selfpromo: true,
|
||||
exclusive_access: true,
|
||||
interaction: true,
|
||||
intro: true,
|
||||
outro: true,
|
||||
preview: true,
|
||||
music_offtopic: true,
|
||||
filler: true,
|
||||
poi_highlight: true,
|
||||
chapter: false,
|
||||
},
|
||||
};
|
||||
assert.ok(partialDeepEquals(res.data, expected));
|
||||
done(); // pass
|
||||
});
|
||||
});
|
||||
|
||||
it("Should ignore chapters for saved time calculations", (done) => {
|
||||
client.get(endpoint, { params: { userID: "getuserinfo_user_04" } })
|
||||
.then(res => {
|
||||
|
||||
76
test/cases/getUserInfoFree.ts
Normal file
76
test/cases/getUserInfoFree.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { db } from "../../src/databases/databases";
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import assert from "assert";
|
||||
import { client } from "../utils/httpClient";
|
||||
|
||||
describe("getUserInfo Free Chapters", () => {
|
||||
const endpoint = "/api/userInfo";
|
||||
|
||||
const newQualifyUserID = "getUserInfo-Free-newQualify";
|
||||
const vipQualifyUserID = "getUserInfo-Free-VIP";
|
||||
const repQualifyUserID = "getUserInfo-Free-RepQualify";
|
||||
const oldQualifyUserID = "getUserInfo-Free-OldQualify";
|
||||
const newNoQualityUserID = "getUserInfo-Free-newNoQualify";
|
||||
const postOldQualify = 1600000000000;
|
||||
|
||||
before(async () => {
|
||||
const sponsorTimesQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "actionType", "reputation", "shadowHidden") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
await db.prepare("run", sponsorTimesQuery, ["getUserInfoFree", 1, 2, 0, "uuid-guif-0", getHash(repQualifyUserID), postOldQualify, 0, "sponsor", "skip", 20, 0]);
|
||||
await db.prepare("run", sponsorTimesQuery, ["getUserInfoFree", 1, 2, 0, "uuid-guif-1", getHash(oldQualifyUserID), 0, 0, "sponsor", "skip", 0, 0]); // submit at epoch
|
||||
await db.prepare("run", sponsorTimesQuery, ["getUserInfoFree", 1, 2, 0, "uuid-guif-2", getHash(newQualifyUserID), postOldQualify, 0, "sponsor", "skip", 0, 0]);
|
||||
|
||||
await db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES (?)`, [getHash(vipQualifyUserID)]);
|
||||
});
|
||||
|
||||
const getUserInfo = (userID: string) => client.get(endpoint, { params: { userID, value: "freeChaptersAccess" } });
|
||||
|
||||
it("Should not get free access under new rule (newNoQualify)", (done) => {
|
||||
getUserInfo(newNoQualityUserID)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(res.data.freeChaptersAccess, false);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should get free access under new rule (newQualify)", (done) => {
|
||||
getUserInfo(newQualifyUserID)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(res.data.freeChaptersAccess, true);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should get free access (VIP)", (done) => {
|
||||
getUserInfo(vipQualifyUserID)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(res.data.freeChaptersAccess, true);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should get free access (rep)", (done) => {
|
||||
getUserInfo(repQualifyUserID)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(res.data.freeChaptersAccess, true);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should get free access (old)", (done) => {
|
||||
getUserInfo(oldQualifyUserID)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
assert.strictEqual(res.data.freeChaptersAccess, true);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
53
test/cases/getUsername.ts
Normal file
53
test/cases/getUsername.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import { client } from "../utils/httpClient";
|
||||
import assert from "assert";
|
||||
|
||||
// helpers
|
||||
const getUsername = (userID: string) => client({
|
||||
url: "/api/getUsername",
|
||||
params: { userID }
|
||||
});
|
||||
|
||||
const postSetUserName = (userID: string, username: string) => client({
|
||||
method: "POST",
|
||||
url: "/api/setUsername",
|
||||
params: {
|
||||
userID,
|
||||
username,
|
||||
}
|
||||
});
|
||||
|
||||
const userOnePrivate = "getUsername_0";
|
||||
const userOnePublic = getHash(userOnePrivate);
|
||||
const userOneUsername = "getUsername_username";
|
||||
|
||||
describe("getUsername test", function() {
|
||||
it("Should get back publicUserID if not set", (done) => {
|
||||
getUsername(userOnePrivate)
|
||||
.then(result => {
|
||||
assert.strictEqual(result.data.userName, userOnePublic);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should be able to get username after setting", (done) => {
|
||||
postSetUserName(userOnePrivate, userOneUsername)
|
||||
.then(async () => {
|
||||
const result = await getUsername(userOnePrivate);
|
||||
const actual = result.data.userName;
|
||||
assert.strictEqual(actual, userOneUsername);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should return 400 if no userID provided", (done) => {
|
||||
client({
|
||||
url: "/api/getUsername"
|
||||
})
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
62
test/cases/getViewsForUser.ts
Normal file
62
test/cases/getViewsForUser.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import { db } from "../../src/databases/databases";
|
||||
import { client } from "../utils/httpClient";
|
||||
import assert from "assert";
|
||||
|
||||
// helpers
|
||||
const endpoint = "/api/getViewsForUser";
|
||||
const getViewsForUser = (userID: string) => client({
|
||||
url: endpoint,
|
||||
params: { userID }
|
||||
});
|
||||
|
||||
const getViewUserOne = "getViewUser1";
|
||||
const userOneViewsFirst = 30;
|
||||
const userOneViewsSecond = 0;
|
||||
|
||||
const getViewUserTwo = "getViewUser2";
|
||||
const userTwoViews = 0;
|
||||
|
||||
const getViewUserThree = "getViewUser3";
|
||||
|
||||
|
||||
describe("getViewsForUser", function() {
|
||||
before(() => {
|
||||
const insertSponsorTimeQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "actionType", "videoDuration", "shadowHidden", "hashedVideoID") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
db.prepare("run", insertSponsorTimeQuery, ["getViewUserVideo", 0, 1, 0, "getViewUserVideo0", getHash(getViewUserOne), 0, userOneViewsFirst, "sponsor", "skip", 0, 0, "getViewUserVideo"]);
|
||||
db.prepare("run", insertSponsorTimeQuery, ["getViewUserVideo", 0, 1, 0, "getViewUserVideo1", getHash(getViewUserOne), 0, userOneViewsSecond, "sponsor", "skip", 0, 0, "getViewUserVideo"]);
|
||||
db.prepare("run", insertSponsorTimeQuery, ["getViewUserVideo", 0, 1, 0, "getViewUserVideo2", getHash(getViewUserTwo), 0, userTwoViews, "sponsor", "skip", 0, 0, "getViewUserVideo"]);
|
||||
});
|
||||
it("Should get back views for user one", (done) => {
|
||||
getViewsForUser(getViewUserOne)
|
||||
.then(result => {
|
||||
assert.strictEqual(result.data.viewCount, userOneViewsFirst + userOneViewsSecond);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should get back views for user two", (done) => {
|
||||
getViewsForUser(getViewUserTwo)
|
||||
.then(result => {
|
||||
assert.strictEqual(result.data.viewCount, userTwoViews);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should get 404 if no submissions", (done) => {
|
||||
getViewsForUser(getViewUserThree)
|
||||
.then(result => {
|
||||
assert.strictEqual(result.status, 404);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("Should return 400 if no userID provided", (done) => {
|
||||
client({ url: endpoint })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
252
test/cases/lockCategoriesHttp.ts
Normal file
252
test/cases/lockCategoriesHttp.ts
Normal file
@@ -0,0 +1,252 @@
|
||||
import assert from "assert";
|
||||
import { client } from "../utils/httpClient";
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import { db } from "../../src/databases/databases";
|
||||
import { UserID } from "../../src/types/user.model";
|
||||
import { Category, VideoID } from "../../src/types/segments.model";
|
||||
|
||||
interface LockCategory {
|
||||
category: Category,
|
||||
reason: string,
|
||||
videoID: VideoID,
|
||||
userID: UserID
|
||||
}
|
||||
const lockVIPUser = "lockCategoriesHttpVIPUser";
|
||||
const lockVIPUserHash = getHash(lockVIPUser);
|
||||
const endpoint = "/api/lockCategories";
|
||||
const checkLockCategories = (videoID: string): Promise<LockCategory[]> => db.prepare("all", 'SELECT * FROM "lockCategories" WHERE "videoID" = ?', [videoID]);
|
||||
|
||||
|
||||
const goodResponse = (): any => ({
|
||||
videoID: "test-videoid",
|
||||
userID: "not-vip-test-userid",
|
||||
categories: ["sponsor"],
|
||||
actionTypes: ["skip"]
|
||||
});
|
||||
|
||||
describe("POST lockCategories HTTP submitting", () => {
|
||||
before(async () => {
|
||||
const insertVipUserQuery = 'INSERT INTO "vipUsers" ("userID") VALUES (?)';
|
||||
await db.prepare("run", insertVipUserQuery, [lockVIPUserHash]);
|
||||
});
|
||||
|
||||
it("Should update the database version when starting the application", async () => {
|
||||
const version = (await db.prepare("get", "SELECT key, value FROM config where key = ?", ["version"])).value;
|
||||
assert.ok(version > 1);
|
||||
});
|
||||
|
||||
it("should be able to add poi type category by type skip", (done) => {
|
||||
const videoID = "add-record-poi";
|
||||
client.post(endpoint, {
|
||||
videoID,
|
||||
userID: lockVIPUser,
|
||||
categories: ["poi_highlight"],
|
||||
actionTypes: ["skip"]
|
||||
})
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
checkLockCategories(videoID)
|
||||
.then(result => {
|
||||
assert.strictEqual(result.length, 1);
|
||||
assert.strictEqual(result[0], "poi_highlight");
|
||||
});
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should not add lock of invalid type", (done) => {
|
||||
const videoID = "add_invalid_type";
|
||||
client.post(endpoint, {
|
||||
videoID,
|
||||
userID: lockVIPUser,
|
||||
categories: ["future_unused_invalid_type"],
|
||||
actionTypes: ["skip"]
|
||||
})
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
checkLockCategories(videoID)
|
||||
.then(result => {
|
||||
assert.strictEqual(result.length, 0);
|
||||
});
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
describe("DELETE lockCategories 403/400 tests", () => {
|
||||
it(" Should return 400 for no data", (done) => {
|
||||
client.delete(endpoint, {})
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 for no categories", (done) => {
|
||||
const json: any = {
|
||||
videoID: "test",
|
||||
userID: "test",
|
||||
categories: [],
|
||||
};
|
||||
client.delete(endpoint, json)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 for no userID", (done) => {
|
||||
const json: any = {
|
||||
videoID: "test",
|
||||
userID: null,
|
||||
categories: ["sponsor"],
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 for no videoID", (done) => {
|
||||
const json: any = {
|
||||
videoID: null,
|
||||
userID: "test",
|
||||
categories: ["sponsor"],
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 for invalid category array", (done) => {
|
||||
const json = {
|
||||
videoID: "test",
|
||||
userID: "test",
|
||||
categories: {},
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 for bad format categories", (done) => {
|
||||
const json = {
|
||||
videoID: "test",
|
||||
userID: "test",
|
||||
categories: "sponsor",
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 403 if user is not VIP", (done) => {
|
||||
const json = {
|
||||
videoID: "test",
|
||||
userID: "test",
|
||||
categories: [
|
||||
"sponsor",
|
||||
],
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
describe("manual DELETE/POST lockCategories 400 tests", () => {
|
||||
it("DELETE Should return 400 for no data", (done) => {
|
||||
client.delete(endpoint, { data: {} })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("POST Should return 400 for no data", (done) => {
|
||||
client.post(endpoint, {})
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("DELETE Should return 400 for bad format categories", (done) => {
|
||||
const data = goodResponse();
|
||||
data.categories = "sponsor";
|
||||
client.delete(endpoint, { data })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("POST Should return 400 for bad format categories", (done) => {
|
||||
const data = goodResponse();
|
||||
data.categories = "sponsor";
|
||||
client.post(endpoint, data)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("DELETE Should return 403 if user is not VIP", (done) => {
|
||||
const data = goodResponse();
|
||||
client.delete(endpoint, { data })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
it("POST Should return 403 if user is not VIP", (done) => {
|
||||
const data = goodResponse();
|
||||
client.post(endpoint, data)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
describe("array of DELETE/POST lockCategories 400 tests", () => {
|
||||
for (const key of [ "videoID", "userID", "categories" ]) {
|
||||
for (const method of ["DELETE", "POST"]) {
|
||||
it(`${method} - Should return 400 for invalid ${key}`, (done) => {
|
||||
const data = goodResponse();
|
||||
data[key] = null;
|
||||
client(endpoint, { data, method })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -266,106 +266,6 @@ describe("lockCategoriesRecords", () => {
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 for missing params", (done) => {
|
||||
client.post(endpoint, {})
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 for no categories", (done) => {
|
||||
const json: any = {
|
||||
videoID: "test",
|
||||
userID: "test",
|
||||
categories: [],
|
||||
};
|
||||
client.post(endpoint, json)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 for no userID", (done) => {
|
||||
const json: any = {
|
||||
videoID: "test",
|
||||
userID: null,
|
||||
categories: ["sponsor"],
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 for no videoID", (done) => {
|
||||
const json: any = {
|
||||
videoID: null,
|
||||
userID: "test",
|
||||
categories: ["sponsor"],
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 object categories", (done) => {
|
||||
const json = {
|
||||
videoID: "test",
|
||||
userID: "test",
|
||||
categories: {},
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 bad format categories", (done) => {
|
||||
const json = {
|
||||
videoID: "test",
|
||||
userID: "test",
|
||||
categories: "sponsor",
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 403 if user is not VIP", (done) => {
|
||||
const json = {
|
||||
videoID: "test",
|
||||
userID: "test",
|
||||
categories: [
|
||||
"sponsor",
|
||||
],
|
||||
};
|
||||
|
||||
client.post(endpoint, json)
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to delete a lockCategories record", (done) => {
|
||||
const videoID = "delete-record";
|
||||
const json = {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { partialDeepEquals, arrayDeepEquals } from "../utils/partialDeepEquals";
|
||||
import { db } from "../../src/databases/databases";
|
||||
import { ImportMock } from "ts-mock-imports";
|
||||
import * as YouTubeAPIModule from "../../src/utils/youtubeApi";
|
||||
import { YouTubeApiMock } from "../youtubeMock";
|
||||
import { YouTubeApiMock } from "../mocks/youtubeMock";
|
||||
import assert from "assert";
|
||||
import { client } from "../utils/httpClient";
|
||||
import { Feature } from "../../src/types/user.model";
|
||||
|
||||
@@ -187,10 +187,34 @@ describe("shadowBanUser", () => {
|
||||
})
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const videoRow = await getShadowBanSegmentCategory(userID, 1);
|
||||
const videoRow = await getShadowBanSegmentCategory(userID, 0);
|
||||
const shadowRow = await getShadowBan(userID);
|
||||
assert.ok(shadowRow); // ban still exists
|
||||
assert.strictEqual(videoRow.length, 1); // videos should be hidden
|
||||
assert.strictEqual(videoRow.length, 0); // videos should be hidden
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should be able to un-shadowban user to restore old submissions", (done) => {
|
||||
const userID = "shadowBanned4";
|
||||
client({
|
||||
method: "POST",
|
||||
url: endpoint,
|
||||
params: {
|
||||
userID,
|
||||
adminUserID: VIPuserID,
|
||||
enabled: false,
|
||||
categories: `["sponsor"]`,
|
||||
unHideOldSubmissions: true
|
||||
}
|
||||
})
|
||||
.then(async res => {
|
||||
assert.strictEqual(res.status, 200);
|
||||
const videoRow = await getShadowBanSegmentCategory(userID, 0);
|
||||
const shadowRow = await getShadowBan(userID);
|
||||
assert.ok(!shadowRow); // ban still exists
|
||||
assert.strictEqual(videoRow.length, 1); // videos should be visible
|
||||
assert.strictEqual(videoRow[0].category, "sponsor");
|
||||
done();
|
||||
})
|
||||
|
||||
48
test/cases/shadowBanUser4xx.ts
Normal file
48
test/cases/shadowBanUser4xx.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { db } from "../../src/databases/databases";
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import assert from "assert";
|
||||
import { client } from "../utils/httpClient";
|
||||
|
||||
const endpoint = "/api/shadowBanUser";
|
||||
|
||||
const postShadowBan = (params: Record<string, string>) => client({
|
||||
method: "POST",
|
||||
url: endpoint,
|
||||
params
|
||||
});
|
||||
|
||||
describe("shadowBanUser 4xx", () => {
|
||||
const VIPuserID = "shadow-ban-4xx-vip";
|
||||
|
||||
before(async () => {
|
||||
await db.prepare("run", `INSERT INTO "vipUsers" ("userID") VALUES(?)`, [getHash(VIPuserID)]);
|
||||
});
|
||||
|
||||
it("Should return 400 if no adminUserID", (done) => {
|
||||
const userID = "shadowBanned";
|
||||
postShadowBan({ userID })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 400 if no userID", (done) => {
|
||||
postShadowBan({ adminUserID: VIPuserID })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 400);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it("Should return 403 if not authorized", (done) => {
|
||||
postShadowBan({ adminUserID: "notVIPUserID", userID: "shadowBanned" })
|
||||
.then(res => {
|
||||
assert.strictEqual(res.status, 403);
|
||||
done();
|
||||
})
|
||||
.catch(err => done(err));
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
import assert from "assert";
|
||||
import { partialDeepEquals } from "../utils/partialDeepEquals";
|
||||
import { partialDeepEquals, mixedDeepEquals } from "../utils/partialDeepEquals";
|
||||
|
||||
describe("Test utils ", () => {
|
||||
it("objectContain", () => {
|
||||
@@ -135,4 +135,45 @@ describe("Test utils ", () => {
|
||||
}
|
||||
), "Did not match partial child array");
|
||||
});
|
||||
it("mixedDeepEquals exists", () => {
|
||||
assert(!mixedDeepEquals({
|
||||
name: "lorem",
|
||||
values: [{
|
||||
name: "ipsum",
|
||||
}],
|
||||
child: {
|
||||
name: "dolor",
|
||||
},
|
||||
ignore: true
|
||||
}, {
|
||||
name: "lorem",
|
||||
values: [{
|
||||
name: "ipsum",
|
||||
}],
|
||||
child: {
|
||||
name: "dolor",
|
||||
},
|
||||
ignore: false
|
||||
}));
|
||||
});
|
||||
it("mixedDeepEquals noProperty", () => {
|
||||
assert(!mixedDeepEquals({
|
||||
name: "lorem",
|
||||
values: [{
|
||||
name: "ipsum",
|
||||
}],
|
||||
child: {
|
||||
name: "dolor",
|
||||
}
|
||||
}, {
|
||||
name: "lorem",
|
||||
values: [{
|
||||
name: "ipsum",
|
||||
}],
|
||||
child: {
|
||||
name: "dolor",
|
||||
},
|
||||
ignore: false
|
||||
}));
|
||||
});
|
||||
});
|
||||
50
test/cases/tokenUtils.ts
Normal file
50
test/cases/tokenUtils.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import assert from "assert";
|
||||
import { config } from "../../src/config";
|
||||
import axios from "axios";
|
||||
import * as tokenUtils from "../../src/utils/tokenUtils";
|
||||
import MockAdapter from "axios-mock-adapter";
|
||||
import { validatelicenseKeyRegex } from "../../src/routes/verifyToken";
|
||||
let mock: MockAdapter;
|
||||
import * as patreon from "../mocks/patreonMock";
|
||||
|
||||
const validateToken = validatelicenseKeyRegex;
|
||||
|
||||
describe("tokenUtils test", function() {
|
||||
before(function() {
|
||||
mock = new MockAdapter(axios, { onNoMatch: "throwException" });
|
||||
mock.onPost("https://www.patreon.com/api/oauth2/token").reply(200, patreon.fakeOauth);
|
||||
mock.onGet(/identity/).reply(200, patreon.activeIdentity);
|
||||
});
|
||||
|
||||
it("Should be able to create patreon token", function (done) {
|
||||
if (!config?.patreon) this.skip();
|
||||
tokenUtils.createAndSaveToken(tokenUtils.TokenType.patreon, "test_code").then((licenseKey) => {
|
||||
assert.ok(validateToken(licenseKey));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should be able to create local token", (done) => {
|
||||
tokenUtils.createAndSaveToken(tokenUtils.TokenType.local).then((licenseKey) => {
|
||||
assert.ok(validateToken(licenseKey));
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should be able to get patreon identity", function (done) {
|
||||
if (!config?.patreon) this.skip();
|
||||
tokenUtils.getPatreonIdentity("fake_access_token").then((result) => {
|
||||
assert.deepEqual(result, patreon.activeIdentity);
|
||||
done();
|
||||
});
|
||||
});
|
||||
it("Should be able to refresh token", function (done) {
|
||||
if (!config?.patreon) this.skip();
|
||||
tokenUtils.refreshToken(tokenUtils.TokenType.patreon, "fake-licence-Key", "fake_refresh_token").then((result) => {
|
||||
assert.strictEqual(result, true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
after(function () {
|
||||
mock.restore();
|
||||
});
|
||||
});
|
||||
@@ -3,10 +3,9 @@ import assert from "assert";
|
||||
import { config } from "../../src/config";
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
|
||||
|
||||
describe("userCounter", () => {
|
||||
it("Should return 200", (done) => {
|
||||
if (!config.userCounterURL) return done(); // skip if no userCounterURL is set
|
||||
it("Should return 200", function (done) {
|
||||
if (!config.userCounterURL) this.skip(); // skip if no userCounterURL is set
|
||||
axios.request({
|
||||
method: "POST",
|
||||
baseURL: config.userCounterURL,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { db, privateDB } from "../../src/databases/databases";
|
||||
import { getHash } from "../../src/utils/getHash";
|
||||
import { ImportMock } from "ts-mock-imports";
|
||||
import * as YouTubeAPIModule from "../../src/utils/youtubeApi";
|
||||
import { YouTubeApiMock } from "../youtubeMock";
|
||||
import { YouTubeApiMock } from "../mocks/youtubeMock";
|
||||
import assert from "assert";
|
||||
import { client } from "../utils/httpClient";
|
||||
import { arrayDeepEquals } from "../utils/partialDeepEquals";
|
||||
|
||||
@@ -1,23 +1,24 @@
|
||||
import express from "express";
|
||||
import { config } from "../src/config";
|
||||
import { Server } from "http";
|
||||
import { UserCounter } from "./mocks/UserCounter";
|
||||
|
||||
const app = express();
|
||||
|
||||
app.post("/ReportChannelWebhook", (req, res) => {
|
||||
app.post("/webhook/ReportChannel", (req, res) => {
|
||||
res.sendStatus(200);
|
||||
});
|
||||
|
||||
app.post("/FirstTimeSubmissionsWebhook", (req, res) => {
|
||||
app.post("/webhook/FirstTimeSubmissions", (req, res) => {
|
||||
res.sendStatus(200);
|
||||
});
|
||||
|
||||
app.post("/CompletelyIncorrectReportWebhook", (req, res) => {
|
||||
app.post("/webhook/CompletelyIncorrectReport", (req, res) => {
|
||||
res.sendStatus(200);
|
||||
});
|
||||
|
||||
// Testing NeuralBlock
|
||||
app.post("/NeuralBlockRejectWebhook", (req, res) => {
|
||||
app.post("/webhook/NeuralBlockReject", (req, res) => {
|
||||
res.sendStatus(200);
|
||||
});
|
||||
|
||||
@@ -47,6 +48,9 @@ app.post("/CustomWebhook", (req, res) => {
|
||||
res.sendStatus(200);
|
||||
});
|
||||
|
||||
// mocks
|
||||
app.use("/UserCounter", UserCounter);
|
||||
|
||||
export function createMockServer(callback: () => void): Server {
|
||||
return app.listen(config.mockPort, callback);
|
||||
}
|
||||
|
||||
11
test/mocks/UserCounter.ts
Normal file
11
test/mocks/UserCounter.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Router } from "express";
|
||||
export const UserCounter = Router();
|
||||
|
||||
UserCounter.post("/api/v1/addIP", (req, res) => {
|
||||
res.sendStatus(200);
|
||||
});
|
||||
UserCounter.get("/api/v1/userCount", (req, res) => {
|
||||
res.send({
|
||||
userCount: 100
|
||||
});
|
||||
});
|
||||
22
test/mocks/gumroadMock.ts
Normal file
22
test/mocks/gumroadMock.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
export const licenseSuccess = {
|
||||
success: true,
|
||||
uses: 4,
|
||||
purchase: {}
|
||||
};
|
||||
|
||||
export const licenseFail = {
|
||||
success: false,
|
||||
message: "That license does not exist for the provided product."
|
||||
};
|
||||
|
||||
|
||||
const subCode = (length = 8) => {
|
||||
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
let result = "";
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += characters[(Math.floor(Math.random() * characters.length))];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export const generateLicense = (): string => `${subCode()}-${subCode()}-${subCode()}-${subCode()}`;
|
||||
33
test/mocks/mockExpressRequest.ts
Normal file
33
test/mocks/mockExpressRequest.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
const nullStub = (): any => null;
|
||||
|
||||
export const createRequest = (options: any) => ({
|
||||
app: {},
|
||||
baseUrl: "",
|
||||
body: {},
|
||||
cookies: {},
|
||||
fresh: true,
|
||||
headers: {},
|
||||
hostname: "example.com",
|
||||
ip: "",
|
||||
ips: [],
|
||||
method: "GET",
|
||||
originalUrl: "/",
|
||||
params: {},
|
||||
path: "/",
|
||||
protocol: "https",
|
||||
query: {},
|
||||
route: {},
|
||||
secure: true,
|
||||
signedCookies: {},
|
||||
stale: false,
|
||||
subdomains: [],
|
||||
xhr: true,
|
||||
accepts: nullStub(),
|
||||
acceptsCharsets: nullStub(),
|
||||
acceptsEncodings: nullStub(),
|
||||
acceptsLanguages: nullStub(),
|
||||
get: nullStub(),
|
||||
is: nullStub(),
|
||||
range: nullStub(),
|
||||
...options
|
||||
});
|
||||
59
test/mocks/patreonMock.ts
Normal file
59
test/mocks/patreonMock.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
export const activeIdentity = {
|
||||
data: {},
|
||||
links: {},
|
||||
included: [
|
||||
{
|
||||
attributes: {
|
||||
is_monthly: true,
|
||||
currently_entitled_amount_cents: 100,
|
||||
patron_status: "active_patron",
|
||||
},
|
||||
id: "id",
|
||||
type: "campaign"
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
export const invalidIdentity = {
|
||||
data: {},
|
||||
links: {},
|
||||
included: [{}],
|
||||
};
|
||||
|
||||
export const formerIdentitySucceed = {
|
||||
data: {},
|
||||
links: {},
|
||||
included: [
|
||||
{
|
||||
attributes: {
|
||||
is_monthly: true,
|
||||
campaign_lifetime_support_cents: 500,
|
||||
patron_status: "former_patron",
|
||||
},
|
||||
id: "id",
|
||||
type: "campaign"
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
export const formerIdentityFail = {
|
||||
data: {},
|
||||
links: {},
|
||||
included: [
|
||||
{
|
||||
attributes: {
|
||||
is_monthly: true,
|
||||
campaign_lifetime_support_cents: 1,
|
||||
patron_status: "former_patron",
|
||||
},
|
||||
id: "id",
|
||||
type: "campaign"
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
export const fakeOauth = {
|
||||
access_token: "test_access_token",
|
||||
refresh_token: "test_refresh_token",
|
||||
expires_in: 3600,
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import { APIVideoData, APIVideoInfo } from "../src/types/youtubeApi.model";
|
||||
import { APIVideoData, APIVideoInfo } from "../../src/types/youtubeApi.model";
|
||||
|
||||
export class YouTubeApiMock {
|
||||
// eslint-disable-next-line require-await
|
||||
Reference in New Issue
Block a user