Merge branch 'v2.0-dev' as v2.0.0
[squeep-api-dingus] / test / lib / dingus.js
index 12f40e8a83dad33690f7bbc535d68dfc19a4c9c3..9d471229d3a26ebde87ebfae9d53efbde46c9aaa 100644 (file)
@@ -7,15 +7,20 @@ const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-requi
 const fs = require('fs');
 
 const Dingus = require('../../lib/dingus');
-const { DingusError } = require('../../lib/errors');
+const { DingusError, RouterNoMethodError } = require('../../lib/errors');
 const Enum = require('../../lib/enum');
 
 const noExpectedException = 'did not get expected exception';
 
+const noLogger = {
+  debug: () => {},
+  error: () => {},
+};
+
 describe('Dingus', function () {
   let dingus;
   beforeEach(function () {
-    dingus = new Dingus();
+    dingus = new Dingus(noLogger, {});
   });
   afterEach(function () {
     sinon.restore();
@@ -23,7 +28,7 @@ describe('Dingus', function () {
 
   describe('constructor', function () {
     it('covers', function () {
-      const d = new Dingus({}, {});
+      const d = new Dingus();
       assert(d);
     });
   }); // constructor
@@ -36,7 +41,7 @@ describe('Dingus', function () {
     });
     it('returns normal path', function () {
       const p = '////a///b/./bar/..///c';
-      const expected = '/a/b/c'
+      const expected = '/a/b/c';
       const r = dingus._normalizePath(p);
       assert.strictEqual(r, expected);
     });
@@ -152,7 +157,7 @@ describe('Dingus', function () {
       const expected = {
         clientAddress: '',
         clientProtocol: 'http',
-      }
+      };
       dingus.clientAddressContext(req, res, ctx);
       assert.deepStrictEqual(ctx, expected);
       assert(!req.getHeader.called);
@@ -162,7 +167,7 @@ describe('Dingus', function () {
       const expected = {
         clientAddress: '::1',
         clientProtocol: 'https',
-      }
+      };
       req.connection.remoteAddress = '::1';
       req.connection.encrypted = true;
       dingus.clientAddressContext(req, res, ctx);
@@ -350,6 +355,7 @@ describe('Dingus', function () {
       sinon.spy(dingus, 'handlerNotFound');
       sinon.spy(dingus, 'handlerBadRequest');
       sinon.spy(dingus, 'handlerInternalServerError');
+      sinon.spy(Dingus, 'setHeadHandler');
       stubHandler = sinon.stub();
     });
     afterEach(function () {
@@ -455,6 +461,40 @@ describe('Dingus', function () {
       assert.strictEqual(stubHandler.args[0][3], 'foo');
       assert.strictEqual(stubHandler.args[0][4], 'bar');
     });
+    describe('intrinsic HEAD handling', function () {
+      it('covers no intrinsic HEAD handling', async function () {
+        dingus.intrinsicHeadMethod = false;
+        dingus.on('GET', '/', stubHandler);
+        req.method = 'HEAD';
+        await dingus.dispatch(req, res, ctx);
+        assert(!stubHandler.called);
+        assert(dingus.handlerMethodNotAllowed.called);
+      });
+      it('calls HEAD setup and GET handler', async function () {
+        dingus.on('GET', '/', stubHandler);
+        req.method = 'HEAD';
+        await dingus.dispatch(req, res, ctx);
+        assert(Dingus.setHeadHandler.called);
+        assert(stubHandler.called);
+      });
+      it('covers no GET handler', async function () {
+        dingus.on('POST', '/', stubHandler);
+        req.method = 'HEAD';
+        await dingus.dispatch(req, res, ctx);
+        assert(!stubHandler.called);
+        assert(dingus.handlerMethodNotAllowed.called);
+      });
+      it('covers unexpected router error', async function () {
+        sinon.stub(dingus.router, 'lookup')
+          .onFirstCall().throws(new RouterNoMethodError())
+          .onSecondCall().throws(new DingusError())
+        ;
+        dingus.on('GET', '/', stubHandler);
+        req.method = 'HEAD';
+        await dingus.dispatch(req, res, ctx);
+        assert(dingus.handlerInternalServerError.called);
+      });
+    });
   }); // dispatch
 
   describe('parseBody', function () {
@@ -472,14 +512,14 @@ describe('Dingus', function () {
     });
     it('parses json', function () {
       const src = { foo: 'bar' };
-      ctx.rawBody = JSON.stringify(src);
-      dingus.parseBody(Enum.ContentType.ApplicationJson, ctx);
+      const rawBody = JSON.stringify(src);
+      dingus.parseBody(Enum.ContentType.ApplicationJson, ctx, rawBody);
       assert.deepStrictEqual(ctx.parsedBody, src);
     });
     it('handles unparsable json', function () {
-      ctx.rawBody = 'not json';
+      const rawBody = 'not json';
       try {
-        dingus.parseBody(Enum.ContentType.ApplicationJson, ctx);
+        dingus.parseBody(Enum.ContentType.ApplicationJson, ctx, rawBody);
         assert.fail(noExpectedException);
       } catch (e) {
         assert.strictEqual(e.statusCode, 400);
@@ -489,8 +529,8 @@ describe('Dingus', function () {
       const expected = Object.assign(Object.create(null), {
         foo: 'bar',
       });
-      ctx.rawBody = 'foo=bar';
-      dingus.parseBody('application/x-www-form-urlencoded', ctx);
+      const rawBody = 'foo=bar';
+      dingus.parseBody('application/x-www-form-urlencoded', ctx, rawBody);
       assert.deepStrictEqual(ctx.parsedBody, expected);
     });
 
@@ -549,7 +589,7 @@ describe('Dingus', function () {
       const req = {};
       const res = {};
       const ctx = {};
-      sinon.stub(dingus, 'bodyData').resolves('{"foo":"bar"}')
+      sinon.stub(dingus, 'bodyData').resolves('{"foo":"bar"}');
       sinon.stub(Dingus, 'getRequestContentType').returns(Enum.ContentType.ApplicationJson);
       await dingus.ingestBody(req, res, ctx);
       assert.deepStrictEqual(ctx.parsedBody, { foo: 'bar' });