<commit_before>/**
 * @module datasource-executor
 */
'use strict';

var _ = require('lodash');
var Promise = require('when').Promise;
var cast = require('./cast');
var Status = require('flora-cluster').Status;
var Profiler = require('./profiler');

/**
 * Actually execute a resolved request and call the DataSources.
 *
 * @param {Api}     api
 * @param {flora.Request} request
 * @param {Object}  dst         - DataSourceTree
 * @param {Function}callback
 */
module.exports = function execute(api, request, dst, callback) {
    if (!request._status) request._status = new Status();
    dst._profiler = dst._profiler || new Profiler();
    executeDst(api, request, dst)
        .then(function (results) {
            callback(null, results);
        }, callback);
};

/**
 * Execute all DataSources.
 *
 * Executes all subFilters, the main request and the subRequests, and may be
 * recursively called by the subRequests.
 *
 * @param {Api}    api
 * @param {flora.Request} request
 * @param {Object} dst DataSourceTree
 * @return {Promise}
 * @private
 */
function executeDst(api, request, dst) {
    var globalResults;

    return (new Promise(function (resolve) {
            resolve();
        }))

        // Execute subFilters
        .then(function executeSubFilters() {
            var subFilters = [];
            if (dst.subFilters) {
                subFilters = dst.subFilters.map(function (subFilter) {
                    subFilter._profiler = dst._profiler;
                    return executeDst(api, request, subFilter);
                });
            }

            return Promise.all(subFilters);
        })

        // Adjust the main request's filter to include the results from the subFilters
        .then(function handleSubFilterResults(subFilterResults) {
            if (!dst.request.filter) return true;

            // Build filter array for the main request
            var parentValues = {};
            subFilterResults.forEach(function (subFilterResult) {
                subFilterResult = subFilterResult[0];
                var parentKey = subFilterResult.parentKey.join('-');
                parentValues[parentKey] = parentValues[parentKey] || [];
                parentValues[parentKey].push(subFilterResult.data.map(function (ff) {
                    return subFilterResult.childKey.map(function (childKeyPart) {
                        return ff[childKeyPart];
                    });
                }));
            });

            // Prevent duplicates for all parentValues properties
            for (var parentKeyIdx in parentValues) {
                for (var i = 0; i < parentValues[parentKeyIdx].length; i++) {
                    parentValues[parentKeyIdx][i] = _.uniq(parentValues[parentKeyIdx][i], false, String);
                }
            }

            // Replace "valueFromSubFilter" properties for the main resource
            // by the values from the parentValues object
            var requestFilter = [];
            dst.request.filter.forEach(function (filter) {
                var filterNew = [];
                filter.forEach(function (filterPart) {
                    if (dst._isEmpty) return;

                    if (!filterPart.valueFromSubFilter) {
                        filterNew.push(filterPart);
                        return;
                    }

                    var attributeIdx = Array.isArray(filterPart.attribute)
                        ? filterPart.attribute.join('-')
                        : filterPart.attribute;

                    if (!parentValues[attributeIdx]) {
                        throw new Error('Missing subFilter for attribute "' + filterPart.attribute + '"');
                    }

                    parentValues[attributeIdx].forEach(function (pv) {
                        if (dst._isEmpty) return;
                        if (pv.length === 0) {
                            // One of the subFilters return an empty result,
                            // so the main results will also be empty, no need to execute
                            dst._isEmpty = true;
                            filterNew.push(filterPart);
                            return;
                        }

                        var filterPartNew = _.clone(filterPart);

                        if (!Array.isArray(filterPart.attribute)) {
                            // We silently assume that childKey/parentKey have length 1
                            filterPartNew.value = pv.map(function (parentValue) {
                                return parentValue[0];
                            });
                        } else {
                            filterPartNew.value = [];
                            for (var j = 0; j < filterPart.attribute.length; j++) {
                                filterPartNew.value[j] = pv[j];
                            }
                        }

                        filterNew.push(filterPartNew);
                    });
                });
                requestFilter.push(filterNew);
            });

            dst.request.filter = requestFilter;
        })

        // Cast filter values to their storedType
        .then(function castFilterValues() {
            if (dst._isEmpty) return;
            if (!dst.request.filter) return;
            if (!dst.attributeOptions) return;

            dst.request.filter.forEach(function (filter) {
                if (!filter) return;

                filter.forEach(function (filterPart) {
                    var storedType;

                    if (Array.isArray(filterPart.attribute)) {
                        for (var j = 0; j < filterPart.attribute.length; j++) {
                            storedType = (dst.attributeOptions[filterPart.attribute[j]]) ?
                                dst.attributeOptions[filterPart.attribute[j]].storedType : null;
                            if (!storedType) continue;
                            if (Array.isArray(filterPart.value[j])) {
                                filterPart.value[j] = filterPart.value[j].map(function (valuePart) {
                                    return cast(valuePart, {type: storedType});
                                });
                            } else {
                                filterPart.value[j] = cast(filterPart.value[j], {type: storedType});
                            }
                        }
                    } else {
                        storedType = (dst.attributeOptions[filterPart.attribute]) ?
                            dst.attributeOptions[filterPart.attribute].storedType : null;
                        if (!storedType) return;
                        if (Array.isArray(filterPart.value)) {
                            filterPart.value = filterPart.value.map(function (valuePart) {
                                return cast(valuePart, {type: storedType});
                            });
                        } else {
                            filterPart.value = cast(filterPart.value, {type: storedType});
                        }
                    }
                });
            });
        })

        // extension: "preExecute" (resource)
        .then(function invokePreExecute() {
            var resource = api.getResource(dst.resourceName);
            if (resource && resource.extensions && resource.extensions.preExecute) {
                api.log.trace('handle: "preExecute" extension (%s)', dst.resourceName);
                resource.extensions.preExecute({
                    request: request,
                    dataSourceTree: dst
                });
            }
        })

        // Execute the main request
        .then(function executeMainRequest() {
            var result = {
                data: [],
                totalCount: 0
            };
            ['attributePath', 'dataSourceName', 'childKey', 'parentKey',
                'multiValuedParentKey', 'uniqueChildKey'].forEach(function (key) {
                if (dst.hasOwnProperty(key)) result[key] = dst[key];
            });

            return new Promise(function (resolve, reject) {
                if (dst._isEmpty) return resolve(result);

                var ds = api.dataSources[dst.request.type];
                if (!ds) return reject(new Error('Unknown DataSource type "' + dst.request.type + '"'));

                dst.request._status = request._status.addChild('dataSourceRequests');
                dst.request._status.set('name', dst.attributePath ?
                    dst.attributePath.join('.') + ':' + dst.dataSourceName : '');
                dst.request._status.set('type', dst.request.type);

                dst.request._profiler = dst._profiler.child(dst.attributePath ?
                    dst.attributePath.join('.') + ':' + dst.dataSourceName : 'dataSourceRequest');

                ds.process(dst.request, function (err, rows) {
                    dst.request._profiler.end();
                    dst.request._status.close();
                    if (err) return reject(err);

                    result.data = rows.data;
                    result.totalCount = rows.totalCount;
                    resolve(result);
                });
            });
        })

        // Transform the main results, do type casting
        .then(function transformMainResults(mainResults) {
            if (!dst.attributeOptions) return mainResults;
            if (typeof dst.attributeOptions !== 'object') return mainResults;

            for (var idx in mainResults.data) {
                if (typeof mainResults.data[idx] !== 'object') continue;
                for (var key in mainResults.data[idx]) {
                    if (!dst.attributeOptions[key] || !dst.attributeOptions[key].type) continue;
                    mainResults.data[idx][key] = cast(mainResults.data[idx][key], dst.attributeOptions[key]);
                }
            }

            return mainResults;
        })

        // extension: "postExecute" (resource)
        .then(function invokePostExecute(mainResults) {
            var resource = api.getResource(dst.resourceName);
            if (resource && resource.extensions && resource.extensions.postExecute) {
                api.log.trace('handle: "postExecute" extension (%s)', dst.resourceName);
                resource.extensions.postExecute({
                    request: request,
                    rawResults: mainResults
                });
            }

            return mainResults;
        })

        // Add the main results to our global results array
        .then(function handleMainResults(mainResults) {
            globalResults = [mainResults];
            return mainResults;
        })

        // Execute the subRequests
        .then(function executeSubRequests(mainResults) {
            if (!dst.subRequests) return [];
            if (!mainResults || mainResults.data.length === 0) return [];

            // Prepare the subRequests that may be dependent from the main results.
            // "valueFromParentKey" properties are replaced by the appropriate values.
            var subRequests = dst.subRequests.map(function (subRequest) {
                var parentValues = [];

                mainResults.data.forEach(function (mainResult) {
                    var isNull = true;
                    var value = subRequest.parentKey.map(function (m) {
                        if (mainResult[m] !== null) isNull = false;
                        return mainResult[m];
                    });
                    if (!isNull) parentValues.push(value);
                });

                // Flatten multiValued keys (not supported for combined keys!)
                if (subRequest.parentKey.length === 1 &&
                    dst.attributeOptions &&
                    dst.attributeOptions[subRequest.parentKey[0]] &&
                    dst.attributeOptions[subRequest.parentKey[0]].multiValued) {
                    var newParentValues = [];
                    parentValues.forEach(function (parentValue) {
                        if (!Array.isArray(parentValue[0])) return;
                        newParentValues = newParentValues.concat(parentValue[0].map(function (value) {
                            return [value];
                        }));
                    });
                    parentValues = newParentValues;
                }

                parentValues = _.uniq(parentValues, false, String);

                subRequest.request.filter.forEach(function (filters) {
                    filters.forEach(function (filter) {
                        if (!filter.valueFromParentKey) return;
                        if (!Array.isArray(filter.attribute)) {
                            filter.value = parentValues.map(function (value) {
                                return value[0];
                            });
                        } else {
                            filter.value = parentValues;
                        }
                    });
                });

                subRequest._profiler = dst._profiler;
                return executeDst(api, request, subRequest);
            });

            return Promise.all(subRequests);
        })

        // Add the subRequest results to the global results array
        .then(function handleSubResults(subResults) {
            delete(dst._isEmpty); // clean up

            subResults.forEach(function (subResult) {
                globalResults = globalResults.concat(subResult);
            });
            return globalResults;
        });
}
<commit_msg>status: handle unavailable "_status" locally in datasource-executor<commit_after>/**
 * @module datasource-executor
 */
'use strict';

var _ = require('lodash');
var Promise = require('when').Promise;
var cast = require('./cast');
var Status = require('flora-cluster').Status;
var Profiler = require('./profiler');

/**
 * Actually execute a resolved request and call the DataSources.
 *
 * @param {Api}     api
 * @param {flora.Request} request
 * @param {Object}  dst         - DataSourceTree
 * @param {Function}callback
 */
module.exports = function execute(api, request, dst, callback) {
    dst._profiler = dst._profiler || new Profiler();
    executeDst(api, request, dst)
        .then(function (results) {
            callback(null, results);
        }, callback);
};

/**
 * Execute all DataSources.
 *
 * Executes all subFilters, the main request and the subRequests, and may be
 * recursively called by the subRequests.
 *
 * @param {Api}    api
 * @param {flora.Request} request
 * @param {Object} dst DataSourceTree
 * @return {Promise}
 * @private
 */
