<commit_before>(function() {
    'use strict';

    angular.module('chaise.record', [
        'ngSanitize',
        'ngCookies',
        'chaise.alerts',
        'chaise.delete',
        'chaise.errors',
        'chaise.modal',
        'chaise.navbar',
        'chaise.record.display',
        'chaise.record.table',
        'chaise.html',
        'chaise.utils',
        'ermrestjs',
        'ui.bootstrap',
        'chaise.footer',
        'chaise.upload',
        'chaise.recordcreate'
    ])

    .factory('constants', [function(){
        return {
            defaultPageSize: 25,
        };
    }])

    .config(['$cookiesProvider', function($cookiesProvider) {
        $cookiesProvider.defaults.path = '/';
    }])

    // Configure all tooltips to be attached to the body by default. To attach a
    // tooltip on the element instead, set the `tooltip-append-to-body` attribute
    // to `false` on the element.
    .config(['$uibTooltipProvider', function($uibTooltipProvider) {
        $uibTooltipProvider.options({appendToBody: true});
    }])

    .run(['constants', 'DataUtils', 'ERMrest', 'ErrorService', 'headInjector', 'MathUtils', 'modalBox', 'Session', 'UiUtils', 'UriUtils', '$log', '$rootScope', '$window',
        function runApp(constants, DataUtils, ERMrest, ErrorService, headInjector, MathUtils, modalBox, Session, UiUtils, UriUtils, $log, $rootScope, $window) {

        var session,
            context = {};
        $rootScope.displayReady = false;
        $rootScope.recDisplayReady = false;

        UriUtils.setOrigin();
        headInjector.setupHead();

        $rootScope.showEmptyRelatedTables = false;
        $rootScope.modifyRecord = chaiseConfig.editRecord === false ? false : true;
        $rootScope.showDeleteButton = chaiseConfig.deleteRecord === true ? true : false;

        var ermrestUri = UriUtils.chaiseURItoErmrestURI($window.location);

        $rootScope.context = context;

        // The context object won't change unless the app is reloaded
        context.appName = "record";
        context.pageId = MathUtils.uuid();

        ERMrest.appLinkFn(UriUtils.appTagToURL);

        /**
        * getPageSize(obj) returms page size of the display attribute in the object.
        * @param {object} obj Object reference that has the display attribute
        */
        function getPageSize(obj){
            return ((!angular.isUndefined(obj) && obj.display.defaultPageSize)?obj.display.defaultPageSize:constants.defaultPageSize);
        }

        /**
        * getRelatedTableData(refObj, accordionOpen, callback) returns model object with all required component values
        * that is needed by <record-table>, <record-action-bar> and <record-display> diretives.
        * @param {object} refObj Reference object with component details
        * @param {bool} accordionOpen if paased as TRUE accordion should be expanded
        * @param {callback} callback to be called after function processing
        */
        function getRelatedTableData(refObj, accordionOpen, callback){

            var pageSize = getPageSize(refObj);
            refObj.read(pageSize).then(function (page) {
                var model = {
                    reference: refObj,
                    columns: refObj.columns,
                    page: page,
                    pageLimit: pageSize,
                    hasNext: page.hasNext,      // used to determine if a link should be shown
                    hasLoaded: true,            // used to determine if the current table and next table should be rendered
                    open: accordionOpen,        // to define if the accordion is open or closed
                    enableSort: true,           // allow sorting on table
                    sortby: null,               // column name, user selected or null
                    sortOrder: null,            // asc (default) or desc
                    rowValues: [],              // array of rows values
                    selectedRows: [],           // array of selected rows, needs to be defined even if not used
                    search: null,                // search term
                    displayType: refObj.display.type,
                    context: "compact/brief",
                    fromTuple: $rootScope.tuple
                };
                model.rowValues = DataUtils.getRowValuesFromPage(page);
                model.config = {
                    viewable: true,
                    editable: $rootScope.modifyRecord,
                    deletable: $rootScope.modifyRecord && $rootScope.showDeleteButton,
                    selectMode: modalBox.noSelect
                };
                // return model;
                callback(model);
                },function readFail(error) {
                    var model = {
                        hasLoaded: true
                    };
                    // return model;
                    callback(model);
                    throw error;
                }).catch(function(e) {
                    // The .catch from the outer promise won't catch errors from this closure
                    // so a .catch needs to be appended here.
                    throw e;
                });
        }
        // Subscribe to on change event for session
        var subId = Session.subscribeOnChange(function() {

            // Unsubscribe onchange event to avoid this function getting called again
            Session.unsubscribeOnChange(subId);

            ERMrest.resolve(ermrestUri, {cid: context.appName, pid: context.pageId, wid: $window.name}).then(function getReference(reference) {
                context.filter = reference.location.filter;

                DataUtils.verify(context.filter, 'No filter was defined. Cannot find a record without a filter.');

                // if the user can fetch the reference, they can see the content for the rest of the page
                // set loading to force the loading text to appear and to prevent the on focus from firing while code is initializing
                session = Session.getSessionValue();

                // $rootScope.reference != reference after contextualization
                $rootScope.reference = reference.contextualize.detailed;
                $rootScope.reference.session = session;
                $log.info("Reference: ", $rootScope.reference);

                // There should only ever be one entity related to this reference, we are reading 2 entities now and if we get more than 1 entity than we throw a multipleRecordError.
                return $rootScope.reference.read(2);
            }, function error(exception) {
                throw exception;
            }).then(function getPage(page) {
                $log.info("Page: ", page);

                if (page.tuples.length < 1) {
                    var noDataError = ErrorService.noRecordError(context.filter.filters);
                    throw noDataError;
                }
                else if(page.tuples.length > 1){
                    var recordSetLink = page.reference.contextualize.compact.appLink;
                    var multipleRecordError = ErrorService.multipleRecordError();
                    multipleRecordError.redirectUrl=recordSetLink;
                    $rootScope.displayReady = true;
                    throw multipleRecordError;
                }

                var tuple = $rootScope.tuple = page.tuples[0];
                // Used directly in the record-display directive
                $rootScope.recordDisplayname = tuple.displayname;

                // related references
                $rootScope.relatedReferences = $rootScope.reference.related(tuple);

                $rootScope.loading = $rootScope.relatedReferences.length > 0;

                // Collate tuple.isHTML and tuple.values into an array of objects
                // i.e. {isHTML: false, value: 'sample'}
                $rootScope.recordValues = [];
                tuple.values.forEach(function(value, index) {
                    $rootScope.recordValues.push({
                        isHTML: tuple.isHTML[index],
                        value: value
                    });
                });

                $rootScope.columns = $rootScope.reference.generateColumnsList(tuple);
                var allInbFKColsIdx = [];
                var allInbFKCols = $rootScope.columns.filter(function (o, i) {
                    if(o.isInboundForeignKey){
                        allInbFKColsIdx.push(i);
                        return o;
                    }
                });
                $rootScope.inboundFKCols = allInbFKCols;
                $rootScope.inboundFKColsIdx = allInbFKColsIdx;
                $rootScope.inbFKRef = allInbFKCols;
                if(allInbFKCols.length>0){

                    $rootScope.rtrefDisTypetable = [];
                    $rootScope.colTableModels = [];

                    for(var i =0;i<allInbFKCols.length;i++){
                        allInbFKCols[i].reference = allInbFKCols[i].reference.contextualize.compactBrief;
                        var ifkPageSize = getPageSize(allInbFKCols[i].reference);
                        (function(i) {
                            getRelatedTableData(allInbFKCols[i].reference, true, function(model){

                                $rootScope.colTableModels[allInbFKColsIdx[i]] = model;
                                $rootScope.rtrefDisTypetable[allInbFKColsIdx[i]] = allInbFKCols[i].reference;
                                $rootScope.recDisplayReady =  (i==allInbFKCols.length-1)?true:false;

                            });
                        })(i);
                    }
                }else{
                    $rootScope.recDisplayReady =  true;
                }

                $rootScope.tableModels = [];
                $rootScope.lastRendered = null;
                var cutOff = chaiseConfig.maxRelatedTablesOpen > 0? chaiseConfig.maxRelatedTablesOpen : Infinity;
                var boolIsOpen = $rootScope.relatedReferences.length>cutOff?false:true;

                for (var i = 0; i < $rootScope.relatedReferences.length; i++) {

                    $rootScope.relatedReferences[i] = $rootScope.relatedReferences[i].contextualize.compactBrief;
                    var pageSize = getPageSize($rootScope.relatedReferences[i]);
                    (function(i) {
                        if ($rootScope.relatedReferences[i].canCreate && $rootScope.modifyRecord && !$rootScope.showEmptyRelatedTables) {
                            $rootScope.showEmptyRelatedTables = true;
                        }
                        getRelatedTableData($rootScope.relatedReferences[i], boolIsOpen, function(model){
                            $rootScope.tableModels[i] = model;
                            $rootScope.displayReady = true;
                        });
                    })(i);
                }
            }).catch(function genericCatch(exception) {
                throw exception;
            });

        })

        /**
         * it saves the location in $rootScope.location.
         * When address bar is changed, this code compares the address bar location
         * with the last save recordset location. If it's the same, the change of url was
         * done internally, do not refresh page. If not, the change was done manually
         * outside recordset, refresh page.
         *
         */
        UriUtils.setLocationChangeHandling();

        // This is to allow the dropdown button to open at the top/bottom depending on the space available
        UiUtils.setBootstrapDropdownButtonBehavior();
    }]);
})();
<commit_msg>spinner wouldn't disappear on record with 0 related tables<commit_after>(function() {
    'use strict';

    angular.module('chaise.record', [
        'ngSanitize',
        'ngCookies',
        'chaise.alerts',
        'chaise.delete',
        'chaise.errors',
        'chaise.modal',
        'chaise.navbar',
        'chaise.record.display',
        'chaise.record.table',
        'chaise.html',
        'chaise.utils',
        'ermrestjs',
        'ui.bootstrap',
        'chaise.footer',
        'chaise.upload',
        'chaise.recordcreate'
    ])

    .factory('constants', [function(){
        return {
            defaultPageSize: 25,
        };
    }])

    .config(['$cookiesProvider', function($cookiesProvider) {
        $cookiesProvider.defaults.path = '/';
    }])

    // Configure all tooltips to be attached to the body by default. To attach a
    // tooltip on the element instead, set the `tooltip-append-to-body` attribute
    // to `false` on the element.
    .config(['$uibTooltipProvider', function($uibTooltipProvider) {
        $uibTooltipProvider.options({appendToBody: true});
    }])

    .run(['constants', 'DataUtils', 'ERMrest', 'ErrorService', 'headInjector', 'MathUtils', 'modalBox', 'Session', 'UiUtils', 'UriUtils', '$log', '$rootScope', '$window',
        function runApp(constants, DataUtils, ERMrest, ErrorService, headInjector, MathUtils, modalBox, Session, UiUtils, UriUtils, $log, $rootScope, $window) {

        var session,
            context = {};
        $rootScope.displayReady = false;
        $rootScope.recDisplayReady = false;

        UriUtils.setOrigin();
        headInjector.setupHead();

        $rootScope.showEmptyRelatedTables = false;
        $rootScope.modifyRecord = chaiseConfig.editRecord === false ? false : true;
        $rootScope.showDeleteButton = chaiseConfig.deleteRecord === true ? true : false;

        var ermrestUri = UriUtils.chaiseURItoErmrestURI($window.location);

        $rootScope.context = context;

        // The context object won't change unless the app is reloaded
        context.appName = "record";
        context.pageId = MathUtils.uuid();

        ERMrest.appLinkFn(UriUtils.appTagToURL);

        /**
        * getPageSize(obj) returms page size of the display attribute in the object.
        * @param {object} obj Object reference that has the display attribute
        */
        function getPageSize(obj){
            return ((!angular.isUndefined(obj) && obj.display.defaultPageSize)?obj.display.defaultPageSize:constants.defaultPageSize);
        }

        /**
        * getRelatedTableData(refObj, accordionOpen, callback) returns model object with all required component values
        * that is needed by <record-table>, <record-action-bar> and <record-display> diretives.
        * @param {object} refObj Reference object with component details
        * @param {bool} accordionOpen if paased as TRUE accordion should be expanded
        * @param {callback} callback to be called after function processing
        */
        function getRelatedTableData(refObj, accordionOpen, callback){

            var pageSize = getPageSize(refObj);
            refObj.read(pageSize).then(function (page) {
                var model = {
                    reference: refObj,
                    columns: refObj.columns,
                    page: page,
                    pageLimit: pageSize,
                    hasNext: page.hasNext,      // used to determine if a link should be shown
                    hasLoaded: true,            // used to determine if the current table and next table should be rendered
                    open: accordionOpen,        // to define if the accordion is open or closed
                    enableSort: true,           // allow sorting on table
                    sortby: null,               // column name, user selected or null
                    sortOrder: null,            // asc (default) or desc
                    rowValues: [],              // array of rows values
                    selectedRows: [],           // array of selected rows, needs to be defined even if not used
                    search: null,                // search term
                    displayType: refObj.display.type,
                    context: "compact/brief",
                    fromTuple: $rootScope.tuple
                };
                model.rowValues = DataUtils.getRowValuesFromPage(page);
                model.config = {
                    viewable: true,
                    editable: $rootScope.modifyRecord,
                    deletable: $rootScope.modifyRecord && $rootScope.showDeleteButton,
                    selectMode: modalBox.noSelect
                };
                // return model;
                callback(model);
                },function readFail(error) {
                    var model = {
                        hasLoaded: true
                    };
                    // return model;
                    callback(model);
                    throw error;
                }).catch(function(e) {
                    // The .catch from the outer promise won't catch errors from this closure
                    // so a .catch needs to be appended here.
                    throw e;
                });
        }
        // Subscribe to on change event for session
        var subId = Session.subscribeOnChange(function() {

            // Unsubscribe onchange event to avoid this function getting called again
            Session.unsubscribeOnChange(subId);

            ERMrest.resolve(ermrestUri, {cid: context.appName, pid: context.pageId, wid: $window.name}).then(function getReference(reference) {
                context.filter = reference.location.filter;

                DataUtils.verify(context.filter, 'No filter was defined. Cannot find a record without a filter.');

                // if the user can fetch the reference, they can see the content for the rest of the page
                // set loading to force the loading text to appear and to prevent the on focus from firing while code is initializing
                session = Session.getSessionValue();

                // $rootScope.reference != reference after contextualization
                $rootScope.reference = reference.contextualize.detailed;
                $rootScope.reference.session = session;
                $log.info("Reference: ", $rootScope.reference);

                // There should only ever be one entity related to this reference, we are reading 2 entities now and if we get more than 1 entity than we throw a multipleRecordError.
                return $rootScope.reference.read(2);
            }, function error(exception) {
                throw exception;
            }).then(function getPage(page) {
                $log.info("Page: ", page);

                if (page.tuples.length < 1) {
                    var noDataError = ErrorService.noRecordError(context.filter.filters);
                    throw noDataError;
                }
                else if(page.tuples.length > 1){
                    var recordSetLink = page.reference.contextualize.compact.appLink;
                    var multipleRecordError = ErrorService.multipleRecordError();
                    multipleRecordError.redirectUrl=recordSetLink;
                    $rootScope.displayReady = true;
                    throw multipleRecordError;
                }

                var tuple = $rootScope.tuple = page.tuples[0];
                // Used directly in the record-display directive
                $rootScope.recordDisplayname = tuple.displayname;

                // related references
                $rootScope.relatedReferences = $rootScope.reference.related(tuple);

                $rootScope.loading = $rootScope.relatedReferences.length > 0;

                // Collate tuple.isHTML and tuple.values into an array of objects
                // i.e. {isHTML: false, value: 'sample'}
                $rootScope.recordValues = [];
                tuple.values.forEach(function(value, index) {
                    $rootScope.recordValues.push({
                        isHTML: tuple.isHTML[index],
                        value: value
                    });
                });

                $rootScope.columns = $rootScope.reference.generateColumnsList(tuple);
                var allInbFKColsIdx = [];
                var allInbFKCols = $rootScope.columns.filter(function (o, i) {
                    if(o.isInboundForeignKey){
                        allInbFKColsIdx.push(i);
                        return o;
                    }
                });
                $rootScope.inboundFKCols = allInbFKCols;
                $rootScope.inboundFKColsIdx = allInbFKColsIdx;
                $rootScope.inbFKRef = allInbFKCols;
                if(allInbFKCols.length>0){

                    $rootScope.rtrefDisTypetable = [];
                    $rootScope.colTableModels = [];

                    for(var i =0;i<allInbFKCols.length;i++){
                        allInbFKCols[i].reference = allInbFKCols[i].reference.contextualize.compactBrief;
                        var ifkPageSize = getPageSize(allInbFKCols[i].reference);
                        (function(i) {
                            getRelatedTableData(allInbFKCols[i].reference, true, function(model){

                                $rootScope.colTableModels[allInbFKColsIdx[i]] = model;
                                $rootScope.rtrefDisTypetable[allInbFKColsIdx[i]] = allInbFKCols[i].reference;
                                $rootScope.recDisplayReady =  (i==allInbFKCols.length-1)?true:false;

                            });
                        })(i);
                    }
                }else{
                    $rootScope.recDisplayReady =  true;
                }

                $rootScope.tableModels = [];
                $rootScope.lastRendered = null;
                var cutOff = chaiseConfig.maxRelatedTablesOpen > 0? chaiseConfig.maxRelatedTablesOpen : Infinity;
                var boolIsOpen = $rootScope.relatedReferences.length>cutOff?false:true;

                for (var i = 0; i < $rootScope.relatedReferences.length; i++) {

                    $rootScope.relatedReferences[i] = $rootScope.relatedReferences[i].contextualize.compactBrief;
                    var pageSize = getPageSize($rootScope.relatedReferences[i]);
                    (function(i) {
                        if ($rootScope.relatedReferences[i].canCreate && $rootScope.modifyRecord && !$rootScope.showEmptyRelatedTables) {
                            $rootScope.showEmptyRelatedTables = true;
                        }
                        getRelatedTableData($rootScope.relatedReferences[i], boolIsOpen, function(model){
                            $rootScope.tableModels[i] = model;
                            $rootScope.displayReady = true;
                        });
                    })(i);
                }
                if ($rootScope.relatedReferences.length == 0) {
                    $rootScope.displayReady = true;
                }
            }).catch(function genericCatch(exception) {
                throw exception;
            });

        })

        /**
         * it saves the location in $rootScope.location.
         * When address bar is changed, this code compares the address bar location
         * with the last save recordset location. If it's the same, the change of url was
         * done internally, do not refresh page. If not, the change was done manually
         * outside recordset, refresh page.
         *
         */
        UriUtils.setLocationChangeHandling();

        // This is to allow the dropdown button to open at the top/bottom depending on the space available
        UiUtils.setBootstrapDropdownButtonBehavior();
    }]);
})();
<|endoftext|>


