Updating request to focus on single request, started working on reservationScheduler

This commit is contained in:
Collin Duncan 2021-11-24 15:38:58 +01:00
parent 743cc08887
commit 7246ecabf2
No known key found for this signature in database
7 changed files with 127 additions and 94 deletions

View file

@ -7,19 +7,20 @@ import { DateRange, Opponent } from './reservation'
export interface ReservationRequest {
username: string
password: string
dateRanges: {
dateRange: {
start: Dayjs
end: Dayjs
}[]
}
opponent: Opponent
}
export enum ValidationErrorCode {
UNDEFINED_REQUEST_BODY = 1,
INVALID_REQUEST_BODY = 2,
INVALID_DATE_RANGE = 3,
INVALID_START_OR_END_DATE = 4,
INVALID_OPPONENT = 5,
UNDEFINED_REQUEST_BODY,
INVALID_JSON,
INVALID_REQUEST_BODY,
INVALID_DATE_RANGE,
INVALID_START_OR_END_DATE,
INVALID_OPPONENT,
}
export class ValidationError extends Error {
@ -31,11 +32,16 @@ export class ValidationError extends Error {
}
}
/**
* Validates an incoming request body and converts to ReservationRequest
* @param body String of request body
* @returns ReservationRequest
*/
export const validateRequest = (
body: string
): ReservationRequest => {
const request = validateRequestBody(body)
validateRequestDateRanges(request.dateRanges)
validateRequestDateRange(request.dateRange)
validateRequestOpponent(request.opponent)
return request
}
@ -46,15 +52,16 @@ const validateRequestBody = (body?: string): ReservationRequest => {
}
const jsonBody = transformRequestBody(body)
const { username, password, opponent, dateRanges } = jsonBody
const { username, password, opponent, dateRange } = jsonBody
if (
!username ||
username.length < 1 ||
!password ||
password.length < 1 ||
!dateRanges ||
dateRanges.length < 1 ||
!dateRange ||
!dateRange.start ||
!dateRange.end ||
(opponent && opponent.id && opponent.id.length < 1) ||
(opponent && opponent.name && opponent.name.length < 1)
) {
@ -65,24 +72,26 @@ const validateRequestBody = (body?: string): ReservationRequest => {
}
const transformRequestBody = (body: string): ReservationRequest => {
const json = JSON.parse(body)
const dateRanges: DateRange[] = json.dateRanges?.map(
({ start, end }: { start: string; end: string }): DateRange => {
return { start: dayjs(start), end: dayjs(end) }
let json
try {
json = JSON.parse(body)
} catch (err) {
throw new ValidationError('Invalid request', ValidationErrorCode.INVALID_JSON)
}
)
const startTime = json.dateRange?.start ?? 'invalid'
const endTime = json.dateRange?.end ?? 'invalid'
const dateRange: DateRange = { start: dayjs(startTime), end: dayjs(endTime) }
return {
username: json.username,
password: json.password,
opponent: json.opponent,
dateRanges,
dateRange,
}
}
const validateRequestDateRanges = (dateRanges: DateRange[]): void => {
for (let i = 0; i < dateRanges.length; i++) {
const validateRequestDateRange = (dateRange: DateRange): void => {
// checking that both dates are valid
const { start, end } = dateRanges[i]
const { start, end } = dateRange
if (!start.isValid() || !end.isValid()) {
throw new ValidationError('Invalid request', ValidationErrorCode.INVALID_DATE_RANGE)
}
@ -99,7 +108,6 @@ const validateRequestDateRanges = (dateRanges: DateRange[]): void => {
throw new ValidationError('Invalid request', ValidationErrorCode.INVALID_START_OR_END_DATE)
}
}
}
const validateRequestOpponent = (opponent?: Opponent): void => {
if (!opponent) return

View file

@ -1,18 +0,0 @@
import { SQSEvent, SQSHandler } from 'aws-lambda'
import { validateRequest } from '../common/request'
import { Reservation } from '../common/reservation'
import { Runner } from '../common/runner'
export const run: SQSHandler = async (event: SQSEvent): Promise<void> => {
const { request, error } = validateRequest(event.Records[0].body)
if (error || !request) {
throw new Error(error?.message)
}
const { username, password, dateRanges, opponent } = request
const reservations = dateRanges.map((dr) => new Reservation(dr, opponent))
const runner = new Runner(username, password, reservations)
await runner.run({ headless: false })
}

View file

@ -1,18 +0,0 @@
import { SQSEvent, SQSHandler } from 'aws-lambda'
import { validateRequestEvent } from '../common/request'
import { Reservation } from '../common/reservation'
import { Runner } from '../common/runner'
export const run: SQSHandler = async (event: SQSEvent): Promise<void> => {
const { request, error } = validateRequestEvent(event)
if (error || !request) {
throw new Error(error?.message)
}
const { username, password, dateTimes, opponent } = request
const reservations = dateTimes.map((dt) => new Reservation(dt, opponent))
const runner = new Runner(username, password, reservations)
await runner.run({ headless: false })
}

View file

@ -0,0 +1,7 @@
import { Handler } from 'aws-lambda'
import { Reservation } from '../common/reservation'
import { Runner } from '../common/runner'
export const run: Handler = async (payload: string): Promise<void> => {
}

View file

@ -0,0 +1,22 @@
import { Handler } from 'aws-lambda'
import dayjs from 'dayjs'
import { InputEvent } from '../stepFunctions/event'
import { Reservation } from '../common/reservation'
import { validateRequest } from '../common/request'
import { Runner } from '../common/runner'
export const run: Handler<InputEvent, void> = async (input: InputEvent): Promise<void> => {
console.log(`Handling event: ${input}`)
const { username, password, dateRange, opponent } = validateRequest(JSON.stringify(input.reservationRequest))
console.log('Successfully validated request')
console.log('Creating reservation')
const reservation = new Reservation(dateRange, opponent)
console.log('Created reservation')
console.log('Runner starting')
const runner = new Runner(username, password, [reservation])
await runner.run()
console.log('Runner finished')
}

View file

@ -0,0 +1,9 @@
import { ReservationRequest } from "../common/request";
export interface RawReservationRequest extends Omit<ReservationRequest, 'dateRanges'> {
dateRanges: { start: string, end: string }[]
}
export interface InputEvent {
reservationRequest: RawReservationRequest
}

View file

@ -12,9 +12,10 @@ describe('request', () => {
const body = JSON.stringify({
username: 'collin',
password: '123abc',
dateRanges: [
{ start: '2021-12-25T12:34:56Z', end: '2021-12-25T12:45:56Z' }
],
dateRange: {
start: '2021-12-25T12:34:56Z',
end: '2021-12-25T12:45:56Z'
},
opponent: {
id: '123',
name: 'collin',
@ -28,17 +29,36 @@ describe('request', () => {
expect(() => validateRequest(undefined)).toThrowError(new ValidationError('Invalid request', ValidationErrorCode.UNDEFINED_REQUEST_BODY))
})
test('should fail for invalid json', () => {
const body = `A{
username: 'collin',
password: '123abc',
dateRange: {
start: '2021-12-25T12:34:56Z',
end: '2021-12-25T12:45:56Z'
},
opponent: {
id: '123',
name: 'collin',
}
}`
expect(() => validateRequest(body)).toThrowError(new ValidationError('Invalid request', ValidationErrorCode.INVALID_JSON))
})
test.each([
{ username: '', password: '1qaz2wsx', dateRanges: [{ start: '1', end: '1' }], opponent: { id: '123', name: 'abc' } },
{ password: '1qaz2wsx', dateRanges: [{ start: '1', end: '1' }], opponent: { id: '123', name: 'abc' } },
{ username: 'collin', password: '', dateRanges: [{ start: '1', end: '1' }], opponent: { id: '123', name: 'abc' } },
{ username: 'collin', dateRanges: [{ start: '1', end: '1' }], opponent: { id: '123', name: 'abc' } },
{ username: 'collin', password: '1qaz2wsx', dateRanges: [], opponent: { id: '123', name: 'abc' } },
{ username: '', password: '1qaz2wsx', dateRange: { start: '1', end: '1' }, opponent: { id: '123', name: 'abc' } },
{ password: '1qaz2wsx', dateRange: { start: '1', end: '1' }, opponent: { id: '123', name: 'abc' } },
{ username: 'collin', password: '', dateRange: { start: '1', end: '1' }, opponent: { id: '123', name: 'abc' } },
{ username: 'collin', dateRange: { start: '1', end: '1' }, opponent: { id: '123', name: 'abc' } },
{ username: 'collin', password: '1qaz2wsx', dateRange: {}, opponent: { id: '123', name: 'abc' } },
{ username: 'collin', password: '1qaz2wsx', dateRange: { start: '1' }, opponent: { id: '123', name: 'abc' } },
{ username: 'collin', password: '1qaz2wsx', dateRange: { end: '1' }, opponent: { id: '123', name: 'abc' } },
{ username: 'collin', password: '1qaz2wsx', opponent: { id: '123', name: 'abc' } },
{ username: 'collin', password: '1qaz2wsx', dateRanges: [{ start: '1', end: '1' }], opponent: { id: '', name: 'abc' } },
{ username: 'collin', password: '1qaz2wsx', dateRanges: [{ start: '1', end: '1' }], opponent: { name: 'abc' } },
{ username: 'collin', password: '1qaz2wsx', dateRanges: [{ start: '1', end: '1' }], opponent: { id: '123', name: '' } },
{ username: 'collin', password: '1qaz2wsx', dateRanges: [{ start: '1', end: '1' }], opponent: { id: '123' } },
{ username: 'collin', password: '1qaz2wsx', dateRange: { start: '1', end: '1' }, opponent: { id: '', name: 'abc' } },
{ username: 'collin', password: '1qaz2wsx', dateRange: { start: '1', end: '1' }, opponent: { name: 'abc' } },
{ username: 'collin', password: '1qaz2wsx', dateRange: { start: '1', end: '1' }, opponent: { id: '123', name: '' } },
{ username: 'collin', password: '1qaz2wsx', dateRange: { start: '1', end: '1' }, opponent: { id: '123' } },
])('should fail for body missing required values', (body) => {
expect(() => validateRequest(JSON.stringify(body))).toThrowError(new ValidationError('Invalid request', ValidationErrorCode.INVALID_REQUEST_BODY))
})
@ -47,9 +67,10 @@ describe('request', () => {
const body = JSON.stringify({
username: 'collin',
password: '123abc',
dateRanges: [
{ start: 'monkey', end: '2021-12-25T12:45:56Z' }
],
dateRange: {
start: 'monkey',
end: '2021-12-25T12:45:56Z'
},
opponent: {
id: '123',
name: 'collin',
@ -67,7 +88,7 @@ describe('request', () => {
const body = JSON.stringify({
username: 'collin',
password: '123abc',
dateRanges: [
dateRange: [
dateRange
],
opponent: {
@ -83,9 +104,10 @@ describe('request', () => {
const body = JSON.stringify({
username: 'collin',
password: '123abc',
dateRanges: [
{ start: '2021-12-25T12:34:56Z', end: '2021-12-25T12:45:56Z' }
],
dateRange: {
start: '2021-12-25T12:34:56Z',
end: '2021-12-25T12:45:56Z'
},
})
expect(() => validateRequest(body)).not.toThrow()
@ -100,9 +122,10 @@ describe('request', () => {
const body = JSON.stringify({
username: 'collin',
password: '123abc',
dateRanges: [
{ start: '2021-12-25T12:34:56Z', end: '2021-12-25T12:45:56Z' }
],
dateRange: {
start: '2021-12-25T12:34:56Z',
end: '2021-12-25T12:45:56Z'
},
opponent,
})