-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch '631-frontend-connect-the-policy-to-sanity' of https://g…
…ithub.com/UoaWDCC/uasc-web into 631-frontend-connect-the-policy-to-sanity
- Loading branch information
Showing
12 changed files
with
778 additions
and
23 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { admin } from "business-layer/security/Firebase" | ||
|
||
const converter = <T>() => ({ | ||
toFirestore: (data: any) => data, | ||
fromFirestore: (doc: any) => doc.data() as T | ||
}) | ||
|
||
/** | ||
* Firestore adapter for the application. | ||
*/ | ||
const firestore = Object.assign( | ||
() => { | ||
return admin.firestore() | ||
}, | ||
{ | ||
doc: <T>(path: string) => { | ||
return admin.firestore().doc(path).withConverter<T>(converter<T>()) | ||
}, | ||
/** | ||
* Collection adapter for Firestore. | ||
* @param path The path to the collection. | ||
* @returns The collection adapter. | ||
*/ | ||
collection: <T>(path: string) => { | ||
return admin.firestore().collection(path).withConverter<T>(converter<T>()) | ||
}, | ||
/** | ||
* Subcollection adapter for Firestore. | ||
* @param path The path to the main collection. | ||
* @param docId The document ID from the main collection to retrieve. | ||
* @param subpath The path to the subcollection. | ||
* @returns The subcollection adapter. | ||
*/ | ||
subcollection: <T>(path: string, docId: string, subpath: string) => { | ||
return admin | ||
.firestore() | ||
.collection(path) // The main collection | ||
.doc(docId) // The document | ||
.collection(subpath) // The sub collection | ||
.withConverter<T>(converter<T>()) | ||
} | ||
} | ||
) | ||
|
||
export default firestore |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,20 @@ | ||
// credit https://plainenglish.io/blog/using-firestore-with-typescript-in-the-v9-sdk-cf36851bb099 | ||
import "dotenv/config" | ||
import firestore from "./Firestore" | ||
import { | ||
Booking, | ||
BookingHistoryEvent, | ||
BookingSlot, | ||
Event, | ||
UserAdditionalInfo | ||
} from "data-layer/models/firebase" | ||
import { admin } from "business-layer/security/Firebase" | ||
|
||
const converter = <T>() => ({ | ||
toFirestore: (data: any) => data, | ||
fromFirestore: (doc: any) => doc.data() as T | ||
}) | ||
|
||
const firestore = Object.assign( | ||
() => { | ||
return admin.firestore() | ||
}, | ||
{ | ||
doc: <T>(path: string) => { | ||
return admin.firestore().doc(path).withConverter<T>(converter<T>()) | ||
}, | ||
collection: <T>(path: string) => { | ||
return admin.firestore().collection(path).withConverter<T>(converter<T>()) | ||
} | ||
} | ||
) | ||
|
||
const db = { | ||
const FirestoreCollections = { | ||
users: firestore.collection<UserAdditionalInfo>("users"), | ||
bookings: firestore.collection<Booking>("bookings"), | ||
bookingSlots: firestore.collection<BookingSlot>("booking_slots"), | ||
bookingHistory: firestore.collection<BookingHistoryEvent>("booking_history") | ||
bookingHistory: firestore.collection<BookingHistoryEvent>("booking_history"), | ||
events: firestore.collection<Event>("events") | ||
} as const | ||
|
||
export default db | ||
export default FirestoreCollections |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// credit https://plainenglish.io/blog/using-firestore-with-typescript-in-the-v9-sdk-cf36851bb099 | ||
import "dotenv/config" | ||
import firestore from "./Firestore" | ||
import { EventReservation } from "data-layer/models/firebase" | ||
|
||
const FirestoreSubcollections = { | ||
reservations: (eventId: string) => | ||
firestore.subcollection<EventReservation>("events", eventId, "reservations") | ||
} as const | ||
|
||
export default FirestoreSubcollections |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
import { cleanFirestore } from "test-config/TestUtils" | ||
import EventService from "./EventService" | ||
import { | ||
dateToFirestoreTimeStamp, | ||
removeUnderscoresFromTimestamp | ||
} from "data-layer/adapters/DateUtils" | ||
import { Event, EventReservation } from "data-layer/models/firebase" | ||
import FirestoreCollections from "data-layer/adapters/FirestoreCollections" | ||
|
||
const eventService = new EventService() | ||
|
||
const startDate = dateToFirestoreTimeStamp(new Date(2024, 1, 1)) | ||
const endDate = dateToFirestoreTimeStamp(new Date(2024, 1, 2)) | ||
|
||
const event1: Event = { | ||
title: "UASC new event", | ||
description: "Grand opening of the website.", | ||
location: "Virtual pizza event", | ||
start_date: startDate, | ||
end_date: endDate | ||
} | ||
const event2: Event = { | ||
title: "Snowboard racing", | ||
description: "Race and see who's the fastest!", | ||
location: "Snowsport club", | ||
start_date: startDate, | ||
end_date: endDate | ||
} | ||
|
||
const reservation1: EventReservation = { | ||
first_name: "John", | ||
last_name: "Appleseed", | ||
email: "[email protected]", | ||
is_member: true | ||
} | ||
const reservation2: EventReservation = { | ||
first_name: "Jane", | ||
last_name: "Pearseed", | ||
email: "[email protected]", | ||
is_member: false | ||
} | ||
|
||
describe("EventService integration tests", () => { | ||
afterEach(async () => { | ||
await cleanFirestore() | ||
}) | ||
|
||
it("Should be able to add an event", async () => { | ||
const newEvent = await eventService.createEvent(event1) | ||
|
||
const fetchedEvent = await FirestoreCollections.events | ||
.doc(newEvent.id) | ||
.get() | ||
|
||
const data = fetchedEvent.data() | ||
|
||
expect({ | ||
...data, | ||
end_date: removeUnderscoresFromTimestamp(data.end_date), | ||
start_date: removeUnderscoresFromTimestamp(data.start_date) | ||
}).toEqual(event1) | ||
}) | ||
|
||
it("Should be able to get an event", async () => { | ||
const newEvent = await eventService.createEvent(event1) | ||
|
||
const fetchedEvent = await eventService.getEventById(newEvent.id) | ||
|
||
expect({ | ||
...fetchedEvent, | ||
end_date: removeUnderscoresFromTimestamp(fetchedEvent.end_date), | ||
start_date: removeUnderscoresFromTimestamp(fetchedEvent.start_date) | ||
}).toEqual(event1) | ||
}) | ||
|
||
it("Should be able to update an event", async () => { | ||
const newEvent = await eventService.createEvent(event1) | ||
|
||
await eventService.updateEvent(newEvent.id, { | ||
title: "Wow pizza???" | ||
}) | ||
|
||
const fetchedEvent = await eventService.getEventById(newEvent.id) | ||
|
||
expect(fetchedEvent.title).toBe("Wow pizza???") | ||
}) | ||
|
||
it("Should be able to delete an event", async () => { | ||
const newEvent = await eventService.createEvent(event1) | ||
await eventService.deleteEvent(newEvent.id) | ||
|
||
const fetchedEvent = await eventService.getEventById(newEvent.id) | ||
|
||
expect(fetchedEvent).toBe(undefined) | ||
}) | ||
|
||
it("Should delete an event and also all reservations", async () => { | ||
const newEvent = await eventService.createEvent(event1) | ||
const newReservation1 = await eventService.addReservation( | ||
newEvent.id, | ||
reservation1 | ||
) | ||
const newReservation2 = await eventService.addReservation( | ||
newEvent.id, | ||
reservation2 | ||
) | ||
|
||
await eventService.deleteEvent(newEvent.id) | ||
|
||
const fetchedReservation1 = await eventService.getReservationById( | ||
newEvent.id, | ||
newReservation1.id | ||
) | ||
expect(fetchedReservation1).toBe(undefined) | ||
const fetchedReservation2 = await eventService.getReservationById( | ||
newEvent.id, | ||
newReservation2.id | ||
) | ||
expect(fetchedReservation2).toBe(undefined) | ||
}) | ||
|
||
it("Should not delete other reservations when deleting an event document", async () => { | ||
const newEvent = await eventService.createEvent(event1) | ||
await eventService.addReservation(newEvent.id, reservation1) | ||
await eventService.addReservation(newEvent.id, reservation2) | ||
const newEvent2 = await eventService.createEvent(event2) | ||
const newReservation3 = await eventService.addReservation( | ||
newEvent2.id, | ||
reservation1 | ||
) | ||
const newReservation4 = await eventService.addReservation( | ||
newEvent2.id, | ||
reservation2 | ||
) | ||
|
||
await eventService.deleteEvent(newEvent.id) | ||
const fetchedReservation3 = await eventService.getReservationById( | ||
newEvent2.id, | ||
newReservation3.id | ||
) | ||
expect(fetchedReservation3).toEqual(reservation1) | ||
const fetchedReservation4 = await eventService.getReservationById( | ||
newEvent2.id, | ||
newReservation4.id | ||
) | ||
expect(fetchedReservation4).toEqual(reservation2) | ||
}) | ||
|
||
/** | ||
* Event reservation nested collection methods | ||
*/ | ||
describe("EventReservation integration tests", () => { | ||
it("Should be able to add a event reservation", async () => { | ||
const newEvent = await eventService.createEvent(event1) | ||
|
||
const reservation = await eventService.addReservation( | ||
newEvent.id, | ||
reservation1 | ||
) | ||
const fetchedReservation = await FirestoreCollections.events | ||
.doc(newEvent.id) | ||
.collection("reservations") // subject to place as a constant somewhere | ||
.doc(reservation.id) | ||
.get() | ||
expect(fetchedReservation.data()).toEqual(reservation1) | ||
}) | ||
|
||
it("Should be able to get an event reservation", async () => { | ||
const newEvent = await eventService.createEvent(event1) | ||
const reservation = await eventService.addReservation( | ||
newEvent.id, | ||
reservation1 | ||
) | ||
const fetchedReservation = await eventService.getReservationById( | ||
newEvent.id, | ||
reservation.id | ||
) | ||
expect(fetchedReservation).toEqual(reservation1) | ||
}) | ||
|
||
it("Should get all event reservations", async () => { | ||
const newEvent = await eventService.createEvent(event1) | ||
await eventService.addReservation(newEvent.id, reservation1) | ||
await eventService.addReservation(newEvent.id, reservation2) | ||
const reservations = await eventService.getAllReservations(newEvent.id) | ||
expect(reservations.length).toBe(2) | ||
expect(reservations).toContainEqual(reservation1) | ||
expect(reservations).toContainEqual(reservation2) | ||
}) | ||
|
||
it("Should be able to update an event reservation", async () => { | ||
const newEvent = await eventService.createEvent(event1) | ||
|
||
const reservation = await eventService.addReservation( | ||
newEvent.id, | ||
reservation1 | ||
) | ||
|
||
await eventService.updateReservation(newEvent.id, reservation.id, { | ||
first_name: "Jan" | ||
}) | ||
|
||
const fetchedReservation = await FirestoreCollections.events | ||
.doc(newEvent.id) | ||
.collection("reservations") // subject to place as a constant somewhere | ||
.doc(reservation.id) | ||
.get() | ||
|
||
expect(fetchedReservation.data().first_name).toBe("Jan") | ||
}) | ||
|
||
it("Should be able to delete an event reservation", async () => { | ||
const newEvent = await eventService.createEvent(event1) | ||
|
||
const reservation = await eventService.addReservation( | ||
newEvent.id, | ||
reservation1 | ||
) | ||
|
||
await eventService.deleteReservation(newEvent.id, reservation.id) | ||
|
||
const fetchedReservation = await FirestoreCollections.events | ||
.doc(newEvent.id) | ||
.collection("reservations") // subject to place as a constant somewhere | ||
.doc(reservation.id) | ||
.get() | ||
expect(fetchedReservation.data()).toBe(undefined) | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.