<commit_before>"use strict";
const assert = require('assert');

const Connection = require('../../../lib/connection.js');
const defaultOptions = require('../../../lib/client-options.js').defaultOptions();
const utils = require('../../../lib/utils.js');
const requests = require('../../../lib/requests.js');
const helper = require('../../test-helper.js');
const vit = helper.vit;

describe('Connection', function () {
  this.timeout(120000);
  describe('#open()', function () {
    before(helper.ccmHelper.start(1));
    after(helper.ccmHelper.remove);
    it('should open', function (done) {
      const localCon = newInstance();
      localCon.open(function (err) {
        assert.ifError(err);
        assert.ok(localCon.connected, 'Must be status connected');
        localCon.close(done);
      });
    });
    it('should use the max supported protocol version', function (done) {
      const localCon = newInstance(null, null);
      localCon.open(function (err) {
        assert.ifError(err);
        assert.strictEqual(localCon.protocolVersion, getProtocolVersion());
        localCon.close(done);
      });
    });
    vit('3.0', 'should callback in error when protocol version is not supported server side', function (done) {
      // Attempting to connect with protocol v2
      const localCon = newInstance(null, 2);
      localCon.open(function (err) {
        helper.assertInstanceOf(err, Error);
        assert.ok(!localCon.connected);
        helper.assertContains(err.message, 'protocol version');
        localCon.close(done);
      });
    });
    vit('2.0', 'should limit the max protocol version based on the protocolOptions', function (done) {
      const options = utils.extend({}, defaultOptions);
      options.protocolOptions.maxVersion = getProtocolVersion() - 1;
      const localCon = newInstance(null, null, options);
      localCon.open(function (err) {
        assert.ifError(err);
        assert.strictEqual(localCon.protocolVersion, options.protocolOptions.maxVersion);
        localCon.close(done);
      });
    });
    it('should open with all the protocol versions supported', function (done) {
      const maxProtocolVersionSupported = getProtocolVersion();
      const minProtocolVersionSupported = getMinProtocolVersion();
      let protocolVersion;
      if(helper.getCassandraVersion()) {
        protocolVersion = minProtocolVersionSupported - 1;
      }
      utils.whilst(function condition() {
        return (++protocolVersion) <= maxProtocolVersionSupported;
      }, function iterator (next) {
        const localCon = newInstance(null, protocolVersion);
        localCon.open(function (err) {
          assert.ifError(err);
          assert.ok(localCon.connected, 'Must be status connected');
          localCon.close(next);
        });
      }, done);
    });
    it('should fail when the host does not exits', function (done) {
      const localCon = newInstance('1.1.1.1');
      localCon.open(function (err) {
        assert.ok(err, 'Must return a connection error');
        assert.ok(!localCon.connected);
        localCon.close(done);
      });
    });
    it('should fail when the host exists but port closed', function (done) {
      const localCon = newInstance('127.0.0.1:8090');
      localCon.open(function (err) {
        assert.ok(err, 'Must return a connection error');
        assert.ok(!localCon.connected);
        localCon.close(done);
      });
    });
    it('should set the timeout for the heartbeat', function (done) {
      const options = utils.extend({}, defaultOptions);
      options.pooling.heartBeatInterval = 100;
      const c = newInstance(null, undefined, options);
      let sendCounter = 0;
      c.open(function (err) {
        assert.ifError(err);
        const originalSend = c.sendStream;
        c.sendStream = function() {
          sendCounter++;
          originalSend.apply(c, arguments);
        };
        setTimeout(function () {
          assert.ok(sendCounter > 3, 'sendCounter ' + sendCounter);
          done();
        }, 600);
      });
    });
  });
  describe('#open with ssl', function () {
    before(helper.ccmHelper.start(1, {ssl: true}));
    after(helper.ccmHelper.remove);
    it('should open to a ssl enabled host', function (done) {
      const localCon = newInstance();
      localCon.options.sslOptions = {};
      localCon.open(function (err) {
        assert.ifError(err);
        assert.ok(localCon.connected, 'Must be status connected');
        localCon.sendStream(getRequest(helper.queries.basic), null, function (err, result) {
          assert.ifError(err);
          assert.ok(result);
          assert.ok(result.rows.length);
          localCon.close(done);
        });
      });
    });
  });
  describe('#changeKeyspace()', function () {
    before(helper.ccmHelper.start(1));
    after(helper.ccmHelper.remove);
    it('should change active keyspace', function (done) {
      const localCon = newInstance();
      const keyspace = helper.getRandomName();
      utils.series([
        localCon.open.bind(localCon),
        function creating(next) {
          const query = 'CREATE KEYSPACE ' + keyspace + ' WITH replication = {\'class\': \'SimpleStrategy\', \'replication_factor\' : 1};';
          localCon.sendStream(getRequest(query), {}, next);
        },
        function changing(next) {
          localCon.changeKeyspace(keyspace, next);
        },
        function asserting(next) {
          assert.strictEqual(localCon.keyspace, keyspace);
          next();
        }
      ], done);
    });
    it('should be case sensitive', function (done) {
      const localCon = newInstance();
      const keyspace = helper.getRandomName().toUpperCase();
      assert.notStrictEqual(keyspace, keyspace.toLowerCase());
      utils.series([
        localCon.open.bind(localCon),
        function creating(next) {
          const query = 'CREATE KEYSPACE "' + keyspace + '" WITH replication = {\'class\': \'SimpleStrategy\', \'replication_factor\' : 1};';
          localCon.sendStream(getRequest(query), {}, next);
        },
        function changing(next) {
          localCon.changeKeyspace(keyspace, next);
        },
        function asserting(next) {
          assert.strictEqual(localCon.keyspace, keyspace);
          next();
        }
      ], done);
    });
  });
  describe('#sendStream()', function () {
    before(helper.ccmHelper.start(1));
    after(helper.ccmHelper.remove);
    it('should queue pending if there is not an available stream id', function (done) {
      const options = utils.extend({}, defaultOptions);
      options.socketOptions.readTimeout = 0;
      options.policies.retry = new helper.RetryMultipleTimes(3);
      const connection = newInstance(null, null, options);
      const maxRequests = connection.protocolVersion < 3 ? 128 : Math.pow(2, 15);
      utils.series([
        connection.open.bind(connection),
        function asserting(seriesNext) {
          utils.times(maxRequests + 10, function (n, next) {
            const request = getRequest(helper.queries.basic);
            connection.sendStream(request, null, next);
          }, seriesNext);
        }
      ], done);
    });
    it('should callback the pending queue if the connection is there is a socket error', function (done) {
      const options = utils.extend({}, defaultOptions);
      options.socketOptions.readTimeout = 0;
      options.policies.retry = new helper.RetryMultipleTimes(3);
      const connection = newInstance(null, null, options);
      const maxRequests = connection.protocolVersion < 3 ? 128 : Math.pow(2, 15);
      let killed = false;
      utils.series([
        connection.open.bind(connection),
        function asserting(seriesNext) {
          utils.times(maxRequests + 10, function (n, next) {
            if (n === maxRequests + 9) {
              connection.netClient.destroy();
              killed = true;
              return next();
            }
            const request = getRequest('SELECT key FROM system.local');
            connection.sendStream(request, null, function (err) {
              if (killed && err) {
                assert.ok(err.isSocketError);
                err = null;
              }
              next(err);
            });
          }, seriesNext);
        },
        connection.close.bind(connection)
      ], done);
    });
    it('should not consume streamIds for requests that cant be serialized', function (done) {
      const options = utils.extend({}, defaultOptions);
      options.socketOptions.readTimeout = 0;
      options.policies.retry = new helper.RetryMultipleTimes(3);
      const connection = newInstance(null, null, options);
      const testError = new Error('Dummy serialization error');
      utils.series([
        next => connection.open(next),
        next => {
          setImmediate(() => {
            assert.strictEqual(connection.getInFlight(), 0);
            next();
          });
        },
        seriesNext => {
          utils.timesSeries(1, function (n, next) {
            const request = getRequest(helper.queries.basic);
            request.write = () => { throw testError; };
            connection.sendStream(request, null, err => {
              assert.strictEqual(err, testError);
              next();
            });
          }, seriesNext);
        },
        next => {
          setImmediate(() => {
            assert.strictEqual(connection.getInFlight(), 0);
            next();
          });
        },
        next => connection.close(next)
      ], done);
    });
  });
});

/** @returns {Connection} */
function newInstance(address, protocolVersion, options){
  if (!address) {
    address = helper.baseOptions.contactPoints[0];
  }
  if (typeof protocolVersion === 'undefined') {
    protocolVersion = getProtocolVersion();
  }
  //var logEmitter = function (name, type) { if (type === 'verbose') { return; } console.log.apply(console, arguments);};
  options = utils.deepExtend({logEmitter: helper.noop}, options || defaultOptions);
  return new Connection(address + ':' + options.protocolOptions.port, protocolVersion, options);
}

function getRequest(query) {
  return new requests.QueryRequest(query, null, null);
}

/**
 * Gets the max supported protocol version for the current Cassandra version
 * @returns {number}
 */
function getProtocolVersion() {
  //expected protocol version
  if (helper.getCassandraVersion().indexOf('2.1.') === 0) {
    return 3;
  }
  if (helper.getCassandraVersion().indexOf('2.0.') === 0) {
    return 2;
  }
  if (helper.getCassandraVersion().indexOf('1.') === 0) {
    return 1;
  }
  return 4;
}

/**
 * Gets the minimum supported protocol version for the current Cassandra version
 *
 * For < C* 3.0 returns 1.  Otherwise returns maximum supported protocol
 * version - 1.
 *
 * @returns {number}
 */
