Skip to content

Commit 8000c22

Browse files
committed
TestCasesforGet & POST and DELETE for ticket
1 parent 079d4ff commit 8000c22

File tree

3 files changed

+275
-23
lines changed

3 files changed

+275
-23
lines changed

src/routes/paidEvents.ts

Lines changed: 119 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@ import {
55
QueryCommand,
66
ScanCommand,
77
ConditionalCheckFailedException,
8+
PutItemCommand,
9+
DeleteItemCommand,
810
} from "@aws-sdk/client-dynamodb";
911
import { genericConfig } from "../config.js";
10-
import { unmarshall } from "@aws-sdk/util-dynamodb";
12+
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";
1113
import { DatabaseFetchError } from "../errors/index.js";
1214
import { z } from "zod";
1315
import { zodToJsonSchema } from "zod-to-json-schema";
16+
import { AppRoles } from "../roles.js";
1417

1518
const dynamoclient = new DynamoDBClient({
1619
region: genericConfig.AwsRegion,
@@ -28,22 +31,28 @@ type EventUpdateRequest = {
2831
Body: { attribute: string; value: string };
2932
};
3033

31-
/*const updateJsonSchema = zodToJsonSchema(
32-
z.object({
33-
event_id: z.number(),
34-
event_name: z.string(),
35-
eventCost: z.record(z.number()),
36-
eventDetails: z.optional(z.string()),
37-
eventImage: z.optional(z.string()),
38-
eventProps: z.record(z.string(), z.string()),
39-
event_capacity: z.number(),
40-
event_sales_active_utc: z.string(),
41-
event_time: z.number(),
42-
member_price: z.optional(z.string()),
43-
nonmember_price: z.optional(z.string()),
44-
tickets_sold: z.number()
45-
})
46-
)*/
34+
type EventDeleteRequest = {
35+
Params: { id: string };
36+
Querystring: undefined;
37+
Body: undefined;
38+
};
39+
40+
export const postTicketSchema = z.object({
41+
event_id: z.string(),
42+
event_name: z.string(),
43+
eventCost: z.record(z.number()),
44+
eventDetails: z.optional(z.string()),
45+
eventImage: z.optional(z.string()),
46+
eventProps: z.optional(z.record(z.string(), z.string())),
47+
event_capacity: z.number(),
48+
event_sales_active_utc: z.string(),
49+
event_time: z.number(),
50+
member_price: z.optional(z.string()),
51+
nonmember_price: z.optional(z.string()),
52+
tickets_sold: z.number(),
53+
});
54+
55+
type TicketPostSchema = z.infer<typeof postTicketSchema>;
4756

4857
const responseJsonSchema = zodToJsonSchema(
4958
z.object({
@@ -214,20 +223,18 @@ const paidEventsPlugin: FastifyPluginAsync = async (fastify, _options) => {
214223
});
215224
} catch (e: unknown) {
216225
if (e instanceof Error) {
217-
request.log.error("Failed to get from DynamoDB: " + e.toString());
226+
request.log.error("Failed to update to DynamoDB: " + e.toString());
218227
}
219228
if (e instanceof ConditionalCheckFailedException) {
220229
request.log.error("Attribute does not exist");
221230
}
222231
throw new DatabaseFetchError({
223-
message: "Failed to get event from Dynamo table.",
232+
message: "Failed to update event in Dynamo table.",
224233
});
225234
}
226235
},
227236
);
228237

229-
//Multiple attribute udpates...
230-
231238
fastify.put<EventUpdateRequest>(
232239
"/merchEvents/:id",
233240
{
@@ -274,13 +281,102 @@ const paidEventsPlugin: FastifyPluginAsync = async (fastify, _options) => {
274281
});
275282
} catch (e: unknown) {
276283
if (e instanceof Error) {
277-
request.log.error("Failed to get from DynamoDB: " + e.toString());
284+
request.log.error("Failed to update to DynamoDB: " + e.toString());
278285
}
279286
if (e instanceof ConditionalCheckFailedException) {
280287
request.log.error("Attribute does not exist");
281288
}
282289
throw new DatabaseFetchError({
283-
message: "Failed to get event from Dynamo table.",
290+
message: "Failed to update event in Dynamo table.",
291+
});
292+
}
293+
},
294+
);
295+
296+
fastify.post<{ Body: TicketPostSchema }>(
297+
"/ticketEvents",
298+
{
299+
schema: {
300+
response: { 200: responseJsonSchema },
301+
},
302+
preValidation: async (request, reply) => {
303+
await fastify.zodValidateBody(request, reply, postTicketSchema);
304+
},
305+
/*onRequest: async (request, reply) => {
306+
await fastify.authorize(request, reply, [AppRoles.EVENTS_MANAGER]);
307+
},*/ //validation taken off
308+
},
309+
async (request: FastifyRequest<{ Body: TicketPostSchema }>, reply) => {
310+
const id = request.body.event_id;
311+
try {
312+
//Verify if event_id already exists
313+
const response = await dynamoclient.send(
314+
new QueryCommand({
315+
TableName: genericConfig.TicketMetadataTableName,
316+
KeyConditionExpression: "event_id = :id",
317+
ExpressionAttributeValues: {
318+
":id": { S: id },
319+
},
320+
}),
321+
);
322+
if (response.Items?.length != 0) {
323+
throw new Error("Event_id already exists");
324+
}
325+
const entry = {
326+
...request.body,
327+
};
328+
await dynamoclient.send(
329+
new PutItemCommand({
330+
TableName: genericConfig.TicketMetadataTableName,
331+
Item: marshall(entry),
332+
}),
333+
);
334+
reply.send({
335+
id: id,
336+
resource: `/api/v1/paidEvents/ticketEvents/${id}`,
337+
});
338+
} catch (e: unknown) {
339+
if (e instanceof Error) {
340+
request.log.error("Failed to post to DynamoDB: " + e.toString());
341+
}
342+
throw new DatabaseFetchError({
343+
message: "Failed to post event to Dynamo table.",
344+
});
345+
}
346+
},
347+
);
348+
349+
fastify.delete<EventDeleteRequest>(
350+
"/ticketEvents/:id",
351+
{
352+
schema: {
353+
response: { 200: responseJsonSchema },
354+
},
355+
onRequest: async (request, reply) => {
356+
await fastify.authorize(request, reply, [AppRoles.EVENTS_MANAGER]);
357+
}, //auth
358+
},
359+
async (request: FastifyRequest<EventDeleteRequest>, reply) => {
360+
const id = request.params.id;
361+
try {
362+
await dynamoclient.send(
363+
new DeleteItemCommand({
364+
TableName: genericConfig.TicketMetadataTableName,
365+
Key: {
366+
event_id: { S: id },
367+
},
368+
}),
369+
);
370+
reply.send({
371+
id: id,
372+
resource: `/api/v1/paidEvents/ticketEvents/${id}`,
373+
});
374+
} catch (e: unknown) {
375+
if (e instanceof Error) {
376+
request.log.error("Failed to delete from DynamoDB: " + e.toString());
377+
}
378+
throw new DatabaseFetchError({
379+
message: "Failed to delete event from Dynamo table.",
284380
});
285381
}
286382
},
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { unmarshall } from "@aws-sdk/util-dynamodb";
2+
3+
const dynamoTableData = [
4+
{
5+
event_id: {
6+
S: "test_barcrawl",
7+
},
8+
eventCost: {
9+
M: {
10+
others: {
11+
N: "100",
12+
},
13+
paid: {
14+
N: "0",
15+
},
16+
},
17+
},
18+
eventDetails: {
19+
S: "Join ACM",
20+
},
21+
eventImage: {
22+
S: "img/test.png",
23+
},
24+
eventProps: {
25+
M: {
26+
end: {
27+
N: "",
28+
},
29+
host: {
30+
S: "",
31+
},
32+
location: {
33+
S: "",
34+
},
35+
},
36+
},
37+
event_capacity: {
38+
N: "130",
39+
},
40+
event_name: {
41+
S: "ACM Fall 2023 Bar Crawl",
42+
},
43+
event_sales_active_utc: {
44+
N: "0",
45+
},
46+
event_time: {
47+
N: "1699578000",
48+
},
49+
member_price: {
50+
S: "price_1O6zHhDiGOXU9RuSvlrcIfOv",
51+
},
52+
nonmember_price: {
53+
S: "price_1O6zHhDiGOXU9RuSvlrcIfOv",
54+
},
55+
tickets_sold: {
56+
N: "0",
57+
},
58+
},
59+
];
60+
61+
const dynamoTableDataUnmarshalled = dynamoTableData.map((x: any) => {
62+
const temp = unmarshall(x);
63+
return temp;
64+
});
65+
66+
const dynamoTableDataUnmarshalledUpcomingOnly = dynamoTableData
67+
.map((x: any) => {
68+
const temp = unmarshall(x);
69+
return temp;
70+
})
71+
.filter((x: any) => x.title != "Event in the past.");
72+
73+
export {
74+
dynamoTableData,
75+
dynamoTableDataUnmarshalled,
76+
dynamoTableDataUnmarshalledUpcomingOnly,
77+
};

tests/unit/paidEvents.test.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { afterAll, expect, test, beforeEach, vi } from "vitest";
2+
import {
3+
ScanCommand,
4+
DynamoDBClient,
5+
QueryCommand,
6+
} from "@aws-sdk/client-dynamodb";
7+
import { mockClient } from "aws-sdk-client-mock";
8+
import init from "../../src/index.js";
9+
import {
10+
dynamoTableData,
11+
dynamoTableDataUnmarshalled,
12+
} from "./mockPaidEventData.testdata.js";
13+
import { secretObject } from "./secret.testdata.js";
14+
15+
const ddbMock = mockClient(DynamoDBClient);
16+
const jwt_secret = secretObject["jwt_key"];
17+
vi.stubEnv("JwtSigningKey", jwt_secret);
18+
19+
const app = await init();
20+
test("Test paidEvents up", async () => {
21+
const response = await app.inject({
22+
method: "GET",
23+
url: "/api/v1/paidEvents",
24+
});
25+
expect(response.statusCode).toBe(200);
26+
const responseDataJson = await response.json();
27+
expect(responseDataJson).toEqual({ Status: "Up" });
28+
});
29+
30+
test("Test paidEvents get ticketEvents", async () => {
31+
ddbMock.on(ScanCommand).resolves({
32+
Items: dynamoTableData as any,
33+
});
34+
const response = await app.inject({
35+
method: "GET",
36+
url: "/api/v1/paidEvents/ticketEvents",
37+
});
38+
expect(response.statusCode).toBe(200);
39+
const responseDataJson = await response.json();
40+
expect(responseDataJson).toEqual(dynamoTableDataUnmarshalled);
41+
});
42+
43+
test("Test paidEvents get ticketEvents by id", async () => {
44+
ddbMock.on(QueryCommand).resolves({
45+
Items: dynamoTableData as any,
46+
});
47+
const response = await app.inject({
48+
method: "GET",
49+
url: "/api/v1/paidEvents/ticketEvents/test_barcrawl",
50+
});
51+
expect(response.statusCode).toBe(200);
52+
const responseDataJson = await response.json();
53+
expect(responseDataJson).toEqual(dynamoTableDataUnmarshalled[0]); //[0] since unmarshalled gives an array
54+
});
55+
56+
test("Test dynamodb error handling", async () => {
57+
ddbMock.onAnyCommand().rejects("Nope");
58+
const response = await app.inject({
59+
method: "GET",
60+
url: "/api/v1/paidEvents/ticketEvents",
61+
});
62+
expect(response.statusCode).toBe(500);
63+
const responseDataJson = await response.json();
64+
expect(responseDataJson).toEqual({
65+
error: true,
66+
name: "DatabaseFetchError",
67+
id: 106,
68+
message: "Failed to get events from Dynamo table.",
69+
});
70+
});
71+
72+
afterAll(async () => {
73+
await app.close();
74+
vi.useRealTimers();
75+
});
76+
beforeEach(() => {
77+
ddbMock.reset();
78+
vi.useFakeTimers();
79+
});

0 commit comments

Comments
 (0)