<commit_before>import Collection, {ModelAlreadyExists} from '../collection'
import difference from 'lodash.difference'
import filter from 'lodash.filter'
import getKey from 'lodash.keys'
import {createClient as createRedisClient, RedisClient, Multi} from 'redis'

import {
  forEach,
  isEmpty,
  mapToArray,
  promisifyAll
} from '../utils'

// ===================================================================

promisifyAll(RedisClient.prototype)
promisifyAll(Multi.prototype)

// ===================================================================

// ///////////////////////////////////////////////////////////////////
// Data model:
// - prefix +'_id': value of the last generated identifier;
// - prefix +'_ids': set containing identifier of all models;
// - prefix +'_'+ index +':' + value: set of identifiers which have
//   value for the given index.
// - prefix +':'+ id: hash containing the properties of a model;
// ///////////////////////////////////////////////////////////////////

// TODO: then-redis sends commands in order, we should use this
// semantic to simplify the code.

// TODO: Merge the options in the object to obtain extend-time
// configuration like Backbone.

// TODO: Remote events.

export default class Redis extends Collection {
  constructor ({
    connection,
    indexes = [],
    prefix,
    uri = 'tcp://localhost:6379'
  }) {
    super()

    this.indexes = indexes
    this.prefix = prefix
    this.redis = connection || createRedisClient(uri)
  }

  _extract (ids) {
    const prefix = this.prefix + ':'
    const {redis} = this

    const models = []
    return Promise.all(mapToArray(ids, id => {
      return redis.hgetallAsync(prefix + id).then(model => {
        // If empty, consider it a no match.
        if (isEmpty(model)) {
          return
        }

        // Mix the identifier in.
        model.id = id

        models.push(model)
      })
    })).then(() => models)
  }

  _add (models, {replace = false} = {}) {
    // TODO: remove “replace” which is a temporary measure, implement
    // “set()” instead.

    const {indexes, prefix, redis, idPrefix = ''} = this

    return Promise.all(mapToArray(models, async model => {
      // Generate a new identifier if necessary.
      if (model.id === undefined) {
        model.id = idPrefix + String(await redis.incrAsync(prefix + '_id'))
      }

      const success = await redis.saddAsync(prefix + '_ids', model.id)

      // The entry already exists an we are not in replace mode.
      if (!success && !replace) {
        throw new ModelAlreadyExists(model.id)
      }

      // TODO: Remove existing fields.

      const params = []
      forEach(model, (value, name) => {
        // No need to store the identifier (already in the key).
        if (name === 'id') {
          return
        }

        params.push(name, value)
      })

      const promises = [
        redis.hmsetAsync(prefix + ':' + model.id, ...params)
      ]

      // Update indexes.
      forEach(indexes, (index) => {
        const value = model[index]
        if (value === undefined) {
          return
        }

        const key = prefix + '_' + index + ':' + value
        promises.push(redis.saddAsync(key, model.id))
      })

      await Promise.all(promises)

      return model
    }))
  }

