# 23T1 tut05 test ```javascript= import request, { HttpVerb } from 'sync-request'; import { port, url } from './src/config.json'; const SERVER_URL = `${url}:${port}`; interface PersonAddReturn { personId: number; } /** * Make an object that has the error structure together with a status code, as this will * be compared with errors that the requestHelper function will create.. */ const makeCustomErrorForTest = (status: number) => ({ status, error: expect.any(String) }); /** * Sends a request to the given route and return its results * Errors will be returned in the form { status: number, error: string } */ const requestHelper = (method: HttpVerb, path: string, payload: object) => { let qs = {}; let body = {}; if (['GET', 'DELETE'].includes(method)) { qs = payload; } else { // PUT/POST body = payload; } const res = request(method, SERVER_URL + path, { qs, body, timeout: 20000 }); const bodyString = res.body.toString(); let bodyObject: any; try { // Return if valid JSON bodyObject = JSON.parse(bodyString); } catch (error: any) { bodyObject = { error: `Server responded with ${res.statusCode}, but body is not JSON! Given: ${bodyString}. Reason: ${error.message}. HINT: Did you res.json(undefined)?` }; } if ('error' in bodyObject) { return { status: res.statusCode, ...bodyObject }; } return bodyObject; }; // ========================================================================= // // Wrapper functions const requestPeopleAdd = (id: int, name: string, age: number) => { return requestHelper('PUT', `/people/add/add/${id}`, {name,age}); }; const requestPeopleList = (minAge: number) => { return ''; }; const requestPersonView = (personId: number) => { return ''; }; const requestPersonEdit = (personId: number, name: string, age: number) => { return ''; }; const requestPersonRemove = (personId: number) => { return ''; }; const requestPeopleStats = () => { return ''; }; const requestClear = () => { return ''; }; // ========================================================================= // beforeEach(() => { requestClear(); }); describe('/people/add', () => { describe('error', () => { test.each([ { name: '', age: 20 }, { name: 'valid', age: 0 }, ])('name=$name, age=$age', ({ name, age }) => { expect(requestPeopleAdd(name, age)).toStrictEqual(makeCustomErrorForTest(400)); }); }); test('return value', () => { const person = requestPeopleAdd('valid', 20); expect(person).toStrictEqual({ personId: expect.any(Number)}); expect(requestPeopleList(0)).toStrictEqual({ people: [{ personId: person.personId, name: 'valid', age: 20 }] }); }); }); describe('/people/list', () => { describe('minAge 0', () => { test('empty', () => { expect(requestPeopleList(0)).toStrictEqual({ people: [] }); }); test('one item', () => { const { personId } = requestPeopleAdd('one', 1); expect(requestPeopleList(0)).toStrictEqual({ people: [{ personId, name: 'one', age: 1 }] }); }); test('multiple items', () => { const p1 = requestPeopleAdd('alsothree', 3); const p2 = requestPeopleAdd('two', 2); const p3 = requestPeopleAdd('one', 1); const p4 = requestPeopleAdd('three', 3); expect(requestPeopleList(0)).toStrictEqual({ people: [ { personId: p1.personId, name: 'alsothree', age: 3 }, { personId: p4.personId, name: 'three', age: 3 }, { personId: p2.personId, name: 'two', age: 2 }, { personId: p3.personId, name: 'one', age: 1 }, ] }); }); }); describe('with minAge', () => { test('error: minAge negative', () => { requestPeopleAdd('three', 3); expect(requestPeopleList(-1)).toStrictEqual(makeCustomErrorForTest(400)); }); test('higher minAge than existing people means empty', () => { requestPeopleAdd('three', 3); expect(requestPeopleList(4)).toStrictEqual({ people: [] }); }); test('minAge filter', () => { requestPeopleAdd('three', 3); const p2 = requestPeopleAdd('five', 5); expect(requestPeopleList(4)).toStrictEqual({ people: [{ personId: p2.personId, name: 'five', age: 5 }] }); }); }); }); describe('GET /person/:personid', () => { let person: PersonAddReturn; beforeEach(() => { person = requestPeopleAdd('Tam', 22); }); describe('error', () => { test('does not exist', () => { expect(requestPersonView(person.personId + 1)).toStrictEqual(makeCustomErrorForTest(400)); }); }); describe('success', () => { test('valid view', () => { expect(requestPersonView(person.personId)).toStrictEqual({ person: { personId: person.personId, name: 'Tam', age: 22, } }); }); }); }); describe('PUT /person/:personid', () => { let person: PersonAddReturn; beforeEach(() => { person = requestPeopleAdd('Tam', 22); }); describe('error', () => { test('does not exist', () => { expect(requestPersonEdit(person.personId + 1, 'invalid', 20)).toStrictEqual(makeCustomErrorForTest(400)); }); test('negative age', () => { expect(requestPersonEdit(person.personId, 'valid', -20)).toStrictEqual(makeCustomErrorForTest(400)); }); test('empty name', () => { expect(requestPersonEdit(person.personId, '', 20)).toStrictEqual(makeCustomErrorForTest(400)); }); test('name already taken', () => { requestPeopleAdd('Rani', 22); expect(requestPersonEdit(person.personId, 'Rani', 20)).toStrictEqual(makeCustomErrorForTest(400)); }); }); test('successful edit', () => { expect(requestPeopleList(0)).toStrictEqual({ people: [{ personId: person.personId, name: 'Tam', age: 22 }] }); expect(requestPersonEdit(person.personId, 'valid', 20)).toStrictEqual({}); expect(requestPeopleList(0)).toStrictEqual({ people: [{ personId: person.personId, name: 'valid', age: 20 }] }); }); test('editing just age is okay', () => { expect(requestPeopleList(0)).toStrictEqual({ people: [{ personId: person.personId, name: 'Tam', age: 22 }] }); expect(requestPersonEdit(person.personId, 'Tam', 20)).toStrictEqual({}); expect(requestPeopleList(0)).toStrictEqual({ people: [{ personId: person.personId, name: 'Tam', age: 20 }] }); }); }); describe('DELETE person/:personid', () => { let person: PersonAddReturn; beforeEach(() => { person = requestPeopleAdd('Tam', 22); }); describe('error', () => { test('does not exist', () => { expect(requestPersonRemove(person.personId + 1)).toStrictEqual(makeCustomErrorForTest(400)); }); test('double remove', () => { expect(requestPersonRemove(person.personId)).toStrictEqual({}); expect(requestPersonRemove(person.personId)).toStrictEqual(makeCustomErrorForTest(400)); }); }); test('successful remove', () => { expect(requestPeopleList(0)).toStrictEqual({ people: [{ personId: person.personId, name: 'Tam', age: 22 }] }); requestPersonRemove(person.personId); expect(requestPeopleList(0)).toStrictEqual({ people: [] }); }); }); describe('/getstats', () => { describe('error', () => { test('empty data', () => { expect(requestPeopleStats()).toStrictEqual(makeCustomErrorForTest(400)); }); }); test('single entry', () => { requestPeopleAdd('valid', 10); expect(requestPeopleStats()).toStrictEqual({ stats: { minAge: 10, maxAge: 10, averageAge: 10, } }); }); test('multiple entries', () => { requestPeopleAdd('one', 1); requestPeopleAdd('five', 5); requestPeopleAdd('three', 3); requestPeopleAdd('two', 2); requestPeopleAdd('four', 4); expect(requestPeopleStats()).toStrictEqual({ stats: { minAge: 1, maxAge: 5, averageAge: 3, } }); }); }); describe('clear', () => { test('clear on empty', () => { expect(requestClear()).toStrictEqual({}); }); test('clear success', () => { requestPeopleAdd('one', 1); expect(requestClear()).toStrictEqual({}); expect(requestPeopleList(0)).toStrictEqual({ people: [] }); }); }); ```