diff --git a/src/util.js b/src/util.js index 2d23109..267cba6 100644 --- a/src/util.js +++ b/src/util.js @@ -25,6 +25,18 @@ const bootstrapKoaApp = () => { const isValidDate = date => Object.prototype.toString.call(date) === '[object Date]' && !isNaN(date.getTime()); +const repeatPerKey = (keys = {}) => count => (key, fn) => () => { + if (!(key in keys)) { + keys[key] = 0; + } + if (keys[key] < count) { + fn(); + keys[key]++; + } +}; + +const oncePerKey = repeatPerKey()(1); + class AsyncCounter { constructor(countTimes) { let currentCount = 0; @@ -45,4 +57,4 @@ class AsyncCounter { } } -export {bootstrapKoaApp, isValidDate, AsyncCounter}; +export {bootstrapKoaApp, isValidDate, oncePerKey, AsyncCounter}; diff --git a/test.js b/test.js index 89ecf96..59cfc32 100644 --- a/test.js +++ b/test.js @@ -1,7 +1,7 @@ const {promisify} = require('util'); const test = require('ava'); const request = require('supertest'); -const {bootstrapKoaApp, AsyncCounter} = require('./src/util'); +const {bootstrapKoaApp, oncePerKey, AsyncCounter} = require('./src/util'); const agendaAppUrl = 'http://localhost:4041'; const testAppUrl = 'http://localhost:4042'; @@ -54,36 +54,44 @@ test.serial('PUT /api/job succeeds when the job exists', async t => { t.is(res.status, 200); }); -let counter; +const fooProps = {}; + +const defineFooEndpoint = (route, message, countTimes = 1, statusCode = 200) => { + const counter = new AsyncCounter(countTimes); + fooProps.counter = counter; + fooProps.message = message; + fooProps.statusCode = statusCode; + + const define = oncePerKey(route, () => testAppRouter.post(route, async (ctx, next) => { + ctx.body = fooProps.message; + ctx.status = fooProps.statusCode; + console.log(`${fooProps.message}! ${await fooProps.counter.count()} of ${fooProps.counter.countTimes}`); + await next(); + })); + define(); + return counter; +}; -testAppRouter.post('/foo', async (ctx, next) => { - ctx.body = 'foo success'; - ctx.status = 200; - console.log(`foo invoked! ${await counter.count()} of ${counter.countTimes} times`); - await next(); -}); /* TODO -const defineEndpointFooParam = done => testAppRouter.post('/foo/:fooParam', async (ctx, next) => { +testAppRouter.post('/foo/:fooParam', async (ctx, next) => { console.log('foo with params invoked!'); console.log(ctx.params); console.log(ctx.request.body); ctx.body = 'foo with params success'; ctx.status = 200; - done(); await next(); }); -const defineEndpointFooCallback = done => testAppRouter.post('/foo/cb', async (ctx, next) => { +testAppRouter.post('/foo/cb', async (ctx, next) => { console.log('foo callback invoked!'); ctx.body = 'foo callback success'; ctx.status = 200; - done(); await next(); }); */ test.serial('POST /api/job/now with existing foo definition invokes the foo endpoint', async t => { - counter = new AsyncCounter(1); + const counter = defineFooEndpoint('/foo', 'foo now invoked'); const res = await agendaAppRequest .post('/api/job/now') .send({name: 'foo'}); @@ -94,7 +102,7 @@ test.serial('POST /api/job/now with existing foo definition invokes the foo endp }); test.serial('POST /api/job/every with existing foo definition invokes the foo endpoint', async t => { - counter = new AsyncCounter(3); + const counter = defineFooEndpoint('/foo', 'foo every invoked', 3); const res = await agendaAppRequest .post('/api/job/every') .send({name: 'foo', interval: '2 seconds'}); @@ -104,6 +112,18 @@ test.serial('POST /api/job/every with existing foo definition invokes the foo en await counter.finished; }); +test.serial('POST /api/job/once with existing foo definition invokes the foo endpoint', async t => { + const counter = defineFooEndpoint('/foo', 'foo once invoked'); + const res = await agendaAppRequest + .post('/api/job/once') + .send({name: 'foo', interval: new Date().getTime() + 10000}); + // .send({name: 'foo', interval: 'in 10 seconds'}); + + t.is(res.text, 'job scheduled for once'); + + await counter.finished; +}); + test.serial('DELETE /api/job succeeds when a job is defined', async t => { const res = await agendaAppRequest .delete('/api/job/foo');