  _get (properties) {
    const {prefix, redis} = this

    if (isEmpty(properties)) {
      return redis.smembersAsync(prefix + '_ids').then(ids => this._extract(ids))
    }

    // Special treatment for the identifier.
    const id = properties.id
    if (id !== undefined) {
      delete properties.id
      return this._extract([id]).then(models => {
        return (models.length && !isEmpty(properties))
          ? filter(models)
          : models
      })
    }

    const {indexes} = this

    // Check for non indexed fields.
    const unfit = difference(getKey(properties), indexes)
    if (unfit.length) {
      throw new Error('fields not indexed: ' + unfit.join())
    }

    const keys = mapToArray(properties, (value, index) => `${prefix}_${index}:${value}`)
    return redis.sinterAsync(...keys).then(ids => this._extract(ids))
  }

  _remove (ids) {
    const {prefix, redis} = this

    // TODO: handle indexes.

    return Promise.all([
      // Remove the identifiers from the main index.
      redis.sremAsync(prefix + '_ids', ...ids),

      // Remove the models.
      redis.delAsync(mapToArray(ids, id => `${prefix}:${id}`))
    ])
  }

  _update (models) {
    return this._add(models, { replace: true })
  }
}
<commit_msg>Fix items updates in Redis.<commit_after>import Collection, {ModelAlreadyExists} from '../collection'
import difference from 'lodash.difference'
import filter from 'lodash.filter'
import getKey from 'lodash.keys'
import {createClient as createRedisClient, RedisClient, Multi} from 'redis'

import {
  forEach,
  isEmpty,
  mapToArray,
  promisifyAll
} from '../utils'

// ===================================================================

promisifyAll(RedisClient.prototype)
promisifyAll(Multi.prototype)

// ===================================================================

// ///////////////////////////////////////////////////////////////////
// Data model:
// - prefix +'_id': value of the last generated identifier;
// - prefix +'_ids': set containing identifier of all models;
// - prefix +'_'+ index +':' + value: set of identifiers which have
//   value for the given index.
// - prefix +':'+ id: hash containing the properties of a model;
// ///////////////////////////////////////////////////////////////////

// TODO: then-redis sends commands in order, we should use this
// semantic to simplify the code.

// TODO: Merge the options in the object to obtain extend-time
// configuration like Backbone.

// TODO: Remote events.

export default class Redis extends Collection {
  constructor ({
    connection,
    indexes = [],
    prefix,
    uri = 'tcp://localhost:6379'
  }) {
    super()

    this.indexes = indexes
    this.prefix = prefix
    this.redis = connection || createRedisClient(uri)
  }

  _extract (ids) {
    const prefix = this.prefix + ':'
    const {redis} = this

    const models = []
    return Promise.all(mapToArray(ids, id => {
      return redis.hgetallAsync(prefix + id).then(model => {
        // If empty, consider it a no match.
        if (isEmpty(model)) {
          return
        }

        // Mix the identifier in.
        model.id = id

        models.push(model)
      })
    })).then(() => models)
  }

  _add (models, {replace = false} = {}) {
    // TODO: remove “replace” which is a temporary measure, implement
    // “set()” instead.

    const {indexes, prefix, redis, idPrefix = ''} = this

    return Promise.all(mapToArray(models, async model => {
      // Generate a new identifier if necessary.
      if (model.id === undefined) {
        model.id = idPrefix + String(await redis.incrAsync(prefix + '_id'))
      }

      const success = await redis.saddAsync(prefix + '_ids', model.id)

      // The entry already exists an we are not in replace mode.
      if (!success && !replace) {
        throw new ModelAlreadyExists(model.id)
      }

      // TODO: Remove existing fields.

      const params = []
      forEach(model, (value, name) => {
        // No need to store the identifier (already in the key).
        if (name === 'id') {
          return
        }

        params.push(name, value)
      })

      const key = `${prefix}:${model.id}`
      const promises = [
        redis.delAsync(key),
        redis.hmsetAsync(key, ...params)
      ]

      // Update indexes.
      forEach(indexes, (index) => {
        const value = model[index]
        if (value === undefined) {
          return
        }

        const key = prefix + '_' + index + ':' + value
        promises.push(redis.saddAsync(key, model.id))
      })

      await Promise.all(promises)

      return model
    }))
  }

  _get (properties) {
    const {prefix, redis} = this

    if (isEmpty(properties)) {
      return redis.smembersAsync(prefix + '_ids').then(ids => this._extract(ids))
    }

    // Special treatment for the identifier.
    const id = properties.id
    if (id !== undefined) {
      delete properties.id
      return this._extract([id]).then(models => {
        return (models.length && !isEmpty(properties))
          ? filter(models)
          : models
      })
    }

    const {indexes} = this

    // Check for non indexed fields.
    const unfit = difference(getKey(properties), indexes)
    if (unfit.length) {
      throw new Error('fields not indexed: ' + unfit.join())
    }

    const keys = mapToArray(properties, (value, index) => `${prefix}_${index}:${value}`)
    return redis.sinterAsync(...keys).then(ids => this._extract(ids))
  }

  _remove (ids) {
    const {prefix, redis} = this

    // TODO: handle indexes.

    return Promise.all([
      // Remove the identifiers from the main index.
      redis.sremAsync(prefix + '_ids', ...ids),

      // Remove the models.
      redis.delAsync(mapToArray(ids, id => `${prefix}:${id}`))
    ])
  }

  _update (models) {
    return this._add(models, { replace: true })
  }
}
<|endoftext|>


<commit_before>exports.run = function (client, msg, args, db) {

	if (!permissions.isAdmin(msg.member, msg.channel.guild.id, db)) return msg.channel.createMessage({ embed: {
		color: 0x1E90FF,
		title: "Insufficient Permissions",
	}});

	if (!args[0]) return msg.channel.createMessage({ embed: {
		color: 0x1E90FF,
		title: "Specify a user"
	}});

	let usr = isNaN(args.join(" ")) ? msg.channel.guild.members.filter(u => u.username.toLowerCase().includes(args.join(" ").toLowerCase())) : msg.channel.guild.members.get(args.join(" "));
	if (typeof usr === Array && usr[0]) usr = usr[0];
	if (usr.length === 0) return msg.channel.createMessage({ embed: {
		color: 0x1E90FF,
		title: "No users found matching the specified name"
	}});
	let admins = db.admins.filter;
	rethonk.db("data").table("guilds").update({ id: msg.channel.guild.id, admins: db.admins.filter(id => id !== usr[0].id) }).run()
	.then(() => {
		msg.channel.createMessage({	embed: {
			color: 0x1E90FF,
			title: `Removed ${usr[0].username}#${usr[0].discriminator} from admins.`
		}});
	})
	.catch(err => {
		msg.channel.createMessage({	embed: {
			color: 0x1E90FF,
			title: "Failed to update admins",
			description: err.message
		}});
	});

}

exports.usage = {
	main: "{prefix}{command}",
	args: "<@mention>"
};
<commit_msg>cleanup<commit_after>exports.run = function (client, msg, args, db) {

	if (!permissions.isAdmin(msg.member, msg.channel.guild.id, db)) return msg.channel.createMessage({ embed: {
		color: 0x1E90FF,
		title: "Insufficient Permissions",
	}});

	if (!args[0]) return msg.channel.createMessage({ embed: {
		color: 0x1E90FF,
		title: "Specify a user"
	}});

	let usr = isNaN(args.join(" ")) ? msg.channel.guild.members.filter(u => u.username.toLowerCase().includes(args.join(" ").toLowerCase())) : msg.channel.guild.members.get(args.join(" "));
	if (typeof usr === Array && usr[0]) usr = usr[0];
	if (usr.length === 0) return msg.channel.createMessage({ embed: {
		color: 0x1E90FF,
		title: "No users found matching the specified name"
	}});
	let admins = db.admins.filter;
	rethonk.db("data").table("guilds").update({ id: msg.channel.guild.id, admins: db.admins.filter(id => id !== usr.id) }).run()
	.then(() => {
		msg.channel.createMessage({	embed: {
			color: 0x1E90FF,
			title: `Removed ${usr[0].username}#${usr.discriminator} from admins.`
		}});
	})
	.catch(err => {
		msg.channel.createMessage({	embed: {
			color: 0x1E90FF,
			title: "Failed to update admins",
			description: err.message
		}});
	});

}

exports.usage = {
	main: "{prefix}{command}",
	args: "<@mention>"
};
<|endoftext|>


<commit_before>
'use strict';

var should = require('should'),
    spanner = require('./../');

describe('Spanner', function() {

    describe('#getDigits()', function() {

        it('should return `0` when the value = 0 and set digit = 0', function() {
            spanner.padDigits(0, 0).should.equal('0');
        });

        it('should return `0` when the value = 0 and set digit = 1', function() {
            spanner.padDigits(0, 1).should.equal('0');
        });

        it('should return `00` when the value = 0 and set digit = 2', function() {
            spanner.padDigits(0, 2).should.equal('00');
        });

        it('should return `000` when the value = 0 and set digit = 3', function() {
            spanner.padDigits(0, 3).should.equal('000');
        });

    });

});

<commit_msg>Add new tests for padDigits()<commit_after>
'use strict';

var should = require('should'),
    spanner = require('./../');

describe('Spanner', function() {

    describe('#padDigits()', function() {

        it('should return `0` when the value = 0 and set digit = 1', function() {
            spanner.padDigits(0, 1).should.equal('0');
        });

        it('should return `00` when the value = 0 and set digit = 2', function() {
            spanner.padDigits(0, 2).should.equal('00');
        });

        it('should return `000` when the value = 0 and set digit = 3', function() {
            spanner.padDigits(0, 3).should.equal('000');
        });

        it('should return `0000000000` when the value = 0 and set digit = 10', function() {
            spanner.padDigits(0, 10).should.equal('0000000000');
        });

        it('should return `1` when the value = 1 and set digit = 0', function() {
            spanner.padDigits(1, 0).should.equal('1');
        });

        it('should return `1` when the value = 1 and set digit = 1', function() {
            spanner.padDigits(1, 1).should.equal('1');
        });

        it('should return `01` when the value = 1 and set digit = 2', function() {
            spanner.padDigits(1, 2).should.equal('01');
        });

        it('should return `001` when the value = 1 and set digit = 3', function() {
            spanner.padDigits(1, 3).should.equal('001');
        });

        it('should return `0000000001` when the value = 1 and set digit = 10', function() {
            spanner.padDigits(1, 10).should.equal('0000000001');
        });

        it('should return `10` when the value = 10 and set digit = 0', function() {
            spanner.padDigits(10, 0).should.equal('10');
        });

        it('should return `10` when the value = 10 and set digit = 1', function() {
            spanner.padDigits(10, 1).should.equal('10');
        });

        it('should return `10` when the value = 10 and set digit = 2', function() {
            spanner.padDigits(10, 2).should.equal('10');
        });

        it('should return `010` when the value = 10 and set digit = 3', function() {
            spanner.padDigits(10, 3).should.equal('010');
        });

        it('should return `0000000010` when the value = 10 and set digit = 10', function() {
            spanner.padDigits(10, 10).should.equal('0000000010');
        });

    });

});