function executeDst(api, request, dst) {
    var globalResults;

    return (new Promise(function (resolve) {
            resolve();
        }))

        // Execute subFilters
        .then(function executeSubFilters() {
            var subFilters = [];
            if (dst.subFilters) {
                subFilters = dst.subFilters.map(function (subFilter) {
                    subFilter._profiler = dst._profiler;
                    return executeDst(api, request, subFilter);
                });
            }

            return Promise.all(subFilters);
        })

        // Adjust the main request's filter to include the results from the subFilters
        .then(function handleSubFilterResults(subFilterResults) {
            if (!dst.request.filter) return true;

            // Build filter array for the main request
            var parentValues = {};
            subFilterResults.forEach(function (subFilterResult) {
                subFilterResult = subFilterResult[0];
                var parentKey = subFilterResult.parentKey.join('-');
                parentValues[parentKey] = parentValues[parentKey] || [];
                parentValues[parentKey].push(subFilterResult.data.map(function (ff) {
                    return subFilterResult.childKey.map(function (childKeyPart) {
                        return ff[childKeyPart];
                    });
                }));
            });

            // Prevent duplicates for all parentValues properties
            for (var parentKeyIdx in parentValues) {
                for (var i = 0; i < parentValues[parentKeyIdx].length; i++) {
                    parentValues[parentKeyIdx][i] = _.uniq(parentValues[parentKeyIdx][i], false, String);
                }
            }

            // Replace "valueFromSubFilter" properties for the main resource
            // by the values from the parentValues object
            var requestFilter = [];
            dst.request.filter.forEach(function (filter) {
                var filterNew = [];
                filter.forEach(function (filterPart) {
                    if (dst._isEmpty) return;

                    if (!filterPart.valueFromSubFilter) {
                        filterNew.push(filterPart);
                        return;
                    }

                    var attributeIdx = Array.isArray(filterPart.attribute)
                        ? filterPart.attribute.join('-')
                        : filterPart.attribute;

                    if (!parentValues[attributeIdx]) {
                        throw new Error('Missing subFilter for attribute "' + filterPart.attribute + '"');
                    }

                    parentValues[attributeIdx].forEach(function (pv) {
                        if (dst._isEmpty) return;
                        if (pv.length === 0) {
                            // One of the subFilters return an empty result,
                            // so the main results will also be empty, no need to execute
                            dst._isEmpty = true;
                            filterNew.push(filterPart);
                            return;
                        }

                        var filterPartNew = _.clone(filterPart);

                        if (!Array.isArray(filterPart.attribute)) {
                            // We silently assume that childKey/parentKey have length 1
                            filterPartNew.value = pv.map(function (parentValue) {
                                return parentValue[0];
                            });
                        } else {
                            filterPartNew.value = [];
                            for (var j = 0; j < filterPart.attribute.length; j++) {
                                filterPartNew.value[j] = pv[j];
                            }
                        }

                        filterNew.push(filterPartNew);
                    });
                });
                requestFilter.push(filterNew);
            });

            dst.request.filter = requestFilter;
        })

        // Cast filter values to their storedType
        .then(function castFilterValues() {
            if (dst._isEmpty) return;
            if (!dst.request.filter) return;
            if (!dst.attributeOptions) return;

            dst.request.filter.forEach(function (filter) {
                if (!filter) return;

                filter.forEach(function (filterPart) {
                    var storedType;

                    if (Array.isArray(filterPart.attribute)) {
                        for (var j = 0; j < filterPart.attribute.length; j++) {
                            storedType = (dst.attributeOptions[filterPart.attribute[j]]) ?
                                dst.attributeOptions[filterPart.attribute[j]].storedType : null;
                            if (!storedType) continue;
                            if (Array.isArray(filterPart.value[j])) {
                                filterPart.value[j] = filterPart.value[j].map(function (valuePart) {
                                    return cast(valuePart, {type: storedType});
                                });
                            } else {
                                filterPart.value[j] = cast(filterPart.value[j], {type: storedType});
                            }
                        }
                    } else {
                        storedType = (dst.attributeOptions[filterPart.attribute]) ?
                            dst.attributeOptions[filterPart.attribute].storedType : null;
                        if (!storedType) return;
                        if (Array.isArray(filterPart.value)) {
                            filterPart.value = filterPart.value.map(function (valuePart) {
                                return cast(valuePart, {type: storedType});
                            });
                        } else {
                            filterPart.value = cast(filterPart.value, {type: storedType});
                        }
                    }
                });
            });
        })

        // extension: "preExecute" (resource)
        .then(function invokePreExecute() {
            var resource = api.getResource(dst.resourceName);
            if (resource && resource.extensions && resource.extensions.preExecute) {
                api.log.trace('handle: "preExecute" extension (%s)', dst.resourceName);
                resource.extensions.preExecute({
                    request: request,
                    dataSourceTree: dst
                });
            }
        })

        // Execute the main request
        .then(function executeMainRequest() {
            var result = {
                data: [],
                totalCount: 0
            };
            ['attributePath', 'dataSourceName', 'childKey', 'parentKey',
                'multiValuedParentKey', 'uniqueChildKey'].forEach(function (key) {
                if (dst.hasOwnProperty(key)) result[key] = dst[key];
            });

            return new Promise(function (resolve, reject) {
                if (dst._isEmpty) return resolve(result);

                var ds = api.dataSources[dst.request.type];
                if (!ds) return reject(new Error('Unknown DataSource type "' + dst.request.type + '"'));

                dst.request._status = request._status ? request._status.addChild('dataSourceRequests') : new Status();
                dst.request._status.set('name', dst.attributePath ?
                    dst.attributePath.join('.') + ':' + dst.dataSourceName : '');
                dst.request._status.set('type', dst.request.type);

                dst.request._profiler = dst._profiler.child(dst.attributePath ?
                    dst.attributePath.join('.') + ':' + dst.dataSourceName : 'dataSourceRequest');

                ds.process(dst.request, function (err, rows) {
                    dst.request._profiler.end();
                    dst.request._status.close();
                    if (err) return reject(err);

                    result.data = rows.data;
                    result.totalCount = rows.totalCount;
                    resolve(result);
                });
            });
        })

        // Transform the main results, do type casting
        .then(function transformMainResults(mainResults) {
            if (!dst.attributeOptions) return mainResults;
            if (typeof dst.attributeOptions !== 'object') return mainResults;

            for (var idx in mainResults.data) {
                if (typeof mainResults.data[idx] !== 'object') continue;
                for (var key in mainResults.data[idx]) {
                    if (!dst.attributeOptions[key] || !dst.attributeOptions[key].type) continue;
                    mainResults.data[idx][key] = cast(mainResults.data[idx][key], dst.attributeOptions[key]);
                }
            }

            return mainResults;
        })

        // extension: "postExecute" (resource)
        .then(function invokePostExecute(mainResults) {
            var resource = api.getResource(dst.resourceName);
            if (resource && resource.extensions && resource.extensions.postExecute) {
                api.log.trace('handle: "postExecute" extension (%s)', dst.resourceName);
                resource.extensions.postExecute({
                    request: request,
                    rawResults: mainResults
                });
            }

            return mainResults;
        })

        // Add the main results to our global results array
        .then(function handleMainResults(mainResults) {
            globalResults = [mainResults];
            return mainResults;
        })

        // Execute the subRequests
        .then(function executeSubRequests(mainResults) {
            if (!dst.subRequests) return [];
            if (!mainResults || mainResults.data.length === 0) return [];

            // Prepare the subRequests that may be dependent from the main results.
            // "valueFromParentKey" properties are replaced by the appropriate values.
            var subRequests = dst.subRequests.map(function (subRequest) {
                var parentValues = [];

                mainResults.data.forEach(function (mainResult) {
                    var isNull = true;
                    var value = subRequest.parentKey.map(function (m) {
                        if (mainResult[m] !== null) isNull = false;
                        return mainResult[m];
                    });
                    if (!isNull) parentValues.push(value);
                });

                // Flatten multiValued keys (not supported for combined keys!)
                if (subRequest.parentKey.length === 1 &&
                    dst.attributeOptions &&
                    dst.attributeOptions[subRequest.parentKey[0]] &&
                    dst.attributeOptions[subRequest.parentKey[0]].multiValued) {
                    var newParentValues = [];
                    parentValues.forEach(function (parentValue) {
                        if (!Array.isArray(parentValue[0])) return;
                        newParentValues = newParentValues.concat(parentValue[0].map(function (value) {
                            return [value];
                        }));
                    });
                    parentValues = newParentValues;
                }

                parentValues = _.uniq(parentValues, false, String);

                subRequest.request.filter.forEach(function (filters) {
                    filters.forEach(function (filter) {
                        if (!filter.valueFromParentKey) return;
                        if (!Array.isArray(filter.attribute)) {
                            filter.value = parentValues.map(function (value) {
                                return value[0];
                            });
                        } else {
                            filter.value = parentValues;
                        }
                    });
                });

                subRequest._profiler = dst._profiler;
                return executeDst(api, request, subRequest);
            });

            return Promise.all(subRequests);
        })

        // Add the subRequest results to the global results array
        .then(function handleSubResults(subResults) {
            delete(dst._isEmpty); // clean up

            subResults.forEach(function (subResult) {
                globalResults = globalResults.concat(subResult);
            });
            return globalResults;
        });
}
<|endoftext|>


<commit_before>var test = require("tape").test

var align = require("../align")

var spy = require("through2-spy")
var spigot = require("stream-spigot")

test("init", function (t) {
  t.equals(typeof align, "function", "Align loaded and is a function")
  t.end()
})

test("align", function (t) {
  t.plan(6)

  var left = spigot({objectMode: true}, [
    {v: 0, foo: 100},
    {v: 1, foo: 200},
    {v: 2, foo: 300},
    {v: 3, foo: 400},
    {v: 4, foo: 500},
  ])

  var right = spigot({objectMode: true}, [
    {v: 0, bar: 100},
    {v: 2, bar: 200},
    {v: 4, bar: 300},
    {v: 8, bar: 400},
  ])

  var expected = [
    [ { v: 0, foo: 100 }, { v: 0, bar: 100 } ],
    [ { v: 1, foo: 200 }, null ],
    [ { v: 2, foo: 300 }, { v: 2, bar: 200 } ],
    [ { v: 3, foo: 400 }, null ],
    [ { v: 4, foo: 500 }, {v: 4, bar: 300} ],
    [ null, { v: 8, bar: 400 } ],
  ]

  function check(r) {
    t.deepEquals(r, expected.shift(), "Expected record emitted")
  }

  align("v", left, right)
    .pipe(spy({objectMode: true}, check))
})