function getMinProtocolVersion() {
  if (helper.getCassandraVersion().indexOf('2') === 0
    || helper.getCassandraVersion().indexOf('1') === 0) {
    return 1;
  }
  return getProtocolVersion() - 1;
}<commit_msg>Minor test fix<commit_after>"use strict";
const assert = require('assert');

const Connection = require('../../../lib/connection.js');
const defaultOptions = require('../../../lib/client-options.js').defaultOptions();
const utils = require('../../../lib/utils.js');
const requests = require('../../../lib/requests.js');
const helper = require('../../test-helper.js');
const errors = require('../../../lib/errors');
const types = require('../../../lib/types');
const vit = helper.vit;

describe('Connection', function () {
  this.timeout(120000);
  describe('#open()', function () {
    before(helper.ccmHelper.start(1));
    after(helper.ccmHelper.remove);
    it('should open', function (done) {
      const localCon = newInstance();
      localCon.open(function (err) {
        assert.ifError(err);
        assert.ok(localCon.connected, 'Must be status connected');
        localCon.close(done);
      });
    });
    it('should use the max supported protocol version', function (done) {
      const localCon = newInstance(null, null);
      localCon.open(function (err) {
        assert.ifError(err);
        assert.strictEqual(localCon.protocolVersion, getProtocolVersion());
        localCon.close(done);
      });
    });
    vit('3.0', 'should callback in error when protocol version is not supported server side', function (done) {
      // Attempting to connect with protocol v2
      const localCon = newInstance(null, 2);
      localCon.open(function (err) {
        helper.assertInstanceOf(err, Error);
        assert.ok(!localCon.connected);
        helper.assertContains(err.message, 'protocol version');
        localCon.close(done);
      });
    });
    vit('2.0', 'should limit the max protocol version based on the protocolOptions', function (done) {
      const options = utils.extend({}, defaultOptions);
      options.protocolOptions.maxVersion = getProtocolVersion() - 1;
      const localCon = newInstance(null, null, options);
      localCon.open(function (err) {
        assert.ifError(err);
        assert.strictEqual(localCon.protocolVersion, options.protocolOptions.maxVersion);
        localCon.close(done);
      });
    });
    it('should open with all the protocol versions supported', function (done) {
      const maxProtocolVersionSupported = getProtocolVersion();
      const minProtocolVersionSupported = getMinProtocolVersion();
      let protocolVersion;
      if(helper.getCassandraVersion()) {
        protocolVersion = minProtocolVersionSupported - 1;
      }
      utils.whilst(function condition() {
        return (++protocolVersion) <= maxProtocolVersionSupported;
      }, function iterator (next) {
        const localCon = newInstance(null, protocolVersion);
        localCon.open(function (err) {
          assert.ifError(err);
          assert.ok(localCon.connected, 'Must be status connected');
          localCon.close(next);
        });
      }, done);
    });
    it('should fail when the host does not exits', function (done) {
      const localCon = newInstance('1.1.1.1');
      localCon.open(function (err) {
        assert.ok(err, 'Must return a connection error');
        assert.ok(!localCon.connected);
        localCon.close(done);
      });
    });
    it('should fail when the host exists but port closed', function (done) {
      const localCon = newInstance('127.0.0.1:8090');
      localCon.open(function (err) {
        assert.ok(err, 'Must return a connection error');
        assert.ok(!localCon.connected);
        localCon.close(done);
      });
    });
    it('should set the timeout for the heartbeat', function (done) {
      const options = utils.extend({}, defaultOptions);
      options.pooling.heartBeatInterval = 100;
      const c = newInstance(null, undefined, options);
      let sendCounter = 0;
      c.open(function (err) {
        assert.ifError(err);
        const originalSend = c.sendStream;
        c.sendStream = function() {
          sendCounter++;
          originalSend.apply(c, arguments);
        };
        setTimeout(function () {
          assert.ok(sendCounter > 3, 'sendCounter ' + sendCounter);
          done();
        }, 600);
      });
    });
  });
  describe('#open with ssl', function () {
    before(helper.ccmHelper.start(1, {ssl: true}));
    after(helper.ccmHelper.remove);
    it('should open to a ssl enabled host', function (done) {
      const localCon = newInstance();
      localCon.options.sslOptions = {};
      localCon.open(function (err) {
        assert.ifError(err);
        assert.ok(localCon.connected, 'Must be status connected');
        localCon.sendStream(getRequest(helper.queries.basic), null, function (err, result) {
          assert.ifError(err);
          assert.ok(result);
          assert.ok(result.rows.length);
          localCon.close(done);
        });
      });
    });
  });
  describe('#changeKeyspace()', function () {
    before(helper.ccmHelper.start(1));
    after(helper.ccmHelper.remove);
    it('should change active keyspace', function (done) {
      const localCon = newInstance();
      const keyspace = helper.getRandomName();
      utils.series([
        localCon.open.bind(localCon),
        function creating(next) {
          const query = 'CREATE KEYSPACE ' + keyspace + ' WITH replication = {\'class\': \'SimpleStrategy\', \'replication_factor\' : 1};';
          localCon.sendStream(getRequest(query), {}, next);
        },
        function changing(next) {
          localCon.changeKeyspace(keyspace, next);
        },
        function asserting(next) {
          assert.strictEqual(localCon.keyspace, keyspace);
          next();
        }
      ], done);
    });
    it('should be case sensitive', function (done) {
      const localCon = newInstance();
      const keyspace = helper.getRandomName().toUpperCase();
      assert.notStrictEqual(keyspace, keyspace.toLowerCase());
      utils.series([
        localCon.open.bind(localCon),
        function creating(next) {
          const query = 'CREATE KEYSPACE "' + keyspace + '" WITH replication = {\'class\': \'SimpleStrategy\', \'replication_factor\' : 1};';
          localCon.sendStream(getRequest(query), {}, next);
        },
        function changing(next) {
          localCon.changeKeyspace(keyspace, next);
        },
        function asserting(next) {
          assert.strictEqual(localCon.keyspace, keyspace);
          next();
        }
      ], done);
    });
  });
  describe('#sendStream()', function () {
    before(helper.ccmHelper.start(1));
    after(helper.ccmHelper.remove);
    it('should queue pending if there is not an available stream id', function (done) {
      const options = utils.extend({}, defaultOptions);
      options.socketOptions.readTimeout = 0;
      options.policies.retry = new helper.RetryMultipleTimes(3);
      const connection = newInstance(null, null, options);
      const maxRequests = connection.protocolVersion < 3 ? 128 : Math.pow(2, 15);
      utils.series([
        connection.open.bind(connection),
        function asserting(seriesNext) {
          utils.times(maxRequests + 10, function (n, next) {
            const request = getRequest(helper.queries.basic);
            connection.sendStream(request, null, err => {
              if (err) {
                helper.assertInstanceOf(err, errors.ResponseError);
                assert.strictEqual(err.code, types.responseErrorCodes.readTimeout);
              }

              next();
            });
          }, seriesNext);
        }
      ], done);
    });
    it('should callback the pending queue if the connection is there is a socket error', function (done) {
      const options = utils.extend({}, defaultOptions);
      options.socketOptions.readTimeout = 0;
      options.policies.retry = new helper.RetryMultipleTimes(3);
      const connection = newInstance(null, null, options);
      const maxRequests = connection.protocolVersion < 3 ? 128 : Math.pow(2, 15);
      let killed = false;
      utils.series([
        connection.open.bind(connection),
        function asserting(seriesNext) {
          utils.times(maxRequests + 10, function (n, next) {
            if (n === maxRequests + 9) {
              connection.netClient.destroy();
              killed = true;
              return next();
            }
            const request = getRequest('SELECT key FROM system.local');
            connection.sendStream(request, null, function (err) {
              if (killed && err) {
                assert.ok(err.isSocketError);
                err = null;
              }
              next(err);
            });
          }, seriesNext);
        },
        connection.close.bind(connection)
      ], done);
    });
    it('should not consume streamIds for requests that cant be serialized', function (done) {
      const options = utils.extend({}, defaultOptions);
      options.socketOptions.readTimeout = 0;
      options.policies.retry = new helper.RetryMultipleTimes(3);
      const connection = newInstance(null, null, options);
      const testError = new Error('Dummy serialization error');
      utils.series([
        next => connection.open(next),
        next => {
          setImmediate(() => {
            assert.strictEqual(connection.getInFlight(), 0);
            next();
          });
        },
        seriesNext => {
          utils.timesSeries(1, function (n, next) {
            const request = getRequest(helper.queries.basic);
            request.write = () => { throw testError; };
            connection.sendStream(request, null, err => {
              assert.strictEqual(err, testError);
              next();
            });
          }, seriesNext);
        },
        next => {
          setImmediate(() => {
            assert.strictEqual(connection.getInFlight(), 0);
            next();
          });
        },
        next => connection.close(next)
      ], done);
    });
  });
});

/** @returns {Connection} */
function newInstance(address, protocolVersion, options){
  if (!address) {
    address = helper.baseOptions.contactPoints[0];
  }
  if (typeof protocolVersion === 'undefined') {
    protocolVersion = getProtocolVersion();
  }
  //var logEmitter = function (name, type) { if (type === 'verbose') { return; } console.log.apply(console, arguments);};
  options = utils.deepExtend({logEmitter: helper.noop}, options || defaultOptions);
  return new Connection(address + ':' + options.protocolOptions.port, protocolVersion, options);
}

function getRequest(query) {
  return new requests.QueryRequest(query, null, null);
}

/**
 * Gets the max supported protocol version for the current Cassandra version
 * @returns {number}
 */
function getProtocolVersion() {
  //expected protocol version
  if (helper.getCassandraVersion().indexOf('2.1.') === 0) {
    return 3;
  }
  if (helper.getCassandraVersion().indexOf('2.0.') === 0) {
    return 2;
  }
  if (helper.getCassandraVersion().indexOf('1.') === 0) {
    return 1;
  }
  return 4;
}