<|endoftext|>


<commit_before>/* global core */

core.controller('LoginController', function ($scope, $location, AuthService) {

  'use strict';

  if ($scope.loggedIn()) {
    $location.path('/#tickets');
  }

  $scope.login = function() {
    AuthService.login().then(function(user){
      $location.path('/tickets');
    });
  };

  $scope.logout = function() {
    AuthService.logout();
  };

});
<commit_msg>cleanup<commit_after>/* global core */

core.controller('LoginController', function ($scope, $location, AuthService) {

  'use strict';

  if ($scope.loggedIn()) {
    $location.path('/#tickets');
  }

  $scope.login = function() {
    AuthService.login().then(function(){
      $location.path('/tickets');
    });
  };

  $scope.logout = function() {
    AuthService.logout();
  };

});
<|endoftext|>


<commit_before>var should = require('should'),
  inquirer = require('inquirer'),
  gulp = require('gulp'),
  path = require('path'),
  mockGulpDest = require('mock-gulp-dest')(gulp);

var generator = require('../slushfile');

describe('slush-react-express', function () {
  this.timeout(10000);

  before(function () {
    process.chdir(__dirname);
  });

  describe('minimal generator', function () {
    beforeEach(function () {
      mockPrompt({ 'appname': 'Test Name', 'type': 'Minimal', 'createDir': false });
    });

    it('should put files in current working directory', function (done) {
      generator.generate(function () {
        mockGulpDest.cwd().should.equal(__dirname);
        mockGulpDest.basePath().should.equal(__dirname);
        done();
      });
    });

    it('should add package.json to project root', function (done) {
      generator.generate(function () {
        mockGulpDest.assertDestContains('package.json');
        done();
      });
    });

    it('should add .gitignore to project root', function (done) {
      generator.generate(function () {
        mockGulpDest.assertDestContains('.gitignore');
        done();
      });
    });

    it('should add the client files to the public folder', function (done) {
      generator.generate(function () {
        mockGulpDest.assertDestContains([
          'public/index.html',
          'public/stylesheets/index.css',
          'public/javascripts/main.jsx'
        ]);
        done();
      });
    });

    it('should add the node server file to the root folder', function (done) {
      generator.generate(function () {
        mockGulpDest.assertDestContains('server.js');
        done();
      });
    });
  });

  describe('full generator', function () {
    beforeEach(function () {
      mockPrompt({ 'appname': 'Test Name', 'type': 'Full', 'ts': 'JavaScript', 'sass': 'CSS', 'createDir': false });
    });

    it('should put files in current working directory', function (done) {
      generator.generate(function () {
        mockGulpDest.cwd().should.equal(__dirname);
        mockGulpDest.basePath().should.equal(__dirname);
        done();
      });
    });

    it('should add package.json to project root', function (done) {
      generator.generate(function () {
        mockGulpDest.assertDestContains('package.json');
        done();
      });
    });

    it('should add .gitignore to project root', function (done) {
      generator.generate(function () {
        mockGulpDest.assertDestContains('.gitignore');
        done();
      });
    });

    it('should add a gulpfile to project root', function (done) {
      gulp.start('default').once('stop', function () {
        mockGulpDest.assertDestContains('gulpfile.js');
        done();
      });
    });

    it('should add static files to src', function (done) {
      generator.generate(function () {
        mockGulpDest.assertDestContains([
          'src/favicon.ico',
          'src/index.html'
        ]);
        done();
      });
    });

    describe('css', function () {
      beforeEach(function () {
        mockPrompt({ 'appname': 'Test Name', 'type': 'Full', 'ts': 'JavaScript', 'sass': 'CSS', 'createDir': false });
      });

      it('should add css file to src by default', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('src/stylesheets/index.css');
          mockGulpDest.assertDestNotContains('src/stylesheets/index.scss');
          done();
        });
      });
    });

    describe('sass', function () {
      beforeEach(function () {
        mockPrompt({ 'appname': 'Test Name', 'type': 'Full', 'ts': 'JavaScript', 'sass': 'SASS', 'createDir': false });
      });

      it('should add sass file to src', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestNotContains('src/stylesheets/index.css');
          mockGulpDest.assertDestContains('src/stylesheets/index.scss');
          done();
        });
      });
    });

    describe('javascript', function () {
      beforeEach(function () {
        mockPrompt({ 'appname': 'Test Name', 'type': 'Full', 'ts': 'JavaScript', 'sass': 'CSS', 'createDir': false });
      });

      it('should add javascript files by default', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('routes/index.js');
          mockGulpDest.assertDestContains('src/react/main.jsx');
          mockGulpDest.assertDestContains('tests/test.js');
          mockGulpDest.assertDestContains('app.js');
          mockGulpDest.assertDestContains('server.js');

          // Should not contain Typescript files
          mockGulpDest.assertDestNotContains('routes/index.ts');
          mockGulpDest.assertDestNotContains('src/react/main.tsx');
          mockGulpDest.assertDestNotContains('tests/test.ts');
          mockGulpDest.assertDestNotContains('app.ts');
          mockGulpDest.assertDestNotContains('server.ts');
          mockGulpDest.assertDestNotContains('tsconfig.json');
          mockGulpDest.assertDestNotContains('tsd.json');
          done();
        });
      });
    });

    describe('typescript', function () {
      beforeEach(function () {
        mockPrompt({ 'appname': 'Test Name', 'type': 'Full', 'sass': 'CSS', 'ts': 'TypeScript', 'createDir': false });
      });

      it('should add typescript files', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestNotContains('routes/index.js');
          mockGulpDest.assertDestNotContains('src/react/main.jsx');
          mockGulpDest.assertDestNotContains('tests/test.js');
          mockGulpDest.assertDestNotContains('app.js');
          mockGulpDest.assertDestNotContains('server.js');

          // Should contain Typescript files
          mockGulpDest.assertDestContains('routes/index.ts');
          mockGulpDest.assertDestContains('src/react/main.tsx');
          mockGulpDest.assertDestContains('tests/test.ts');
          mockGulpDest.assertDestContains('app.ts');
          mockGulpDest.assertDestContains('server.ts');
          mockGulpDest.assertDestContains('tsconfig.json');
          mockGulpDest.assertDestContains('tsd.json');
          done();
        });
      });
    });
  });
});

function mockPrompt(answers) {
  inquirer.prompt = function (prompts, done) {

    [].concat(prompts).forEach(function (prompt) {
      if (!(prompt.name in answers)) {
        answers[prompt.name] = prompt.default;
      }
    });

    done(answers);
  };
} <commit_msg>Refactor tests to have fewer asserts within them<commit_after>var should = require('should'),
  inquirer = require('inquirer'),
  gulp = require('gulp'),
  path = require('path'),
  mockGulpDest = require('mock-gulp-dest')(gulp);

var generator = require('../slushfile');

describe('slush-react-express', function () {
  this.timeout(10000);

  before(function () {
    process.chdir(__dirname);
  });

  describe('Minimal generator', function () {
    beforeEach(function () {
      mockPrompt({ 'appname': 'Test Name', 'type': 'Minimal', 'createDir': false });
    });

    it('should put files in current working directory', function (done) {
      generator.generate(function () {
        mockGulpDest.cwd().should.equal(__dirname);
        mockGulpDest.basePath().should.equal(__dirname);
        done();
      });
    });

    it('should add package.json to project root', function (done) {
      generator.generate(function () {
        mockGulpDest.assertDestContains('package.json');
        done();
      });
    });

    it('should add .gitignore to project root', function (done) {
      generator.generate(function () {
        mockGulpDest.assertDestContains('.gitignore');
        done();
      });
    });

    describe('should add the client files to the public folder', function () {
      it('should add index.html', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('public/index.html');
          done();
        });
      });

      it('should add index.css', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('public/stylesheets/index.css');
          done();
        });
      });

      it('should add main.jsx', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('public/javascripts/main.jsx');
          done();
        });
      });
    });

    it('should add the node server file to the root folder', function (done) {
      generator.generate(function () {
        mockGulpDest.assertDestContains('server.js');
        done();
      });
    });
  });

  describe('Full generator', function () {
    beforeEach(function () {
      mockPrompt({ 'appname': 'Test Name', 'type': 'Full', 'ts': 'JavaScript', 'sass': 'CSS', 'createDir': false });
    });

    it('should put files in current working directory', function (done) {
      generator.generate(function () {
        mockGulpDest.cwd().should.equal(__dirname);
        mockGulpDest.basePath().should.equal(__dirname);
        done();
      });
    });

    it('should add package.json to project root', function (done) {
      generator.generate(function () {
        mockGulpDest.assertDestContains('package.json');
        done();
      });
    });

    it('should add .gitignore to project root', function (done) {
      generator.generate(function () {
        mockGulpDest.assertDestContains('.gitignore');
        done();
      });
    });

    it('should add a gulpfile to project root', function (done) {
      gulp.start('default').once('stop', function () {
        mockGulpDest.assertDestContains('gulpfile.js');
        done();
      });
    });

    describe('should add static files to src', function () {
      it('should add favicon.ico', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('src/favicon.ico');
          done();
        });
      });

      it('should add index.html', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('src/index.html');
          done();
        });
      });
    });

    describe('CSS', function () {
      beforeEach(function () {
        mockPrompt({ 'appname': 'Test Name', 'type': 'Full', 'ts': 'JavaScript', 'sass': 'CSS', 'createDir': false });
      });

      it('should add css file to src by default', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('src/stylesheets/index.css');
          mockGulpDest.assertDestNotContains('src/stylesheets/index.scss');
          done();
        });
      });
    });

    describe('Sass', function () {
      beforeEach(function () {
        mockPrompt({ 'appname': 'Test Name', 'type': 'Full', 'ts': 'JavaScript', 'sass': 'SASS', 'createDir': false });
      });

      it('should add sass file to src', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestNotContains('src/stylesheets/index.css');
          mockGulpDest.assertDestContains('src/stylesheets/index.scss');
          done();
        });
      });
    });

    describe('JavaScript', function () {
      beforeEach(function () {
        mockPrompt({ 'appname': 'Test Name', 'type': 'Full', 'ts': 'JavaScript', 'sass': 'CSS', 'createDir': false });
      });

      it('should add index.js', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('routes/index.js');
          // Should not contain Typescript files
          mockGulpDest.assertDestNotContains('routes/index.ts');
          done();
        });
      });

      it('should add main.jsx', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('src/react/main.jsx');
          // Should not contain Typescript files
          mockGulpDest.assertDestNotContains('src/react/main.tsx');
          done();
        });
      });

      it('should add test.js', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('tests/test.js');
          // Should not contain Typescript files
          mockGulpDest.assertDestNotContains('tests/test.ts');
          done();
        });
      });

      it('should add server.js', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('server.js');
          // Should not contain Typescript files
          mockGulpDest.assertDestNotContains('server.ts');
          done();
        });
      });

      it('should not contain tsconfig.json', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestNotContains('tsconfig.json');
          done();
        });
      });

      it('should not contain tsd.json', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestNotContains('tsd.json');
          done();
        });
      });
    });

    describe('TypeScript', function () {
      beforeEach(function () {
        mockPrompt({ 'appname': 'Test Name', 'type': 'Full', 'sass': 'CSS', 'ts': 'TypeScript', 'createDir': false });
      });

      it('should add index.ts', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('routes/index.ts');
          // Should not contain JavaScript files
          mockGulpDest.assertDestNotContains('routes/index.js');
          done();
        });
      });

      it('should add main.tsx', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('src/react/main.tsx');
          // Should not contain JavaScript files
          mockGulpDest.assertDestNotContains('src/react/main.jsx');
          done();
        });
      });

      it('should add test.ts', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('tests/test.ts');
          // Should not contain JavaScript files
          mockGulpDest.assertDestNotContains('tests/test.js');
          done();
        });
      });

      it('should add app.ts', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('app.ts');
          // Should not contain JavaScript files
          mockGulpDest.assertDestNotContains('app.js');
          done();
        });
      });

      it('should add server.ts', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('server.ts');
          // Should not contain JavaScript files
          mockGulpDest.assertDestNotContains('server.js');
          done();
        });
      });

      it('should add tsconfig.json', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('tsconfig.json');
          done();
        });
      });

      it('should add tsd.json', function (done) {
        generator.generate(function () {
          mockGulpDest.assertDestContains('tsd.json');
          done();
        });
      });
    });
  });
});