test("align new key", function (t) {
  t.plan(5)

  var left = spigot({objectMode: true}, [
    {v: 0, foo: 100},
    {v: 1, foo: 200},
    {v: 2, foo: 300},
    {v: 3, foo: 400},
    {v: 4, foo: 500},
  ])

  var right = spigot({objectMode: true}, [
    {v: 0, foo: 100},
    {v: 2, foo: 200},
    {v: 4, foo: 300},
    {v: 8, foo: 400},
  ])

  var expected = [
    [ { v: 0, foo: 100 }, { v: 0, foo: 100 } ],
    [ { v: 1, foo: 200 }, { v: 2, foo: 200 } ],
    [ { v: 2, foo: 300 }, { v: 4, foo: 300 } ],
    [ { v: 3, foo: 400 }, { v: 8, foo: 400 } ],
    [ { v: 4, foo: 500 }, null ]
  ]

  function check(r) {
    t.deepEquals(r, expected.shift(), "Expected record emitted")
  }

  align("foo", left, right)
    .pipe(spy({objectMode: true}, check))
})

test("align float keys", function (t) {
    t.plan(6)

    var left = spigot({objectMode: true}, [
        {v: 0.11, foo: 100},
        {v: 1.11, foo: 200},
        {v: 2.11, foo: 300},
        {v: 3.11, foo: 400},
        {v: 4.11, foo: 500},
    ])

    var right = spigot({objectMode: true}, [
        {v: 0.12, bar: 100},
        {v: 2.12, bar: 200},
        {v: 4.12, bar: 300},
        {v: 8.12, bar: 400},
    ])

    var expected = [
        [ { v: 0.11, foo: 100 }, { v: 0.12, bar: 100 } ],
        [ { v: 1.11, foo: 200 }, null ],
        [ { v: 2.11, foo: 300 }, { v: 2.12, bar: 200 } ],
        [ { v: 3.11, foo: 400 }, null ],
        [ { v: 4.11, foo: 500 }, {v: 4.12, bar: 300} ],
        [ null, { v: 8.12, bar: 400 } ],
    ]

    function check(r) {
        t.deepEquals(r, expected.shift(), "Expected record emitted")
    }

    align("v", left, right, 0.011)
        .pipe(spy({objectMode: true}, check))
})
<commit_msg>format changes<commit_after>var test = require("tape").test

var align = require("../align")

var spy = require("through2-spy")
var spigot = require("stream-spigot")

test("init", function (t) {
  t.equals(typeof align, "function", "Align loaded and is a function")
  t.end()
})

test("align", function (t) {
  t.plan(6)

  var left = spigot({objectMode: true}, [
    {v: 0, foo: 100},
    {v: 1, foo: 200},
    {v: 2, foo: 300},
    {v: 3, foo: 400},
    {v: 4, foo: 500},
  ])

  var right = spigot({objectMode: true}, [
    {v: 0, bar: 100},
    {v: 2, bar: 200},
    {v: 4, bar: 300},
    {v: 8, bar: 400},
  ])

  var expected = [
    [ { v: 0, foo: 100 }, { v: 0, bar: 100 } ],
    [ { v: 1, foo: 200 }, null ],
    [ { v: 2, foo: 300 }, { v: 2, bar: 200 } ],
    [ { v: 3, foo: 400 }, null ],
    [ { v: 4, foo: 500 }, {v: 4, bar: 300} ],
    [ null, { v: 8, bar: 400 } ],
  ]

  function check(r) {
    t.deepEquals(r, expected.shift(), "Expected record emitted")
  }

  align("v", left, right)
    .pipe(spy({objectMode: true}, check))
})

test("align new key", function (t) {
  t.plan(5)

  var left = spigot({objectMode: true}, [
    {v: 0, foo: 100},
    {v: 1, foo: 200},
    {v: 2, foo: 300},
    {v: 3, foo: 400},
    {v: 4, foo: 500},
  ])

  var right = spigot({objectMode: true}, [
    {v: 0, foo: 100},
    {v: 2, foo: 200},
    {v: 4, foo: 300},
    {v: 8, foo: 400},
  ])

  var expected = [
    [ { v: 0, foo: 100 }, { v: 0, foo: 100 } ],
    [ { v: 1, foo: 200 }, { v: 2, foo: 200 } ],
    [ { v: 2, foo: 300 }, { v: 4, foo: 300 } ],
    [ { v: 3, foo: 400 }, { v: 8, foo: 400 } ],
    [ { v: 4, foo: 500 }, null ]
  ]

  function check(r) {
    t.deepEquals(r, expected.shift(), "Expected record emitted")
  }

  align("foo", left, right)
    .pipe(spy({objectMode: true}, check))
})

test("align float keys", function (t) {
  t.plan(6)

  var left = spigot({objectMode: true}, [
    {v: 0.11, foo: 100},
    {v: 1.11, foo: 200},
    {v: 2.11, foo: 300},
    {v: 3.11, foo: 400},
    {v: 4.11, foo: 500},
  ])

  var right = spigot({objectMode: true}, [
    {v: 0.12, bar: 100},
    {v: 2.12, bar: 200},
    {v: 4.12, bar: 300},
    {v: 8.12, bar: 400},
  ])

  var expected = [
    [ { v: 0.11, foo: 100 }, { v: 0.12, bar: 100 } ],
    [ { v: 1.11, foo: 200 }, null ],
    [ { v: 2.11, foo: 300 }, { v: 2.12, bar: 200 } ],
    [ { v: 3.11, foo: 400 }, null ],
    [ { v: 4.11, foo: 500 }, {v: 4.12, bar: 300} ],
    [ null, { v: 8.12, bar: 400 } ],
  ]

  function check(r) {
    t.deepEquals(r, expected.shift(), "Expected record emitted")
  }

  align("v", left, right, 0.011)
    .pipe(spy({objectMode: true}, check))
})
<|endoftext|>


<commit_before>function contacts_group(_args) {
	var win = Ti.UI.createWindow({
		title:_args.title
	});

	var imageDisplay = null;

	var infoLabel = Ti.UI.createLabel({
		top:20,
		width:'auto',
		height:'auto'
	});

	var groups = Titanium.Contacts.getAllGroups();

	// Create a test group IF we need it
	if (groups.length === 0) {
		Titanium.Contacts.save(); // Need to save before creating groups
		var testGroup = Titanium.Contacts.createGroup();
		testGroup.name = '__KSTESTGROUP';
		Titanium.Contacts.save();

		groups = Titanium.Contacts.getAllGroups();
	}

	var selectedGroup = groups[0];
	var data = [];
	var people = [];

	var updatePeople = function() {
		people = selectedGroup.members();
		var text = 'People: ';
		if (people != null) {
			for (var i=0; i < people.length; i++) {
				text += people[i].fullName +', ';
			}
		}
		else {
			people = [];
		}
		infoLabel.text = text;
	};

	updatePeople();

	for (var i=0; i < groups.length; i++) {
		data[i] = Ti.UI.createPickerRow({title:groups[i].name});
	}

	var groupPicker = Ti.UI.createPicker({
		top:50
	});
	groupPicker.addEventListener('change', function(e) {
		selectedGroup = groups[e.rowIndex];
		updatePeople();
	});

	groupPicker.selectionIndicator = true;
	groupPicker.add(data);

	var addPerson = Ti.UI.createButton({
		title:'Add person',
		left:10,
		bottom:20,
		width:120,
		height:40
	});
	addPerson.addEventListener('click', function() {
		Titanium.Contacts.showContacts({
			selectedPerson: function(e) {
				selectedGroup.add(e.person);
				Titanium.Contacts.save();
				updatePeople();
			}
		});
	});

	var removePerson = Ti.UI.createButton({
		title:'Remove person',
		right:10,
		bottom:20,
		width:120,
		height:40
	});
	removePerson.addEventListener('click', function() {
		Titanium.Contacts.showContacts({
			selectedPerson: function(e) {
				selectedGroup.remove(e.person);
				Titanium.Contacts.save();
				updatePeople();
			}
		});
	});

	win.add(infoLabel);
	win.add(groupPicker);
	win.add(addPerson);
	win.add(removePerson);

	var reloadHandler = function(){
		addPerson.enabled = false;
		removePerson.enabled = false;
		addPerson.visible = false;
		removePerson.visible = false;
		infoLabel.text = 'Contacts fired reload Event. Please reopen window to modify more groups.'
	}

	// Nasty thing to get around picker bug where we can't select before
	// drawing, and then also have to change the value to fire an event.
	win.addEventListener('open', function() {
		if (data.length > 1) {
			groupPicker.setSelectedRow(0,1,false);
			groupPicker.setSelectedRow(0,0,false);
		}
	});

	Ti.Contacts.addEventListener('reload',reloadHandler);

	win.addEventListener('close',function(){
		Ti.Contacts.removeEventListener('reload',reloadHandler);
	})

	return win;
};

module.exports = contacts_group;<commit_msg>[TIMOB-13478] Address comments<commit_after>function contacts_group(_args) {
	var win = Ti.UI.createWindow({
		title:_args.title
	});

	var imageDisplay = null;

	var infoLabel = Ti.UI.createLabel({
		top:20,
		width:'auto',
		height:'auto'
	});

	var groups = Titanium.Contacts.getAllGroups();

	// Create a test group IF we need it
	if (groups.length === 0) {
		Titanium.Contacts.save(); // Need to save before creating groups
		var testGroup = Titanium.Contacts.createGroup();
		testGroup.name = '__KSTESTGROUP';
		Titanium.Contacts.save();

		groups = Titanium.Contacts.getAllGroups();
	}

	var selectedGroup = groups[0];
	var data = [];
	var people = [];

	var updatePeople = function() {
		people = selectedGroup.members();
		var text = 'People: ';
		if (people != null) {
			for (var i=0; i < people.length; i++) {
				text += people[i].fullName +', ';
			}
		}
		else {
			people = [];
		}
		infoLabel.text = text;
	};

	updatePeople();

	for (var i=0; i < groups.length; i++) {
		data[i] = Ti.UI.createPickerRow({title:groups[i].name});
	}

	var groupPicker = Ti.UI.createPicker({
		top:50
	});
	groupPicker.addEventListener('change', function(e) {
		selectedGroup = groups[e.rowIndex];
		updatePeople();
	});

	groupPicker.selectionIndicator = true;
	groupPicker.add(data);

	var addPerson = Ti.UI.createButton({
		title:'Add person',
		left:10,
		bottom:20,
		width:120,
		height:40
	});
	addPerson.addEventListener('click', function() {
		Titanium.Contacts.showContacts({
			selectedPerson: function(e) {
				selectedGroup.add(e.person);
				Titanium.Contacts.save();
				updatePeople();
			}
		});
	});

	var removePerson = Ti.UI.createButton({
		title:'Remove person',
		right:10,
		bottom:20,
		width:120,
		height:40
	});
	removePerson.addEventListener('click', function() {
		Titanium.Contacts.showContacts({
			selectedPerson: function(e) {
				selectedGroup.remove(e.person);
				Titanium.Contacts.save();
				updatePeople();
			}
		});
	});

	win.add(infoLabel);
	win.add(groupPicker);
	win.add(addPerson);
	win.add(removePerson);

	var reloadHandler = function(){
		addPerson.enabled = false;
		removePerson.enabled = false;
		addPerson.visible = false;
		removePerson.visible = false;
		infoLabel.text = 'Contacts fired reload Event. Please reopen window to modify more groups.'
	}

	// Nasty thing to get around picker bug where we can't select before
	// drawing, and then also have to change the value to fire an event.
	win.addEventListener('open', function() {
		if (data.length > 1) {
			groupPicker.setSelectedRow(0,1,false);
			groupPicker.setSelectedRow(0,0,false);
		}
	});

	Ti.Contacts.addEventListener('reload',reloadHandler);

	win.addEventListener('close',function(){
		Ti.Contacts.removeEventListener('reload',reloadHandler);
	});

	return win;
};