/**
 * Gets the minimum supported protocol version for the current Cassandra version
 *
 * For < C* 3.0 returns 1.  Otherwise returns maximum supported protocol
 * version - 1.
 *
 * @returns {number}
 */
function getMinProtocolVersion() {
  if (helper.getCassandraVersion().indexOf('2') === 0
    || helper.getCassandraVersion().indexOf('1') === 0) {
    return 1;
  }
  return getProtocolVersion() - 1;
}<|endoftext|>


<commit_before>// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/

import childProcess from 'child_process';
import path from 'path';
import os from 'os';
import { spawn, getElectronPath, normalizeCommand } from './utils';

const DEFAULT_UNIT_TESTS = path.join(__dirname, '..', 'test', 'unit');
const DEFAULT_RENDERER_TESTS = path.join(__dirname, '..', 'test', 'renderer');
const DEFAULT_WEBDRIVER_TESTS = path.join(__dirname, '..', 'test', 'webdriver');
const MOCHA = path.join(__dirname, '..', 'node_modules', '.bin', 'mocha');
const ELECTRON_MOCHA = path.join(__dirname, '..', 'node_modules', '.bin', 'electron-mocha');
const PATH_TO_ELECTRON_MOCHA_OPTS = path.join(__dirname, '..', 'test', 'renderer', 'mocha.opts');

export default async function(args) {
  // If no arguments passed in, we must run all tests; both mocha
  // and electron-mocha.
  if (!args.length) {
    // Catch all errors from each suite so we can continue
    // running in the event of failure, because we still want to run
    // all tests in series, but reject if any suite fails after
    // we're done.
    const errors = [];
    await runMochaTests(DEFAULT_UNIT_TESTS).catch(e => errors.push(e));
    await runRendererTests(DEFAULT_RENDERER_TESTS).catch(e => errors.push(e));
    await runMochaTests(DEFAULT_WEBDRIVER_TESTS).catch(e => errors.push(e));
    if (errors.length) {
      throw errors[0];
    }
  } else {
    // If we get a path passed in, crudely check if we should run
    // our renderer tests, or normal mocha tests. This will fail for complex
    // globbing, but this is more than fine for now.
    const pathToTests = args[0];
    if (pathToTests.indexOf(path.join('test', 'renderer')) !== -1) {
      await runRendererTests(pathToTests);
    } else {
      await runMochaTests(pathToTests);
    }
  }
}

function runMochaTests(pathToTests) {
  return spawn(MOCHA, [pathToTests], {
    stdio: 'inherit',
  });
}

async function runRendererTests(pathToTests) {
  const command = await normalizeCommand(ELECTRON_MOCHA);

  const child = childProcess.spawn(command, [
    '--renderer',
    '--opts', PATH_TO_ELECTRON_MOCHA_OPTS,
    pathToTests,
  ], {
    // Must pass in our whole environment to `electron-mocha`, as
    // that spawns another process which uses something in the current environment
    // (so `process.env`, or the `env` object we pass in here), otherwise the electron process
    // immediately crashes.
    env: Object.assign({}, process.env, { ELECTRON_PATH: getElectronPath() }),
  });

  return new Promise((resolve, reject) => {
    let failedFromStdout = false;

    // Parse and pipe the stdout from electron-mocha
    // so we can observe if tests are passing, but we get an error
    // on shutdown, for the Windows edge case below.
    child.stdout.on('data', data => {
      if (/\s\d+ failing/.test(`${data}`.trim())) {
        failedFromStdout = true;
      }
      process.stdout.write(data);
    });

    child.stderr.pipe(process.stderr);
    child.on('error', reject);
    child.on('exit', code => {
      if (code !== 0) {
        if (os.platform() === 'win32' && !failedFromStdout) {
          // If the exit code is not 0 and we didn't observe any
          // failure messages when running tests, we are running into
          // an issue where Electron crashes in electron-mocha when cleaning up
          // tests due to the main process firing a `webContents.send()` during clean up
          // resulting in a 'Object has been destroyed' error. Can't seem to figure out
          // why, but looks like a part of Electron, and burned enough time on this,
          // so this is good enough for now™.
          resolve();
        } else {
          reject(new Error(`Child process ${command} exited with exit code ${code}`));
        }
      } else {
        resolve();
      }
    });
  });
}
<commit_msg>Log when tests start<commit_after>// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/

import colors from 'colors/safe';
import childProcess from 'child_process';
import path from 'path';
import os from 'os';
import { spawn, getElectronPath, normalizeCommand } from './utils';
import { logger } from './logging';

const DEFAULT_UNIT_TESTS = path.join(__dirname, '..', 'test', 'unit');
const DEFAULT_RENDERER_TESTS = path.join(__dirname, '..', 'test', 'renderer');
const DEFAULT_WEBDRIVER_TESTS = path.join(__dirname, '..', 'test', 'webdriver');
const MOCHA = path.join(__dirname, '..', 'node_modules', '.bin', 'mocha');
const ELECTRON_MOCHA = path.join(__dirname, '..', 'node_modules', '.bin', 'electron-mocha');
const PATH_TO_ELECTRON_MOCHA_OPTS = path.join(__dirname, '..', 'test', 'renderer', 'mocha.opts');

export default async function(args) {
  logger.info(colors.green('Running tests...'));

  // If no arguments passed in, we must run all tests; both mocha
  // and electron-mocha.
  if (!args.length) {
    // Catch all errors from each suite so we can continue
    // running in the event of failure, because we still want to run
    // all tests in series, but reject if any suite fails after
    // we're done.
    const errors = [];
    await runMochaTests(DEFAULT_UNIT_TESTS).catch(e => errors.push(e));
    await runRendererTests(DEFAULT_RENDERER_TESTS).catch(e => errors.push(e));
    await runMochaTests(DEFAULT_WEBDRIVER_TESTS).catch(e => errors.push(e));
    if (errors.length) {
      throw errors[0];
    }
  } else {
    // If we get a path passed in, crudely check if we should run
    // our renderer tests, or normal mocha tests. This will fail for complex
    // globbing, but this is more than fine for now.
    const pathToTests = args[0];
    if (pathToTests.indexOf(path.join('test', 'renderer')) !== -1) {
      await runRendererTests(pathToTests);
    } else {
      await runMochaTests(pathToTests);
    }
  }
}

function runMochaTests(pathToTests) {
  return spawn(MOCHA, [pathToTests], {
    stdio: 'inherit',
  });
}

async function runRendererTests(pathToTests) {
  const command = await normalizeCommand(ELECTRON_MOCHA);

  const child = childProcess.spawn(command, [
    '--renderer',
    '--opts', PATH_TO_ELECTRON_MOCHA_OPTS,
    pathToTests,
  ], {
    // Must pass in our whole environment to `electron-mocha`, as
    // that spawns another process which uses something in the current environment
    // (so `process.env`, or the `env` object we pass in here), otherwise the electron process
    // immediately crashes.
    env: Object.assign({}, process.env, { ELECTRON_PATH: getElectronPath() }),
  });

  return new Promise((resolve, reject) => {
    let failedFromStdout = false;

    // Parse and pipe the stdout from electron-mocha
    // so we can observe if tests are passing, but we get an error
    // on shutdown, for the Windows edge case below.
    child.stdout.on('data', data => {
      if (/\s\d+ failing/.test(`${data}`.trim())) {
        failedFromStdout = true;
      }
      process.stdout.write(data);
    });

    child.stderr.pipe(process.stderr);
    child.on('error', reject);
    child.on('exit', code => {
      if (code !== 0) {
        if (os.platform() === 'win32' && !failedFromStdout) {
          // If the exit code is not 0 and we didn't observe any
          // failure messages when running tests, we are running into
          // an issue where Electron crashes in electron-mocha when cleaning up
          // tests due to the main process firing a `webContents.send()` during clean up
          // resulting in a 'Object has been destroyed' error. Can't seem to figure out
          // why, but looks like a part of Electron, and burned enough time on this,
          // so this is good enough for now™.
          resolve();
        } else {
          reject(new Error(`Child process ${command} exited with exit code ${code}`));
        }
      } else {
        resolve();
      }
    });
  });
}
<|endoftext|>


<commit_before>var requirejs = require( 'requirejs' ),
	path = require( 'path' ),
	fs = require( 'fs' ),
	util = require( 'util' );

module.exports = function( grunt ) {
	var config = grunt.config.get( 'global' ),
		helpers = config.helpers;

	grunt.registerTask( 'css:compile', 'use require js to sort out deps', function() {
		var theme = grunt.config.get( 'css' ).theme,
			themeFile = grunt.config.get( 'css' ).themeFile,
			require = grunt.config.get( 'css' ).require;

		// pull the includes together using require js
		requirejs.optimize( require.all );

		// pull the includes together using require js
		requirejs.optimize( require.structure );

		// simple theme file compile
		grunt.file.write( themeFile + '.css', 'css/themes/' + theme + '/jquery.mobile.theme.css' );
	});

	// TODO image copy would be better in compile though not perfect
	grunt.registerTask( 'css:cleanup', 'compile and minify the css', function() {
		var done = this.async(),
			theme = grunt.config.get( 'css' ).theme,
			require = grunt.config.get( 'css' ).require,
			global_config = grunt.config.get( 'global' );

		// remove the requirejs compile output
		fs.unlink( require.all.out );
		fs.unlink( require.structure.out );

		// copy images directory
		var imagesPath = path.join( global_config.dirs.output, 'images' ), fileCount = 0;

		grunt.file.mkdir( imagesPath );
		grunt.file.recurse( 'css/themes/' + theme + '/images', function( full, root, sub, filename ) {

			fileCount++;
			var is = fs.createReadStream( full );
			var os = fs.createWriteStream( path.join(imagesPath, filename) );
			util.pump(is, os, function() {
				fileCount--;
				if( fileCount == 0 ) { done(); }
			});
		});
	});

	// NOTE the progression of events is not obvious from the above
	//      compile -> concat x 3 -> min all -> cleanup the compiled stuff
	grunt.registerTask( 'css', 'custom_init config:async css:compile concat:regular concat:structure concat:theme cssmin css:cleanup' );
};
<commit_msg>rename jquery.mobile to umobi<commit_after>var requirejs = require( 'requirejs' ),
	path = require( 'path' ),
	fs = require( 'fs' ),
	util = require( 'util' );

