diff --git a/.gitignore b/.gitignore index 0ec8b79..6ca1b17 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ node_modules/ .env build/ -.nyc_output/ \ No newline at end of file +.nyc_output/ diff --git a/src/controllers/FlightRequest.controller.ts b/src/controllers/FlightRequest.controller.ts index 59eaa1b..af1eecd 100644 --- a/src/controllers/FlightRequest.controller.ts +++ b/src/controllers/FlightRequest.controller.ts @@ -1,5 +1,9 @@ +/* eslint-disable no-irregular-whitespace */ import { createTestFlightLegData } from '../data/test-data'; +import Airtable from 'airtable'; +import dotenv from 'dotenv'; import type { Request, Response } from 'express'; +dotenv.config(); /** * This function returns all flight requests for a given user @@ -7,8 +11,8 @@ import type { Request, Response } from 'express'; * Steps to complete: * 1. Get the userId from the query parameters, if it doesn't exist return a 400 * 2. Make a call to AirTable to get all flight requests for the user, if that fails return a 500 (hint, use try/catch) - * If there are no flight requests for the user return a 400. (hint: use the AirTable API, see TestControllers/retrievePassengers.ts for an example) - * Another hint - we will be filtering by the "Passenger ID" field in the AirTable + *    If there are no flight requests for the user return a 400. (hint: use the AirTable API, see TestControllers/retrievePassengers.ts for an example) + *    Another hint - we will be filtering by the "Passenger ID" field in the AirTable * 3. Remove any unnecessary data from the flight requests (there is a lot of data in the AirTable response we don't need) * 4. Return the flight requests for the user * @@ -20,39 +24,89 @@ export const getAllFlightRequestsForUser = async ( res: Response ) => { // get the userId from the query parameters - // const { userId } = req.query; + const { userId } = req.query; + + if (userId === null) { + return res.status(400).json({ error: 'Passenger ID missing' }); + } // create a fake array of flight requests - // create a fake array of flight requests const flightRequests = Array.from({ length: 10 }, () => createTestFlightLegData() - ); + ); // return the flight requests for the user - // return the flight requests for the user res.status(200).send(flightRequests); }; /** - * This function returns a flight request for a given flightRequestId - * - * Steps to complete: - * 1. Get the flightRequestId from the query parameters, if it doesn't exist return a 400 - * 2. Make a call to AirTable to get the flight request, if that fails return a 500 (hint, use try/catch) - * If there is no flight request for the flightRequestId return a 400. (hint: use the AirTable API, see TestControllers/retrievePassengers.ts for an example) - * 3. Remove any unnecessary data from the flight requests (there is a lot of data in the AirTable response we don't need) - * 4. Return the flight request + * Get a flight request by its ID * * @param req - the request object * @param res - the response object */ export const getFlightRequestById = async (req: Request, res: Response) => { // get the flightRequestId from the query parameters - // const { flightRequestId } = req.query; - // create a fake flight request - const flightRequest = createTestFlightLegData(); + const { id } = req.params; - // return the flight request - res.status(200).send(flightRequest); + if (!id) { + return res.status(400).json({ error: 'Flight Request ID missing' }); + } + + const base = new Airtable({ + apiKey: process.env.AIRTABLE_API_KEY || '', + }).base('appwPsfAb6U8CV3mf'); + + try { + await base('Flight Requests (Trips)').find( + id.toString(), + function (err, record) { + if (err) { + return res.status(400).json({ error: 'No record found' }); + } + + return res.status(200).send(record); + } + ); + } catch (err: any) { + console.error(err); + return res.status(500).json({ error: 'Error fetching record' }); + } +}; + +/** + * Get the flight legs for a given flight request ID + * + * @param req - the request object + * @param res - the response object + */ +export const getFlightLegsById = async (req: Request, res: Response) => { + const { id } = req.params; + let flightLegs; + + if (!id) { + return res.status(400).json({ error: 'Flight Request ID missing' }); + } + + const base = new Airtable({ + apiKey: process.env.AIRTABLE_API_KEY || '', + }).base('appwPsfAb6U8CV3mf'); + + try { + flightLegs = await base('Flight Legs') + .select({ + filterByFormula: `{Request AirTable Record ID} = "${id.toString()}"`, + }) + .all(); + + if (flightLegs.length === 0) { + return res.status(400).json({ error: 'No record found' }); + } + } catch (err: any) { + console.error(err); + return res.status(500).json({ error: 'Error fetching record' }); + } + + return res.status(200).send(flightLegs); }; /** @@ -74,9 +128,8 @@ export const createFlightRequest = async (req: Request, res: Response) => { // ... // create a fake flight request - const flightRequest = createTestFlightLegData(); + const flightRequest = createTestFlightLegData(); // return the flight request - // return the flight request res.status(200).send(flightRequest); }; @@ -100,8 +153,7 @@ export const updateFlightRequest = async (req: Request, res: Response) => { // ... // create a fake flight request that was "updated" - const flightRequest = createTestFlightLegData(); + const flightRequest = createTestFlightLegData(); // return the flight request - // return the flight request res.status(200).send(flightRequest); }; diff --git a/src/controllers/Passenger.controller.ts b/src/controllers/Passenger.controller.ts index d6e1821..5f4d820 100644 --- a/src/controllers/Passenger.controller.ts +++ b/src/controllers/Passenger.controller.ts @@ -7,15 +7,7 @@ import type { PassengerData } from '../interfaces/passenger/passenger.interface' import type { Request, Response } from 'express'; /** - * This function returns all passengers connected to a user - * - * Steps to complete: - * 1. Get the userId from the query parameters, if it doesn't exist return a 400 - * 2. Make a call to AirTable to get all passengers for the user, if that fails return a 500 (hint, use try/catch) - * If there are no passengers for the user return a 400. (hint: use the AirTable API, see TestControllers/retrievePassengers.ts for an example) - * Another hint - we will be filtering by the "Passenger ID" field in the AirTable - * 3. Remove any unnecessary data from the passengers (there is a lot of data in the AirTable response we don't need) - * 4. Return the passengers for the user + * Get all of the related passengers for a user (people they have flown with in the past) * * @param req - the request object * @param res - the response object diff --git a/src/controllers/TestControllers/retrievePassengers.ts b/src/controllers/TestControllers/retrievePassengers.ts index 8697d39..257ac51 100644 --- a/src/controllers/TestControllers/retrievePassengers.ts +++ b/src/controllers/TestControllers/retrievePassengers.ts @@ -14,15 +14,17 @@ export const retrievePassengers = async (req: Request, res: Response) => { base('Flight Requests (Trips)') .select({ - // Selecting the first 3 records in All Requests [MASTER]: + // Selecting the first 100 records in All Requests [MASTER]: maxRecords: 100, view: 'All Requests [MASTER]', }) + .firstPage(async function (err, records) { if (err) { logger.error(err); return; } + if (records) { const flightLegs = records.map(record => record.fields['Flight Legs'] !== undefined diff --git a/src/routes/routes.ts b/src/routes/routes.ts index 1aff4e0..20fc663 100644 --- a/src/routes/routes.ts +++ b/src/routes/routes.ts @@ -9,6 +9,7 @@ import { getFlightRequestById, createFlightRequest, updateFlightRequest, + getFlightLegsById, } from '../controllers/FlightRequest.controller'; import { queryParameterExample } from '../controllers/TestControllers/queryParameterExample'; import { pathParameterExample } from '../controllers/TestControllers/pathParameterExample'; @@ -39,6 +40,7 @@ const routes = (app: Express) => { /* Flight Request Controller Routes */ app.get('/requests/', getAllFlightRequestsForUser); app.get('/requests/:id', getFlightRequestById); + app.get('/requests/:id/legs', getFlightLegsById); app.post('/requests/', createFlightRequest); app.put('/requests/:id', updateFlightRequest); diff --git a/src/tests/Examples.tests.ts b/src/tests/Examples.tests.ts index 0647e4a..d748d11 100644 --- a/src/tests/Examples.tests.ts +++ b/src/tests/Examples.tests.ts @@ -27,7 +27,7 @@ after(done => { }); // Test case -describe('POST test/bodyParameterExample', () => { +describe('EXAMPLE test/bodyParameterExample', () => { it('should return a 418 response', done => { chai .request(app) @@ -51,7 +51,7 @@ describe('POST test/bodyParameterExample', () => { }); // test queryParameterExample -describe('queryParameterExample', () => { +describe('EXAMPLE queryParameterExample', () => { it('should return 418 and a message with the query parameter', done => { chai .request(app) @@ -78,7 +78,7 @@ describe('queryParameterExample', () => { }); // test queryParameterExample -describe('pathParameterExample', () => { +describe('EXAMPLE pathParameterExample', () => { it('should return 418 and a message with the path parameter', done => { chai .request(app) diff --git a/src/tests/FlightRequest.tests.ts b/src/tests/FlightRequest.tests.ts new file mode 100644 index 0000000..5942b96 --- /dev/null +++ b/src/tests/FlightRequest.tests.ts @@ -0,0 +1,89 @@ +import { configureServer } from '../config/server.config'; +import chaiHttp from 'chai-http'; +import dotenv from 'dotenv'; +import chai, { expect } from 'chai'; +import type { Server } from 'http'; +dotenv.config(); + +// set up chai +chai.use(chaiHttp); +chai.should(); + +// set up mock server +const app = configureServer(); +let server: Server; + +// start mock server +before(done => { + server = app.listen(3484, () => { + done(); + }); +}); + +// close mock server +after(done => { + server.close(); + done(); +}); + +// Test getFlightRequestByID +describe('GET /requests', () => { + it('should return the correct request ID, origin airport, destination airport, and passenger name', done => { + chai + .request(app) + .get('/requests/recp5zrIaW8EZhJtu') + .end((err, res) => { + expect(res).to.have.status(200); + expect(res.body.fields).to.include.all.keys( + 'Request ID', + 'Origin Airport', + 'Destination Airport', + 'Patient Name' + ); + expect(res.body.fields['Request ID']).to.equal( + '2022-12-08 | In Progress | Gilchrist, Stormie | 2014-06-21' + ); + expect(res.body.fields['Origin Airport']).to.equal('SEA'); + expect(res.body.fields['Destination Airport']).to.equal('JFK'); + expect(res.body.fields['Patient Name']).to.equal('Stormie Gilchrist'); + done(); + }); + }); + + it('should return a 400 response for invalid or missing ID', done => { + chai + .request(app) + .get('/requests/blahblahblah') + .end((err, res) => { + expect(res).to.have.status(400); + done(); + }); + }); +}); + +// Test getFlightLegsById +describe('GET /requests/:id/legs', () => { + it('should return the correct passenger names, leg IDs, and Airtable record IDs for the flight legs', done => { + chai + .request(app) + .get('/requests/recp5zrIaW8EZhJtu/legs') + .end((err, res) => { + expect(res).to.have.status(200); + expect(res.body).to.be.an('array').that.is.not.empty; + + expect(res.body[0]).to.have.property('fields').that.is.an('object').that + .is.not.empty; + const firstFlightLegFields = res.body[0].fields; + expect(firstFlightLegFields['Passenger Names']).to.equal( + 'Stormie Gilchrist, Jessie Gilchrist ' + ); + expect(firstFlightLegFields['Leg ID']).to.equal( + '2023-02-06 | Pending | Departure SEA > JFK' + ); + expect(firstFlightLegFields['AirTable Record ID']).to.equal( + 'rec0uwOR2O7cvLbDA' + ); + done(); + }); + }); +}); diff --git a/src/tests/Trimming.tests.ts b/src/tests/Trimming.tests.ts index 85dbe82..2f7c7a3 100644 --- a/src/tests/Trimming.tests.ts +++ b/src/tests/Trimming.tests.ts @@ -13,7 +13,7 @@ import type { TrimmedFlightRequest } from '../interfaces/requests/trimmed-flight import type { TrimmedPassenger } from '../interfaces/passenger/trimmed-passenger.interface'; chai.should(); -describe('Trimming', () => { +describe('UTIL Trimming', () => { it('should properly trim request', () => { const requestData: FlightRequestData = createTestFlightRequestData(); const trimmedRequest: TrimmedFlightRequest = trimRequest(requestData);