diff --git a/src/routes/getTopCategoryUsers.ts b/src/routes/getTopCategoryUsers.ts index 7f95a24..f22fbc1 100644 --- a/src/routes/getTopCategoryUsers.ts +++ b/src/routes/getTopCategoryUsers.ts @@ -24,9 +24,9 @@ async function generateTopCategoryUsersStats(sortBy: string, category: string) { SUM(((CASE WHEN "sponsorTimes"."endTime" - "sponsorTimes"."startTime" > ? THEN ? ELSE "sponsorTimes"."endTime" - "sponsorTimes"."startTime" END) / 60) * "sponsorTimes"."views") as "minutesSaved", SUM("votes") as "userVotes", COALESCE("userNames"."userName", "sponsorTimes"."userID") as "userName" FROM "sponsorTimes" LEFT JOIN "userNames" ON "sponsorTimes"."userID"="userNames"."userID" LEFT JOIN "shadowBannedUsers" ON "sponsorTimes"."userID"="shadowBannedUsers"."userID" - WHERE category = ? AND "sponsorTimes"."votes" > -1 AND "sponsorTimes"."shadowHidden" != 1 AND "shadowBannedUsers"."userID" IS NULL + WHERE "sponsorTimes"."category" = ? AND "sponsorTimes"."votes" > -1 AND "sponsorTimes"."shadowHidden" != 1 AND "shadowBannedUsers"."userID" IS NULL GROUP BY COALESCE("userName", "sponsorTimes"."userID") HAVING SUM("votes") > 20 - ORDER BY "${sortBy}" DESC LIMIT 100`, [category, maxRewardTimePerSegmentInSeconds, maxRewardTimePerSegmentInSeconds]); + ORDER BY "${sortBy}" DESC LIMIT 100`, [maxRewardTimePerSegmentInSeconds, maxRewardTimePerSegmentInSeconds, category]); for (const row of rows) { userNames.push(row.userName); @@ -47,7 +47,7 @@ export async function getTopCategoryUsers(req: Request, res: Response): Promise< const sortType = parseInt(req.query.sortType as string); const category = req.query.category as string; - if (sortType == undefined || config.categoryList.includes(category) ) { + if (sortType == undefined || !config.categoryList.includes(category) ) { //invalid request return res.sendStatus(400); } diff --git a/test/cases/getTopCategoryUsers.ts b/test/cases/getTopCategoryUsers.ts new file mode 100644 index 0000000..f321373 --- /dev/null +++ b/test/cases/getTopCategoryUsers.ts @@ -0,0 +1,124 @@ +import { db } from "../../src/databases/databases"; +import { getHash } from "../../src/utils/getHash"; +import assert from "assert"; +import { client } from "../utils/httpClient"; + +const generateSegment = (userid: string, category: string) => ["getTopCategory", 0, 60, 50, `getTopCategoryUUID_${category}`, getHash(userid), 1, 1, category, 0]; + +describe("getTopCategoryUsers", () => { + const endpoint = "/api/getTopCategoryUsers"; + const user1 = "gettopcategory_1"; + const user2 = "gettopcategory_2"; + before(async () => { + const insertUserNameQuery = 'INSERT INTO "userNames" ("userID", "userName") VALUES(?, ?)'; + await db.prepare("run", insertUserNameQuery, [getHash(user1), user1]); + await db.prepare("run", insertUserNameQuery, [getHash(user2), user2]); + + const sponsorTimesQuery = 'INSERT INTO "sponsorTimes" ("videoID", "startTime", "endTime", "votes", "UUID", "userID", "timeSubmitted", views, category, "shadowHidden") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; + await db.prepare("run", sponsorTimesQuery, generateSegment(user1, "sponsor")); + await db.prepare("run", sponsorTimesQuery, generateSegment(user1, "selfpromo")); + await db.prepare("run", sponsorTimesQuery, generateSegment(user2, "interaction")); + }); + + it("Should return 400 if no sortType", (done) => { + client.get(endpoint) + .then(res => { + assert.strictEqual(res.status, 400); + done(); + }) + .catch(err => done(err)); + }); + + it("Should return 400 if invalid sortType provided", (done) => { + client.get(endpoint, { params: { sortType: "a" } }) + .then(res => { + assert.strictEqual(res.status, 400); + done(); + }) + .catch(err => done(err)); + }); + + it("Should return 400 if invalid category provided", (done) => { + client.get(endpoint, { params: { sortType: 1, category: "never_valid_category" } }) + .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: { category: "sponsor", sortType: 0 } })// minutesSaved + .then(res => { + assert.strictEqual(res.status, 200); + }) + .catch(err => done(err)); + client.get(endpoint, { params: { category: "sponsor", sortType: 1 } }) // viewCount + .then(res => { + assert.strictEqual(res.status, 200); + }) + .catch(err => done(err)); + client.get(endpoint, { params: { category: "sponsor", sortType: 2 } }) // totalSubmissions + .then(res => { + assert.strictEqual(res.status, 200); + }) + .catch(err => done(err)); + done(); + }); + + it("Should return accurate sponsor data", (done) => { + client.get(endpoint, { params: { sortType: 1, category: "sponsor" } }) + .then(res => { + assert.strictEqual(res.status, 200); + assert.ok(!res.data.userNames.includes(user2), "User 2 should not be present"); + const user1idx = res.data.userNames.indexOf(user1); + assert.ok(user1idx > -1, "User 1 should be present"); + assert.strictEqual(res.data.viewCounts[user1idx], 1, "User should have 1 view"); + assert.strictEqual(res.data.totalSubmissions[user1idx], 1, "User should have 1 submission"); + assert.strictEqual(res.data.minutesSaved[user1idx], 1, "User should have 1 minutes saved"); + done(); + }) + .catch(err => done(err)); + }); + + it("Should return accurate selfpromo data", (done) => { + client.get(endpoint, { params: { sortType: 1, category: "selfpromo" } }) + .then(res => { + assert.strictEqual(res.status, 200); + assert.ok(!res.data.userNames.includes(user2), "User 2 should not be present"); + const user1idx = res.data.userNames.indexOf(user1); + assert.ok(user1idx > -1, "User 1 should be present"); + assert.strictEqual(res.data.viewCounts[user1idx], 1, "User should have 1 view"); + assert.strictEqual(res.data.totalSubmissions[user1idx], 1, "User should have 1 submission"); + assert.strictEqual(res.data.minutesSaved[user1idx], 1, "User should have 1 minutes saved"); + done(); + }) + .catch(err => done(err)); + }); + + it("Should return accurate interaction data", (done) => { + client.get(endpoint, { params: { sortType: 1, category: "interaction" } }) + .then(res => { + assert.strictEqual(res.status, 200); + assert.ok(!res.data.userNames.includes(user1), "User 1 should not be present"); + const user1idx = res.data.userNames.indexOf(user2); + assert.ok(user1idx > -1, "User 2 should be present"); + assert.strictEqual(res.data.viewCounts[user1idx], 1, "User should have 1 view"); + assert.strictEqual(res.data.totalSubmissions[user1idx], 1, "User should have 1 submission"); + assert.strictEqual(res.data.minutesSaved[user1idx], 1, "User should have 1 minutes saved"); + done(); + }) + .catch(err => done(err)); + }); + + it("Should return accurate outro data", (done) => { + client.get(endpoint, { params: { sortType: 1, category: "outro" } }) + .then(res => { + assert.strictEqual(res.status, 200); + assert.ok(!res.data.userNames.includes(user1), "User 1 should not be present"); + assert.ok(!res.data.userNames.includes(user2), "User 2 should not be present"); + done(); + }) + .catch(err => done(err)); + }); +});