module.exports = function( grunt ) {
	var config = grunt.config.get( 'global' ),
		helpers = config.helpers;

	grunt.registerTask( 'css:compile', 'use require js to sort out deps', function() {
		var theme = grunt.config.get( 'css' ).theme,
			themeFile = grunt.config.get( 'css' ).themeFile,
			require = grunt.config.get( 'css' ).require;

		// pull the includes together using require js
		requirejs.optimize( require.all );

		// pull the includes together using require js
		requirejs.optimize( require.structure );

		// simple theme file compile
		grunt.file.write( themeFile + '.css', 'css/themes/' + theme + '/umobi.theme.css' );
	});

	// TODO image copy would be better in compile though not perfect
	grunt.registerTask( 'css:cleanup', 'compile and minify the css', function() {
		var done = this.async(),
			theme = grunt.config.get( 'css' ).theme,
			require = grunt.config.get( 'css' ).require,
			global_config = grunt.config.get( 'global' );

		// remove the requirejs compile output
		fs.unlink( require.all.out );
		fs.unlink( require.structure.out );

		// copy images directory
		var imagesPath = path.join( global_config.dirs.output, 'images' ), fileCount = 0;

		grunt.file.mkdir( imagesPath );
		grunt.file.recurse( 'css/themes/' + theme + '/images', function( full, root, sub, filename ) {

			fileCount++;
			var is = fs.createReadStream( full );
			var os = fs.createWriteStream( path.join(imagesPath, filename) );
			util.pump(is, os, function() {
				fileCount--;
				if( fileCount == 0 ) { done(); }
			});
		});
	});

	// NOTE the progression of events is not obvious from the above
	//      compile -> concat x 3 -> min all -> cleanup the compiled stuff
	grunt.registerTask( 'css', 'custom_init config:async css:compile concat:regular concat:structure concat:theme cssmin css:cleanup' );
};
<|endoftext|>


<commit_before>var AST = {}

AST.InstrumentDefinition = function(time, number, unit_generators) {
    this.time = time;
    this.number = number;
    this.unit_generators = unit_generators;
};

AST.Oscillator = function(amplitude, frequency, output, stored_function, initial_value) {
    this.amplitude = amplitude;
    this.frequency = frequency;
    this.output = output;
    this.stored_function = stored_function;
    this.initial_value = initial_value;
};

AST.Output = function(input, output) {
    this.input = input;
    this.output = output;
};

AST.GeneratedFunction = function(time, subroutine_number, function_number, points) {
    this.time = time;
    this.subroutine_number = subroutine_number;
    this.function_number = function_number;
    this.points = points;
};

AST.Note = function(time, instrument_number, duration, params) {
    this.time = time;
    this.instrument_number = instrument_number;
    this.duration = duration;
    this.params = params;
};

AST.Note.prototype.add_to_score = function(score) {
    var amplitude = parseInt(this.params[0]);
    var frequency = parseFloat(this.params[1]);
    score.notes.push(new Model.Note(this.time, this.duration, amplitude, frequency));
};

AST.Terminator = function(time) {
    this.time = time;
};

AST.Terminator.prototype.add_to_score = function(score) {
    score.duration = this.time;
}

AST.Score = function(data_statements) {
    this.data_statements = data_statements;
};

AST.Score.prototype.to_score = function() {
    var score = new Model.Score();
    this.data_statements.forEach(function(statement) {
        if(statement.add_to_score) { statement.add_to_score(score) };
    });
    return score;
};

var Model = {};
Model.Note = function(time, duration, amplitude, frequency) {
    this.start = time;
    this.end = this.start + duration;
    this.amplitude = amplitude;
    this.frequency = frequency;
};

Model.Score = function() {
    this.notes = [];
};

Model.Instrument = function() {
}

Model.Instrument.prototype.to_data = function(note, context, maxAmplitude, blockSize, rate) {
    var note_buffer = context.createBuffer(1, (note.end - note.start) * context.sampleRate, context.sampleRate);
    var note_data = note_buffer.getChannelData(0);

    var amplitude = note.amplitude / maxAmplitude;
    var frequency = note.frequency / (blockSize/rate);
    var angular_frequency = 2*Math.PI*frequency;

    for (var i = 0; i < note_buffer.length; i++) {
        var t = i / context.sampleRate;
        note_data[i] = Math.sin(t*angular_frequency) * amplitude;
    }

    return note_data;
}

Model.Score.prototype.getInstrument = function(instrument_number) {
    return new Model.Instrument();
};

Model.Score.prototype.play = function(context, maxAmplitude, blockSize, rate) {
    var buffer = context.createBuffer(1, this.duration * context.sampleRate, context.sampleRate);
    var data = buffer.getChannelData(0);

    this.notes.forEach(function(note) {
        var instrument = this.getInstrument(note.instrument_number);
        var note_data = instrument.to_data(note, context, maxAmplitude, blockSize, rate);

        var start = note.start * context.sampleRate;

        for (var i = 0; i < note_data.length; i++) {
            data[start+i] += note_data[i];
        };
    }, this);

    var source = context.createBufferSource();
    source.buffer = buffer;
    source.connect(context.destination);
    source.start();
};

var score_source = document.getElementById('score').value
var grammar = document.getElementById('grammar').value

var parser = PEG.buildParser(grammar);
var ast = parser.parse(score_source);
console.log(ast);

var score = ast.to_score();
console.log(score);

var context = new AudioContext();
score.play(context, 2047, 511, 20000);
<commit_msg>Extract context out of to_data method<commit_after>var AST = {}

AST.InstrumentDefinition = function(time, number, unit_generators) {
    this.time = time;
    this.number = number;
    this.unit_generators = unit_generators;
};

AST.Oscillator = function(amplitude, frequency, output, stored_function, initial_value) {
    this.amplitude = amplitude;
    this.frequency = frequency;
    this.output = output;
    this.stored_function = stored_function;
    this.initial_value = initial_value;
};

AST.Output = function(input, output) {
    this.input = input;
    this.output = output;
};

AST.GeneratedFunction = function(time, subroutine_number, function_number, points) {
    this.time = time;
    this.subroutine_number = subroutine_number;
    this.function_number = function_number;
    this.points = points;
};

AST.Note = function(time, instrument_number, duration, params) {
    this.time = time;
    this.instrument_number = instrument_number;
    this.duration = duration;
    this.params = params;
};

AST.Note.prototype.add_to_score = function(score) {
    var amplitude = parseInt(this.params[0]);
    var frequency = parseFloat(this.params[1]);
    score.notes.push(new Model.Note(this.time, this.duration, amplitude, frequency));
};

AST.Terminator = function(time) {
    this.time = time;
};

AST.Terminator.prototype.add_to_score = function(score) {
    score.duration = this.time;
}

AST.Score = function(data_statements) {
    this.data_statements = data_statements;
};

AST.Score.prototype.to_score = function() {
    var score = new Model.Score();
    this.data_statements.forEach(function(statement) {
        if(statement.add_to_score) { statement.add_to_score(score) };
    });
    return score;
};

var Model = {};
Model.Note = function(time, duration, amplitude, frequency) {
    this.start = time;
    this.end = this.start + duration;
    this.amplitude = amplitude;
    this.frequency = frequency;
};

Model.Score = function() {
    this.notes = [];
};

Model.Instrument = function() {
}

Model.Instrument.prototype.to_data = function(note, sampleRate, maxAmplitude, blockSize, rate) {
    var size = (note.end - note.start) * sampleRate;
    var note_data = new Float32Array(Math.round(size));

    var amplitude = note.amplitude / maxAmplitude;
    var frequency = note.frequency / (blockSize/rate);
    var angular_frequency = 2*Math.PI*frequency;

    for (var i = 0; i < note_data.length; i++) {
        var t = i / sampleRate;
        note_data[i] = Math.sin(t*angular_frequency) * amplitude;
    }

    return note_data;
}

Model.Score.prototype.getInstrument = function(instrument_number) {
    return new Model.Instrument();
};

Model.Score.prototype.to_data = function(sampleRate, maxAmplitude, blockSize, rate) {
    var data = new Float32Array(this.duration * sampleRate);

    this.notes.forEach(function(note) {
        var instrument = this.getInstrument(note.instrument_number);
        var note_data = instrument.to_data(note, sampleRate, maxAmplitude, blockSize, rate);

        var start = note.start * sampleRate;

        for (var i = 0; i < note_data.length; i++) {
            data[start+i] += note_data[i];
        };
    }, this);

    return data;
};

var score_source = document.getElementById('score').value
var grammar = document.getElementById('grammar').value

var parser = PEG.buildParser(grammar);
var ast = parser.parse(score_source);
console.log(ast);

var score = ast.to_score();
console.log(score);

var context = new AudioContext();
var data = score.to_data(context.sampleRate, 2047, 511, 20000);
var buffer = context.createBuffer(1, data.length, context.sampleRate);
buffer.copyToChannel(data, 0);

