Skip to content

Commit bfbd1f2

Browse files
committed
feat: add getUserSetRequests() function
1 parent e359928 commit bfbd1f2

File tree

7 files changed

+271
-0
lines changed

7 files changed

+271
-0
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import { http, HttpResponse } from "msw";
2+
import { setupServer } from "msw/node";
3+
4+
import { apiBaseUrl } from "../utils/internal";
5+
import { buildAuthorization } from "../utils/public";
6+
import { getUserSetRequests } from "./getUserSetRequests";
7+
import type { GetUserSetRequestsResponse, UserSetRequests } from "./models";
8+
import { RequestListType } from "./models";
9+
10+
const server = setupServer();
11+
12+
describe("Function: getUserSetRequests", () => {
13+
// MSW Setup
14+
beforeAll(() => server.listen());
15+
afterEach(() => server.resetHandlers());
16+
afterAll(() => server.close());
17+
18+
it("is defined #sanity", () => {
19+
// ASSERT
20+
expect(getUserSetRequests).toBeDefined();
21+
});
22+
23+
it("using defaults, retrieves the list of set requests of the given user", async () => {
24+
// ARRANGE
25+
const authorization = buildAuthorization({
26+
username: "mockUserName",
27+
webApiKey: "mockWebApiKey",
28+
});
29+
30+
const mockResponse = mockGetUserSetRequestsResponse;
31+
32+
server.use(
33+
http.get(`${apiBaseUrl}/API_GetUserSetRequests.php`, (info) => {
34+
const url = new URL(info.request.url);
35+
expect(url.searchParams.get("u")).toEqual(mockOtherUsername);
36+
expect(url.searchParams.has("t")).toBeFalsy();
37+
return HttpResponse.json(mockResponse);
38+
})
39+
);
40+
41+
// ACT
42+
const response = await getUserSetRequests(authorization, {
43+
username: mockOtherUsername,
44+
});
45+
expect(response).toEqual(mockUserSetRequestsValue);
46+
});
47+
48+
it.each([
49+
{ requestListType: RequestListType.ActiveRequests },
50+
{ requestListType: RequestListType.AllRequests },
51+
])(
52+
"calls the 'User Set Requests' endpoint with a given request list type ($requestListType)",
53+
async ({ requestListType: expectedRequestListType }) => {
54+
// ARRANGE
55+
const authorization = buildAuthorization({
56+
username: "mockUserName",
57+
webApiKey: "mockWebApiKey",
58+
});
59+
60+
server.use(
61+
http.get(`${apiBaseUrl}/API_GetUserSetRequests.php`, (info) => {
62+
const url = new URL(info.request.url);
63+
expect(url.searchParams.get("u")).toEqual(mockOtherUsername);
64+
expect(url.searchParams.get("t")).toEqual(
65+
String(expectedRequestListType)
66+
);
67+
return HttpResponse.json(mockGetUserSetRequestsResponse);
68+
})
69+
);
70+
71+
// ACT
72+
await getUserSetRequests(authorization, {
73+
username: mockOtherUsername,
74+
requestListType: expectedRequestListType,
75+
});
76+
}
77+
);
78+
79+
it.each([
80+
{ status: 503, statusText: "The API is currently down" },
81+
{ status: 422, statusText: "HTTP Error: Status 422 Unprocessable Entity" },
82+
])(
83+
"given the API returns a $status, throws an error",
84+
async ({ status, statusText }) => {
85+
// ARRANGE
86+
const authorization = buildAuthorization({
87+
username: "mockUserName",
88+
webApiKey: "mockWebApiKey",
89+
});
90+
91+
const mockResponse = `<html><body>${statusText}</body></html>`;
92+
93+
server.use(
94+
http.get(`${apiBaseUrl}/API_GetUserSetRequests.php`, () =>
95+
HttpResponse.json(mockResponse, { status, statusText })
96+
)
97+
);
98+
99+
// ASSERT
100+
await expect(
101+
getUserSetRequests(authorization, { username: mockOtherUsername })
102+
).rejects.toThrow();
103+
}
104+
);
105+
});
106+
107+
const mockOtherUsername = "otherMockUser";
108+
109+
const mockGetUserSetRequestsResponse: GetUserSetRequestsResponse = {
110+
RequestedSets: [
111+
{
112+
GameID: 8149,
113+
Title: "Example Set 1",
114+
ConsoleID: 0,
115+
ConsoleName: "Example Console",
116+
ImageIcon: "/Images/000001.png",
117+
},
118+
{
119+
GameID: 9001,
120+
Title: "Example Set 2",
121+
ConsoleID: 2,
122+
ConsoleName: "Example Console 2",
123+
ImageIcon: "/Images/000002.png",
124+
},
125+
],
126+
TotalRequests: 5,
127+
PointsForNext: 5000,
128+
};
129+
130+
const mockUserSetRequestsValue: UserSetRequests = {
131+
requestedSets: [
132+
{
133+
gameId: 8149,
134+
title: "Example Set 1",
135+
consoleId: 0,
136+
consoleName: "Example Console",
137+
imageIcon: "/Images/000001.png",
138+
},
139+
{
140+
gameId: 9001,
141+
title: "Example Set 2",
142+
consoleId: 2,
143+
consoleName: "Example Console 2",
144+
imageIcon: "/Images/000002.png",
145+
},
146+
],
147+
totalRequests: 5,
148+
pointsForNext: 5000,
149+
};