module.exports = contacts_group;<|endoftext|>


<commit_before>/*jshint unused: false */
/*jslint indent: 4 */
/*global jasmine, process, require, define, describe, xdescribe, it, xit, expect, beforeEach, afterEach, afterLast, spyOn */
(function () {

    'use strict';

    var result, helper,
        cwd = process.cwd(),
        qPromiseFunc = function () {
            return {
                promise: 'yo! it\'s a promise',
                reject: function () {
                    return 'yo! promise rejected';
                },
                resolve: function () {
                    return 'yo! promise resolved';
                }
            };
        },
        options = {
            depth: 1,
            filters: ['../*.md']
        },
        //
        Q = require('q'),
        FS = require('fs'),
        Path = require('path'),
        sinon = require('sinon'),
        lodash = require('lodash'),
        //
        Utils = require(Path.join(cwd, 'src', 'lib', 'utils')),
        Scandir = require(Path.join(cwd, 'src', 'lib', 'scandir-async'));

    describe('scandir', function () {

        describe('scandir.options()', function () {
            it('returns defaults options', function () {
                helper = new Scandir();
                result = helper.options();
                expect(result.root).toEqual('.');
                expect(result.depth).toEqual(0);
                expect(result.filters).toEqual([]);
            });
        });

        describe('scandir.node()', function () {
            it('returns an object', function () {
                var base = cwd,
                    stats = {};
                helper = new Scandir();
                result = helper.node(base, stats);
                expect(result).toEqual({
                    files: [],
                    stats: {},
                    fullpath: cwd,
                    name: Utils.dirname(cwd)
                });
            });
        });

        describe('scandir.files/files', function () {

            it('returns Q.promise', function () {
                var promise;
                sinon.stub(Q, 'defer', qPromiseFunc);
                helper = new Scandir();
                promise = helper.files('toto');
                expect(promise).toEqual('yo! it\'s a promise');
                Q.defer.restore();
            });

            it('use FS.readdir', function () {
                helper = new Scandir();
                sinon.stub(FS, 'readdir');
                helper.files('test_fs_readdir');
                expect(FS.readdir.calledOnce).toEqual(true);
                FS.readdir.restore();
            });

            it('Q.reject called on non existent path', function (done) {
                var msg = 'Invalid path. Aborted';
                helper = new Scandir();
                helper.files('test_invalid_path').then(function () {}, function (err) {
                    expect(err.hasOwnProperty('path')).toBe(true);
                    expect(err.hasOwnProperty('code')).toBe(true);
                    expect(err.hasOwnProperty('errno')).toBe(true);
                    done();
                });
            });

            it('Q.resolved with false (no file in folder)', function (done) {
                var no_file_path = Path.join(cwd, 'spec', 'expected', 'files_method', 'nofile');
                helper = new Scandir();
                helper.files(no_file_path).then(function (result) {
                    expect(result).toEqual(false);
                    done();
                }, function (err) {
                    // no error
                    // console.log(err);
                    // done();
                });
            });

            it('Q.resolved with array of files (length = 4)', function (done) {
                var no_file_path = Path.join(cwd, 'spec', 'expected', 'files_method', 'threefile');
                helper = new Scandir();
                helper.files(no_file_path).then(function (result) {
                    expect(result.length).toEqual(4);
                    done();
                }, function (err) {
                    // no error
                    // console.log(err);
                    // done();
                });

            });

        });

        describe('browsable method (async)', function () {
            it('resolve w/ stats', function (done) {
                var base = Path.join(cwd, 'spec', 'expected', 'explore_method');
                helper = new Scandir();
                helper.browsable(base).then(function (stats) {
                    expect(stats.isDirectory()).toEqual(true);
                    done();
                }, function (err) {
                    // no error
                    // console.log(err);
                    // done();
                });
            });
            it('resolve w/ FS.error', function (done) {
                var base = Path.join(cwd, 'spec', 'expected', 'non_exists');
                helper = new Scandir();
                helper.browsable(base).then(function () {}, function (err) {
                    // returns an FS Error
                    expect(err.hasOwnProperty('path')).toBe(true);
                    expect(err.hasOwnProperty('code')).toBe(true);
                    expect(err.hasOwnProperty('errno')).toBe(true);
                    done();
                });
            });
        });

        describe('list items/build method', function () {
            it('returns plain object', function (done) {
                var file = Path.join(cwd, 'spec', 'expected', 'explore_method'),
                    base = {
                        files: [],
                        fullpath: file,
                        name: 'explore_method',
                        stats: FS.statSync(file)
                    };
                helper = new Scandir();
                helper.build(base, helper).then(function (data) {
                    expect(lodash.isPlainObject(data)).toEqual(true);
                    expect(data.files.length).toEqual(4);
                    expect(data.files[0].files).toEqual(false); // index.html
                    expect(data.files[1].files).toEqual(false); // subnofiles
                    expect(data.files[2].files.length).toEqual(1); // subone
                    expect(data.files[2].files[0].files.length).toEqual(2); // subone/file && subone/file.txt
                    expect(data.files[2].files[0].files[0].name).toEqual('file'); // subone/file && subone/file.txt
                    expect(data.files[2].files[0].files[1].name).toEqual('file.txt'); // subone/file && subone/file.txt
                    expect(data.files[3].files.length).toEqual(3); // subtwo
                    expect(data.files[3].files[0].name).toEqual('file.js'); // subtwo/file.js
                    expect(data.files[3].files[1].name).toEqual('file.md'); // subtwo/file.md
                    expect(data.files[3].files[2].files.length).toEqual(1); // subtwo/subsub
                    expect(data.files[3].files[2].files[0].files.length).toEqual(1); // subtwo/subsub/subsubsub
                    expect(data.files[3].files[2].files[0].files[0].name).toEqual('file.css'); // subtwo/subsub/subsubsub/file.css
                    done();
                }, function (err) {
                    // no error
                    // console.log(err);
                    // done();
                });
            });
        });

        describe('scandir/exec/scandir.exec', function () {

            it('returns Q.promise', function () {
                helper = new Scandir();
                sinon.stub(FS, 'stat');
                sinon.stub(helper, 'build');
                sinon.stub(Q, 'defer', qPromiseFunc);
                result = helper.exec('toto');
                expect(result).toEqual('yo! it\'s a promise');
                helper.build.restore();
                FS.stat.restore();
                Q.defer.restore();
            });

            it('returns a path/test scandir.options().root', function () {
                var promise, p, e;
                helper = new Scandir();
                sinon.stub(FS, 'stat');
                sinon.stub(helper, 'build');
                /* --- */
                p = '';
                helper.exec(p);
                expect(helper.options().root).toEqual(cwd);
                //
                p = '.';
                helper.exec(p);
                expect(helper.options().root).toEqual(cwd);
                //
                p = 'toto';
                helper.exec(p);
                expect(helper.options().root).toEqual(Path.join(cwd, p));
                //
                p = Path.join(cwd, 'toto');
                helper.exec(p);
                expect(helper.options().root).toEqual(Path.join(cwd, 'toto'));
                //
                p = Path.join(cwd, '..', '..', 'toto');
                helper.exec(p);
                expect(helper.options().root).toEqual(Path.resolve(cwd, Path.join('..', '..', 'toto')));
                //
                p = Path.join(cwd, '..', '.', '..', 'toto');
                helper.exec(p);
                expect(helper.options().root).toEqual(Path.resolve(cwd, Path.join('..', '.', '..', 'toto')));
                /* --- */
                expect(FS.stat.called).toEqual(true);
                helper.build.restore();
                FS.stat.restore();
            });

            it('returns options with default root', function () {
                helper = new Scandir();
                var defaults = helper.options(),
                    opts = {
                        filters: ['**/*.hml'],
                        added: 'no default'
                    };
                helper.exec(opts);
                result = {
                    depth: 0,
                    root: cwd,
                    added: 'no default',
                    filters: ['**/*.hml']
                };
                expect(helper.options()).toEqual(result);
            });

            it('Q.reject', function (done) {
                var msg = 'Invalid arguments. Aborted.';
                helper = new Scandir();
                helper.exec().then(function (data) {}, function (err) {
                    expect(err.message).toEqual(msg);
                    done();
                });
                helper.exec([]).then(function (data) {}, function (err) {
                    expect(err.message).toEqual(msg);
                    done();
                });
                helper.exec(123).then(function (data) {}, function (err) {
                    expect(err.message).toEqual(msg);
                    done();
                });
                helper.exec(null).then(function (data) {}, function (err) {
                    expect(err.message).toEqual(msg);
                    done();
                });
                helper.exec(undefined).then(function (data) {}, function (err) {
                    expect(err.message).toEqual(msg);
                    done();
                });
            });

            it('reject w/ a FS.stat error', function (done) {
                var path = Path.join(cwd, 'spec', 'expected', 'non_exists');
                helper = new Scandir();
                helper.exec(path).then(function (data) {
                    // no data
                }, function (err) {
                    // returns an FS Error
                    expect(err.hasOwnProperty('path')).toBe(true);
                    expect(err.hasOwnProperty('code')).toBe(true);
                    expect(err.hasOwnProperty('errno')).toBe(true);
                    done();
                });
            });

            it('reject w/ not directory', function (done) {
                var path = Path.join(cwd, 'spec', 'expected', 'not_directory');
                helper = new Scandir();
                helper.exec(path).then(function (data) {
                    // no data
                }, function (err) {
                    expect(err.message).toEqual('Invalid path. Aborted.');
                    done();
                });
            });

            it('does not reject', function (done) {
                var path = Path.join(cwd, 'spec', 'expected', 'explore_method');
                //
                helper = new Scandir();
                sinon.stub(helper, 'build', function () {
                    var deferred = Q.defer();
                    setTimeout(function () {
                        deferred.resolve('ok');
                    }, 1000);
                    return deferred.promise;
                });
                helper.exec(path).then(function (data) {
                    // no data
                    expect(helper.options().root).toEqual(path);
                    done();
                }, function (err) {});

                helper.exec(options).then(function (data) {
                    // no data
                    expect(helper.options().filters).toEqual(options.filters);
                    done();
                }, function (err) {});

                helper.exec(path, options).then(function (data) {
                    // no data
                    expect(helper.options().root).toEqual(path);
                    expect(helper.options().filters).toEqual(options.filters);
                    done();
                }, function (err) {
                    // no error
                    // console.log(err);
                    // done();
                });
                helper.build.restore();

            });

            xit('returns a plainObject w/ basename as property', function (done) {
                var name,
                    path = Path.join(cwd, 'spec', 'expected', 'explore_method');
                name = Utils.dirname(path);
                //
                helper = new Scandir();
                helper.exec(path).then(function (data) {
                    console.log(data);
                    expect(lodash.isPlainObject(data)).toBe(true);
                    expect(data[name].name).toEqual(name);
                    done();
                }, function (err) {
                    console.log(err);
                    // done();
                });
                //
                path = '.';
                name = Utils.dirname(cwd);
                helper.exec(path).then(function (data) {
                    expect(lodash.isPlainObject(data)).toBe(true);
                    expect(data[name].name).toEqual(name);
                    done();
                }, function (err) {
                    // no error
                    console.log('unexpected tests error: ');
                    console.log('returns a plainObject w/ basename as property');
                    console.log(err);
                    // done();
                });
            });
        });

    });

}());
<commit_msg>update test<commit_after>/*jshint unused: false */
/*jslint indent: 4 */
/*global jasmine, process, require, define, describe, xdescribe, it, xit, expect, beforeEach, afterEach, afterLast, spyOn */
(function () {

    'use strict';

    var result, helper,
        cwd = process.cwd(),
        qPromiseFunc = function () {
            return {
                promise: 'yo! it\'s a promise',
                reject: function () {
                    return 'yo! promise rejected';
                },
                resolve: function () {
                    return 'yo! promise resolved';
                }
            };
        },
        options = {
            depth: 1,
            filters: ['../*.md']
        },
        //
        Q = require('q'),
        FS = require('fs'),
        Path = require('path'),
        sinon = require('sinon'),
        lodash = require('lodash'),
        //
        Utils = require(Path.join(cwd, 'src', 'lib', 'utils')),
        Scandir = require(Path.join(cwd, 'src', 'lib', 'scandir-async'));

    describe('scandir', function () {

        describe('scandir.options()', function () {
            it('returns defaults options', function () {
                helper = new Scandir();
                result = helper.options();
                expect(result.root).toEqual('.');
                expect(result.depth).toEqual(0);
                expect(result.filters).toEqual([]);
            });
        });

        describe('scandir.node()', function () {
            it('returns an object', function () {
                var base = cwd,
                    stats = {};
                helper = new Scandir();
                result = helper.node(base, stats);
                expect(result).toEqual({
                    files: [],
                    stats: {},
                    fullpath: cwd,
                    name: Utils.dirname(cwd)
                });
            });
        });

        describe('scandir.files/files', function () {

            it('returns Q.promise', function () {
                var promise;
                sinon.stub(Q, 'defer', qPromiseFunc);
                helper = new Scandir();
                promise = helper.files('toto');
                expect(promise).toEqual('yo! it\'s a promise');
                Q.defer.restore();
            });

            it('use FS.readdir', function () {
                helper = new Scandir();
                sinon.stub(FS, 'readdir');
                helper.files('test_fs_readdir');
                expect(FS.readdir.calledOnce).toEqual(true);
                FS.readdir.restore();
            });

            it('Q.reject called on non existent path', function (done) {
                var msg = 'Invalid path. Aborted';
                helper = new Scandir();
                helper.files('test_invalid_path').then(function () {}, function (err) {
                    expect(err.hasOwnProperty('path')).toBe(true);
                    expect(err.hasOwnProperty('code')).toBe(true);
                    expect(err.hasOwnProperty('errno')).toBe(true);
                    done();
                });
            });

            it('Q.resolved with false (no file in folder)', function (done) {
                var no_file_path = Path.join(cwd, 'spec', 'expected', 'files_method', 'nofile');
                helper = new Scandir();
                helper.files(no_file_path).then(function (result) {
                    expect(result).toEqual(false);
                    done();
                }, function (err) {
                    // no error
                    // console.log(err);
                    // done();
                });
            });

            it('Q.resolved with array of files (length = 4)', function (done) {
                var no_file_path = Path.join(cwd, 'spec', 'expected', 'files_method', 'threefile');
                helper = new Scandir();
                helper.files(no_file_path).then(function (result) {
                    expect(result.length).toEqual(4);
                    done();
                }, function (err) {
                    // no error
                    // console.log(err);
                    // done();
                });

            });

        });

        describe('browsable method (async)', function () {
            it('resolve w/ stats', function (done) {
                var base = Path.join(cwd, 'spec', 'expected', 'explore_method');
                helper = new Scandir();
                helper.browsable(base).then(function (stats) {
                    expect(stats.isDirectory()).toEqual(true);
                    done();
                }, function (err) {
                    // no error
                    // console.log(err);
                    // done();
                });
            });
            it('resolve w/ FS.error', function (done) {
                var base = Path.join(cwd, 'spec', 'expected', 'non_exists');
                helper = new Scandir();
                helper.browsable(base).then(function () {}, function (err) {
                    // returns an FS Error
                    expect(err.hasOwnProperty('path')).toBe(true);
                    expect(err.hasOwnProperty('code')).toBe(true);
                    expect(err.hasOwnProperty('errno')).toBe(true);
                    done();
                });
            });
        });

        describe('list items/build method', function () {
            it('returns plain object', function (done) {
                var file = Path.join(cwd, 'spec', 'expected', 'explore_method'),
                    base = {
                        files: [],
                        fullpath: file,
                        name: 'explore_method',
                        stats: FS.statSync(file)
                    };
                helper = new Scandir();
                helper.build(base, helper).then(function (data) {
                    expect(lodash.isPlainObject(data)).toEqual(true);
                    expect(data.files.length).toEqual(4);
                    expect(data.files[0].files).toEqual(false); // index.html
                    expect(data.files[1].files).toEqual(false); // subnofiles
                    expect(data.files[2].files.length).toEqual(1); // subone
                    expect(data.files[2].files[0].files.length).toEqual(2); // subone/file && subone/file.txt
                    expect(data.files[2].files[0].files[0].name).toEqual('file'); // subone/file && subone/file.txt
                    expect(data.files[2].files[0].files[1].name).toEqual('file.txt'); // subone/file && subone/file.txt
                    expect(data.files[3].files.length).toEqual(3); // subtwo
                    expect(data.files[3].files[0].name).toEqual('file.js'); // subtwo/file.js
                    expect(data.files[3].files[1].name).toEqual('file.md'); // subtwo/file.md
                    expect(data.files[3].files[2].files.length).toEqual(1); // subtwo/subsub
                    expect(data.files[3].files[2].files[0].files.length).toEqual(1); // subtwo/subsub/subsubsub
                    expect(data.files[3].files[2].files[0].files[0].name).toEqual('file.css'); // subtwo/subsub/subsubsub/file.css
                    done();
                }, function (err) {
                    // no error
                    // console.log(err);
                    // done();
                });
            });
        });

        describe('scandir/exec/scandir.exec', function () {

            it('returns Q.promise', function () {
                helper = new Scandir();
                sinon.stub(FS, 'stat');
                sinon.stub(helper, 'build');
                sinon.stub(Q, 'defer', qPromiseFunc);
                result = helper.exec('toto');
                expect(result).toEqual('yo! it\'s a promise');
                helper.build.restore();
                FS.stat.restore();
                Q.defer.restore();
            });

            it('returns a path/test scandir.options().root', function () {
                var promise, p, e;
                helper = new Scandir();
                sinon.stub(FS, 'stat');
                sinon.stub(helper, 'build');
                /* --- */
                p = '';
                helper.exec(p);
                expect(helper.options().root).toEqual(cwd);
                //
                p = '.';
                helper.exec(p);
                expect(helper.options().root).toEqual(cwd);
                //
                p = 'toto';
                helper.exec(p);
                expect(helper.options().root).toEqual(Path.join(cwd, p));
                //
                p = Path.join(cwd, 'toto');
                helper.exec(p);
                expect(helper.options().root).toEqual(Path.join(cwd, 'toto'));
                //
                p = Path.join(cwd, '..', '..', 'toto');
                helper.exec(p);
                expect(helper.options().root).toEqual(Path.resolve(cwd, Path.join('..', '..', 'toto')));
                //
                p = Path.join(cwd, '..', '.', '..', 'toto');
                helper.exec(p);
                expect(helper.options().root).toEqual(Path.resolve(cwd, Path.join('..', '.', '..', 'toto')));
                /* --- */
                expect(FS.stat.called).toEqual(true);
                helper.build.restore();
                FS.stat.restore();
            });

            it('returns options with default root', function () {
                helper = new Scandir();
                var defaults = helper.options(),
                    opts = {
                        filters: ['**/*.hml'],
                        added: 'no default'
                    };
                helper.exec(opts);
                result = {
                    depth: 0,
                    root: cwd,
                    added: 'no default',
                    filters: ['**/*.hml']
                };
                expect(helper.options()).toEqual(result);
            });

            it('Q.reject', function (done) {
                var msg = 'Invalid arguments. Aborted.';
                helper = new Scandir();
                helper.exec().then(function (data) {}, function (err) {
                    expect(err.message).toEqual(msg);
                    done();
                });
                helper.exec([]).then(function (data) {}, function (err) {
                    expect(err.message).toEqual(msg);
                    done();
                });
                helper.exec(123).then(function (data) {}, function (err) {
                    expect(err.message).toEqual(msg);
                    done();
                });
                helper.exec(null).then(function (data) {}, function (err) {
                    expect(err.message).toEqual(msg);
                    done();
                });
                helper.exec(undefined).then(function (data) {}, function (err) {
                    expect(err.message).toEqual(msg);
                    done();
                });
            });

            it('reject w/ a FS.stat error', function (done) {
                var path = Path.join(cwd, 'spec', 'expected', 'non_exists');
                helper = new Scandir();
                helper.exec(path).then(function (data) {
                    // no data
                }, function (err) {
                    // returns an FS Error
                    expect(err.hasOwnProperty('path')).toBe(true);
                    expect(err.hasOwnProperty('code')).toBe(true);
                    expect(err.hasOwnProperty('errno')).toBe(true);
                    done();
                });
            });

            it('reject w/ not directory', function (done) {
                var path = Path.join(cwd, 'spec', 'expected', 'not_directory');
                helper = new Scandir();
                helper.exec(path).then(function (data) {
                    // no data
                }, function (err) {
                    expect(err.message).toEqual('Invalid path. Aborted.');
                    done();
                });
            });

            it('does not reject', function (done) {
                var path = Path.join(cwd, 'spec', 'expected', 'explore_method');
                //
                helper = new Scandir();
                sinon.stub(helper, 'build', function () {
                    var deferred = Q.defer();
                    setTimeout(function () {
                        deferred.resolve('ok');
                    }, 1000);
                    return deferred.promise;
                });
                helper.exec(path).then(function (data) {
                    // no data
                    expect(helper.options().root).toEqual(path);
                    done();
                }, function (err) {});

                helper.exec(options).then(function (data) {
                    // no data
                    expect(helper.options().filters).toEqual(options.filters);
                    done();
                }, function (err) {});

                helper.exec(path, options).then(function (data) {
                    // no data
                    expect(helper.options().root).toEqual(path);
                    expect(helper.options().filters).toEqual(options.filters);
                    done();
                }, function (err) {
                    // no error
                    // console.log(err);
                    // done();
                });
                helper.build.restore();

            });

            it('returns a plainObject w/ basename as property', function (done) {
                var name,
                    path = Path.join(cwd, 'spec', 'expected', 'explore_method');
                name = Utils.dirname(path);
                //
                helper = new Scandir();
                helper.exec(path).then(function (data) {
                    console.log(data);
                    expect(lodash.isPlainObject(data)).toBe(true);
                    expect(data[name].name).toEqual(name);
                    done();
                }, function (err) {
                    // console.log(err);
                    // done();
                });
            });

            it('returns a plainObject w/ basename as property dot base', function (done) {
                var path = '.',
                    name = Utils.dirname(cwd);
                helper.exec(path).then(function (data) {
                    expect(lodash.isPlainObject(data)).toBe(true);
                    expect(data[name].name).toEqual(name);
                    done();
                }, function (err) {
                    // no error
                    // console.log('unexpected tests error: ');
                    // console.log('returns a plainObject w/ basename as property');
                    // console.log(err);
                    // done();
                });
            });
        });

    });

}());
<|endoftext|>