var source = context.createBufferSource();
source.buffer = buffer;
source.connect(context.destination);
source.start();
<|endoftext|>


<commit_before>var gulp = require('gulp');
var paths = require('../paths');
var typedoc = require('gulp-typedoc');
var typedocExtractor = require('gulp-typedoc-extractor');
var runSequence = require('run-sequence');

gulp.task('doc-generate', function(){
  return gulp.src([paths.output + '*.d.ts', paths.doc + '/core-js.d.ts', './jspm_packages/npm/*/*.d.ts'])
    .pipe(typedoc({
            target: 'es6',
            includeDeclarations: true,
            json: paths.doc + '/api.json',
            name: paths.packageName + '-docs',
						mode: 'modules',
						excludeExternals: true,
            ignoreCompilerErrors: false,
            version: true
        }));
});

gulp.task('doc-extract', function(){
	return gulp.src([paths.doc + '/api.json'])
		.pipe(typedocExtractor(paths.packageName))
		.pipe(gulp.dest(paths.doc));
});

gulp.task('doc', function(callback){
  return runSequence(
  	'doc-generate',
  	'doc-extract',
    callback
  );
});
<commit_msg>unused gulp task deleted<commit_after><|endoftext|>


<commit_before>import '../testHelper';
import deepFreeze from 'deep-freeze';
import userTrainingStatus from '../../app/assets/javascripts/reducers/user_training_status';
import { RECEIVE_USER_TRAINING_STATUS } from '../../app/assets/javascripts/constants';

describe('user training status reducer', () => {
  it('should return initial state when no action nor state is provided', () => {
    const newState = userTrainingStatus(undefined, { type: null });
    expect(newState).to.be.an('array');
  });

  it('returns user training status with RECEIVE_USER_TRAINING_STATUS', () => {
    const initialState = [];
    deepFreeze(initialState);
    const mockedAction = {
      type: RECEIVE_USER_TRAINING_STATUS,
      data: { user: { training_modules: [] } }
    };

    const newState = userTrainingStatus(initialState, mockedAction);
    expect(newState).to.be.an('array');
  });
});
<commit_msg>mock array of objects<commit_after>import '../testHelper';
import deepFreeze from 'deep-freeze';
import userTrainingStatus from '../../app/assets/javascripts/reducers/user_training_status';
import { RECEIVE_USER_TRAINING_STATUS } from '../../app/assets/javascripts/constants';

describe('user training status reducer', () => {
  it('should return initial state when no action nor state is provided', () => {
    const newState = userTrainingStatus(undefined, { type: null });
    expect(newState).to.be.an('array');
  });

  it('returns user training status with RECEIVE_USER_TRAINING_STATUS', () => {
    const initialState = [];
    deepFreeze(initialState);
    const mockedAction = {
      type: RECEIVE_USER_TRAINING_STATUS,
      data: { user: { training_modules: [{ id: 1 }, { id: 2 }] } }
    };

    const newState = userTrainingStatus(initialState, mockedAction);
    expect(newState).to.deep.eq([{ id: 1 }, { id: 2 }]);
  });
});
<|endoftext|>


<commit_before>'use strict';

var projectView = {};

projectView.handleNavBar = function() {
  $('#projects').fadeIn(2500);
  $('.navbar').on('click', '.tab', function() {
    $('.tabContent').hide();
    $('#' + $(this).data('content')).fadeIn();
  });
  $('.navbar .tab:first').click()
}

$(document).ready(function() {
  // projectView.handleNavBar();
});
<commit_msg>got rid of all un-needed console.logs and commented out code<commit_after>'use strict';

var projectView = {};

projectView.handleNavBar = function() {
  $('#projects').fadeIn(2500);
  $('.navbar').on('click', '.tab', function() {
    $('.tabContent').hide();
    $('#' + $(this).data('content')).fadeIn();
  });
  $('.navbar .tab:first').click()
}
<|endoftext|>


<commit_before>'use strict'

var fs = require('fs');
var seneca = require('seneca')();
var async = require('async');

var dojos = JSON.parse(fs.readFileSync('./data/dojos.json', 'utf8'));
var plugin = "load-dojos";
var config = require('config');
var ENTITY_NS = "cd/dojos";

var pg = require('pg');
var conString = config.postgresql.connstring;

function pgEscapeString(str){
  var escapedStr = str ? str.split("'").join("''") : "";
  return escapedStr;
}

seneca.ready(function() {
  seneca.add({ role: plugin, cmd: 'insert' }, function (args, done) {

    var client = new pg.Client(conString);

    client.connect(function(err){

      if(err){
        console.error('could not connect to postgres', err);
        return done(err)
      }

      function createDojo(dojo, cb){

        var query = "INSERT INTO cd_dojos(id, mysql_dojo_id, name, creator, created, verified_at, verified_by," +
                    "verified, need_mentors, stage, time, location, coordinates, notes, email, " +
                    "website, twitter, google_group, eb_id, supporter_image, deleted, deleted_by, deleted_at," +
                    "private, url_slug, continent, alpha2, alpha3, country_number, country_name)" +
                    " VALUES ('" + dojo.id + "','" + dojo.mysql_dojo_id + "','" + pgEscapeString(dojo.name) + "','"+
                     dojo.creator + "','" + dojo.created + "','"  + dojo.verified_at + "','"  +
                     dojo.verified_by + "'," + dojo.verified + "," + dojo.need_mentors + "," +
                     dojo.stage + ",'" + pgEscapeString(dojo.time) + "','" + pgEscapeString(dojo.location) + "','" +
                     pgEscapeString(dojo.coordinates) + "','" + pgEscapeString(dojo.notes) + "','" + dojo.email + "','" + dojo.website + "','" +
                     dojo.twitter + "','" + dojo.google_group + "','" + dojo.eb_id + "','" + dojo.supporter_image + "','" +
                     dojo.deleted + "','" + dojo.deleted_by + "','"  + dojo.deleted_at + "','" + dojo.private + "','" +  dojo.url_slug +
                     "','" + dojo.continent +  "','"  + dojo.alpha2 + "','" + dojo.alpha3 + "'," + dojo.country_number + ",'" + pgEscapeString(dojo.country_name) + "')";

        client.query(query, function(err, result) {
          if(err) {
            console.error('error running query', err);
            return cb(err);
          }

          return cb();
        });
      }

      var loadDojos = function (done) {
        async.eachSeries(dojos, createDojo , done);
      };

      async.series([
        loadDojos
      ], function(err){
        if(err){
          return done(err);
        }

        client.end();
        done();
      });

    });

  });

  seneca.act({ role: plugin, cmd: 'insert', timeout: false }, function(err){
    if(err){
      console.log(err);
      process.exit(1);
    } else{
      console.log("dojos complete");
      process.exit(0);
    }
  });

});
<commit_msg>Create dojo via seneca<commit_after>'use strict';

var fs = require('fs');
var seneca = require('seneca')();
var async = require('async');

var dojos = JSON.parse(fs.readFileSync('./data/dojos.json', 'utf8'));
var plugin = "load-dojos";
var config = require('config');
var ENTITY_NS = "cd/dojos";

seneca.use('postgresql-store', config['postgresql-store']);

seneca.ready(function() {
  seneca.add({ role: plugin, cmd: 'insert' }, function (args, done) {

    function createDojo(dojo, cb){
      dojo.id$ = dojo.id;
      delete dojo.country;
      delete dojo.id;
      seneca.make(ENTITY_NS).save$(dojo, function(err, dojo){
        if(err){
          return cb(err);
        }

        return cb();
      });
    }

    var loadDojos = function (done) {
      async.eachSeries(dojos, createDojo , done);
    };

    async.series([
      loadDojos
    ], function(err){
      if(err){
        return done(err);
      }
      done();
    });

  });

  seneca.act({ role: plugin, cmd: 'insert', timeout: false }, function(err){
    if(err){
      console.log(err);
      process.exit(1);
    } else{
      console.log("dojos complete");
      process.exit(0);
    }
  });

});
<|endoftext|>


<commit_before>"use strict";
var status = require('http-status-codes');

var addSocketResponse = require('./socket/response');
var addSocketKeys = require('./socket/keys');

class WebsocketRest {
	constructor(){
		this.socket = null;
		this.apiVersion = null;
		this.modules = {};
		this.onUrlConnect = {};
		this.onUrlClose = {};
		this._connectedClients = {};

	}

    init(socket, apiVersion) {
        this.socket = socket;
        this.apiVersion = apiVersion;
    }

	getConnectedClient(key){
		if(key in this._connectedClients){
			return this._connectedClients[key];
		}
	}
	getConnectedClients(){
		return this._connectedClients;
	}

    registerModule(moduleName, module) {
        if (moduleName in this.modules) {
            throw new Error(moduleName + ' is allready in registered modules!');
        } else {
            this.modules[moduleName] = module;
        }
    }

	registerOnConnectUrl(url,fun){
		var self = this;
		if(url in this.onUrlConnect){
			throw new Error(url + ' is allready in registered connect methods!');
		} else {
			this.onUrlConnect[url] = function(socket){
				try {
					fun(socket,function(){
						self._connectedClients[socket.key] = socket;
					});
				} catch (err) {
					console.trace(err);
					return socket.error(
						'Internal error: Contact developers',
						[err.stack],
						status.INTERNAL_SERVER_ERROR
					);
				}

			} ;
		}
	}

	registerOnCloseUrl(url, fun) {
		if (url in this.onUrlClose) {
			throw new Error(url + ' is allready in registered connect methods!');
		} else {
			this.onUrlClose[url] = fun;
		}
	}