src/user/getUserSetRequests.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import {
2+
apiBaseUrl,
3+
buildRequestUrl,
4+
call,
5+
serializeProperties,
6+
} from "../utils/internal";
7+
import type { AuthObject } from "../utils/public";
8+
import type {
9+
GetUserSetRequestsResponse,
10+
RequestListType,
11+
UserSetRequests,
12+
} from "./models";
13+
14+
/**
15+
* A call to this function will retrieve a given user's set requests.
16+
*
17+
* @param authorization An object containing your username and webApiKey.
18+
* This can be constructed with `buildAuthorization()`.
19+
*
20+
* @param payload.username The user for which to retrieve the set requests
21+
* for.
22+
*
23+
* @param payload.requestListType An optional parameter to filter set requests
24+
* by their current status. If omittted, the API will return only active
25+
* requests.
26+
*
27+
* @example
28+
* ```
29+
* const userSetRequests = await getUserSetRequests(authorization, {
30+
* username: "ExampleUser"
31+
* });
32+
* ```
33+
*
34+
* @returns An object containing a list of requested sets that the
35+
* given user made.
36+
* ```json
37+
* {
38+
* "requestedSets": [
39+
* {
40+
* "gameId": 8149,
41+
* "title": "Example Set 1",
42+
* "consoleId": 0,
43+
* "consoleName": "Example Console",
44+
* "imageIcon": "/Images/000001.png"
45+
* },
46+
* {
47+
* "gameId": 9001,
48+
* "title": "Example Set 2",
49+
* "consoleId": 2,
50+
* "consoleName": "Example Console 2",
51+
* "imageIcon": "/Images/000002.png"
52+
* }
53+
* ],
54+
* "totalRequests": 5,
55+
* "pointsForNext": 5000
56+
* }
57+
* ```
58+
*
59+
* @throws If the API was given invalid parameters (422) or if the
60+
* API is currently down (503).
61+
*/
62+
export const getUserSetRequests = async (
63+
authorization: AuthObject,
64+
payload: { username: string; requestListType?: RequestListType }
65+
): Promise<UserSetRequests> => {
66+
const queryParams: Record<string, number | string> = {};
67+
queryParams.u = payload.username;
68+
if (
69+
payload.requestListType !== null &&
70+
payload.requestListType !== undefined
71+
) {
72+
queryParams.t = payload.requestListType;
73+
}
74+
75+
const url = buildRequestUrl(
76+
apiBaseUrl,
77+
"/API_GetUserSetRequests.php",
78+
authorization,
79+
queryParams
80+
);
81+
82+
const rawResponse = await call<GetUserSetRequestsResponse>({ url });
83+
84+
return serializeProperties(rawResponse, {
85+
shouldCastToNumbers: [
86+
"GameID",
87+
"ConsoleID",
88+
"TotalRequests",
89+
"PointsForNext",
90+
],
91+
});
92+
};

src/user/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export * from "./getUserProfile";
1111
export * from "./getUserProgress";
1212
export * from "./getUserRecentAchievements";
1313
export * from "./getUserRecentlyPlayedGames";
14+
export * from "./getUserSetRequests";
1415
export * from "./getUsersIFollow";
1516
export * from "./getUserSummary";
1617
export * from "./getUserWantToPlayList";
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export interface GetUserSetRequestsResponse {
2+
RequestedSets: Array<{
3+
GameID: number | string;
4+
Title: string;
5+
ConsoleID: number | string;
6+
ConsoleName: string;
7+
ImageIcon: string;
8+
}>;
9+
TotalRequests: number;
10+
PointsForNext: number;
11+
}

src/user/models/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ export * from "./get-user-profile-response.model";
1212
export * from "./get-user-progress-response.model";
1313
export * from "./get-user-recent-achievements-response.model";
1414
export * from "./get-user-recently-played-games-response.model";
15+
export * from "./get-user-set-requests-response.model";
1516
export * from "./get-user-summary-response.model";
1617
export * from "./get-user-want-to-play-list-response.model";
1718
export * from "./get-users-i-follow-response.model";
19+
export * from "./request-list-type.enum";
1820
export * from "./user-awards.model";
1921
export * from "./user-claims.model";
2022
export * from "./user-claims-response.model";
@@ -27,6 +29,7 @@ export * from "./user-profile.model";
2729
export * from "./user-progress.model";
2830
export * from "./user-recent-achievement.model";
2931
export * from "./user-recently-played-games.model";
32+
export * from "./user-set-requests.model";
3033
export * from "./user-summary.model";
3134
export * from "./user-want-to-play-list.model";
3235
export * from "./users-i-follow.model";
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export enum RequestListType {
2+
ActiveRequests = 0,
3+
AllRequests = 1,
4+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export interface UserSetRequests {
2+
requestedSets: Array<{
3+
gameId: number;
4+
title: string;
5+
consoleId: number;
6+
consoleName: string;
7+
imageIcon: string;
8+
}>;
9+
totalRequests: number;
10+
pointsForNext: number;
11+
}

0 commit comments

Comments
 (0)