function mockPrompt(answers) {
  inquirer.prompt = function (prompts, done) {

    [].concat(prompts).forEach(function (prompt) {
      if (!(prompt.name in answers)) {
        answers[prompt.name] = prompt.default;
      }
    });

    done(answers);
  };
} <|endoftext|>


<commit_before>'use strict';

// Register `phoneDetail` component, along with its associated controller and template
angular.
  module('onlineTest').
  component('attempt', {
    templateUrl: 'online-test/attempt.template.html',
    controller: ['DiagnosticTest', '$scope', '$location',
      function AttemptController(DiagnosticTest, $scope, $location) {
        if (DiagnosticTest.attempt_ready() == false){
          $location.url("/online-test/")
        }
        console.log("This is AttemptController");
        console.log(DiagnosticTest.getAllData())
        var self = this;
        self.timer_height = 20;
        self.show_all_questions = false;
        self.question_status_data = DiagnosticTest.getAllData().question_status_data
        self.test_start_text = "Hi " + (DiagnosticTest.getData('user') ? DiagnosticTest.getData('user').first_name : "") + ", We have got a personalized test for you designed to improve your week areas based on your last attempt here :)"
        if (DiagnosticTest.getData('personalized')){
          var test_params = {
            standard_id: DiagnosticTest.getData('standard_id'),
            subject_id: DiagnosticTest.getData('standard_id'),
            personalization_type:1,
            diagnostic_test_id:1,
            number:DiagnosticTest.getData('user').number
          }
        } else {
          var test_params = {
            standard_id: DiagnosticTest.getData('standard_id'),
            subject_id: DiagnosticTest.getData('standard_id'),
            stream_id: DiagnosticTest.getData('stream_id'),
          }
        }

        DiagnosticTest.http.get_test( test_params , function(data){
            self.build_diagnostic_test_data(data)
          }
        )

        self.current_question_index = DiagnosticTest.getAllData().current_question_index;

        self.toggleAllQuestionView = function(){
          self.show_all_questions = !self.show_all_questions
        }

        this.show_data = function(){
          console.log(self.question_status_data)
        }

        self.change_question = function(question_index){
          if (question_index < self.fetched_questions.length){
            var previous_question = self.current_question_index.data
            DiagnosticTest.setQuestionStatus(previous_question, {
              class: self.question_status_data.data[previous_question].static_class
            })
            DiagnosticTest.setQuestionStatus(question_index, {class:"attempting"});
            DiagnosticTest.setData('current_question_index',{data:question_index})
          }
        }

        $scope.$watch('$ctrl.current_question_index.data',function(new_val,old_val){
          console.log("Question changed");
          var present_question = self.diagnostic_test_data.diagnostic_test.short_choice_questions[self.fetched_questions[old_val].short_choice_question_id]
          present_question.time_taken += self.get_time_spent();
          DiagnosticTest.setQuestionStatus(new_val, {class:"attempting"})
          self.reset_timer()
        })

        self.reset_timer = function(){
          self.current_question_start_time = Date.now();
        }

        self.reset_timer();

        self.get_time_spent = function(){
          return (Date.now() - self.current_question_start_time)/1000
        }

        self.get_displayed_question_index = function(){
          return self.current_question_index.data;
        }

        self.build_diagnostic_test_data = function(data){
          self.diagnostic_test_data = {
            user: DiagnosticTest.getData("user"),
            diagnostic_test: {
              id: data.diagnostic_test_id,
              short_choice_questions: {
              }
            }
          }
          self.fetched_questions = data.questions
          var temp_question_status_data = []
          $.each(self.fetched_questions, function(key, value) {
            temp_question_status_data.push({class:"untouched", static_class:"untouched"})
            self.diagnostic_test_data.diagnostic_test.short_choice_questions[value.short_choice_question_id] = {
              question_text: value.question_text,
              attempt_count:0,
              attempt:temp_question_status_data[key].attempt || 0,
              index: key,
              score: 0,
              time_taken:0,
              selected_answers: {}
            }
          });
          DiagnosticTest.setData("question_status_data", {data:temp_question_status_data})

          $("#start-test-btn").prop("disabled", false).on("click", function(){
            console.log("Starting the test now");
            self.reset_timer();
            $("#attempt-overlay").addClass("hidden");
          })
        }

        self.submit_test = function(){
          DiagnosticTest.http.submit_test(self.diagnostic_test_data, function(data){
            DiagnosticTest.setData('diagnostic_test_result', {data:{
              personalized_test_remaining: data.personalized_test_remaining,
              result: data.result,
              weak_entity: data.weak_entity,
              difficulty_breakup: data.difficulty_breakup,
              question_analysis: data.question_analysis,
            }})
            $location.url('/online-test/result')
          })
        }

        self.select_answer = function(question_id, answer_index){
          var answer_object = self.fetched_questions[self.get_displayed_question_index()].answers[answer_index];
          var present_question = self.diagnostic_test_data.diagnostic_test.short_choice_questions[question_id];
          present_question.attempt_count += 1
          present_question.attempt = answer_object.correct ? 3 : 2
          present_question.selected_answers[answer_object.short_choice_answer_id] = {
            text: answer_object.answer_text,
            index: present_question.attempt_count,
            time_taken: self.get_time_spent(),
          }

          if (answer_object.correct){
            var max_score = 1000
            var max_time_allotted = 90
            var time_elapsed = self.get_time_spent()
            if (time_elapsed <= (max_time_allotted / 3)) {
              present_question.score = max_score;
            }else if((time_elapsed > (max_time_allotted / 3))&&(time_elapsed < (max_time_allotted))){
              present_question.score = ((29 * max_time_allotted - 27 * time_elapsed) * (max_score)) / (20 * max_time_allotted);
            }else {
              present_question.score = max_score / 10;
            }
          }

          DiagnosticTest.setQuestionStatus(self.get_displayed_question_index(),{class:'attempted', static_class:'attempted'})
          present_question.answer_selected = answer_object.short_choice_answer_id;
          present_question.time_taken += self.get_time_spent();
          console.log(self.current_question_index)
          console.log(self.fetched_questions.length)
          if (self.current_question_index.data < self.fetched_questions.length - 1){
            DiagnosticTest.setData('current_question_index',{data:self.get_displayed_question_index() + 1})
          } else {
            self.show_all_questions = true;
          }
        }

      }
    ]
  });

angular.
  module('onlineTest').directive('mathJaxBind', function() {
  var refresh = function(element) {
      MathJax.Hub.Queue(["Typeset", MathJax.Hub, element]);
  };
  return {
    link: function(scope, element, attrs) {
      scope.$watch(attrs.mathJaxBind, function(newValue, oldValue) {
        element.html(newValue);
        refresh(element[0]);
      });
    }
  };
});

angular.
  module('onlineTest').directive('animatedTimer',['$interval', function($interval) {
  return {
    link: function(scope, element, attrs) {
      $interval(function(){
        if (scope.$ctrl.diagnostic_test_data){
          var time_spent = scope.$ctrl.get_time_spent() + scope.$ctrl.diagnostic_test_data.diagnostic_test.short_choice_questions[attrs['animatedTimer']].time_taken
          element.css('height', ((time_spent/90)*100).toString() + "%")
        }
      },1000, 0);
    }
  };
}]);
<commit_msg>limiting timer height<commit_after>'use strict';