	_onConnection(socket){
		let urlPath = socket.urlPath;

		if(urlPath in this.onUrlConnect){
			this.onUrlConnect[urlPath](socket);
		} else {
			var err = `UrlPath: ${socket.urlPath}] not found !`;
			socket.error(status.getStatusText(status.NOT_FOUND), [err], status.NOT_FOUND);
		}
	}

    initServer() {
        var self = this;
        this.socket.on('connection', function (socket) {

	        addSocketResponse(socket,self.apiVersion);
	        addSocketKeys(socket);

	        self._onConnection(socket);

			socket.on('close',function(){
				delete self._connectedClients[socket.key];
				if (socket.urlPath in self.onUrlConnect) {
					self.onUrlConnect[socket.urlPath](socket);
				}
			});

            socket.on('message', function (msg) {
                var req = JSON.parse(msg || "{}");

				//check req
                var reqKeys = ['module', 'method'];
                var keyError = [];
                for (var i in reqKeys) {
                    if (!(reqKeys[i] in req)) keyError.push(reqKeys[i]);
                }
                if (keyError.length != 0) {
                    var err = `Keys: [${keyError}] not in request!`;
                    console.error(err);
                    socket.error(status.getStatusText(status.BAD_REQUEST),[err],status.BAD_REQUEST);

                } else if(0 == req.method.indexOf("private")){
					var err = `You can not call private methods!`;
					console.error(err);
					socket.error(status.getStatusText(status.METHOD_NOT_ALLOWED),[err],status.METHOD_NOT_ALLOWED);
				} else {
					socket.REST.module = req['module'];
					socket.REST.method = req['method'];

	                //For standardization with express...
	                if (req.hasOwnProperty('data')) {
		                req['body'] = req['data'];
		                delete req['data'];
	                }

                    self.modules[req['module']][req['method']](req, socket);
                }
            });
        });
    }
}

module.exports = new WebsocketRest();
<commit_msg>Fast update<commit_after>"use strict";
var status = require('http-status-codes');

var addSocketResponse = require('./socket/response');
var addSocketKeys = require('./socket/keys');

class WebsocketRest {
	constructor(){
		this.socket = null;
		this.apiVersion = null;
		this.modules = {};
		this.onUrlConnect = {};
		this.onUrlClose = {};
		this._connectedClients = {};

	}

    init(socket, apiVersion) {
        this.socket = socket;
        this.apiVersion = apiVersion;
    }

	getConnectedClient(key){
		if(key in this._connectedClients){
			return this._connectedClients[key];
		}
	}
	getConnectedClients(){
		return this._connectedClients;
	}

    registerModule(moduleName, module) {
        if (moduleName in this.modules) {
            throw new Error(moduleName + ' is allready in registered modules!');
        } else {
            this.modules[moduleName] = module;
        }
    }

	registerOnConnectUrl(url,fun){
		var self = this;
		if(url in this.onUrlConnect){
			throw new Error(url + ' is allready in registered connect methods!');
		} else {
			this.onUrlConnect[url] = function(socket){
				try {
					fun(socket,function(){
						self._connectedClients[socket.key] = socket;
					});
				} catch (err) {
					console.trace(err);
				}
			};
		}
	}

	registerOnCloseUrl(url, fun) {
		if (url in this.onUrlClose) {
			throw new Error(url + ' is allready in registered connect methods!');
		} else {
			this.onUrlClose[url] = fun;
		}
	}

	_onConnection(socket){
		let urlPath = socket.urlPath;

		if(urlPath in this.onUrlConnect){
			this.onUrlConnect[urlPath](socket);
		} else {
			var err = `UrlPath: ${socket.urlPath}] not found !`;
			socket.error(status.getStatusText(status.NOT_FOUND), [err], status.NOT_FOUND);
		}
	}

    initServer() {
        var self = this;
        this.socket.on('connection', function (socket) {

	        addSocketResponse(socket,self.apiVersion);
	        addSocketKeys(socket);

	        self._onConnection(socket);

			socket.on('close',function(){
				delete self._connectedClients[socket.key];
				if (socket.urlPath in self.onUrlConnect) {
					self.onUrlConnect[socket.urlPath](socket);
				}
			});

            socket.on('message', function (msg) {
                var req = JSON.parse(msg || "{}");

				//check req
                var reqKeys = ['module', 'method'];
                var keyError = [];
                for (var i in reqKeys) {
                    if (!(reqKeys[i] in req)) keyError.push(reqKeys[i]);
                }
                if (keyError.length != 0) {
                    var err = `Keys: [${keyError}] not in request!`;
                    console.error(err);
                    socket.error(status.getStatusText(status.BAD_REQUEST),[err],status.BAD_REQUEST);

                } else if(0 == req.method.indexOf("private")){
					var err = `You can not call private methods!`;
					console.error(err);
					socket.error(status.getStatusText(status.METHOD_NOT_ALLOWED),[err],status.METHOD_NOT_ALLOWED);
				} else {
					socket.REST.module = req['module'];
					socket.REST.method = req['method'];

	                //For standardization with express...
	                if (req.hasOwnProperty('data')) {
		                req['body'] = req['data'];
		                delete req['data'];
	                }

                    self.modules[req['module']][req['method']](req, socket);
                }
            });
        });
    }
}

module.exports = new WebsocketRest();
<|endoftext|>


<commit_before>/**
 * Created by nuintun on 2015/11/18.
 */

'use strict';

var fs = require('fs');
var path = require('path');
var join = path.join;
// module to control application life
var app = require('app');
var ipc = require('ipc-main');
var dialog = require('dialog');
var shell = require('shell');

const USERDATA = app.getPath('userData');
const USERDESKTOP = app.getPath('userDesktop');
const CONFIGURENAME = 'command-manager.config';
const CONFIGUREPATH = join(USERDATA, CONFIGURENAME);
const TEMPCONFIGUREPATH = join(USERDESKTOP, CONFIGURENAME);
const DEFAULTCONFIGURE = { projects: [] };
const ERRORMESSAGE = {
  NONEXISTS: '不存在',
  READERROR: '读取失败',
  WRITEERROR: '写入失败',
  PARSEERROR: '解析失败',
  VALIDERROR: '校验失败'
};

/**
 * ConfigureError
 * @param code
 * @param message
 * @constructor
 */
function ConfigureError(code, message){
  this.code = code;
  this.message = message;
  this.name = 'ConfigureError';
}

// ConfigureError prototype
ConfigureError.prototype = Object.create(Error.prototype);
ConfigureError.prototype.constructor = ConfigureError;

/**
 * verify configure
 * @param configure
 * @returns {*}
 */
function verifyConfigure(configure){
  if (!configure) {
    return false;
  }

  if (!Array.isArray(configure.projects)) {
    return false;
  }

  return configure.projects.every(function (project){
    if (!project.name || typeof project.name !== 'string') {
      return false;
    }

    if (!project.path || typeof project.path !== 'string') {
      return false;
    }

    if (Array.isArray(project.env)) {
      var envValid = project.env.every(function (env){
        return env.name && typeof env.name === 'string'
          && env.value && typeof env.value === 'string';
      });

      if (!envValid) {
        return false;
      }
    } else {
      return false
    }

    if (Array.isArray(project.command)) {
      var commandValid = project.command.every(function (command){
        return command.name && typeof command.name === 'string'
          && command.value && typeof command.value === 'string';
      });

      if (!commandValid) {
        return false;
      }
    } else {
      return false;
    }

    return true;
  });
}

/**
 * unique array by a track
 * @param array
 * @param progress
 * @param track
 * @returns {Array}
 */
function unique(array, progress, track){
  var cache = {};

  progress = typeof progress === 'function' ? progress : function (){};
  track = track && typeof track === 'string' ? track : 'name';

  return array.filter(function (item){
    var key = item[track];

    if (cache[key]) {
      return false;
    } else {
      cache[key] = true;

      progress.apply(this, arguments);

      return true;
    }
  });
}

/**
 * filter configure
 * @param configure
 * @returns {*}
 */
function filterConfigure(configure){
  configure.projects = unique(configure.projects, function (project){
    if (project.env) {
      project.env = unique(project.env);
    }

    if (project.command) {
      project.command = unique(project.command);
    }
  });

  return configure;
}

/**
 * AppConfigure
 * @param window
 * @param tray
 * @constructor
 */
function AppConfigure(window, tray){
  this.window = window;
  this.tray = tray;
  this.title = window.getTitle();

  this.init();
}

/**
 * AppConfigure prototype
 */
