From dc4f6244379a055dbeee829c0304cb155ae8a4c2 Mon Sep 17 00:00:00 2001 From: zkldi Date: Thu, 29 Apr 2021 23:16:03 +0100 Subject: [PATCH] Add Create-PB-Doc test --- .../framework/core/pb/create-pb-doc.test.ts | 169 +++++++++++++++++- .../framework/core/pb/create-pb-doc.ts | 22 ++- 2 files changed, 185 insertions(+), 6 deletions(-) diff --git a/server/src/score-import/framework/core/pb/create-pb-doc.test.ts b/server/src/score-import/framework/core/pb/create-pb-doc.test.ts index fd1900c17..3cbaa8537 100644 --- a/server/src/score-import/framework/core/pb/create-pb-doc.test.ts +++ b/server/src/score-import/framework/core/pb/create-pb-doc.test.ts @@ -1,9 +1,21 @@ import t from "tap"; import db, { CloseMongoConnection } from "../../../../db/db"; import ResetDBState from "../../../../test-utils/reset-db-state"; -import { Testing511SPA, TestingIIDXSPScorePB } from "../../../../test-utils/test-data"; -import { GetRankingInfo } from "./create-pb-doc"; +import { + GetKTDataJSON, + Testing511SPA, + TestingIIDXSPScore, + TestingIIDXSPScorePB, +} from "../../../../test-utils/test-data"; +import { CreatePBDoc, GetRankingInfo } from "./create-pb-doc"; import deepmerge from "deepmerge"; +import CreateLogCtx from "../../../../logger"; +import { KtLogger } from "../../../../types"; +import { lamps } from "kamaitachi-common/js/config"; + +let IIDXScore = TestingIIDXSPScore; + +const logger = CreateLogCtx("create-pb-doc.test.ts"); t.test("#GetRankingInfo", (t) => { t.beforeEach(ResetDBState); @@ -80,4 +92,157 @@ t.test("#GetRankingInfo", (t) => { t.end(); }); +t.test("#CreatePBDoc", (t) => { + t.beforeEach(ResetDBState); + t.beforeEach(() => { + // monk adds _id onto the file when you import it, so lets try and avoid that + IIDXScore = GetKTDataJSON("./kamaitachi/iidx-score.json"); + }); + + let chartID = Testing511SPA.chartID; + + const ExamplePBDoc = { + chartID, + userID: 1, + songID: 1, + outOf: 1, + ranking: 1, + highlight: false, + game: "iidx", + playtype: "SP", + comments: [], + composedFrom: { + scorePB: IIDXScore.scoreID, + lampPB: "LAMP_PB_ID", + }, + scoreData: { + score: IIDXScore.scoreData.score, + percent: IIDXScore.scoreData.percent, + esd: IIDXScore.scoreData.esd, + grade: IIDXScore.scoreData.grade, + gradeIndex: IIDXScore.scoreData.gradeIndex, + hitData: IIDXScore.scoreData.hitData, + lamp: "FULL COMBO", + lampIndex: lamps.iidx.indexOf("FULL COMBO"), + hitMeta: { bp: 1 }, + }, + calculatedData: { + rating: IIDXScore.calculatedData.rating, + lampRating: 12, + gameSpecific: {}, + }, + }; + + t.test( + "(IIDX) Should use the GameSpecificMergeFN to also join the BP PB if necessary.", + async (t) => { + await db.scores.remove({}); + await db.scores.insert([ + IIDXScore, + deepmerge(IIDXScore, { + scoreData: { + lamp: "FULL COMBO", + lampIndex: lamps.iidx.indexOf("FULL COMBO"), + score: 0, + percent: 0, + hitMeta: { + bp: 15, + }, + }, + calculatedData: { + lampRating: 12, + }, + scoreID: "LAMP_PB_ID", + }), + deepmerge(IIDXScore, { + scoreData: { + lamp: "CLEAR", + lampIndex: lamps.iidx.indexOf("CLEAR"), + score: 1, + percent: 1, + hitMeta: { + bp: 5, + }, + }, + calculatedData: { + lampRating: 10, + }, + scoreID: "BP_PB_ID", + }), + ]); + + let res = await CreatePBDoc(1, chartID, logger); + + t.not(res, undefined, "Should actually return something."); + + t.strictSame( + res, + deepmerge(ExamplePBDoc, { + composedFrom: { + other: [{ name: "Best BP", scoreID: "BP_PB_ID" }], + }, + scoreData: { + hitMeta: { + bp: 5, + }, + }, + }), + "Should correctly return a merged PBDocument with BP" + ); + + t.end(); + } + ); + + t.test("Should merge a score and lamp PB into one document.", async (t) => { + let d = deepmerge(IIDXScore, { + scoreData: { + lamp: "FULL COMBO", + lampIndex: lamps.iidx.indexOf("FULL COMBO"), + score: 0, + percent: 0, + hitMeta: { + bp: 1, + }, + }, + calculatedData: { + lampRating: 12, + }, + scoreID: "LAMP_PB_ID", + }); + + await db.scores.remove({}); + await db.scores.insert([IIDXScore, d]); + + let res = await CreatePBDoc(1, chartID, logger); + + t.not(res, undefined, "Should actually return something."); + + t.strictSame(res, ExamplePBDoc, "Should correctly return a merged PBDocument"); + + t.end(); + }); + + t.test("Should bail safely if no score exists when one should", async (t) => { + // a work of genius + const fakeLogger = ({ + severe: () => (severeCalled = true), + } as unknown) as KtLogger; + + let severeCalled = false; + + await db.scores.remove({}); + + let res = await CreatePBDoc(1, chartID, fakeLogger); + + t.equal(res, undefined, "Should return nothing (and emit a warning)"); + + t.equal(severeCalled, true, "Severe logging should have been called."); + + t.end(); + }); + + t.end(); +}); + t.teardown(CloseMongoConnection); diff --git a/server/src/score-import/framework/core/pb/create-pb-doc.ts b/server/src/score-import/framework/core/pb/create-pb-doc.ts index 845e3dcf5..0af391968 100644 --- a/server/src/score-import/framework/core/pb/create-pb-doc.ts +++ b/server/src/score-import/framework/core/pb/create-pb-doc.ts @@ -18,7 +18,7 @@ export async function CreatePBDoc(userID: integer, chartID: string, logger: KtLo ); if (!scorePB) { - logger.warn(`User has no scores on chart, but a PB was attempted to be created?`, { + logger.severe(`User has no scores on chart, but a PB was attempted to be created?`, { chartID, userID, }); @@ -35,10 +35,16 @@ export async function CreatePBDoc(userID: integer, chartID: string, logger: KtLo "scoreData.lampIndex": -1, }, } - )) as ScoreDocument; // guaranteed to not be null, but... + )) as ScoreDocument; // guaranteed to not be null, as this always resolves + // to atleast one score (and we got ScorePB above, so we know there's + // atleast one). const pbDoc = await MergeScoreLampIntoPB(userID, scorePB, lampPB, logger); + if (!pbDoc) { + return; + } + return pbDoc; } @@ -87,7 +93,7 @@ async function MergeScoreLampIntoPB( scorePB: ScoreDocument, lampPB: ScoreDocument, logger: KtLogger -): Promise { +): Promise { let { outOf, ranking } = await GetRankingInfo( scorePB.chartID, userID, @@ -128,7 +134,15 @@ async function MergeScoreLampIntoPB( let GameSpecificMergeFn = GAME_SPECIFIC_MERGE_FNS[scorePB.game]; if (GameSpecificMergeFn) { - await GameSpecificMergeFn(pbDoc, scorePB, lampPB, logger); + let success = await GameSpecificMergeFn(pbDoc, scorePB, lampPB, logger); + + // If the mergeFn returns false, this means something has gone + // rather wrong. We just return undefined here, which in turn + // tells our calling code to skip this PB. This typically results in a + // severe-level warning + if (success === false) { + return; + } } return pbDoc;