// Register `phoneDetail` component, along with its associated controller and template
angular.
  module('onlineTest').
  component('attempt', {
    templateUrl: 'online-test/attempt.template.html',
    controller: ['DiagnosticTest', '$scope', '$location',
      function AttemptController(DiagnosticTest, $scope, $location) {
        if (DiagnosticTest.attempt_ready() == false){
          $location.url("/online-test/")
        }
        console.log("This is AttemptController");
        console.log(DiagnosticTest.getAllData())
        var self = this;
        self.timer_height = 20;
        self.show_all_questions = false;
        self.question_status_data = DiagnosticTest.getAllData().question_status_data
        self.test_start_text = "Hi " + (DiagnosticTest.getData('user') ? DiagnosticTest.getData('user').first_name : "") + ", We have got a personalized test for you designed to improve your week areas based on your last attempt here :)"
        if (DiagnosticTest.getData('personalized')){
          var test_params = {
            standard_id: DiagnosticTest.getData('standard_id'),
            subject_id: DiagnosticTest.getData('standard_id'),
            personalization_type:1,
            diagnostic_test_id:1,
            number:DiagnosticTest.getData('user').number
          }
        } else {
          var test_params = {
            standard_id: DiagnosticTest.getData('standard_id'),
            subject_id: DiagnosticTest.getData('standard_id'),
            stream_id: DiagnosticTest.getData('stream_id'),
          }
        }

        DiagnosticTest.http.get_test( test_params , function(data){
            self.build_diagnostic_test_data(data)
          }
        )

        self.current_question_index = DiagnosticTest.getAllData().current_question_index;

        self.toggleAllQuestionView = function(){
          self.show_all_questions = !self.show_all_questions
        }

        this.show_data = function(){
          console.log(self.question_status_data)
        }

        self.change_question = function(question_index){
          if (question_index < self.fetched_questions.length){
            var previous_question = self.current_question_index.data
            DiagnosticTest.setQuestionStatus(previous_question, {
              class: self.question_status_data.data[previous_question].static_class
            })
            DiagnosticTest.setQuestionStatus(question_index, {class:"attempting"});
            DiagnosticTest.setData('current_question_index',{data:question_index})
          }
        }

        $scope.$watch('$ctrl.current_question_index.data',function(new_val,old_val){
          console.log("Question changed");
          var present_question = self.diagnostic_test_data.diagnostic_test.short_choice_questions[self.fetched_questions[old_val].short_choice_question_id]
          present_question.time_taken += self.get_time_spent();
          DiagnosticTest.setQuestionStatus(new_val, {class:"attempting"})
          self.reset_timer()
        })

        self.reset_timer = function(){
          self.current_question_start_time = Date.now();
        }

        self.reset_timer();

        self.get_time_spent = function(){
          return (Date.now() - self.current_question_start_time)/1000
        }

        self.get_displayed_question_index = function(){
          return self.current_question_index.data;
        }

        self.build_diagnostic_test_data = function(data){
          self.diagnostic_test_data = {
            user: DiagnosticTest.getData("user"),
            diagnostic_test: {
              id: data.diagnostic_test_id,
              short_choice_questions: {
              }
            }
          }
          self.fetched_questions = data.questions
          var temp_question_status_data = []
          $.each(self.fetched_questions, function(key, value) {
            temp_question_status_data.push({class:"untouched", static_class:"untouched"})
            self.diagnostic_test_data.diagnostic_test.short_choice_questions[value.short_choice_question_id] = {
              question_text: value.question_text,
              attempt_count:0,
              attempt:temp_question_status_data[key].attempt || 0,
              index: key,
              score: 0,
              time_taken:0,
              selected_answers: {}
            }
          });
          DiagnosticTest.setData("question_status_data", {data:temp_question_status_data})

          $("#start-test-btn").prop("disabled", false).on("click", function(){
            console.log("Starting the test now");
            self.reset_timer();
            $("#attempt-overlay").addClass("hidden");
          })
        }

        self.submit_test = function(){
          DiagnosticTest.http.submit_test(self.diagnostic_test_data, function(data){
            DiagnosticTest.setData('diagnostic_test_result', {data:{
              personalized_test_remaining: data.personalized_test_remaining,
              result: data.result,
              weak_entity: data.weak_entity,
              difficulty_breakup: data.difficulty_breakup,
              question_analysis: data.question_analysis,
            }})
            $location.url('/online-test/result')
          })
        }

        self.select_answer = function(question_id, answer_index){
          var answer_object = self.fetched_questions[self.get_displayed_question_index()].answers[answer_index];
          var present_question = self.diagnostic_test_data.diagnostic_test.short_choice_questions[question_id];
          present_question.attempt_count += 1
          present_question.attempt = answer_object.correct ? 3 : 2
          present_question.selected_answers[answer_object.short_choice_answer_id] = {
            text: answer_object.answer_text,
            index: present_question.attempt_count,
            time_taken: self.get_time_spent(),
          }

          if (answer_object.correct){
            var max_score = 1000
            var max_time_allotted = 90
            var time_elapsed = self.get_time_spent()
            if (time_elapsed <= (max_time_allotted / 3)) {
              present_question.score = max_score;
            }else if((time_elapsed > (max_time_allotted / 3))&&(time_elapsed < (max_time_allotted))){
              present_question.score = ((29 * max_time_allotted - 27 * time_elapsed) * (max_score)) / (20 * max_time_allotted);
            }else {
              present_question.score = max_score / 10;
            }
          }

          DiagnosticTest.setQuestionStatus(self.get_displayed_question_index(),{class:'attempted', static_class:'attempted'})
          present_question.answer_selected = answer_object.short_choice_answer_id;
          present_question.time_taken += self.get_time_spent();
          console.log(self.current_question_index)
          console.log(self.fetched_questions.length)
          if (self.current_question_index.data < self.fetched_questions.length - 1){
            DiagnosticTest.setData('current_question_index',{data:self.get_displayed_question_index() + 1})
          } else {
            self.show_all_questions = true;
          }
        }

      }
    ]
  });

angular.
  module('onlineTest').directive('mathJaxBind', function() {
  var refresh = function(element) {
      MathJax.Hub.Queue(["Typeset", MathJax.Hub, element]);
  };
  return {
    link: function(scope, element, attrs) {
      scope.$watch(attrs.mathJaxBind, function(newValue, oldValue) {
        element.html(newValue);
        refresh(element[0]);
      });
    }
  };
});

angular.
  module('onlineTest').directive('animatedTimer',['$interval', function($interval) {
  return {
    link: function(scope, element, attrs) {
      $interval(function(){
        if (scope.$ctrl.diagnostic_test_data ){
          var time_spent = scope.$ctrl.get_time_spent() + scope.$ctrl.diagnostic_test_data.diagnostic_test.short_choice_questions[attrs['animatedTimer']].time_taken
          if (time_spent <= 90){
            element.css('height', ((time_spent/90)*100).toString() + "%")
          } else {
            element.css('height', "100%")
          }
        }
      },1000, 0);
    }
  };
}]);
<|endoftext|>


<commit_before>/**
 *
 */

var assert=require('assert');
assert.equal(true, true);

var ws=require('ws');

var testNumber=0;

function EchoTest(BridgeProxy, AutoConnectProxy, config, callback){

	var test=testNumber;
	testNumber++;
	console.log('Running Test: '+test);
	//a ws server that just echos back all messages...
	var echo=(new ws.Server({
		port: config.echo
	},function(){

		var basicauth='';
		basicauth='nickolanack:nick';

//		a bridge server. pairs clients with autoconnect proxy connections.
		var WSBridge=require('../bridgeproxy.js');
		var bridge=new WSBridge({
			port:config.bridge,
			basicauth:basicauth
		}, function(){

			var WSAuto=require('../autoconnectproxy.js');

			if(basicauth.length){
				basicauth=basicauth+'@';
			}
			var autoconnect=new WSAuto({source:'ws://'+basicauth+'localhost:'+config.bridge, destination:'ws://localhost:'+config.echo});

			var clients=0;

			if(typeof(config.beforeTest)=='function'){
				config.beforeTest({
					echo:echo,
					bridge:bridge,
					autoconnect:autoconnect
				})
			}

			var num=config.count;
			for(var i=0;i< num; i++){

				clients++;
				(function(i){
					var success=false;
					var client=(new ws('ws://localhost:'+config.bridge)).on('open', function(){
						setTimeout(function(){
							var tm=setTimeout(function(){
								callback(new Error('test '+test+' client#'+i+' expected response by now.'));
							}, 10000);
								client.on('message',function(message){

									if(message!=='hello world'){
										callback(new Error('test '+test+' client#'+i+' expected "hello world", recieved "'+message+'"'));
									}else{

									}

									success=true;
									clearTimeout(tm);
									this.close();
									clients--;
									if(clients==0){

										setTimeout(function(){
											echo.close();
											autoconnect.close();
											bridge.close();
											callback(null); //success
										},100);

									}
								});
								//console.log('test client #'+i+' sends: hello world');

								client.send('hello world');

						}, i*100);

					}).on('close', function(code, message){

						if(!success){
							callback(new Error('test '+test+' client#'+i+' closed before sending anything: '+code+' - '+message));
						}

					}).on('error',function(error){

						callback(new Error('test '+test+' client#'+i+' error: '+error));

					});
				})(i);

			}

		});

	})).on('connection', function(wsclient){

		wsclient.on('message',function(message){
			wsclient.send(message);
			//console.log('endpoint echos: '+message);
		})

	});

}

var series=require("async").series(
		[
		 function(callback){
			 //test direct load
			 EchoTest(require('../bridgeproxy.js'), require('../autoconnectproxy.js'), {echo:9001, bridge:9002, count:50}, function(err, message){

				 if(err){
					 assert.fail(err);
				 }

				 callback(null);

			 });
		 },
		 function(callback){
			 // test same ports - cleanup must complete
			 EchoTest(require('../bridgeproxy.js'), require('../autoconnectproxy.js'), {echo:9001, bridge:9002, count:5}, function(err, message){

				 if(err){
					 assert.fail(err);
				 }
				 callback(null);

			 });
		 },
		 function(callback){
			 //test using index, this should be the same as require('node-rproxy')
			 EchoTest(require('../index.js').AutoConnect, require('../index.js').Bridge, {echo:9003, bridge:9004, count:5}, function(err, message){

				 if(err){
					 assert.fail(err);
				 }
				 callback(null);

			 });

		 },function(callback){

			 //trigger errors. application stops running
			 EchoTest(require('../index.js').AutoConnect, require('../index.js').Bridge, {echo:9001, bridge:9002, count:5, beforeTest:function(sockets){

				 sockets.echo.close(); //kill the 'application server' but keep the proxies

			 }}, function(err, message){

				 if(!err){
					 assert.fail('Expected an error here');
				 }
				 callback(null);

			 });

		 }
		 ],
		 function(err, results) {
			if(err){
				assert.fail('tests failed');
			}
			console.log(results);
		});

<commit_msg>reassing async callback function so multiple calls wont matter. only the first one<commit_after>/**
 *
 */

var assert=require('assert');
assert.equal(true, true);

var ws=require('ws');

var testNumber=0;

function EchoTest(BridgeProxy, AutoConnectProxy, config, callbackFn){

	var callback=function(err, msg){
		callbackFn(err, msg);
		callback=function(){}; //avoid multiple executions, but don't worry about it below.
	}

	var test=testNumber;
	testNumber++;
	console.log('Running Test: '+test);
	//a ws server that just echos back all messages...
	var echo=(new ws.Server({
		port: config.echo
	},function(){

		var basicauth='';
		basicauth='nickolanack:nick';

//		a bridge server. pairs clients with autoconnect proxy connections.
		var WSBridge=require('../bridgeproxy.js');
		var bridge=new WSBridge({
			port:config.bridge,
			basicauth:basicauth
		}, function(){

			var WSAuto=require('../autoconnectproxy.js');

			if(basicauth.length){
				basicauth=basicauth+'@';
			}
			var autoconnect=new WSAuto({source:'ws://'+basicauth+'localhost:'+config.bridge, destination:'ws://localhost:'+config.echo});

			var clients=0;

			if(typeof(config.beforeTest)=='function'){
				config.beforeTest({
					echo:echo,
					bridge:bridge,
					autoconnect:autoconnect
				})
			}

			var num=config.count;
			for(var i=0;i< num; i++){

				clients++;
				(function(i){
					var success=false;
					var client=(new ws('ws://localhost:'+config.bridge)).on('open', function(){
						setTimeout(function(){
							var tm=setTimeout(function(){
								callback(new Error('test '+test+' client#'+i+' expected response by now.'));
							}, 10000);
								client.on('message',function(message){

									if(message!=='hello world'){
										callback(new Error('test '+test+' client#'+i+' expected "hello world", recieved "'+message+'"'));
									}else{

										//was logging a success message here.

									}

									success=true;
									clearTimeout(tm);
									this.close();
									clients--;
									if(clients==0){

										setTimeout(function(){
											echo.close();
											autoconnect.close();
											bridge.close();
											callback(null); //success
										},100);

									}
								});
								//console.log('test client #'+i+' sends: hello world');

								client.send('hello world');

						}, i*100);

					}).on('close', function(code, message){

						if(!success){
							callback(new Error('test '+test+' client#'+i+' closed before sending anything: '+code+' - '+message));

						}

					}).on('error',function(error){

						callback(new Error('test '+test+' client#'+i+' error: '+error));

					});
				})(i);

			}

		});

	})).on('connection', function(wsclient){

		wsclient.on('message',function(message){
			wsclient.send(message);
			//console.log('endpoint echos: '+message);
		})

	});

}