<commit_before>/*
 * @author  Mudit Ameta
 * @license https://github.com/zeusdeux/isInViewport/blob/master/license.md MIT
 */
!function(a,b){function c(b){var c,d=a("

").css({width:"100%"});return b.append(d),c=b.width()-d.width(),d.remove(),c}function d(e,f){var g=e.getBoundingClientRect(),h=g.top,i=g.bottom,j=g.left,k=g.right,l=a.extend({tolerance:0,viewport:b},f),m=!1,n=l.viewport.jquery?l.viewport:a(l.viewport);n.length||(console.warn("isInViewport: The viewport selector you have provided matches no element on page."),console.warn("isInViewport: Defaulting to viewport as window"),n=a(b));var o=n.height(),p=n.width(),q=n.get(0).toString();if(n[0]!==b&&"[object Window]"!==q&&"[object DOMWindow]"!==q){var r=n.get(0).getBoundingClientRect();h-=r.top,i-=r.top,j-=r.left,k-=r.left,d.scrollBarWidth=d.scrollBarWidth||c(n),p-=d.scrollBarWidth}return l.tolerance=~~Math.round(parseFloat(l.tolerance)),l.tolerance<0&&(l.tolerance=o+l.tolerance),0>=k||j>=p?m:m=l.tolerance?!!(h<=l.tolerance&&i>=l.tolerance):!!(i>0&&o>=h)}String.prototype.hasOwnProperty("trim")||(String.prototype.trim=function(){return this.replace(/^\s*(.*?)\s*$/,"$1")});var e=function(b){if(1===arguments.length&&"function"==typeof b&&(b=[b]),!(b instanceof Array))throw new SyntaxError("isInViewport: Argument(s) passed to .do/.run should be a function or an array of functions");for(var c=0;c<b.length;c++)if("function"==typeof b[c])for(var d=0;d<this.length;d++)b[c].call(a(this[d]));else console.warn("isInViewport: Argument(s) passed to .do/.run should be a function or an array of functions"),console.warn("isInViewport: Ignoring non-function values in array and moving on");return this};a.fn["do"]=function(a){return console.warn("isInViewport: .do causes issues in IE and some browsers since its a reserved. Use $.fn.run instead i.e., $(el).run(fn)."),e(a)},a.fn.run=e,a.extend(a.expr[":"],{"in-viewport":function(a,b,c){if(c[3]){var e=c[3].split(",");return 1===e.length&&isNaN(e[0])&&(e[1]=e[0],e[0]=void 0),d(a,{tolerance:e[0]?e[0].trim():void 0,viewport:e[1]?e[1].trim():void 0})}return d(a)}})}(jQuery,window);<commit_msg>Latest build<commit_after>/*
 * @author  Mudit Ameta
 * @license https://github.com/zeusdeux/isInViewport/blob/master/license.md MIT
 */
!function(a,b){function c(b){var c,d=a("

").css({width:"100%"});return b.append(d),c=b.width()-d.width(),d.remove(),c}function d(e,f){var g=e.getBoundingClientRect(),h=g.top,i=g.bottom,j=g.left,k=g.right,l=a.extend({tolerance:0,viewport:b},f),m=!1,n=l.viewport.jquery?l.viewport:a(l.viewport);n.length||(console.warn("isInViewport: The viewport selector you have provided matches no element on page."),console.warn("isInViewport: Defaulting to viewport as window"),n=a(b));var o=n.height(),p=n.width(),q=n[0].toString();if(n[0]!==b&&"[object Window]"!==q&&"[object DOMWindow]"!==q){var r=n[0].getBoundingClientRect();h-=r.top,i-=r.top,j-=r.left,k-=r.left,d.scrollBarWidth=d.scrollBarWidth||c(n),p-=d.scrollBarWidth}return l.tolerance=~~Math.round(parseFloat(l.tolerance)),l.tolerance<0&&(l.tolerance=o+l.tolerance),0>=k||j>=p?m:m=l.tolerance?!!(h<=l.tolerance&&i>=l.tolerance):!!(i>0&&o>=h)}String.prototype.hasOwnProperty("trim")||(String.prototype.trim=function(){return this.replace(/^\s*(.*?)\s*$/,"$1")});var e=function(b){if(1===arguments.length&&"function"==typeof b&&(b=[b]),!(b instanceof Array))throw new SyntaxError("isInViewport: Argument(s) passed to .do/.run should be a function or an array of functions");for(var c=0;c<b.length;c++)if("function"==typeof b[c])for(var d=0;d<this.length;d++)b[c].call(a(this[d]));else console.warn("isInViewport: Argument(s) passed to .do/.run should be a function or an array of functions"),console.warn("isInViewport: Ignoring non-function values in array and moving on");return this};a.fn["do"]=function(a){return console.warn("isInViewport: .do is deprecated as it causes issues in IE and some browsers since it's a reserved word. Use $.fn.run instead i.e., $(el).run(fn)."),e(a)},a.fn.run=e;var f=function(b){if(b){var c=b.split(",");return 1===c.length&&isNaN(c[0])&&(c[1]=c[0],c[0]=void 0),{tolerance:c[0]?c[0].trim():void 0,viewport:c[1]?a(c[1].trim()):void 0}}return{}};a.extend(a.expr[":"],{"in-viewport":a.expr.createPseudo?a.expr.createPseudo(function(a){return function(b){return d(b,f(a))}}):function(a,b,c){return d(a,f(c[3]))}}),a.fn.isInViewport=function(a){return this.filter(function(b,c){return d(c,a)})}}(jQuery,window);<|endoftext|>


<commit_before>var assert = require('assert');
var async = require('async');
var viewEngine = require('..');
var viewOptions = {
  settings: {
    env: 'development'
  }
};

function testComponent(path, cb) {
  var render = viewEngine.createEngine();
  render(__dirname + '/es5-component.jsx', viewOptions, function(err, source) {
    assert(!err);
    assert(source.indexOf('I can count to 10:1, 2, 3, 4, 5, 6, 7, 8, 9, 10') !== -1);
    cb();
  });
}

async.series([
  function testES5Module(next) {
    testComponent(__dirname + '/es5-component.jsx', next);
  },
  function testES6Module(next) {
    testComponent(__dirname + '/es6-component.jsx', next);
  },
  function testES6FlowModule(next) {
    testComponent(__dirname + '/es6-flow-component.jsx', next);
  }
], function done() {
  console.log('All tests pass!');
  process.exit(0);
});

<commit_msg>Specify the view path, as express would<commit_after>var assert = require('assert');
var async = require('async');
var viewEngine = require('..');
var viewOptions = {
  settings: {
    env: 'development',
    views: __dirname
  }
};

function testComponent(path, cb) {
  var render = viewEngine.createEngine();
  render(__dirname + '/es5-component.jsx', viewOptions, function(err, source) {
    assert(!err);
    assert(source.indexOf('I can count to 10:1, 2, 3, 4, 5, 6, 7, 8, 9, 10') !== -1);
    cb();
  });
}

async.series([
  function testES5Module(next) {
    testComponent(__dirname + '/es5-component.jsx', next);
  },
  function testES6Module(next) {
    testComponent(__dirname + '/es6-component.jsx', next);
  },
  function testES6FlowModule(next) {
    testComponent(__dirname + '/es6-flow-component.jsx', next);
  }
], function done() {
  console.log('All tests pass!');
  process.exit(0);
});

<|endoftext|>


<commit_before>/* global describe, it */
'use strict'
const assert = require('chai').assert
const julian = require('../lib/julian')
const lune = require('../lib/lune')

describe('lune', function () {
  const observations = [
    ['1989-01-07T19:22Z', 0.00],
    ['1989-01-14T13:58Z', 0.25],
    ['1989-01-21T21:33Z', 0.50],
    ['1989-01-30T02:02Z', 0.75],
    ['1989-02-06T07:37Z', 0.00],
    ['1989-02-12T23:15Z', 0.25],
    ['1989-02-20T15:32Z', 0.50],
    ['1989-02-28T20:08Z', 0.75],
    ['1989-03-07T18:19Z', 0.00],
    ['1989-03-14T10:11Z', 0.25],
    ['1989-03-22T09:58Z', 0.50],
    ['1989-03-30T10:21Z', 0.75],
    ['1989-04-06T03:33Z', 0.00],
    ['1989-04-12T23:13Z', 0.25],
    ['1989-04-21T03:13Z', 0.50],
    ['1989-04-28T20:46Z', 0.75],
    ['1989-05-05T11:46Z', 0.00],
    ['1989-05-12T14:19Z', 0.25],
    ['1989-05-20T18:16Z', 0.50],
    ['1989-05-28T04:01Z', 0.75],
    ['1989-06-03T19:53Z', 0.00],
    ['1989-06-11T06:59Z', 0.25],
    ['1989-06-19T06:57Z', 0.50],
    ['1989-06-26T09:09Z', 0.75],
    ['1989-07-03T04:59Z', 0.00],
    ['1989-07-11T00:19Z', 0.25],
    ['1989-07-18T17:42Z', 0.50],
    ['1989-07-25T13:31Z', 0.75],
    ['1989-08-01T16:06Z', 0.00],
    ['1989-08-09T17:28Z', 0.25],
    ['1989-08-17T03:07Z', 0.50],
    ['1989-08-23T18:40Z', 0.75],
    ['1989-08-31T05:44Z', 0.00],
    ['1989-09-08T09:49Z', 0.25],
    ['1989-09-15T11:51Z', 0.50],
    ['1989-09-22T02:10Z', 0.75],
    ['1989-09-29T21:47Z', 0.00]
  ]

  describe('#phase()', function () {
    it('should return expected values for-02-17th data', function () {
      const phase = lune.phase(new Date('2014-02-17T00:00-0500'))

      assert.closeTo(phase.phase, 0.568, 0.001)
      assert.closeTo(phase.illuminated, 0.955, 0.001)
      assert.closeTo(phase.age, 16.779, 0.030)
      assert.closeTo(phase.distance, 396084.5, 384.4)
      assert.closeTo(phase.angular_diameter, 0.5028, 0.0005)
      assert.closeTo(phase.sun_distance, 147822500, 149600)
      assert.closeTo(phase.sun_angular_diameter, 0.5395, 0.0005)
    })

    // http://bazaar.launchpad.net/~keturn/py-moon-phase/trunk/view/head:/moontest.py
    it('should be accurate to astronomical observations', function () {
      let error = 0
      for (let obs of observations) {
        let e = Math.abs(lune.phase(new Date(obs[0])).phase - obs[1])
        if (e > 0.5) {
          // phase is circular
          e = 1 - e
        }

        error += e
      }

      // tolerate an average error of up to a tenth of a percent
      assert.isAtMost(error / observations.length, 0.001)
    })
  })

  describe('#phase_hunt', function () {
    it('should handle timezones correctly', function () {
      // 1415292777000 incorrect EST time
      // 1415312577000 correct UTC time
      // date conversion is now accurate to the millisecond, but these tests
      // were written when they were only accurate to the second
      assert.closeTo(
        lune.phase_hunt(new Date('2014-11-01T06:26-0400')).full_date.getTime(),
        1415312577000,
        500
      )
    })
  })

  describe('#phase_range', function () {
    const NAMES = ['new', 'q1', 'full', 'q3']

    /* http://aa.usno.navy.mil/data/docs/JulianDate.php */
    it('should return all moon phases within a time range', function () {
      const phases = lune.phase_range(
        new Date('1989-01-01T00:00Z'),
        new Date('1989-10-01T00:00Z')
      )

      let error = 0

      assert.strictEqual(phases.length, observations.length)

      for (let i = 0; i < phases.length; i++) {
        const phase = phases[i]
        const obs = observations[i]

        assert.strictEqual(phase.phase, NAMES[Math.round(4 * obs[1])])

        error += Math.abs(phase.date.getTime() - new Date(obs[0]).getTime())
      }

      // tolerate an average error of up to five minutes
      assert.isAtMost(error / observations.length, 300000)
    })
  })
})

describe('julian', function () {
  describe('#fromDate', function () {
    /* http://aa.usno.navy.mil/data/docs/JulianDate.php */
    it('should convert 2000-01-01T00:00Z to 2451544.5', function () {
      assert.closeTo(
        julian.fromDate(new Date('2000-01-01T00:00Z')),
        2451544.5,
        0.5 / 86400
      )
    })
  })

  describe('#toDate', function () {
    /* http://aa.usno.navy.mil/data/docs/JulianDate.php */
    it('should convert 2457464.179862 to 2016-03-16T16:19Z', function () {
      assert.closeTo(
        julian.toDate(2457464.179862).getTime(),
        (new Date('2016-03-16T16:19Z')).getTime(),
        500
      )
    })
  })
})
<commit_msg>Clean up tests.<commit_after>/* global describe, it */
'use strict'
const assert = require('chai').assert
const julian = require('../lib/julian')
const lune = require('../lib/lune')

describe('lune', function () {
  const observations = [
    ['1989-01-07T19:22Z', 0.00, 'new'],
    ['1989-01-14T13:58Z', 0.25, 'q1'],
    ['1989-01-21T21:33Z', 0.50, 'full'],
    ['1989-01-30T02:02Z', 0.75, 'q3'],
    ['1989-02-06T07:37Z', 0.00, 'new'],
    ['1989-02-12T23:15Z', 0.25, 'q1'],
    ['1989-02-20T15:32Z', 0.50, 'full'],
    ['1989-02-28T20:08Z', 0.75, 'q3'],
    ['1989-03-07T18:19Z', 0.00, 'new'],
    ['1989-03-14T10:11Z', 0.25, 'q1'],
    ['1989-03-22T09:58Z', 0.50, 'full'],
    ['1989-03-30T10:21Z', 0.75, 'q3'],
    ['1989-04-06T03:33Z', 0.00, 'new'],
    ['1989-04-12T23:13Z', 0.25, 'q1'],
    ['1989-04-21T03:13Z', 0.50, 'full'],
    ['1989-04-28T20:46Z', 0.75, 'q3'],
    ['1989-05-05T11:46Z', 0.00, 'new'],
    ['1989-05-12T14:19Z', 0.25, 'q1'],
    ['1989-05-20T18:16Z', 0.50, 'full'],
    ['1989-05-28T04:01Z', 0.75, 'q3'],
    ['1989-06-03T19:53Z', 0.00, 'new'],
    ['1989-06-11T06:59Z', 0.25, 'q1'],
    ['1989-06-19T06:57Z', 0.50, 'full'],
    ['1989-06-26T09:09Z', 0.75, 'q3'],
    ['1989-07-03T04:59Z', 0.00, 'new'],
    ['1989-07-11T00:19Z', 0.25, 'q1'],
    ['1989-07-18T17:42Z', 0.50, 'full'],
    ['1989-07-25T13:31Z', 0.75, 'q3'],
    ['1989-08-01T16:06Z', 0.00, 'new'],
    ['1989-08-09T17:28Z', 0.25, 'q1'],
    ['1989-08-17T03:07Z', 0.50, 'full'],
    ['1989-08-23T18:40Z', 0.75, 'q3'],
    ['1989-08-31T05:44Z', 0.00, 'new'],
    ['1989-09-08T09:49Z', 0.25, 'q1'],
    ['1989-09-15T11:51Z', 0.50, 'full'],
    ['1989-09-22T02:10Z', 0.75, 'q3'],
    ['1989-09-29T21:47Z', 0.00, 'new']
  ]

  describe('#phase()', function () {
    it('should return expected values for-02-17th data', function () {
      const phase = lune.phase(new Date('2014-02-17T00:00-0500'))

      assert.closeTo(phase.phase, 0.568, 0.001)
      assert.closeTo(phase.illuminated, 0.955, 0.001)
      assert.closeTo(phase.age, 16.779, 0.030)
      assert.closeTo(phase.distance, 396084.5, 384.4)
      assert.closeTo(phase.angular_diameter, 0.5028, 0.0005)
      assert.closeTo(phase.sun_distance, 147822500, 149600)
      assert.closeTo(phase.sun_angular_diameter, 0.5395, 0.0005)
    })

    // http://bazaar.launchpad.net/~keturn/py-moon-phase/trunk/view/head:/moontest.py
    it('should be accurate to astronomical observations', function () {
      let error = 0
      for (let obs of observations) {
        let e = Math.abs(lune.phase(new Date(obs[0])).phase - obs[1])
        if (e > 0.5) {
          // phase is circular
          e = 1 - e
        }

        error += e
      }

      // tolerate an average error of up to a tenth of a percent
      assert.isAtMost(error / observations.length, 0.001)
    })
  })

  describe('#phase_hunt', function () {
    it('should handle timezones correctly', function () {
      // 1415292777000 incorrect EST time
      // 1415312577000 correct UTC time
      // date conversion is now accurate to the millisecond, but these tests
      // were written when they were only accurate to the second
      assert.closeTo(
        lune.phase_hunt(new Date('2014-11-01T06:26-0400')).full_date.getTime(),
        1415312577000,
        500
      )
    })
  })

  describe('#phase_range', function () {
    /* http://aa.usno.navy.mil/data/docs/JulianDate.php */
    it('should return all moon phases within a time range', function () {
      const phases = lune.phase_range(
        new Date('1989-01-01T00:00Z'),
        new Date('1989-10-01T00:00Z')
      )

      let error = 0

      assert.strictEqual(phases.length, observations.length)

      for (let i = 0; i < phases.length; i++) {
        const phase = phases[i]
        const obs = observations[i]

        assert.strictEqual(phase.phase, obs[2])

        error += Math.abs(phase.date.getTime() - new Date(obs[0]).getTime())
      }

      // tolerate an average error of up to five minutes
      assert.isAtMost(error / observations.length, 300000)
    })
  })
})

describe('julian', function () {
  describe('#fromDate', function () {
    /* http://aa.usno.navy.mil/data/docs/JulianDate.php */
    it('should convert 2000-01-01T00:00Z to 2451544.5', function () {
      assert.closeTo(
        julian.fromDate(new Date('2000-01-01T00:00Z')),
        2451544.5,
        0.5 / 86400
      )
    })
  })

  describe('#toDate', function () {
    /* http://aa.usno.navy.mil/data/docs/JulianDate.php */
    it('should convert 2457464.179862 to 2016-03-16T16:19Z', function () {
      assert.closeTo(
        julian.toDate(2457464.179862).getTime(),
        (new Date('2016-03-16T16:19Z')).getTime(),
        500
      )
    })
  })
})
<|endoftext|>


<commit_before>'use strict';

const resizeImage = require('../index');
const assert = require('assert');

const ASSERT_SIZE = 200;

describe('.resize', function() {

  it('Should throw Error with empty `img`', function() {
    assert.throws(function() {
      resizeImage.resize()
    });
  });

  it('Resize any image to (' + ASSERT_SIZE + ',' + ASSERT_SIZE + ')', function(done) {
    const img = new Image();
    img.onload = function() {
      const base64 = resizeImage.resize(img, ASSERT_SIZE, ASSERT_SIZE, resizeImage.PNG);
      const resizedImg = new Image();
      resizedImg.onload = function() {
        const minWH = Math.min(resizedImg.width, resizedImg.height);
        assert.equal(minWH, ASSERT_SIZE);
        done();
      };
      resizedImg.src = base64;
    };
    // use webpack [url-loader](https://github.com/webpack/url-loader) peer with file-loader
    // use `url-loader!file` here, NO need to specialize in webpack.conf.js
    img.src = require('url-loader!../example/google.png');
  });

  it('Resize any image to width: ' + ASSERT_SIZE, function(done) {
    const img = new Image();
    img.onload = function() {
      const base64 = resizeImage.resize(img, ASSERT_SIZE);
      const resizedImg = new Image();
      resizedImg.onload = function() {
        assert.equal(resizedImg.width, ASSERT_SIZE);
        done();
      };
      resizedImg.src = base64;
    };
    img.src = require('url-loader!../example/google.png');
  });

  it('Resize any image to height: ' + ASSERT_SIZE, function(done) {
    const img = new Image();
    img.onload = function() {
      const base64 = resizeImage.resize(img, 0, ASSERT_SIZE);
      const resizedImg = new Image();
      resizedImg.onload = function() {
        assert.equal(resizedImg.height, ASSERT_SIZE);
        done();
      };
      resizedImg.src = base64;
    };
    img.src = require('url-loader!../example/google.png');
  });

  it('Should fill with #fff for JPEG', function(done) {
    const img = new Image();
    img.onload = function() {
      const base64 = resizeImage.resize(img, ASSERT_SIZE, ASSERT_SIZE, resizeImage.JPEG);
      const resizedImg = new Image();
      resizedImg.onload = function() {
        var canvas = document.createElement('canvas');
        canvas.width = resizedImg.width;
        canvas.height = resizedImg.height;
        var ctx = canvas.getContext('2d');
        ctx.drawImage(resizedImg, 0, 0, resizedImg.width, resizedImg.height);
        const color = ctx.getImageData(1, 1, 1, 1).data;
        assert.equal(color[0], 255);
        assert.equal(color[1], 255);
        assert.equal(color[2], 255);
        assert.equal(color[3], 255);
        done();
      };
      resizedImg.src = base64;
    };
    img.src = require('url-loader!../example/google.png');
  });

});
<commit_msg>test: improve coverage<commit_after>'use strict';

const resizeImage = require('../index');
const assert = require('assert');

const ASSERT_SIZE = 200;

describe('.resize', function() {

  it('Should throw Error with empty `img`', function() {
    assert.throws(function() {
      resizeImage.resize()
    });
  });

  it('Resize any image to (' + ASSERT_SIZE + ',' + ASSERT_SIZE + ')', function(done) {
    const img = new Image();
    img.onload = function() {
      const base64 = resizeImage.resize(img, ASSERT_SIZE, ASSERT_SIZE, resizeImage.PNG);
      const resizedImg = new Image();
      resizedImg.onload = function() {
        const minWH = Math.min(resizedImg.width, resizedImg.height);
        assert.equal(minWH, ASSERT_SIZE);
        done();
      };
      resizedImg.src = base64;
    };
    // use webpack [url-loader](https://github.com/webpack/url-loader) peer with file-loader
    // use `url-loader!file` here, NO need to specialize in webpack.conf.js
    img.src = require('url-loader!../example/google.png');
  });

  it('Resize any image to width: ' + ASSERT_SIZE, function(done) {
    const img = new Image();
    img.onload = function() {
      const base64 = resizeImage.resize(img, ASSERT_SIZE);
      const resizedImg = new Image();
      resizedImg.onload = function() {
        assert.equal(resizedImg.width, ASSERT_SIZE);
        done();
      };
      resizedImg.src = base64;
    };
    img.src = require('url-loader!../example/google.png');
  });

  it('Resize any image to height: ' + ASSERT_SIZE, function(done) {
    const img = new Image();
    img.onload = function() {
      const base64 = resizeImage.resize(img, 0, ASSERT_SIZE);
      const resizedImg = new Image();
      resizedImg.onload = function() {
        assert.equal(resizedImg.height, ASSERT_SIZE);
        done();
      };
      resizedImg.src = base64;
    };
    img.src = require('url-loader!../example/google.png');
  });

  it('Should fill with #fff for JPEG', function(done) {
    const img = new Image();
    img.onload = function() {
      const base64 = resizeImage.resize(img, 0, 0, resizeImage.JPEG);
      const resizedImg = new Image();
      resizedImg.onload = function() {
        const { width, height } = resizedImg;
        // 应该和原图片大小相同
        assert.equal(width, img.width);
        assert.equal(height, img.height);
        // 左上角的点应该是白色
        var canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        var ctx = canvas.getContext('2d');
        ctx.drawImage(resizedImg, 0, 0, width, height);
        const color = ctx.getImageData(1, 1, 1, 1).data;
        assert.equal(color[0], 255);
        assert.equal(color[1], 255);
        assert.equal(color[2], 255);
        assert.equal(color[3], 255);
        done();
      };
      resizedImg.src = base64;
    };
    img.src = require('url-loader!../example/google.png');
  });

});
<|endoftext|>


<commit_before>'use strict';

var url = require('url');

var hopsConfig = require('hops-config');

function defaultCallback(error) {
  if (error) {
    console.error(error.stack.toString());
  } else {
    console.log(
      'hops: Server listening at ' +
        url.format({
          protocol: hopsConfig.https ? 'https' : 'http',
          hostname:
            hopsConfig.host === '0.0.0.0' ? 'localhost' : hopsConfig.host,
          port: hopsConfig.port,
        })
    );
  }
}

exports.run = function run(app, callback) {
  var server = app.listen(hopsConfig.port, hopsConfig.host, function(error) {
    (callback || defaultCallback)(error, server);
  });
};

exports.rewritePath = function rewritePath(req, res, next) {
  var location = hopsConfig.locations.find(function(location) {
    return (
      location !== hopsConfig.basePath + '/' && req.url.indexOf(location) === 0
    );
  });
  if (location) {
    req.url = location.replace(/([^\\/])$/, '$1/');
  }
  next();
};

exports.registerMiddleware = function registerMiddleware(app, middleware) {
  if (hopsConfig.locations.length) {
    hopsConfig.locations.forEach(function(location) {
      app.get(location === '/' ? location : location + '*', middleware);
    });
  } else {
    app.all('*', middleware);
  }
};

exports.bootstrap = hopsConfig.bootstrapServer || function() {};

exports.teardown = hopsConfig.teardownServer || function() {};
<commit_msg>fix(server): only rewrite path if run in static mode<commit_after>'use strict';

var url = require('url');

var hopsConfig = require('hops-config');

function defaultCallback(error) {
  if (error) {
    console.error(error.stack.toString());
  } else {
    console.log(
      'hops: Server listening at ' +
        url.format({
          protocol: hopsConfig.https ? 'https' : 'http',
          hostname:
            hopsConfig.host === '0.0.0.0' ? 'localhost' : hopsConfig.host,
          port: hopsConfig.port,
        })
    );
  }
}

exports.run = function run(app, callback) {
  var server = app.listen(hopsConfig.port, hopsConfig.host, function(error) {
    (callback || defaultCallback)(error, server);
  });
};

exports.rewritePath = function rewritePath(req, res, next) {
  if (
    process.env.HOPS_MODE === 'static' &&
    Array.isArray(hopsConfig.locations)
  ) {
    var location = hopsConfig.locations.find(function(location) {
      return (
        location !== hopsConfig.basePath + '/' &&
        req.url.indexOf(location) === 0
      );
    });
    if (location) {
      req.url = location.replace(/([^\\/])$/, '$1/');
    }
  }
  next();
};

exports.registerMiddleware = function registerMiddleware(app, middleware) {
  if (
    process.env.HOPS_MODE === 'static' &&
    Array.isArray(hopsConfig.locations)
  ) {
    hopsConfig.locations.forEach(function(location) {
      app.get(location === '/' ? location : location + '*', middleware);
    });
  } else {
    app.all('*', middleware);
  }
};

exports.bootstrap = hopsConfig.bootstrapServer || function() {};

exports.teardown = hopsConfig.teardownServer || function() {};
<|endoftext|>


<commit_before>var expect = require('chai').expect,
  OhMyJSONAPI = require('../index');

describe('OhMyJSONAPI', function() {

  it("should return a new instance when called with a valid adapter", function(done) {
    var jsonApi = new OhMyJSONAPI('bookshelf');
    expect(jsonApi).to.be.a('object');
    done();
  });

  it("should throw an error when called with an invalid adapter", function(done) {
    expect(function() {
      return new OhMyJSONAPI('fakeAdapter');
    }).to.throw(Error);
    done();
  });

  it("should throw an error when called without", function(done) {
    expect(function() {
      return new OhMyJSONAPI();
    }).to.throw(Error);
    done();
  });

});

describe("OhMyJSONAPI#toJSONAPI", function() {

  it("should return a valid JSON API payload", function(done) {
    var payload = new OhMyJSONAPI('bookshelf').toJSONAPI({}, 'fakeType');
    expect(payload).to.be.a('object');
    done();
  });

  // it("should throw an error when a `type` isn't defined", function(done) {
  //   expect(function() {
  //     return new OhMyJSONAPI('bookshelf').toJSONAPI();
  //   }).to.throw(Error);
  //   done();
  // });

  it("should throw an error when a `data` isn't defined", function(done) {
    expect(function() {
      return new OhMyJSONAPI('bookshelf').toJSONAPI();
    }).to.throw(Error);
    done();
  });

});
<commit_msg>updated tests<commit_after>var expect = require('chai').expect,
  OhMyJSONAPI = require('../index');

describe('OhMyJSONAPI', function() {

  it("should return a new instance when called with a valid adapter", function(done) {
    var jsonApi = new OhMyJSONAPI('bookshelf');
    expect(jsonApi).to.be.a('object');
    done();
  });

  it("should throw an error when called with an invalid adapter", function(done) {
    expect(function() {
      return new OhMyJSONAPI('fakeAdapter');
    }).to.throw(Error);
    done();
  });
});

describe("OhMyJSONAPI#toJSONAPI", function() {

  it("should throw an error when a `data` isn't defined", function(done) {
    expect(function() {
      return new OhMyJSONAPI('bookshelf').toJSONAPI();
    }).to.throw(Error);
    done();
  });

  it("should throw an error when a `type` isn't defined", function(done) {
    expect(function() {
      return new OhMyJSONAPI('bookshelf').toJSONAPI({}, 'test');
    }).to.throw(Error);
    done();
  });
});
<|endoftext|>


<commit_before>import { action, observe, modelize } from 'shared/model'
import { invoke } from 'lodash';

class Actions {
    constructor(ux) {
        modelize(this);
        this.ux = ux;
        observe(ux.steps, 'currentStepId', ({ newValue: stepId, oldValue: prevStepId }) => {
            invoke(this, stepId, { prevStepId });
        }, true); // true == invoke immediatly
    }

    async needsBook() {
        return this.ux.referenceBook.ensureLoaded();
    }

    async needsExercises() {
        return this.ux.exercises.ensureExercisesLoaded({
            course: this.ux.course,
            ecosystem_id: this.ux.plan.ecosystem_id,
            exercise_ids: this.ux.plan.exerciseIds,
            page_ids: this.ux.selectedPageIds,
        });
    }

    @action chapters() {
        this.needsBook();
    }

    @action reorder() {
        this.needsBook();
    }

    @action async points() {
        this.needsBook();
        this.needsExercises();
    }

    @action async questions() {
        this.needsBook();
        // on questions we always load by not using "ensureLoaded"
        await this.ux.exercises.fetch({
            ecosystem_id: this.ux.plan.ecosystem_id,
            course: this.ux.course,
            book: this.ux.referenceBook,
            page_ids: this.ux.selectedPageIds,
        });
        this.ux.selectedPageIds.forEach(pgId => {
            this.ux.exercises.forPageId(pgId).forEach(
                e => e.isSelected = this.ux.plan.includesExercise(e)
            );
        });
    }

}

export { Actions };
<commit_msg>only fetch homework_core for homework assignments<commit_after>import { action, observe, modelize } from 'shared/model'
import { invoke } from 'lodash';

class Actions {
    constructor(ux) {
        modelize(this);
        this.ux = ux;
        observe(ux.steps, 'currentStepId', ({ newValue: stepId, oldValue: prevStepId }) => {
            invoke(this, stepId, { prevStepId });
        }, true); // true == invoke immediatly
    }

    async needsBook() {
        return this.ux.referenceBook.ensureLoaded();
    }

    async needsExercises() {
        return this.ux.exercises.ensureExercisesLoaded({
            course: this.ux.course,
            ecosystem_id: this.ux.plan.ecosystem_id,
            exercise_ids: this.ux.plan.exerciseIds,
            page_ids: this.ux.selectedPageIds,
        });
    }

    @action chapters() {
        this.needsBook();
    }

    @action reorder() {
        this.needsBook();
    }

    @action async points() {
        this.needsBook();
        this.needsExercises();
    }

    @action async questions() {
        this.needsBook();
        // on questions we always load by not using "ensureLoaded"
        await this.ux.exercises.fetch({
            ecosystem_id: this.ux.plan.ecosystem_id,
            course: this.ux.course,
            book: this.ux.referenceBook,
            page_ids: this.ux.selectedPageIds,
            limit: this.ux.plan.isHomework ? 'homework_core' : false,
        });
        this.ux.selectedPageIds.forEach(pgId => {
            this.ux.exercises.forPageId(pgId).forEach(
                e => e.isSelected = this.ux.plan.includesExercise(e)
            );
        });
    }

}

export { Actions };
<|endoftext|>