AppConfigure.prototype = {
  init: function (){
    var context = this;

    this.create();

    ipc.on('app-configure', function (event, command, configure){
      switch (command) {
        case 'import':
          context.import(function (configure){
            this.showMessageBox('配置文件导入成功！', { type: 'info' });
            event.sender.send('app-configure', 'refresh', configure);
          }, function (error){
            this.showMessageBox('配置文件' + error.message + '！');
          });
          break;
        case 'export':
          context.export(function (path){
            this.showMessageBox('配置文件导出成功！', { type: 'info' }, function (){
              shell.showItemInFolder(path);
            });
          }, function (){
            this.showMessageBox('配置文件导出失败！');
          });
          break;
        case 'refresh':
          context.read(function (configure){
            event.sender.send('app-configure', 'refresh', configure);
          }, function (error){
            context.showMessageBox('配置文件' + error.message + '！', function (){
              context.window.close();
            });
          });
          break;
        case 'save':
          context.save(configure, null, function (){
            this.showMessageBox('保存失败！');
          });
          break;
      }

    });
  },
  create: function (){
    var context = this;

    fs.stat(CONFIGUREPATH, function (error, stats){
      if (error || !stats.isFile()) {
        context.save(DEFAULTCONFIGURE, null, function (){
          context.showMessageBox('配置文件创建失败，请用管理员模式运行重试！', function (){
            context.window.close();
          });
        });
      }
    });
  },
  save: function (configure, done, fail){
    var context = this;

    done = typeof done === 'function' ? done : function (){};
    fail = typeof fail === 'function' ? fail : function (){};

    fs.writeFile(CONFIGUREPATH, JSON.stringify(configure), function (error){
      if (error) {
        var code = error.code === 'ENOENT' ? 'NONEXISTS' : 'WRITEERROR';

        fail.call(context, new ConfigureError(code, ERRORMESSAGE[code]));
      } else {
        done.call(context, configure);
      }
    });
  },
  read: function (done, fail){
    var context = this;

    done = typeof done === 'function' ? done : function (){};
    fail = typeof fail === 'function' ? fail : function (){};

    fs.readFile(CONFIGUREPATH, function (error, configure){
      if (error) {
        var code = error.code === 'ENOENT' ? 'NONEXISTS' : 'READERROR';

        fail.call(context, new ConfigureError(code, ERRORMESSAGE[code]));
      } else {
        try {
          configure = JSON.parse(configure);
        } catch (error) {
          return fail.call(context, new ConfigureError('PARSEERROR', ERRORMESSAGE.PARSEERROR));
        }
      }

      // invalid configure
      if (!verifyConfigure(configure)) {
        return fail.call(context, new ConfigureError('VALIDERROR', ERRORMESSAGE.VALIDERROR));
      }

      done.call(context, configure);
    });
  },
  import: function (done, fail){
    var context = this;

    done = typeof done === 'function' ? done : function (){};
    fail = typeof fail === 'function' ? fail : function (){};

    // show open dialog
    dialog.showOpenDialog(this.window, {
      title: this.title,
      defaultPath: TEMPCONFIGUREPATH,
      properties: ['openFile'],
      filters: [{ name: '配置文件', extensions: ['config'] }]
    }, function (paths){
      if (paths) {
        fs.readFile(paths[0], function (error, configure){
          if (error) {
            var code = error.code === 'ENOENT' ? 'NONEXISTS' : 'READERROR';

            fail.call(context, new ConfigureError(code, ERRORMESSAGE[code]));
          } else {
            try {
              configure = JSON.parse(configure);
            } catch (error) {
              return fail.call(context, new ConfigureError('PARSEERROR', ERRORMESSAGE.PARSEERROR));
            }

            // invalid configure
            if (!verifyConfigure(configure)) {
              return fail.call(context, new ConfigureError('VALIDERROR', ERRORMESSAGE.VALIDERROR));
            }

            // filter configure
            configure = filterConfigure(configure);

            // save configure
            context.save(configure, done, fail);
          }
        });
      }
    });
  },
  export: function (done, fail){
    var context = this;

    done = typeof done === 'function' ? done : function (){};
    fail = typeof fail === 'function' ? fail : function (){};

    // show save dialog
    dialog.showSaveDialog(this.window, {
      title: this.title,
      defaultPath: TEMPCONFIGUREPATH,
      filters: [{ name: '配置文件', extensions: ['config'] }]
    }, function (path){
      if (path) {
        fs.createReadStream(CONFIGUREPATH)
          .on('error', function (error){
            var code = error.code === 'ENOENT' ? 'NONEXISTS' : 'READERROR';

            fail.call(context, new ConfigureError(code, ERRORMESSAGE[code]));
          })
          .pipe(fs.createWriteStream(path))
          .on('finish', function (){
            done.call(context, path);
          })
          .on('error', function (error){
            var code = error.code === 'ENOENT' ? 'NONEXISTS' : 'WRITEERROR';

            fail.call(context, new ConfigureError(code, ERRORMESSAGE[code]));
          });
      }
    });
  },
  showMessageBox: function (message, options, callback){
    if (typeof options === 'function') {
      callback = options;
      options = { message: message };
    }

    options = options || {};
    options.title = this.title;
    options.message = message;
    options.type = options.type || 'error';
    options.buttons = options.buttons || [];

    dialog.showMessageBox(this.window, options, callback);
  }
};

module.exports = AppConfigure;
<commit_msg>update files<commit_after>/**
 * Created by nuintun on 2015/11/18.
 */

'use strict';

var fs = require('fs');
var path = require('path');
var join = path.join;
// module to control application life
var app = require('app');
var ipc = require('ipc-main');
var dialog = require('dialog');
var shell = require('shell');

const USERDATA = app.getPath('userData');
const USERDESKTOP = app.getPath('userDesktop');
const CONFIGURENAME = 'command-manager.config';
const CONFIGUREPATH = join(USERDATA, CONFIGURENAME);
const TEMPCONFIGUREPATH = join(USERDESKTOP, CONFIGURENAME);
const DEFAULTCONFIGURE = { projects: [] };
const ERRORMESSAGE = {
  NONEXISTS: '不存在',
  READERROR: '读取失败',
  WRITEERROR: '写入失败',
  PARSEERROR: '解析失败',
  VALIDERROR: '校验失败'
};

/**
 * ConfigureError
 * @param code
 * @param message
 * @constructor
 */
function ConfigureError(code, message){
  this.code = code;
  this.message = message;
  this.name = 'ConfigureError';
}

// ConfigureError prototype
ConfigureError.prototype = Object.create(Error.prototype);
ConfigureError.prototype.constructor = ConfigureError;

/**
 * verify configure
 * @param configure
 * @returns {*}
 */
function verifyConfigure(configure){
  if (!configure) {
    return false;
  }

  if (!Array.isArray(configure.projects)) {
    return false;
  }

  return configure.projects.every(function (project){
    if (!project.name || typeof project.name !== 'string') {
      return false;
    }

    if (!project.path || typeof project.path !== 'string') {
      return false;
    }

    if (Array.isArray(project.env)) {
      var envValid = project.env.every(function (env){
        return env.name && typeof env.name === 'string'
          && env.value && typeof env.value === 'string';
      });

      if (!envValid) {
        return false;
      }
    } else {
      return false
    }

    if (Array.isArray(project.command)) {
      var commandValid = project.command.every(function (command){
        return command.name && typeof command.name === 'string'
          && command.value && typeof command.value === 'string';
      });

      if (!commandValid) {
        return false;
      }
    } else {
      return false;
    }

    return true;
  });
}

/**
 * unique array by a track
 * @param array
 * @param progress
 * @param track
 * @returns {Array}
 */
function unique(array, progress, track){
  var cache = {};

  progress = typeof progress === 'function' ? progress : function (){};
  track = track && typeof track === 'string' ? track : 'name';

  return array.filter(function (item){
    var key = item[track];

    if (cache[key]) {
      return false;
    } else {
      cache[key] = true;

      progress.apply(this, arguments);

      return true;
    }
  });
}

/**
 * filter configure
 * @param configure
 * @returns {*}
 */
function filterConfigure(configure){
  configure.projects = unique(configure.projects, function (project){
    if (project.env) {
      project.env = unique(project.env);
    }

    if (project.command) {
      project.command = unique(project.command);
    }
  });

  return configure;
}

/**
 * AppConfigure
 * @param window
 * @param tray
 * @constructor
 */
function AppConfigure(window, tray){
  this.window = window;
  this.tray = tray;
  this.title = window.getTitle();

  this.init();
}

/**
 * AppConfigure prototype
 */