var series=require("async").series(
		[
		 function(callback){
			 //test direct load
			 EchoTest(require('../bridgeproxy.js'), require('../autoconnectproxy.js'), {echo:9001, bridge:9002, count:50}, function(err, message){

				 if(err){
					 assert.fail(err);
				 }

				 callback(null);

			 });
		 },
		 function(callback){
			 // test same ports - cleanup must complete
			 EchoTest(require('../bridgeproxy.js'), require('../autoconnectproxy.js'), {echo:9001, bridge:9002, count:5}, function(err, message){

				 if(err){
					 assert.fail(err);
				 }
				 callback(null);

			 });
		 },
		 function(callback){
			 //test using index, this should be the same as require('node-rproxy')
			 EchoTest(require('../index.js').AutoConnect, require('../index.js').Bridge, {echo:9003, bridge:9004, count:5}, function(err, message){

				 if(err){
					 assert.fail(err);
				 }
				 callback(null);

			 });

		 },function(callback){

			 //trigger errors. application stops running
			 EchoTest(require('../index.js').AutoConnect, require('../index.js').Bridge, {echo:9001, bridge:9002, count:5, beforeTest:function(sockets){

				 sockets.echo.close(); //kill the 'application server' but keep the proxies

			 }}, function(err, message){

				 if(!err){
					 assert.fail('Expected an error here');
				 }
				 callback(null);

			 });

		 }
		 ],
		 function(err, results) {
			if(err){
				assert.fail('tests failed');
			}
			console.log(results);
		});

<|endoftext|>


<commit_before>var ast = require('../sample-asts/sample')
var compile = require('../index')

console.dir(ast)
console.log(compile(ast))<commit_msg>Removed test which is really only personal testing code, not a proper automated test<commit_after><|endoftext|>


<commit_before>
// Set `global` to `this` in non-node environment
if (typeof global === 'undefined') {
  global = this
}

// Hack `console` for testing
(function() {
  var console = global.console || ( global.console = {})
  var stack = global.consoleMsgStack = []

  console._log = console.log || noop
  console._warn = console.warn || noop

  console.log = function(msg) {
    stack.push(msg)
    console._log(msg)
  }

  console.warn = function(msg) {
    stack.push(msg)
    console._warn(msg)
  }

  function noop() {}

})()

// Add `printResult` and `printHeader` for browser environment
if (typeof document !== 'undefined') {

  global.printResult = function(txt, style) {
    var d = document.createElement('div')
    d.innerHTML = txt
    d.className = style
    document.getElementById('out').appendChild(d)
  }

  global.printHeader = function(test, url) {
    var h = document.createElement('h3')
    h.innerHTML = test +
        (url ? ' #' : '')
    document.getElementById('out').appendChild(h)
  }

}

// Define test module
(function(factory) {

  if (typeof require === 'function') {
    factory(require, exports)
  }
  else if (typeof define === 'function') {
    define(factory)
  }
  else {
    factory({}, (global.test = {}))
  }

})(function(require, exports) {
  var queue = []
  var time
  var WARNING_TIME = isLocal() ? 50 : 5000

  require.async && require.async('./style.css')
  handleGlobalError()

  exports.print = function(txt, style) {
    sendMessage('printResult', txt, style || 'info')
  }

  exports.assert = function (guard, message) {
    if (typeof message === 'undefined') {
      message = ''
    }

    if (guard) {
      exports.print('[PASS] ' + message, 'pass')
    }
    else {
      exports.print('[FAIL] ' + message, 'fail')
    }
  }

  exports.next = function() {
    if (queue.length) {
      printElapsedTime()
      reset()

      var id = queue.shift()
      sendMessage('printHeader', id, getSingleSpecUri(id))
      time = now()
      seajs.use(id2File(id))
    }
    else {
      printElapsedTime()
      exports.done()
    }
  }

  exports.run = function(ids) {
    var id = parseIdFromUri()
    queue = id ? [id] : ids
    exports.next()
  }

  exports.done = function() {
    sendMessage('testNextPage')
  }

  // Helpers

  var configData = global.seajs && seajs.config.data || {}
  var defaultConfig = copy(configData, {})
  var eventsCache = global.seajs && seajs.events

  function reset() {
    global.consoleMsgStack.length = 0
    seajs.off()

    // Restore initial events
    for (var eventType in eventsCache) {
      if (eventsCache.hasOwnProperty(eventType)) {
        for (var fn in eventsCache[eventType]) {
          seajs.on(eventType, fn)
        }
      }
    }

    // Restore default configurations
    copy(defaultConfig, configData)

    // Set base to current working directory
    seajs.config({
      base: './'
    })
  }

  function copy(from, to) {
    for (var p in to) {
      if (to.hasOwnProperty(p)) {
        delete to[p]
      }
    }

    for (p in from) {
      if (from.hasOwnProperty(p)) {
        to[p] = from[p]
      }
    }

    return to
  }

  function sendMessage(fn, msg, type) {
    var p = this
    if (this != this.parent) {
      p = this.parent
    }

    if (p && p[fn]) {
      p[fn](msg, type)
    }
    else if (msg && typeof console !== 'undefined') {
      console.log(color(msg, type))
    }
  }

  // https://github.com/loopj/commonjs-ansi-color/blob/master/lib/ansi-color.js
  var ANSI_CODES = {
    'fail': 31, // red
    'error': 31, // red
    'pass': 32, // green
    'info': 37 // white
  }

  function color(str, type) {
    return '\033[' + ANSI_CODES[type || 'info'] + 'm  ' + str + '\033[0m'
  }

  function handleGlobalError() {
    if (typeof window === 'undefined') return

    window.onerror = function(err) {
      // Old Safari and Firefox will throw an error when script is 404
      if (err !== 'Error loading script') {
        exports.print('[ERROR] ' + err, 'error')
      }

      // Go on
      exports.next()
    }
  }

  function getSingleSpecUri(id) {
    // For Node.js
    if (typeof location === 'undefined') {
      return ''
    }

    return location.href.replace(/\?.*$/, '') + '?' + encodeURIComponent(id)
  }

  function parseIdFromUri() {
    // For Node.js
    if (typeof location === 'undefined') {
      return ''
    }

    return decodeURIComponent(location.search)
        .replace(/&?t=\d+/, '').substring(1)
  }

  function id2File(id) {
    return id.indexOf('.js') > 0 ? id : id + '/main.js'
  }

  function printElapsedTime() {
    if (time) {
      var diff = now() - time
      var style = diff > WARNING_TIME ? 'warn' : 'info'
      exports.print('Elapsed time: ' + diff + 'ms', style + ' time')
    }
  }

  function now() {
    return new Date().getTime()
  }

  function isLocal() {
    // For Node.js
    if (typeof location === 'undefined') {
      return true
    }

    var host = location.host
    return location.href.indexOf('file://') === 0 ||
        host === 'localhost' || host === '127.0.0.1'
  }

})

<commit_msg>Fix a bug for reset function<commit_after>
// Set `global` to `this` in non-node environment
if (typeof global === 'undefined') {
  global = this
}

// Hack `console` for testing
(function() {
  var console = global.console || ( global.console = {})
  var stack = global.consoleMsgStack = []

  console._log = console.log || noop
  console._warn = console.warn || noop

  console.log = function(msg) {
    stack.push(msg)
    console._log(msg)
  }

  console.warn = function(msg) {
    stack.push(msg)
    console._warn(msg)
  }

  function noop() {}

})()

// Add `printResult` and `printHeader` for browser environment
if (typeof document !== 'undefined') {

  global.printResult = function(txt, style) {
    var d = document.createElement('div')
    d.innerHTML = txt
    d.className = style
    document.getElementById('out').appendChild(d)
  }

  global.printHeader = function(test, url) {
    var h = document.createElement('h3')
    h.innerHTML = test +
        (url ? ' #' : '')
    document.getElementById('out').appendChild(h)
  }

}

