From 5e9fa032ff33ce3d32b2bd8254cc6e984774934f Mon Sep 17 00:00:00 2001 From: Wes Copeland Date: Sun, 14 Jan 2024 12:05:05 -0500 Subject: [PATCH] feat(getUserCompletionProgress): add function (#64) --- src/user/getUserCompletionProgress.test.ts | 81 ++++++++++++++++++ src/user/getUserCompletionProgress.ts | 83 +++++++++++++++++++ src/user/index.ts | 1 + ...user-completion-progress-response.model.ts | 25 ++++++ src/user/models/index.ts | 3 + .../user-completion-progress-entity.model.ts | 19 +++++ .../models/user-completion-progress.model.ts | 7 ++ 7 files changed, 219 insertions(+) create mode 100644 src/user/getUserCompletionProgress.test.ts create mode 100644 src/user/getUserCompletionProgress.ts create mode 100644 src/user/models/get-user-completion-progress-response.model.ts create mode 100644 src/user/models/user-completion-progress-entity.model.ts create mode 100644 src/user/models/user-completion-progress.model.ts diff --git a/src/user/getUserCompletionProgress.test.ts b/src/user/getUserCompletionProgress.test.ts new file mode 100644 index 0000000..9b32bba --- /dev/null +++ b/src/user/getUserCompletionProgress.test.ts @@ -0,0 +1,81 @@ +import { http, HttpResponse } from "msw"; +import { setupServer } from "msw/node"; + +import { apiBaseUrl } from "../utils/internal"; +import { buildAuthorization } from "../utils/public"; +import { getUserCompletionProgress } from "./getUserCompletionProgress"; +import type { GetUserCompletionProgressResponse } from "./models"; + +const server = setupServer(); + +describe("Function: getUserCompletionProgress", () => { + // MSW Setup + beforeAll(() => server.listen()); + afterEach(() => server.resetHandlers()); + afterAll(() => server.close()); + + it("is defined #sanity", () => { + // ASSERT + expect(getUserCompletionProgress).toBeDefined(); + }); + + it("retrieves completion progress by username", async () => { + // ARRANGE + const authorization = buildAuthorization({ + userName: "mockUserName", + webApiKey: "mockWebApiKey" + }); + + const mockResponse: GetUserCompletionProgressResponse = { + Count: 1, + Total: 1, + Results: [ + { + GameID: 680, + Title: "Game & Watch Gallery", + ImageIcon: "/Images/042952.png", + ConsoleID: 4, + ConsoleName: "Game Boy", + MaxPossible: 27, + NumAwarded: 8, + NumAwardedHardcore: 8, + MostRecentAwardedDate: "2022-07-26T23:56:15+00:00", + HighestAwardKind: null, + HighestAwardDate: null + } + ] + }; + + server.use( + http.get(`${apiBaseUrl}/API_GetUserCompletionProgress.php`, () => + HttpResponse.json(mockResponse) + ) + ); + + // ACT + const response = await getUserCompletionProgress(authorization, { + userName: "xelnia" + }); + + // ASSERT + expect(response).toEqual({ + count: 1, + total: 1, + results: [ + { + gameId: 680, + title: "Game & Watch Gallery", + imageIcon: "/Images/042952.png", + consoleId: 4, + consoleName: "Game Boy", + maxPossible: 27, + numAwarded: 8, + numAwardedHardcore: 8, + mostRecentAwardedDate: "2022-07-26T23:56:15+00:00", + highestAwardKind: null, + highestAwardDate: null + } + ] + }); + }); +}); diff --git a/src/user/getUserCompletionProgress.ts b/src/user/getUserCompletionProgress.ts new file mode 100644 index 0000000..9c3e1ed --- /dev/null +++ b/src/user/getUserCompletionProgress.ts @@ -0,0 +1,83 @@ +import { + apiBaseUrl, + buildRequestUrl, + call, + serializeProperties +} from "../utils/internal"; +import type { AuthObject } from "../utils/public"; +import type { + GetUserCompletionProgressResponse, + UserCompletionProgress +} from "./models"; + +/** + * A call to this function will retrieve a given user's completion + * progress, targeted by their username. + * + * @param authorization An object containing your userName and webApiKey. + * This can be constructed with `buildAuthorization()`. + * + * @param payload.userName The user for which to retrieve the progress for. + * + * @param payload.offset Defaults to 0. The number of entries to skip. + * + * @param payload.count Defaults to 100, has a max of 500. + * + * @example + * ``` + * const userCompletionProgress = await getUserCompletionProgress( + * authorization, + * { userName: "xelnia" } + * ); + * ``` + * + * @returns + * ``` + * { + * "count": 100, + * "total": 752, + * "results": [ + * { + gameId: 11406, + title: 'Mortal Kombat 4', + imageIcon: '/Images/042133.png', + consoleId: 12, + consoleName: 'PlayStation', + maxPossible: 131, + numAwarded: 131, + numAwardedHardcore: 131, + mostRecentAwardedDate: '2022-08-07T18:24:44+00:00', + highestAwardKind: 'mastered', + highestAwardDate: '2022-08-07T18:24:44+00:00' + * } + * ] + * } + * ``` + */ +export const getUserCompletionProgress = async ( + authorization: AuthObject, + payload: { userName: string; offset?: number; count?: number } +): Promise => { + const { userName, offset, count } = payload; + + const params: Record = { + u: userName + }; + if (offset) { + params["o"] = offset; + } + if (count) { + params["c"] = count; + } + + const url = buildRequestUrl( + apiBaseUrl, + "/API_GetUserCompletionProgress.php", + authorization, + params + ); + + const rawResponse = await call({ url }); + + return serializeProperties(rawResponse); +}; diff --git a/src/user/index.ts b/src/user/index.ts index 2d7744b..08c853e 100644 --- a/src/user/index.ts +++ b/src/user/index.ts @@ -4,6 +4,7 @@ export * from "./getGameInfoAndUserProgress"; export * from "./getUserAwards"; export * from "./getUserClaims"; export * from "./getUserCompletedGames"; +export * from "./getUserCompletionProgress"; export * from "./getUserGameRankAndScore"; export * from "./getUserPoints"; export * from "./getUserProgress"; diff --git a/src/user/models/get-user-completion-progress-response.model.ts b/src/user/models/get-user-completion-progress-response.model.ts new file mode 100644 index 0000000..a6387f6 --- /dev/null +++ b/src/user/models/get-user-completion-progress-response.model.ts @@ -0,0 +1,25 @@ +interface RawUserCompletionProgressEntity { + GameID: number; + Title: string; + ImageIcon: string; + ConsoleID: number; + ConsoleName: string; + MaxPossible: number; + NumAwarded: number; + NumAwardedHardcore: number; + + MostRecentAwardedDate?: string; + HighestAwardKind?: + | "mastered" + | "completed" + | "beaten-hardcore" + | "beaten-softcore" + | null; + HighestAwardDate?: string | null; +} + +export interface GetUserCompletionProgressResponse { + Count: number; + Total: number; + Results: RawUserCompletionProgressEntity[]; +} diff --git a/src/user/models/index.ts b/src/user/models/index.ts index 848bbed..8c623a3 100644 --- a/src/user/models/index.ts +++ b/src/user/models/index.ts @@ -5,6 +5,7 @@ export * from "./game-info-and-user-progress.model"; export * from "./get-game-info-and-user-progress-response.model"; export * from "./get-user-awards-response.model"; export * from "./get-user-completed-games-response.model"; +export * from "./get-user-completion-progress-response.model"; export * from "./get-user-game-rank-and-score-response.model"; export * from "./get-user-points-response.model"; export * from "./get-user-progress-response.model"; @@ -15,6 +16,8 @@ export * from "./user-awards.model"; export * from "./user-claims.model"; export * from "./user-claims-response.model"; export * from "./user-completed-games.model"; +export * from "./user-completion-progress.model"; +export * from "./user-completion-progress-entity.model"; export * from "./user-game-rank-and-score.model"; export * from "./user-points.model"; export * from "./user-progress.model"; diff --git a/src/user/models/user-completion-progress-entity.model.ts b/src/user/models/user-completion-progress-entity.model.ts new file mode 100644 index 0000000..8896e9e --- /dev/null +++ b/src/user/models/user-completion-progress-entity.model.ts @@ -0,0 +1,19 @@ +export interface UserCompletionProgressEntity { + gameId: number; + title: string; + imageIcon: string; + consoleId: number; + consoleName: string; + maxPossible: number; + numAwarded: number; + numAwardedHardcore: number; + + mostRecentAwardedDate?: string; + highestAwardKind?: + | "mastered" + | "completed" + | "beaten-hardcore" + | "beaten-softcore" + | null; + highestAwardDate?: string; +} diff --git a/src/user/models/user-completion-progress.model.ts b/src/user/models/user-completion-progress.model.ts new file mode 100644 index 0000000..83b6c8d --- /dev/null +++ b/src/user/models/user-completion-progress.model.ts @@ -0,0 +1,7 @@ +import type { UserCompletionProgressEntity } from "./user-completion-progress-entity.model"; + +export interface UserCompletionProgress { + count: number; + total: number; + results: UserCompletionProgressEntity[]; +}