From 3853582d8502d2a057b08b51c8314f7740ff6c24 Mon Sep 17 00:00:00 2001 From: PrabalSingh Date: Fri, 22 May 2020 13:18:32 +0530 Subject: [PATCH 1/3] feat(poll): add endpoint for polling --- src/routes/api/index.ts | 2 ++ src/routes/api/result/controller.ts | 19 +++++++++++++++++++ src/routes/api/result/index.ts | 8 ++++++++ 3 files changed, 29 insertions(+) create mode 100644 src/routes/api/result/controller.ts create mode 100644 src/routes/api/result/index.ts diff --git a/src/routes/api/index.ts b/src/routes/api/index.ts index 4f93a40..2d6d7bb 100644 --- a/src/routes/api/index.ts +++ b/src/routes/api/index.ts @@ -1,6 +1,7 @@ import { NextFunction, Request, Response, Router } from 'express' import run from './run' import submit from './submit' +import result from './result' import { route as langs } from './langs' import { checkValidApiKey } from '../../validators/ApiKeyValidators' import * as debug from 'debug' @@ -26,6 +27,7 @@ route.use((req: Request, res: Response, next: NextFunction) => { }) route.use('/runs', run) +route.use('/result', result) route.use('/submissions', submit) route.use('/langs', langs) diff --git a/src/routes/api/result/controller.ts b/src/routes/api/result/controller.ts new file mode 100644 index 0000000..6d7ff12 --- /dev/null +++ b/src/routes/api/result/controller.ts @@ -0,0 +1,19 @@ +import {Request, Response} from "express"; +import DB from 'models' + +export default { + async sendResult(req: Request, res: Response) { + const submissionId = req.params.id ? parseInt(req.params.id) : null + if (!submissionId) { + res.status(400).json({err: 'SubmissionId not found'}) + } + else { + DB.submissions.findByPk(submissionId) + .then((submission) => { + res.status(200).json(submission.results) + }).catch((err) => { + res.status(404).json({err: 'Submission not found'}) + }) + } + } +} \ No newline at end of file diff --git a/src/routes/api/result/index.ts b/src/routes/api/result/index.ts new file mode 100644 index 0000000..1298bec --- /dev/null +++ b/src/routes/api/result/index.ts @@ -0,0 +1,8 @@ +import { Router } from 'express' +import Controller from './controller' + +const router: Router = Router() + +router.get('/:id', Controller.sendResult) + +export default router From 4e93fe97051909c4f0d5c9031ecfccac70203d6a Mon Sep 17 00:00:00 2001 From: PrabalSingh Date: Fri, 22 May 2020 13:18:51 +0530 Subject: [PATCH 2/3] tests: add tests for polling --- test/e2e/ResultScenario.spec.ts | 80 +++++++++++++++++++++++++++++++++ test/e2e/RunScenario.spec.ts | 7 ++- test/e2e/SubmitScenario.spec.ts | 7 ++- test/utils/utils.ts | 4 ++ 4 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 test/e2e/ResultScenario.spec.ts diff --git a/test/e2e/ResultScenario.spec.ts b/test/e2e/ResultScenario.spec.ts new file mode 100644 index 0000000..b1e3fb8 --- /dev/null +++ b/test/e2e/ResultScenario.spec.ts @@ -0,0 +1,80 @@ +import app from '../../src/server'; +import DB from '../../src/models'; +import * as utils from "../utils/utils"; + +const chai = require('chai'); +const chaiHttp = require('chai-http'); + +chai.use(chaiHttp); +const {expect} = chai; + +const APIKEY = '7718330d2794406c980bdbded6c9dc1d'; + +describe('GET api/result/:id', () => { + before(async () => { + await DB.apikeys.create({ + id: 1, + key: APIKEY, + whitelist_domains: ['*'], + whitelist_ips: ['*'] + }); + }); + after(utils.truncateTables); + + + it('should throw 403 error API key is absent in the request', async () => { + const res = await chai.request(app).get(`/api/result/1`); + expect(res.status).to.equal(403); + expect(res.body.message).to.equal('No API Key in request'); + }); + + it('should throw error if incorrect API key is present', async () => { + const res = await chai.request(app).get('/api/result/1').set({ + 'Authorization': 'Bearer incorrectAPI-KEY', + Accept: 'application/json' + }); + expect(res.status).to.equal(403); + expect(res.body.message).to.equal('Invalid API Key'); + }); + + it('should throw 404 error if POST request is made', async () => { + const res = await chai.request(app).post('/api/result/1').set({ + Authorization: 'Bearer 7718330d2794406c980bdbded6c9dc1d', + Accept: 'application/json' + }); + expect(res.status).to.equal(404); + }); + + it('should throw 404 error resultId is not present', async () => { + const res = await chai.request(app).get('/api/result').set({ + Authorization: `Bearer ${APIKEY}`, + Accept: 'application/json' + }); + + expect(res.status).to.equal(404); + }); + + it('should throw 404 error if result is not found ', async () => { + const res = await chai.request(app).get('/api/result/12').set({ + Authorization: `Bearer ${APIKEY}`, + Accept: 'application/json' + }); + + expect(res.status).to.equal(404); + }); + + it('should return correct result if everything is correct', async () => { + const submission = await DB.submissions.create({ + lang: 'cpp', + mode: 'poll', + results: {stdout: 'SUCCESS'} + }); + const res = await chai.request(app).get(`/api/result/${submission.id}`).set({ + Authorization: `Bearer ${APIKEY}`, + Accept: 'application/json' + }); + + expect(res.status).to.equal(200); + expect(res.body).to.deep.equal(submission.results); + }); +}); \ No newline at end of file diff --git a/test/e2e/RunScenario.spec.ts b/test/e2e/RunScenario.spec.ts index a07336d..d8e4d9c 100644 --- a/test/e2e/RunScenario.spec.ts +++ b/test/e2e/RunScenario.spec.ts @@ -172,11 +172,14 @@ describe('POST api/runs', () => { // there is a delay of 1000 for onSuccess, so setting 2000ms delay here. await delay(2000); - const submission = await DB.submissions.findById(res.body.id); + const resultResponse = await chai.request(app).get(`/api/result/${res.body.id}`).set({ + Authorization: 'Bearer 7718330d2794406c980bdbded6c9dc1d', + Accept: 'application/json' + }).send(params); expect(res.body.id).to.exist; expect(res.status).to.equal(200); - expect(submission.results.stdout).to.equal(expectedOutput); + expect(resultResponse.body.stdout).to.equal(expectedOutput); }); it('should return id and send result to callback url in callback mode', async () => { diff --git a/test/e2e/SubmitScenario.spec.ts b/test/e2e/SubmitScenario.spec.ts index 1a45f1d..ce2c2b4 100644 --- a/test/e2e/SubmitScenario.spec.ts +++ b/test/e2e/SubmitScenario.spec.ts @@ -172,11 +172,14 @@ describe('POST api/submissions', () => { // there is a delay of 1000 for onSuccess, so setting 2000ms delay here. await delay(2000); - const submission = await DB.submissions.findById(res.body.id); + const resultResponse = await chai.request(app).get(`/api/result/${res.body.id}`).set({ + Authorization: 'Bearer 7718330d2794406c980bdbded6c9dc1d', + Accept: 'application/json' + }).send(params); expect(res.body.id).to.exist; expect(res.status).to.equal(200); - expect(submission.results.result).to.equal(expectedResult); + expect(resultResponse.body.result).to.equal(expectedResult); }); it('should return id and send result to callback url in callback mode', async () => { diff --git a/test/utils/utils.ts b/test/utils/utils.ts index 34eb868..393e662 100644 --- a/test/utils/utils.ts +++ b/test/utils/utils.ts @@ -48,4 +48,8 @@ export async function truncateTables() { await DB.apikeys.destroy({truncate: true}); await DB.langs.destroy({truncate: true}); await DB.submissions.destroy({truncate: true}); +} + +export function delay(ms: number) { + return new Promise( resolve => setTimeout(resolve, ms) ); } \ No newline at end of file From 4d94076d56fa94f49677c7b4f9f50188a4968695 Mon Sep 17 00:00:00 2001 From: PrabalSingh Date: Fri, 22 May 2020 13:48:30 +0530 Subject: [PATCH 3/3] shift delay function to util.ts --- src/routes/api/result/controller.ts | 27 +++++++++++++-------------- test/e2e/RunScenario.spec.ts | 9 ++------- test/e2e/SubmitScenario.spec.ts | 9 ++------- 3 files changed, 17 insertions(+), 28 deletions(-) diff --git a/src/routes/api/result/controller.ts b/src/routes/api/result/controller.ts index 6d7ff12..789509e 100644 --- a/src/routes/api/result/controller.ts +++ b/src/routes/api/result/controller.ts @@ -1,19 +1,18 @@ -import {Request, Response} from "express"; +import {Request, Response} from 'express'; import DB from 'models' export default { - async sendResult(req: Request, res: Response) { - const submissionId = req.params.id ? parseInt(req.params.id) : null - if (!submissionId) { - res.status(400).json({err: 'SubmissionId not found'}) - } - else { - DB.submissions.findByPk(submissionId) - .then((submission) => { - res.status(200).json(submission.results) - }).catch((err) => { - res.status(404).json({err: 'Submission not found'}) - }) - } + async sendResult(req: Request, res: Response) { + const submissionId = req.params.id ? parseInt(req.params.id) : null + if (!submissionId) { + res.status(400).json({err: 'SubmissionId not found'}) + } else { + DB.submissions.findByPk(submissionId) + .then((submission) => { + res.status(200).json(submission.results) + }).catch((err) => { + res.status(404).json({err: 'Submission not found'}) + }) } + } } \ No newline at end of file diff --git a/test/e2e/RunScenario.spec.ts b/test/e2e/RunScenario.spec.ts index d8e4d9c..fb80c48 100644 --- a/test/e2e/RunScenario.spec.ts +++ b/test/e2e/RunScenario.spec.ts @@ -23,11 +23,6 @@ const source = ` const stdin = 'Success'; const expectedOutput = 'Success'; - -function delay(ms: number) { - return new Promise( resolve => setTimeout(resolve, ms) ); -} - describe('POST api/runs', () => { before(async () => { await DB.apikeys.create({ @@ -171,7 +166,7 @@ describe('POST api/runs', () => { expect(res.status).to.equal(200); // there is a delay of 1000 for onSuccess, so setting 2000ms delay here. - await delay(2000); + await utils.delay(2000); const resultResponse = await chai.request(app).get(`/api/result/${res.body.id}`).set({ Authorization: 'Bearer 7718330d2794406c980bdbded6c9dc1d', Accept: 'application/json' @@ -209,7 +204,7 @@ describe('POST api/runs', () => { app2.use('/', router); }); - await delay(2000); + await utils.delay(2000); expect(res.body.id).to.exist; expect(res.status).to.equal(200); diff --git a/test/e2e/SubmitScenario.spec.ts b/test/e2e/SubmitScenario.spec.ts index ce2c2b4..39105c5 100644 --- a/test/e2e/SubmitScenario.spec.ts +++ b/test/e2e/SubmitScenario.spec.ts @@ -35,11 +35,6 @@ const testcases = [ ]; const expectedResult = 'Success'; - -function delay(ms: number) { - return new Promise( resolve => setTimeout(resolve, ms) ); -} - describe('POST api/submissions', () => { before(async () => { await DB.apikeys.create({ @@ -171,7 +166,7 @@ describe('POST api/submissions', () => { // there is a delay of 1000 for onSuccess, so setting 2000ms delay here. - await delay(2000); + await utils.delay(2000); const resultResponse = await chai.request(app).get(`/api/result/${res.body.id}`).set({ Authorization: 'Bearer 7718330d2794406c980bdbded6c9dc1d', Accept: 'application/json' @@ -210,7 +205,7 @@ describe('POST api/submissions', () => { app2.use('/', router); }); - await delay(2000); + await utils.delay(2000); expect(res.body.id).to.exist; expect(res.status).to.equal(200);