Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ module.exports = {
moduleNameMapper: {
'^@src/(.*)$': '<rootDir>/src/$1',
},
bail: true
};
7 changes: 3 additions & 4 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -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'), {
Expand Down
34 changes: 34 additions & 0 deletions src/controller/read.ts
Original file line number Diff line number Diff line change
@@ -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;
121 changes: 79 additions & 42 deletions src/tests/write.test.ts → src/tests/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=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&timestamp=R3Pl4C3&hdop=50.0&altitude=5000.000&speed=150.000&heading=361.0&key=test", 422);
});
});


describe("GET /write", () => {
Expand Down Expand Up @@ -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', () => {
Expand All @@ -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");

Check notice

Code scanning / devskim

Accessing localhost could indicate debug code, or could hinder scaling.

Do not leave debug code in production
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");

Check notice

Code scanning / devskim

Accessing localhost could indicate debug code, or could hinder scaling.

Do not leave debug code in production
} 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");

Check notice

Code scanning / devskim

Accessing localhost could indicate debug code, or could hinder scaling.

Do not leave debug code in production
} 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");

Check notice

Code scanning / devskim

Accessing localhost could indicate debug code, or could hinder scaling.

Do not leave debug code in production
expect(response.data.entries.length).toBe(1);
});
});