All files / server/test run.js

93.42% Statements 71/76
85.71% Branches 36/42
93.33% Functions 14/15
95.45% Lines 63/66
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 14824x 24x 24x     24x     105x     105x     105x 105x       105x 7x       105x           24x       98x                   98x 98x     98x     98x         98x         24x     198x 99x     99x     98x   98x 13x 11x       98x   97x 96x   97x 92x   92x 92x 92x 92x 7x 7x   92x     92x     92x     99x   5x 5x 5x 5x 20x 13x 12x 12x 12x 3x 3x     12x 12x   5x             5x             4x     99x 99x 99x 99x 99x       24x  
const server = require('../');
const request = require('request-promises');
const port = require('./port');
 
// Make an object with the options as expected by request()
const normalize = (method, url, port, options) => {
 
  // Make sure it's a simple object
  Iif (typeof options === 'string') options = { url: options };
 
  // Assign independent parts
  options = Object.assign({}, options, { url, method });
 
  // Make sure it has a right URL or localhost otherwise
  Eif (!/^https?:\/\//.test(options.url)) {
    options.url = `http://localhost:${port}${options.url}`;
  }
 
  // Set it to send a JSON when appropriate
  if (options.body && typeof options.body === 'object') {
    options.json = true;
  }
 
  // Finally return the fully formed object
  return options;
};
 
 
 
// Parse the server options
const serverOptions = async middle => {
  // First parameter can be:
  // - options: Number || Object (cannot be ID'd)
  // - middleware: undefined || null || Boolean || Function || Array
  let opts = (
    typeof middle[0] === 'undefined' ||
    typeof middle[0] === 'boolean' ||
    typeof middle[0] === 'string' ||
    middle[0] === null ||
    middle[0] instanceof Function ||
    middle[0] instanceof Array
  ) ? {} : middle.shift();
 
  // In case the port is the defaults one
  let synthetic = !opts || !opts.port;
  await opts;
 
  // Create the port when none was specified
  if (synthetic) opts.port = port();
 
  // Be able to set global variables from outside
  opts = Object.assign({}, opts, module.exports.options || {}, {
    env: undefined,
    secret: undefined
  });
 
  return opts;
};
 
 
 
module.exports = function (...middle) {
 
  // Make sure we are working with an instance
  if (!(this instanceof (module.exports))) {
    return new (module.exports)(...middle);
  }
 
  const launch = async (method, url, reqOpts) => {
 
    // Parse the server options
    const opts = await serverOptions(middle);
 
    const error = server.router.error(ctx => {
      if (!ctx.res.headersSent) {
        return server.reply.status(500).send(ctx.error.message);
      }
    });
 
    const ctx = await server(opts, middle, opts.raw ? false : error);
 
    ctx.close = () => new Promise((resolve, reject) => {
      ctx.server.close(err => err ? reject(err) : resolve());
    });
    if (!method) return ctx;
    const res = await request(normalize(method, url, ctx.options.port, reqOpts));
    // Fix small bug. TODO: report it
    res.method = res.request.method;
    res.status = res.statusCode;
    res.options = ctx.options;
    if (/application\/json/.test(res.headers['content-type']) && typeof res.body === 'string') {
      res.rawBody = res.body;
      res.body = JSON.parse(res.body);
    }
    res.ctx = ctx;
 
    // Close the server once it has all finished
    await ctx.close();
 
    // Return the response that happened from the server
    return res;
  }
 
  this.alive = async cb => {
    let instance;
    try {
      instance = await launch();
      const port = instance.options.port;
      const requestApi = request.defaults({ jar: request.jar() });
      const generic = method => async (url, options) => {
        const res = await requestApi(normalize(method, url, port, options));
        res.method = res.request.method;
        res.status = res.statusCode;
        if (/application\/json/.test(res.headers['content-type']) && typeof res.body === 'string') {
          res.rawBody = res.body;
          res.body = JSON.parse(res.body);
        }
        // console.log(instance);
        res.ctx = instance;
        return res;
      };
      const api = {
        get: generic('GET'),
        post: generic('POST'),
        put: generic('PUT'),
        del: generic('DELETE'),
        ctx: instance
      };
      await cb(api);
    } catch (err) {
      if (!instance) {
        console.log(err);
      }
      throw err;
    } finally {
      instance.close();
    }
  };
  this.get = (url, options) => launch('GET', url, options);
  this.post = (url, options) => launch('POST', url, options);
  this.put = (url, options) => launch('PUT', url, options);
  this.del = (url, options) => launch('DELETE', url, options);
  return this;
};
 
 
module.exports.options = {};