diff --git a/jest.config.js b/jest.config.js index 2adbbae..0a57f54 100644 --- a/jest.config.js +++ b/jest.config.js @@ -6,4 +6,5 @@ module.exports = { moduleNameMapper: { '^@src/(.*)$': '/src/$1', }, + bail: true }; \ No newline at end of file diff --git a/src/app.ts b/src/app.ts index 0aaaa42..0f5b50a 100644 --- a/src/app.ts +++ b/src/app.ts @@ -6,6 +6,7 @@ import hpp from 'hpp'; import cache from './cache'; import * as error from "./error"; import writeRouter from '@src/controller/write'; +import readRouter from '@src/controller/read'; import path from 'path'; import logger from '@src/scripts/logger'; @@ -31,11 +32,9 @@ app.get('/', (req, res) => { res.send('Hello World, via TypeScript and Node.js!'); }); -app.get('/test', (req, res) => { - process.exit(1); - res.send('Hello World 2, via TypeScript and Node.js!'); -}); + app.use('/write', writeRouter); +app.use('/read', readRouter); // use httpdocs as static folder app.use('/', express.static(path.join(__dirname, 'httpdocs'), { diff --git a/src/controller/read.ts b/src/controller/read.ts new file mode 100644 index 0000000..f17c93c --- /dev/null +++ b/src/controller/read.ts @@ -0,0 +1,34 @@ +import express, { Request, Response, NextFunction } from 'express'; +import * as file from '@src/scripts/file'; +import { create as createError } from '@src/error'; +import { validationResult, query } from 'express-validator'; + +const router = express.Router(); + +router.get('/', + [query('index').isInt().withMessage("not an integer") + .isLength({ max: 3 }).withMessage("not in range") + .toInt()], + async function getRead(req:Request, res:Response, next:NextFunction) { + const errors = validationResult(req); + if (!errors.isEmpty()) { + return createError(res, 400, JSON.stringify({errors: errors.array()}), next) + } + + const fileObj: File.Obj = file.getFile(res, next); + fileObj.content = await file.readAsJson(res, fileObj.path, next) + if (!fileObj.content || !Array.isArray(fileObj.content.entries)) { + return createError(res, undefined, `File corrupt: ${fileObj.path}`, next); + } + + let entries = fileObj.content.entries; + + if (req.query.index) { + entries = entries.slice(Number(req.query.index)); + } + + res.json({entries}); +}); + + +export default router; \ No newline at end of file diff --git a/src/tests/write.test.ts b/src/tests/integration.test.ts similarity index 59% rename from src/tests/write.test.ts rename to src/tests/integration.test.ts index b7bd9bc..2d40ced 100644 --- a/src/tests/write.test.ts +++ b/src/tests/integration.test.ts @@ -32,57 +32,57 @@ async function callServer(timestamp = new Date().getTime(), query: string, expec } - function getData(filePath: string) { - const data = fs.readFileSync(filePath); - return JSON.parse(data.toString()); - } - - function isInRange(actual: string | number, expected: number, range: number) { - return Math.abs(Number(actual) - expected) <= range; - } +function getData(filePath: string) { + const data = fs.readFileSync(filePath); + return JSON.parse(data.toString()); +} + +function isInRange(actual: string | number, expected: number, range: number) { + return Math.abs(Number(actual) - expected) <= range; +} - describe('HEAD /write', () => { - it('with all parameters correctly set it should succeed', async () => { - await callServer(undefined, "user=xx&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=180.0&key=test", 200); - }); +describe('HEAD /write', () => { + it('with all parameters correctly set it should succeed', async () => { + await callServer(undefined, "user=xx&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=180.0&key=test", 200); + }); - it('without key it sends 403', async () => { - await callServer(undefined, "user=xx&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=180.0", 403); - }); + it('without key it sends 403', async () => { + await callServer(undefined, "user=xx&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=180.0", 403); + }); - it('with user length not equal to 2 it sends 422', async () => { - await callServer(undefined, "user=x&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=180.0&key=test", 422); - }); + it('with user length not equal to 2 it sends 422', async () => { + await callServer(undefined, "user=x&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=180.0&key=test", 422); + }); - it('with lat not between -90 and 90 it sends 422', async () => { - await callServer(undefined, "user=xx&lat=91.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=180.0&key=test", 422); - }); + it('with lat not between -90 and 90 it sends 422', async () => { + await callServer(undefined, "user=xx&lat=91.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=180.0&key=test", 422); + }); - it('with lon not between -180 and 180 it sends 422', async () => { - await callServer(undefined, "user=xx&lat=45.000&lon=181.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=180.0&key=test", 422); - }); + it('with lon not between -180 and 180 it sends 422', async () => { + await callServer(undefined, "user=xx&lat=45.000&lon=181.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=180.0&key=test", 422); + }); - it('with timestamp to old sends 422', async () => { - const timestamp = new Date().getTime() - 24 * 60 * 60 * 1000 * 2; // two days ago - await callServer(timestamp, "user=xx&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=180.0&key=test", 422); - }) + it('with timestamp to old sends 422', async () => { + const timestamp = new Date().getTime() - 24 * 60 * 60 * 1000 * 2; // two days ago + await callServer(timestamp, "user=xx&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=180.0&key=test", 422); + }) - it('with hdop not between 0 and 100 it sends 422', async () => { - await callServer(undefined, "user=xx&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=101.0&altitude=5000.000&speed=150.000&heading=180.0&key=test", 422); - }); + it('with hdop not between 0 and 100 it sends 422', async () => { + await callServer(undefined, "user=xx&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=101.0&altitude=5000.000&speed=150.000&heading=180.0&key=test", 422); + }); - it('with altitude not between 0 and 10000 it sends 422', async () => { - await callServer(undefined, "user=xx&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=10001.000&speed=150.000&heading=180.0&key=test", 422); - }); + it('with altitude not between 0 and 10000 it sends 422', async () => { + await callServer(undefined, "user=xx&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=10001.000&speed=150.000&heading=180.0&key=test", 422); + }); - it('with speed not between 0 and 300 it sends 422', async () => { - await callServer(undefined, "user=xx&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=301.000&heading=180.0&key=test", 422); - }); + it('with speed not between 0 and 300 it sends 422', async () => { + await callServer(undefined, "user=xx&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=301.000&heading=180.0&key=test", 422); + }); - it('with heading not between 0 and 360 it sends 422', async () => { - await callServer(undefined, "user=xx&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=361.0&key=test", 422); - }); - }); + it('with heading not between 0 and 360 it sends 422', async () => { + await callServer(undefined, "user=xx&lat=45.000&lon=90.000×tamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=361.0&key=test", 422); + }); +}); describe("GET /write", () => { @@ -180,7 +180,7 @@ describe("GET /write", () => { jsonData = getData(filePath); entry = jsonData.entries[1]; // same data point, but not last now therefore ignore true expect(entry.ignore).toBe(true); - }); + }); }); describe('API calls', () => { @@ -200,4 +200,41 @@ describe('API calls', () => { const jsonData = getData(filePath); expect(jsonData.entries.length).toBeLessThanOrEqual(1000); }); +}); + + +describe('/read', () => { + test(`returns json`, async () => { + const response = await axios.get("http://localhost:80/read?index=0"); + expect(response.status).toBe(200); + expect(response.headers['content-type']).toEqual(expect.stringContaining('application/json')); + }); + test(`index parameter to long`, async () => { + try { + await axios.get("http://localhost:80/read?index=1234"); + } catch (error) { + const axiosError = error as AxiosError; + if (axiosError.response) { + expect(axiosError.response.status).toBe(400); + } else { + console.error(axiosError); + } + } + }); + test(`index parameter to be a number`, async () => { + try { + await axios.get("http://localhost:80/read?index=a9"); + } catch (error) { + const axiosError = error as AxiosError; + if (axiosError.response) { + expect(axiosError.response.status).toBe(400); + } else { + console.error(axiosError); + } + } + }); + test(`index parameter reduces length of json`, async () => { + const response = await axios.get("http://localhost:80/read?index=999"); + expect(response.data.entries.length).toBe(1); + }); }); \ No newline at end of file