AppConfigure.prototype = {
  init: function (){
    var context = this;

    this.create();

    ipc.on('app-configure', function (event, command, configure){
      switch (command) {
        case 'import':
          context.import(function (configure){
            this.showMessageBox('配置文件导入成功！', { type: 'info' });
            event.sender.send('app-configure', 'refresh', configure);
          }, function (error){
            this.showMessageBox('配置文件' + error.message + '！');
          });
          break;
        case 'export':
          context.export(function (path){
            this.showMessageBox('配置文件导出成功！', { type: 'info' }, function (){
              shell.showItemInFolder(path);
            });
          }, function (){
            this.showMessageBox('配置文件导出失败！');
          });
          break;
        case 'refresh':
          context.read(function (configure){
            event.sender.send('app-configure', 'refresh', configure);
          }, function (error){
            context.showMessageBox('配置文件' + error.message + '！', function (){
              shell.showItemInFolder(CONFIGUREPATH);
              context.window.close();
            });
          });
          break;
        case 'save':
          context.save(configure, null, function (){
            this.showMessageBox('保存失败！');
          });
          break;
      }

    });
  },
  create: function (){
    var context = this;

    fs.stat(CONFIGUREPATH, function (error, stats){
      if (error || !stats.isFile()) {
        context.save(DEFAULTCONFIGURE, null, function (){
          context.showMessageBox('配置文件创建失败，请用管理员模式运行重试！', function (){
            context.window.close();
          });
        });
      }
    });
  },
  save: function (configure, done, fail){
    var context = this;

    done = typeof done === 'function' ? done : function (){};
    fail = typeof fail === 'function' ? fail : function (){};

    fs.writeFile(CONFIGUREPATH, JSON.stringify(configure), function (error){
      if (error) {
        var code = error.code === 'ENOENT' ? 'NONEXISTS' : 'WRITEERROR';

        fail.call(context, new ConfigureError(code, ERRORMESSAGE[code]));
      } else {
        done.call(context, configure);
      }
    });
  },
  read: function (done, fail){
    var context = this;

    done = typeof done === 'function' ? done : function (){};
    fail = typeof fail === 'function' ? fail : function (){};

    fs.readFile(CONFIGUREPATH, function (error, configure){
      if (error) {
        var code = error.code === 'ENOENT' ? 'NONEXISTS' : 'READERROR';

        fail.call(context, new ConfigureError(code, ERRORMESSAGE[code]));
      } else {
        try {
          configure = JSON.parse(configure);
        } catch (error) {
          return fail.call(context, new ConfigureError('PARSEERROR', ERRORMESSAGE.PARSEERROR));
        }
      }

      // invalid configure
      if (!verifyConfigure(configure)) {
        return fail.call(context, new ConfigureError('VALIDERROR', ERRORMESSAGE.VALIDERROR));
      }

      done.call(context, configure);
    });
  },
  import: function (done, fail){
    var context = this;

    done = typeof done === 'function' ? done : function (){};
    fail = typeof fail === 'function' ? fail : function (){};

    // show open dialog
    dialog.showOpenDialog(this.window, {
      title: this.title,
      defaultPath: TEMPCONFIGUREPATH,
      properties: ['openFile'],
      filters: [{ name: '配置文件', extensions: ['config'] }]
    }, function (paths){
      if (paths) {
        fs.readFile(paths[0], function (error, configure){
          if (error) {
            var code = error.code === 'ENOENT' ? 'NONEXISTS' : 'READERROR';

            fail.call(context, new ConfigureError(code, ERRORMESSAGE[code]));
          } else {
            try {
              configure = JSON.parse(configure);
            } catch (error) {
              return fail.call(context, new ConfigureError('PARSEERROR', ERRORMESSAGE.PARSEERROR));
            }

            // invalid configure
            if (!verifyConfigure(configure)) {
              return fail.call(context, new ConfigureError('VALIDERROR', ERRORMESSAGE.VALIDERROR));
            }

            // filter configure
            configure = filterConfigure(configure);

            // save configure
            context.save(configure, done, fail);
          }
        });
      }
    });
  },
  export: function (done, fail){
    var context = this;

    done = typeof done === 'function' ? done : function (){};
    fail = typeof fail === 'function' ? fail : function (){};

    // show save dialog
    dialog.showSaveDialog(this.window, {
      title: this.title,
      defaultPath: TEMPCONFIGUREPATH,
      filters: [{ name: '配置文件', extensions: ['config'] }]
    }, function (path){
      if (path) {
        fs.createReadStream(CONFIGUREPATH)
          .on('error', function (error){
            var code = error.code === 'ENOENT' ? 'NONEXISTS' : 'READERROR';

            fail.call(context, new ConfigureError(code, ERRORMESSAGE[code]));
          })
          .pipe(fs.createWriteStream(path))
          .on('finish', function (){
            done.call(context, path);
          })
          .on('error', function (error){
            var code = error.code === 'ENOENT' ? 'NONEXISTS' : 'WRITEERROR';

            fail.call(context, new ConfigureError(code, ERRORMESSAGE[code]));
          });
      }
    });
  },
  showMessageBox: function (message, options, callback){
    if (typeof options === 'function') {
      callback = options;
      options = { message: message };
    }

    options = options || {};
    options.title = this.title;
    options.message = message;
    options.type = options.type || 'error';
    options.buttons = options.buttons || [];

    dialog.showMessageBox(this.window, options, callback);
  }
};

module.exports = AppConfigure;
<|endoftext|>


<commit_before>/**
 * Description : This is a test suite that tests an LRS endpoint based on the testing requirements document
 * found at https://github.com/adlnet/xapi-lrs-conformance-requirements
 */

(function (module, fs, extend, moment, request, requestPromise, chai, liburl, Joi, helper, multipartParser, redirect, templatingSelection) {
    // "use strict";

    var expect = chai.expect;
    if(global.OAUTH)
        request = helper.OAuthRequest(request);

describe('Authority Property Requirements (Data 2.4.9)', () => {

/**  Matchup with Conformance Requirements Document
 * XAPI-00098 - in authorities.js
 * XAPI-00099 - below
 * XAPI-00100 - below

 * Note - XAPI-00024 - in authorities.js
 */
    templatingSelection.createTemplate('authorities.js');

/**  XAPI-00100, Data 2.4.9 Authority
 * An LRS rejects with error code 400 Bad Request, a Request whose "authority" is a Group having more than two Agents
 */
    it('An LRS rejects with error code 400 Bad Request, a Request whose "authority" is a Group and consists of non-O-Auth Agents (Data 2.4.9.s3.b3, XAPI-00100)', function (done) {
        var templates = [
            {statement: '{{statements.default}}'},
            {authority: {"objectType": "Group", "name": "xAPI Group", "mbox": "mailto:xapigroup@example.com",
            "member":[{"name":"agentA","mbox":"mailto:agentA@example.com"},{"name":"agentB","mbox":"mailto:agentB@example.com"}]}}
        ];
        var data = helper.createFromTemplate(templates);
        data = data.statement;
        request(helper.getEndpointAndAuth())
            .post(helper.getEndpointStatements())
            .headers(helper.addAllHeaders({}))
            .json(data)
            .expect(400, done)
    });

/**  XAPI-00099, Data 2.4.9 Authority
 * An LRS populates the "authority" property if it is not provided in the Statement
 */
    describe('An LRS populates the "authority" property if it is not provided in the Statement, based on header information with the Agent corresponding to the user (contained within the header) (Implicit, Data 2.4.9.s3.b4, XAPI-00099) ', function () {

        it('should populate authority ', function (done) {

            this.timeout(0);
            var templates = [
                {statement: '{{statements.default}}'}
            ];
            var data = helper.createFromTemplate(templates);
            data = data.statement;
            data.id = helper.generateUUID();
            var query = '?statementId=' + data.id;
            var stmtTime = Date.now();

            request(helper.getEndpointAndAuth())
            .post(helper.getEndpointStatements())
            .headers(helper.addAllHeaders({}))
            .json(data)
            .expect(200)
            .end(function (err, res) {
                if (err) {
                    done(err);
                } else {
                    request(helper.getEndpointAndAuth())
                    .get(helper.getEndpointStatements() + '?statementId=' + data.id)
                    .headers(helper.addAllHeaders({}))
                    .wait(helper.genDelay(stmtTime, query, data.id))
                    .expect(200).end(function (err, res) {
                        if (err) {
                            done(err);
                        } else {
                            var statement = helper.parse(res.body, done);
                            expect(statement).to.have.property('authority');
                            done();
                        }
                    });
                }
            })
        });
    });

});

}(module, require('fs'), require('extend'), require('moment'), require('super-request'), require('supertest-as-promised'), require('chai'), require('url'), require('joi'), require('./../helper'), require('./../multipartParser'), require('./../redirect.js'), require('./../templatingSelection.js')));
<commit_msg>fix #96 in data 2.4.9<commit_after>/**
 * Description : This is a test suite that tests an LRS endpoint based on the testing requirements document
 * found at https://github.com/adlnet/xapi-lrs-conformance-requirements
 */

(function (module, fs, extend, moment, request, requestPromise, chai, liburl, Joi, helper, multipartParser, redirect, templatingSelection) {
    // "use strict";

    var expect = chai.expect;
    if(global.OAUTH)
        request = helper.OAuthRequest(request);

describe('Authority Property Requirements (Data 2.4.9)', () => {

/**  Matchup with Conformance Requirements Document
 * XAPI-00098 - in authorities.js
 * XAPI-00099 - below
 * XAPI-00100 - below

 * Note - XAPI-00024 - in authorities.js
 */
    templatingSelection.createTemplate('authorities.js');

/**  XAPI-00100, Data 2.4.9 Authority
 * An LRS rejects with error code 400 Bad Request, a Request whose "authority" is a Group having more than two Agents
 */
    it('An LRS rejects with error code 400 Bad Request, a Request whose "authority" is a Group and consists of non-O-Auth Agents (Data 2.4.9.s3.b3, XAPI-00100)', function (done) {
        var templates = [
            {statement: '{{statements.default}}'},
            {authority: {"objectType": "Group", "name": "xAPI Group", "mbox": "mailto:xapigroup@example.com",
            "member":[{"name":"agentA","mbox":"mailto:agentA@example.com"},{"name":"agentB","mbox":"mailto:agentB@example.com"}]}}
        ];
        var data = helper.createFromTemplate(templates);
        data = data.statement;
        request(helper.getEndpointAndAuth())
            .post(helper.getEndpointStatements())
            .headers(helper.addAllHeaders({}))
            .json(data)
            .expect(400, done)
    });

/**  XAPI-00099, Data 2.4.9 Authority
 * An LRS populates the "authority" property if it is not provided in the Statement
 */
    describe('An LRS populates the "authority" property if it is not provided in the Statement, based on header information with the Agent corresponding to the user (contained within the header) (Implicit, Data 2.4.9.s3.b4, XAPI-00099) ', function () {

        it('should populate authority ', function (done) {

            this.timeout(0);
            var templates = [
                {statement: '{{statements.default}}'}
            ];
            var data = helper.createFromTemplate(templates);
            data = data.statement;
            data.id = helper.generateUUID();
            var query = '?statementId=' + data.id;
            var stmtTime = Date.now();

            request(helper.getEndpointAndAuth())
            .post(helper.getEndpointStatements())
            .headers(helper.addAllHeaders({}))
            .json(data)
            .expect(200)
            .end(function (err, res) {
                if (err) {
                    done(err);
                } else {
                    request(helper.getEndpointAndAuth())
                    .get(helper.getEndpointStatements() + query)
                    .headers(helper.addAllHeaders({}))
                    .wait(helper.genDelay(stmtTime, query, data.id))
                    .expect(200).end(function (err, res) {
                        if (err) {
                            done(err);
                        } else {
                            var statement = helper.parse(res.body, done);
                            expect(statement).to.have.property('authority');
                            done();
                        }
                    });
                }
            })
        });
    });

});

}(module, require('fs'), require('extend'), require('moment'), require('super-request'), require('supertest-as-promised'), require('chai'), require('url'), require('joi'), require('./../helper'), require('./../multipartParser'), require('./../redirect.js'), require('./../templatingSelection.js')));
<|endoftext|>