// Define test module
(function(factory) {

  if (typeof require === 'function') {
    factory(require, exports)
  }
  else if (typeof define === 'function') {
    define(factory)
  }
  else {
    factory({}, (global.test = {}))
  }

})(function(require, exports) {
  var queue = []
  var time
  var WARNING_TIME = isLocal() ? 50 : 5000

  require.async && require.async('./style.css')
  handleGlobalError()

  exports.print = function(txt, style) {
    sendMessage('printResult', txt, style || 'info')
  }

  exports.assert = function (guard, message) {
    if (typeof message === 'undefined') {
      message = ''
    }

    if (guard) {
      exports.print('[PASS] ' + message, 'pass')
    }
    else {
      exports.print('[FAIL] ' + message, 'fail')
    }
  }

  exports.next = function() {
    if (queue.length) {
      printElapsedTime()
      reset()

      var id = queue.shift()
      sendMessage('printHeader', id, getSingleSpecUri(id))
      time = now()
      seajs.use(id2File(id))
    }
    else {
      printElapsedTime()
      exports.done()
    }
  }

  exports.run = function(ids) {
    var id = parseIdFromUri()
    queue = id ? [id] : ids
    exports.next()
  }

  exports.done = function() {
    sendMessage('testNextPage')
  }

  // Helpers

  var configData = global.seajs && seajs.config.data || {}
  var defaultConfig = copy(configData, {})
  var eventsCache = global.seajs && seajs.events

  function reset() {
    global.consoleMsgStack.length = 0
    seajs.off()

    // Restore initial events
    for (var eventType in eventsCache) {
      if (eventsCache.hasOwnProperty(eventType)) {
        eventsCache[eventType].forEach(function(fn) {
          seajs.on(eventType, fn)
        })
      }
    }

    // Restore default configurations
    copy(defaultConfig, configData)

    // Set base to current working directory
    seajs.config({
      base: './'
    })
  }

  function copy(from, to) {
    for (var p in to) {
      if (to.hasOwnProperty(p)) {
        delete to[p]
      }
    }

    for (p in from) {
      if (from.hasOwnProperty(p)) {
        to[p] = from[p]
      }
    }

    return to
  }

  function sendMessage(fn, msg, type) {
    var p = this
    if (this != this.parent) {
      p = this.parent
    }

    if (p && p[fn]) {
      p[fn](msg, type)
    }
    else if (msg && typeof console !== 'undefined') {
      console.log(color(msg, type))
    }
  }

  // https://github.com/loopj/commonjs-ansi-color/blob/master/lib/ansi-color.js
  var ANSI_CODES = {
    'fail': 31, // red
    'error': 31, // red
    'pass': 32, // green
    'info': 37 // white
  }

  function color(str, type) {
    return '\033[' + ANSI_CODES[type || 'info'] + 'm  ' + str + '\033[0m'
  }

  function handleGlobalError() {
    if (typeof window === 'undefined') return

    window.onerror = function(err) {
      // Old Safari and Firefox will throw an error when script is 404
      if (err !== 'Error loading script') {
        exports.print('[ERROR] ' + err, 'error')
      }

      // Go on
      exports.next()
    }
  }

  function getSingleSpecUri(id) {
    // For Node.js
    if (typeof location === 'undefined') {
      return ''
    }

    return location.href.replace(/\?.*$/, '') + '?' + encodeURIComponent(id)
  }

  function parseIdFromUri() {
    // For Node.js
    if (typeof location === 'undefined') {
      return ''
    }

    return decodeURIComponent(location.search)
        .replace(/&?t=\d+/, '').substring(1)
  }

  function id2File(id) {
    return id.indexOf('.js') > 0 ? id : id + '/main.js'
  }

  function printElapsedTime() {
    if (time) {
      var diff = now() - time
      var style = diff > WARNING_TIME ? 'warn' : 'info'
      exports.print('Elapsed time: ' + diff + 'ms', style + ' time')
    }
  }

  function now() {
    return new Date().getTime()
  }

  function isLocal() {
    // For Node.js
    if (typeof location === 'undefined') {
      return true
    }

    var host = location.host
    return location.href.indexOf('file://') === 0 ||
        host === 'localhost' || host === '127.0.0.1'
  }

})

<|endoftext|>


<commit_before>var should = require("should");

describe('Array', function(){
    describe('#indexOf()', function(){
        it('should return -1 when the value is not present', function(){
            should.equal(-1, [1,2,3].indexOf(5));
            should.equal(-1, [1,2,3].indexOf(0));
        })
    })
})<commit_msg>The first test suit.<commit_after>var should = require("should"),
    requirejs = require('requirejs');

requirejs.config({
    baseUrl: 'pulsr',
    nodeRequire: require
});

describe('Pulsr', function (){
    describe('fileHandler', function (){
        describe('js.js', function (){
            it('should return 200 statusCode for js/mainClient.js request within 10s', function (done){
                this.timeout(10000);

                requirejs(['conf', 'http'], function (conf, http) {
                    http.get('http://' + conf.app.domains.static + '/js/mainClient.js', function (response) {
                        response.should.have.status(200);
                        done();
                    });
                });
            });
        });
    });
});<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var users = require('../../app/controllers/users.server.controller'),
	articles = require('../../app/controllers/articles.server.controller');

module.exports = function(app) {
	// Artigo Routes
	app.route('/articles')
		.get(users.hasAuthorization(['admin','user']), articles.list)
		// .get(users.requiresLogin, articles.list) para verificar apenas se o usuário está logado
		.post(users.requiresLogin, articles.create);

//PAGINATION
  app.route('/articleList/:page')
    .get(articles.articlesList);

//************************

	app.route('/articles/:articleId')
		.get(articles.read)
		.put(users.requiresLogin, articles.hasAuthorization, articles.update)
		.delete(users.requiresLogin, articles.hasAuthorization, articles.delete);

	// Finish by binding the article middleware
	app.param('articleId', articles.articleByID);
};
<commit_msg>Introduzida paginação de Artigos, calculando o total de registros e setando a quantidade de paginas no ClientSide<commit_after>'use strict';

/**
 * Module dependencies.
 */
var users = require('../../app/controllers/users.server.controller'),
	articles = require('../../app/controllers/articles.server.controller');

module.exports = function(app) {
	// Artigo Routes
	app.route('/articles')
		.get(users.hasAuthorization(['admin','user']), articles.list)
		// .get(users.requiresLogin, articles.list) para verificar apenas se o usuário está logado
		.post(users.requiresLogin, articles.create);

//PAGINATION
  app.route('/articleList/:page/:query')
    .get(articles.articlesList);

//************************

	app.route('/articles/:articleId')
		.get(articles.read)
		.put(users.requiresLogin, articles.hasAuthorization, articles.update)
		.delete(users.requiresLogin, articles.hasAuthorization, articles.delete);

	app.route('/totalRegistros')
    .get(articles.totalRegistros);

	// Finish by binding the article middleware
	app.param('articleId', articles.articleByID);
};
<|endoftext|>


<commit_before>class IOCore {constructor (ioFunc) {this.then = cb => ioFunc((...args) => { cb(...args) });};reject (pred) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let result = pred(...args);if (result !== null) {if (Array.isArray(result)) {cb(...result);} else {cb(result);}};});};return this;};maybeFalse (mv, handler) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let result = mv(...args);if (result === false) {handler(...args);} else {cb(...args);}});};return this;};maybeNull (mv, handler) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let result = mv(...args);if (result === null) {handler(...args);} else {cb(...args);}});};return this;};maybeErr (mv, handler) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let result = mv(...args);if (result instanceof Error) {handler(...args);} else {cb(...args);}});};return this;};maybeTrue (mv, handler) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let result = mv(...args);if (result === true) {handler(...args);} else {cb(...args);}});};return this;};maybeUndefined (mv, handler) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let result = mv(...args);if (result === undefined) {handler(...args);} else {cb(...args);}});};return this;};map (transform) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let result = transform(...args);if (Array.isArray(result)) {cb(...result);} else {cb(result);}});};return this;};bind (ioFunc) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let io = ioFunc(...args);io.then((...ioargs) => cb(...args, ...ioargs));});};return this;};static timer (s) {var intervalId;var timer = new IOCore(cb => {intervalId = setInterval(cb, Math.floor(s * 1000))});timer.clear = () => clearInterval(intervalId);return timer;};static createIO (ioFunc) {return new IOCore(ioFunc);};};const readline = require('readline');const fs = require('fs');const rlConfig = {input: process.stdin,output: process.stdout}; class IO extends IOCore {static getLine (str) {const rl = readline.createInterface(rlConfig);return new IOCore(cb => rl.question(str, cb)).map(data => {rl.close();return data;});};static putLine (...data) {return new IOCore(cb => process.nextTick(cb, data)).map(data => {console.log(...data);return data});};static readFile (filename) {return new IOCore(cb => fs.readFile(filename, cb)).map((_, data) => data.toString());};static writeFile (filename, data) {return new IOCore(cb => fs.writeFile(filename, data, cb));};};

const request = require('request');
const fact = n => {
    switch (n) {
    case 1:
        return 1;
    default:
        return n * fact(n - 1);
    }
};
const computeFact = IO.getLine('enter value for factorial: ').map(num => [
    fact(parseInt(num)),
    num
]).bind((val, num) =>
    (IO.putLine(val))).map((val, num) => [String(val)]);
const getAscii = computeFact.map(data => [
    'http://artii.herokuapp.com/make?text=' + data,
    data
]).bind((link, data) => IO.createIO(cb => request(link, cb))).maybeErr((link, data, err, res, body) => err, (link, data, err, res, body) => IO.putLine(err).then(() => null)).bind((link, data, err, res, body) =>
    (IO.putLine(body))).map((link, data, err, res, body) => [body]);
const tempIO = getAscii;
const main = tempIO.then(() => null);
<commit_msg>Update generated `js` file<commit_after>class IOCore {constructor (ioFunc) {this.then = cb => ioFunc((...args) => { cb(...args) });};reject (pred) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let result = pred(...args);if (result !== null) {if (Array.isArray(result)) {cb(...result);} else {cb(result);}};});};return this;};maybeFalse (mv, handler) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let result = mv(...args);if (result === false) {handler(...args);} else {cb(...args);}});};return this;};maybeNull (mv, handler) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let result = mv(...args);if (result === null) {handler(...args);} else {cb(...args);}});};return this;};maybeErr (mv, handler) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let result = mv(...args);if (result instanceof Error) {handler(...args);} else {cb(...args);}});};return this;};maybeTrue (mv, handler) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let result = mv(...args);if (result === true) {handler(...args);} else {cb(...args);}});};return this;};maybeUndefined (mv, handler) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let result = mv(...args);if (result === undefined) {handler(...args);} else {cb(...args);}});};return this;};map (transform) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let result = transform(...args);if (Array.isArray(result)) {cb(...result);} else {cb(result);}});};return this;};bind (ioFunc) {let saveThen = this.then;this.then = cb => {saveThen((...args) => {let io = ioFunc(...args);io.then((...ioargs) => cb(...args, ...ioargs));});};return this;};static timer (s) {var intervalId;var timer = new IOCore(cb => {intervalId = setInterval(cb, Math.floor(s * 1000))});timer.clear = () => clearInterval(intervalId);return timer;};static createIO (ioFunc) {return new IOCore(ioFunc);};};const readline = require('readline');const fs = require('fs');const rlConfig = {input: process.stdin,output: process.stdout}; class IO extends IOCore {static getLine (str) {const rl = readline.createInterface(rlConfig);return new IOCore(cb => rl.question(str, cb)).map(data => {rl.close();return data;});};static putLine (...data) {return new IOCore(cb => process.nextTick(cb, data)).map(data => {console.log(...data);return data});};static readFile (filename) {return new IOCore(cb => fs.readFile(filename, cb)).map((_, data) => data.toString());};static writeFile (filename, data) {return new IOCore(cb => fs.writeFile(filename, data, cb));};};

const request = require('request');
const fact = n => {
    switch (n) {
    case 1:
        return 1;
    default:
        return n * fact(n - 1);
    }
};
const computeFact = () =>
    (IO.getLine('enter value for factorial: ').map(num => [num]).map(num => [
        fact(parseInt(num)),
        num
    ]).bind((val, num) =>
        (IO.putLine(val))).map((val, num) => [String(val)]));
const getAscii = () =>
    (computeFact().map(data => [
        'http://artii.herokuapp.com/make?text=' + data,
        data
    ]).bind((link, data) => IO.createIO(cb => request(link, cb))).map((link, data, err, res, body) => [
        link,
        data,
        err,
        res,
        body
    ]).maybeErr((link, data, err, res, body) => err, (link, data, err, res, body) => IO.putLine(err).then(() => null)).bind((link, data, err, res, body) =>
        (IO.putLine(body))).map((link, data, err, res, body) => [body]));
const tempIO = getAscii;
const main = tempIO().then(() => null);
<|endoftext|>