<commit_before>'use strict';

const comment = require('../utils/comment')
  , compiler = require('./compile')

  , BOILERPLATE = 'if (window.$m == null) window.$m = {};\nif (window.require == null) window.require = function (id) { return $m[id].exports == null ? $m[id]() : $m[id]; }'
  , HEADER = 'generated by Buddy';

/**
 * Concatenate all 'dependencies' content
 * @param {String} type
 * @param {String} content
 * @param {String} id
 * @param {Array} dependencies
 * @param {Object} options
 * @returns {String}
 */
module.exports = function (type, content, id, dependencies, options) {
  switch (type) {
    case 'js':
      return concatJS(content, id, dependencies, options);
    case 'css':
      return concatCSS(content, options);
    default:
      return content;
  }
};

/**
 * Get concatenated JS 'content'
 * @param {String} content
 * @param {String} id
 * @param {Array} dependencies
 * @param {Object} options
 * @returns {String}
 */
function concatJS (content, id, dependencies, options) {
  const contents = [];

  // Add header comment
  if (options.includeHeader) contents.push(comment(HEADER, 'js'));

  // Add require boilerplate
  contents.push(BOILERPLATE);

  // Add helpers
  if (options.includeHelpers) {
    const helpers = compiler.getHelpers('js');

    if (helpers) contents.push(helpers);
  }

  if (!options.bootstrap) contents.push(`$m['${id}']=function () {`);

  // Add dependencies
  dependencies.filter((dependency) => {
    return dependency.type != 'json';
  }).forEach((dependency) => {
    contents.push(dependency.content);
  });

  contents.push(content);

  if (!options.bootstrap) contents.push(`return $m['${id}'];\n}`);

  return contents.join('\n');
}

/**
 * Get concatenated CSS 'content'
 * @param {String} content
 * @param {Object} options
 * @returns {String}
 */
function concatCSS (content, options) {
  // Add comment
  if (options.includeHeader) content = `${comment(HEADER, 'css')}\n${content}`;

  return content;
}<commit_msg>add function name<commit_after>'use strict';

const comment = require('../utils/comment')
  , compiler = require('./compile')

  , BOILERPLATE = 'if (window.$m == null) window.$m = {};\nif (window.require == null) window.require = function require (id) { return $m[id].exports == null ? $m[id]() : $m[id]; }'
  , HEADER = 'generated by Buddy';

/**
 * Concatenate all 'dependencies' content
 * @param {String} type
 * @param {String} content
 * @param {String} id
 * @param {Array} dependencies
 * @param {Object} options
 * @returns {String}
 */
module.exports = function (type, content, id, dependencies, options) {
  switch (type) {
    case 'js':
      return concatJS(content, id, dependencies, options);
    case 'css':
      return concatCSS(content, options);
    default:
      return content;
  }
};

/**
 * Get concatenated JS 'content'
 * @param {String} content
 * @param {String} id
 * @param {Array} dependencies
 * @param {Object} options
 * @returns {String}
 */
function concatJS (content, id, dependencies, options) {
  const contents = [];

  // Add header comment
  if (options.includeHeader) contents.push(comment(HEADER, 'js'));

  // Add require boilerplate
  contents.push(BOILERPLATE);

  // Add helpers
  if (options.includeHelpers) {
    const helpers = compiler.getHelpers('js');

    if (helpers) contents.push(helpers);
  }

  if (!options.bootstrap) contents.push(`$m['${id}']=function () {`);

  // Add dependencies
  dependencies.filter((dependency) => {
    return dependency.type != 'json';
  }).forEach((dependency) => {
    contents.push(dependency.content);
  });

  contents.push(content);

  if (!options.bootstrap) contents.push(`return $m['${id}'];\n}`);

  return contents.join('\n');
}

/**
 * Get concatenated CSS 'content'
 * @param {String} content
 * @param {Object} options
 * @returns {String}
 */
function concatCSS (content, options) {
  // Add comment
  if (options.includeHeader) content = `${comment(HEADER, 'css')}\n${content}`;

  return content;
}<|endoftext|>


<commit_before>const Nightmare = require('nightmare');
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const test_url = "file:///"+path.resolve(__dirname,"../examples/vanilla.html");
const hash_url = test_url + "#group=nogroup&photo=rhinoceros";

const nightmare = Nightmare({
    webPreferences  : {
    partition : 'nopersist',
    preload: path.resolve(__dirname,'./preload.js')
  },
  show: true
});

describe('test',() => {
  it('caption', (done) => {
    nightmare.goto(test_url)
      .click('[data-caption="lion"]')
      .click('.smartphoto-arrow-right a')
      .wait(1000)
      .evaluate(() => {
        return document.querySelector('.smartphoto-caption').innerText;
      })
      .then((result) => {
        assert.equal(result,'camel');
        done();
      })
      .catch((error) => {
        done(error);
      });
  });

  it('hash', (done) => {
    nightmare.goto(hash_url)
      .wait(300)
      .evaluate(() => {
          return document.querySelector('.smartphoto-caption').innerText;
      })
      .then(result => {
        assert.equal(result,'rhinoceros');
        done();
      })
      .catch(error => {
        done(error);
      });
  });
});<commit_msg>fix test.js<commit_after>const Nightmare = require('nightmare');
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const test_url = "file:///"+path.resolve(__dirname,"../examples/vanilla.html");
const hash_url = test_url + "#group=nogroup&photo=rhinoceros";

const nightmare = Nightmare({
    webPreferences  : {
    partition : 'nopersist',
    preload: path.resolve(__dirname,'./preload.js')
  },
  show: true
});

describe('test',() => {
  it('caption', (done) => {
    nightmare.goto(test_url)
      .click('[data-caption="lion"]')
      .click('.smartphoto-arrow-right a')
      .wait(1000)
      .evaluate(() => {
        return document.querySelector('.smartphoto-caption').innerText;
      })
      .then((result) => {
        assert.equal(result,'camel');
        done();
      })
      .catch((error) => {
        done(error);
      });
  });

  it('hash', (done) => {
    nightmare.goto(hash_url)
      .wait(1000)
      .evaluate(() => {
          return document.querySelector('.smartphoto-caption').innerText;
      })
      .then(result => {
        assert.equal(result,'rhinoceros');
        done();
      })
      .catch(error => {
        done(error);
      });
  });
});<|endoftext|>


<commit_before>var logger = Npm.require('debug')('apm:hijack:session');

Meteor.methods({
  '__apm-hijackSession': function() {
    var sessions = Meteor.server.sessions;
    for(var id in sessions) {
      var session = sessions[id];

      var sessionProto = session.constructor.prototype;
      //if called __hijackSession even after the hijack is completed
      if(sessionProto.__apkOk) {
        return;
      }
      wrapSession(sessionProto);

      //pick the subscriptionProto and wrapIt
      for(var sessionId in Meteor.default_server.sessions) {
        var session = Meteor.default_server.sessions[sessionId];
        var subId = _.keys(session._namedSubs)[0];
        if(subId) {
          var subscriptionProto = session._namedSubs[subId].constructor.prototype;
          wrapSubscription(subscriptionProto);
        }
      }

      logger('hijacking completed');
      sessionProto.__apkOk = true;
    }
  }
});

Meteor.publish('__amp-hijackSubscription', function() {
  this.added('___apm_fake_coll1', 'one', {aa: 10});
  this.ready();
});

Apm._startInstrumenting = function(callback) {
  Meteor.startup(function() {
    logger('calling __apm-hijackSession');
    var conn = DDP.connect('http://localhost:' + process.env.PORT);
    conn.subscribe('__amp-hijackSubscription', {
      onReady: callHijack,
      onError: displayError
    });

    function callHijack() {
      conn.call('__apm-hijackSession', function() {
        if(callback) callback();
        conn.disconnect();
      });
    }

    function displayError (err) {
      console.error('APM: something wrong hijacking the subscription: ', err.message);
    }
  });
};<commit_msg>fixed Meteor.startup issue<commit_after>var logger = Npm.require('debug')('apm:hijack:session');

Meteor.methods({
  '__apm-hijackSession': function() {
    var sessions = Meteor.server.sessions;
    for(var id in sessions) {
      var session = sessions[id];

      var sessionProto = session.constructor.prototype;
      //if called __hijackSession even after the hijack is completed
      if(sessionProto.__apkOk) {
        return;
      }
      wrapSession(sessionProto);

      //pick the subscriptionProto and wrapIt
      for(var sessionId in Meteor.default_server.sessions) {
        var session = Meteor.default_server.sessions[sessionId];
        var subId = _.keys(session._namedSubs)[0];
        if(subId) {
          var subscriptionProto = session._namedSubs[subId].constructor.prototype;
          wrapSubscription(subscriptionProto);
        }
      }

      logger('hijacking completed');
      sessionProto.__apkOk = true;
    }
  }
});

Meteor.publish('__amp-hijackSubscription', function() {
  this.added('___apm_fake_coll1', 'one', {aa: 10});
  this.ready();
});

Apm._startInstrumenting = function(callback) {
  logger('calling __apm-hijackSession');
  var conn = DDP.connect('http://localhost:' + process.env.PORT);
  conn.subscribe('__amp-hijackSubscription', {
    onReady: callHijack,
    onError: displayError
  });

  function callHijack() {
    conn.call('__apm-hijackSession', function() {
      if(callback) callback();
      conn.disconnect();
    });
  }

  function displayError (err) {
    console.error('APM: something wrong hijacking the subscription: ', err.message);
  }
};<|endoftext|>


<commit_before>var w = Math.max(document.documentElement.clientWidth * 0.8, window.innerWidth * 0.8, 360),
    h = Math.max(document.documentElement.clientHeight * 0.9, window.innerHeight * 0.9, 400),
    x = d3.scale.linear().range([0, w]),
    y = d3.scale.linear().range([0, h]),
    color = d3.scale.category20c(),
    root,
    node;

function wrap(text, width) {
    text.each(function() {
        var text = d3.select(this),
            words = text.text().split(/\s+/).reverse(),
            word,
            line = [],
            lineNumber = 0,
            lineHeight = 1.1, // ems
            y = text.attr("y"),
            x = text.attr("x"),
            dy = parseFloat(text.attr("dy")),
            tspan = text.text(null).append("tspan").attr("x", x).attr("y", y).attr("dy", dy + "em");
        while (word = words.pop()) {
            line.push(word);
            tspan.text(line.join(" "));
            if (tspan.node().getComputedTextLength() > width) {
                line.pop();
                tspan.text(line.join(" "));
                line = [word];
                tspan = text.append("tspan").attr("x", x).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
            }
        }
    });
}

var treemap = d3.layout.treemap()
        .round(false)
        .size([w, h])
        .sticky(true)
        .value(function(d) { return d.change*-1; });

var svg = d3.select("#d3-container").append("div")
        .attr("class", "chart")
        .style("width", w + "px")
        .style("height", h + "px")
        .append("svg:svg")
        .attr("width", w)
        .attr("height", h)
        .append("svg:g")
        .attr("transform", "translate(.5,.5)");

d3.json("data/asl.json", function(data) {
    node = root = data;

    var nodes = treemap.nodes(root)
            .filter(function(d) { return !d.children; });

    var cell = svg.selectAll("g")
            .data(nodes)
            .enter().append("svg:g")
            .attr("class", "cell")
            .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
            .on("click", function(d) { return zoom(node == d.parent ? root : d.parent); });

    cell.append("svg:rect")
        .attr("width", function(d) { return d.dx; })
        .attr("height", function(d) { return d.dy; })
        .style("fill", function(d) { return color(d.parent.name); });

    cell.append("svg:text")
        .attr('class', 'name')
        .attr("x", function(d) { return d.dx / 2; })
        .attr("y", function(d) { return d.dy / 2; })
        .attr("dy", ".35em")
        .attr("text-anchor", "middle")
        .text(function(d) { return d.name; })
        .style('font-size', 10);

    cell.selectAll('text').call(wrap, Math.min(130, w * 0.3));

    cell.selectAll('text')
        .style("opacity", function(d) {
            d.w = this.getBBox().width;
            d.h = this.getBBox().height;
            if ( d.dx + 10 > d.w && d.dy > d.h ) {
                return 1;
            } else {
                return 0;
            }
        });

    cell.append("svg:text")
        .attr('class', 'number')
        .attr("x", function(d) {
            return d.dx / 2;
        })
        .attr("y", function(d) {
            var name_text = d3.select(this.parentNode).select('text');
            return Number(name_text.attr('y')) + name_text[0][0].getBBox().height;
        })
        .attr("dy", ".35em")
        .attr("text-anchor", "middle")
        .text(function(d) { return "(" + d.change + ")"; })
        .style('font-size', 10)
        .style("opacity", function(d) {
            if ( d.dx > d.w && d.dy > d.h) {
                return 1;
            } else {
                return 0;
            }
        });

    d3.select(window).on("click", function() { zoom(root); });

    d3.select("select").on("change", function() {
        treemap.value(this.value == "size" ? size : count).nodes(root);
        zoom(node);
    });
});

function size(d) {
    return d.change*-1;
}

function count(d) {
    return 1;
}

function zoom(d) {
    var kx = w / d.dx, ky = h / d.dy;
    x.domain([d.x, d.x + d.dx]);
    y.domain([d.y, d.y + d.dy]);

    // Move cell groups to new x, y coordinates
    var t = svg.selectAll("g.cell").transition()
            .duration(d3.event.altKey ? 7500 : 750)
            .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; });

    // Modify width and height so that full svg box is used
    t.select("rect")
        .attr("width", function(d) { return kx * d.dx ; })
        .attr("height", function(d) { return ky * d.dy ; });

    // Move text within this new rectangle
    // Move both the text containers and the tspans
    t.selectAll("text.name tspan")
        .attr("x", function(d) { return kx * d.dx / 2; })
        .attr("y", function(d) {
            return ky * d.dy / 2;
        });
        // .style("opacity", function(d) {
        //     d.w = this.getBoundingClientRect().width;
        //     d.h = this.getBoundingClientRect().height;
        //     if ( kx * d.dx > d.w && ky * d.dy > d.h ) {
        //         return 1;
        //     } else {
        //         return 0;
        //     }
        //     // return kx * d.dx + 10 > d.w ? 1 : 0;
        // });

    t.selectAll("text.name")
        .attr("x", function(d) { return kx * d.dx / 2; })
        .attr("y", function(d) {
            d.new_name_y = ky * d.dy / 2;
            d.bb_y = this.getBBox().height;
            return ky * d.dy / 2;
        })
        .style("opacity", function(d) {
            if ( kx * d.dx > d.w && ky * d.dy > d.h) {
                return 1;
            } else {
                return 0;
            }

            return kx * d.dx > d.w ? 1 : 0;
        });

    t.select("text.number")
        .attr("x", function(d) { return kx * d.dx / 2; })
        .attr("y", function(d) {
            return d.new_name_y + d.bb_y;
            var name_text = d3.select(this.parentNode).select('text.name');
            return Number(name_text.attr('y')) + name_text[0][0].getBBox().height;
            // return ky * d.dy / 2 + 15;
        })
        .style("opacity", function(d) {
            if ( kx * d.dx > d.w && ky * d.dy > d.h) {
                return 1;
            } else {
                return 0;
            }
            // return kx * d.dx > d.w ? 1 : 0;
        });

    node = d;
    d3.event.stopPropagation();
}

<commit_msg>Add grid spacing back<commit_after>var w = Math.max(document.documentElement.clientWidth * 0.8, window.innerWidth * 0.8, 360),
    h = Math.max(document.documentElement.clientHeight * 0.9, window.innerHeight * 0.9, 400),
    x = d3.scale.linear().range([0, w]),
    y = d3.scale.linear().range([0, h]),
    color = d3.scale.category20c(),
    root,
    node;

function wrap(text, width) {
    text.each(function() {
        var text = d3.select(this),
            words = text.text().split(/\s+/).reverse(),
            word,
            line = [],
            lineNumber = 0,
            lineHeight = 1.1, // ems
            y = text.attr("y"),
            x = text.attr("x"),
            dy = parseFloat(text.attr("dy")),
            tspan = text.text(null).append("tspan").attr("x", x).attr("y", y).attr("dy", dy + "em");
        while (word = words.pop()) {
            line.push(word);
            tspan.text(line.join(" "));
            if (tspan.node().getComputedTextLength() > width) {
                line.pop();
                tspan.text(line.join(" "));
                line = [word];
                tspan = text.append("tspan").attr("x", x).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
            }
        }
    });
}

var treemap = d3.layout.treemap()
        .round(false)
        .size([w, h])
        .sticky(true)
        .value(function(d) { return d.change*-1; });

var svg = d3.select("#d3-container").append("div")
        .attr("class", "chart")
        .style("width", w + "px")
        .style("height", h + "px")
        .append("svg:svg")
        .attr("width", w)
        .attr("height", h)
        .append("svg:g")
        .attr("transform", "translate(.5,.5)");

d3.json("data/asl.json", function(data) {
    node = root = data;

    var nodes = treemap.nodes(root)
            .filter(function(d) { return !d.children; });

    var cell = svg.selectAll("g")
            .data(nodes)
            .enter().append("svg:g")
            .attr("class", "cell")
            .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
            .on("click", function(d) { return zoom(node == d.parent ? root : d.parent); });

    cell.append("svg:rect")
        .attr("width", function(d) {
            return d.dx <= 1 ? d.dx: d.dx - 1;
        })
        .attr("height", function(d) { return d.dy <= 1 ? d.dy: d.dy - 1; })
        .style("fill", function(d) { return color(d.parent.name); });

    cell.append("svg:text")
        .attr('class', 'name')
        .attr("x", function(d) { return d.dx / 2; })
        .attr("y", function(d) { return d.dy / 2; })
        .attr("dy", ".35em")
        .attr("text-anchor", "middle")
        .text(function(d) { return d.name; })
        .style('font-size', 10);

    cell.selectAll('text').call(wrap, Math.min(130, w * 0.3));

    cell.selectAll('text')
        .style("opacity", function(d) {
            d.w = this.getBBox().width;
            d.h = this.getBBox().height;
            if ( d.dx + 10 > d.w && d.dy > d.h ) {
                return 1;
            } else {
                return 0;
            }
        });

    cell.append("svg:text")
        .attr('class', 'number')
        .attr("x", function(d) {
            return d.dx / 2;
        })
        .attr("y", function(d) {
            var name_text = d3.select(this.parentNode).select('text');
            return Number(name_text.attr('y')) + name_text[0][0].getBBox().height;
        })
        .attr("dy", ".35em")
        .attr("text-anchor", "middle")
        .text(function(d) { return "(" + d.change + ")"; })
        .style('font-size', 10)
        .style("opacity", function(d) {
            if ( d.dx > d.w && d.dy > d.h) {
                return 1;
            } else {
                return 0;
            }
        });

    d3.select(window).on("click", function() { zoom(root); });

    d3.select("select").on("change", function() {
        treemap.value(this.value == "size" ? size : count).nodes(root);
        zoom(node);
    });
});

function size(d) {
    return d.change*-1;
}

function count(d) {
    return 1;
}

function zoom(d) {
    var kx = w / d.dx, ky = h / d.dy;
    x.domain([d.x, d.x + d.dx]);
    y.domain([d.y, d.y + d.dy]);

    // Move cell groups to new x, y coordinates
    var t = svg.selectAll("g.cell").transition()
            .duration(d3.event.altKey ? 7500 : 750)
            .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; });

    // Modify width and height so that full svg box is used
    t.select("rect")
        .attr("width", function(d) { return kx * d.dx <= 1 ? kx * d.dx: kx * d.dx - 1; })
        .attr("height", function(d) { return ky * d.dy <= 1 ? ky * d.dy: ky * d.dy - 1; });

    // Move text within this new rectangle
    // Move both the text containers and the tspans
    t.selectAll("text.name tspan")
        .attr("x", function(d) { return kx * d.dx / 2; })
        .attr("y", function(d) {
            return ky * d.dy / 2;
        });
        // .style("opacity", function(d) {
        //     d.w = this.getBoundingClientRect().width;
        //     d.h = this.getBoundingClientRect().height;
        //     if ( kx * d.dx > d.w && ky * d.dy > d.h ) {
        //         return 1;
        //     } else {
        //         return 0;
        //     }
        //     // return kx * d.dx + 10 > d.w ? 1 : 0;
        // });

    t.selectAll("text.name")
        .attr("x", function(d) { return kx * d.dx / 2; })
        .attr("y", function(d) {
            d.new_name_y = ky * d.dy / 2;
            d.bb_y = this.getBBox().height;
            return ky * d.dy / 2;
        })
        .style("opacity", function(d) {
            if ( kx * d.dx > d.w && ky * d.dy > d.h) {
                return 1;
            } else {
                return 0;
            }

            return kx * d.dx > d.w ? 1 : 0;
        });

    t.select("text.number")
        .attr("x", function(d) { return kx * d.dx / 2; })
        .attr("y", function(d) {
            return d.new_name_y + d.bb_y;
            var name_text = d3.select(this.parentNode).select('text.name');
            return Number(name_text.attr('y')) + name_text[0][0].getBBox().height;
            // return ky * d.dy / 2 + 15;
        })
        .style("opacity", function(d) {
            if ( kx * d.dx > d.w && ky * d.dy > d.h) {
                return 1;
            } else {
                return 0;
            }
            // return kx * d.dx > d.w ? 1 : 0;
        });

    node = d;
    d3.event.stopPropagation();
}

<|endoftext|>


<commit_before>'use strict';

const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const resolve = require('resolve');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const TerserPlugin = require('terser-webpack-plugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const paths = require('./paths');
const getClientEnvironment = require('./env');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin');
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');

const appPackageJson = require(paths.appPackageJson);

const imageInlineSizeLimit = parseInt(
  process.env.IMAGE_INLINE_SIZE_LIMIT || '10000'
);

const useTypeScript = fs.existsSync(paths.appTsConfig);

module.exports = function(webpackEnv) {
  const isEnvDevelopment = webpackEnv === 'development';
  const isEnvProduction = webpackEnv === 'production';

  const isEnvProductionProfile = isEnvProduction && process.argv.includes('--profile');

  const env = getClientEnvironment();

  return {
    mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
    bail: isEnvProduction,
    devtool: isEnvProduction ? 'source-map' : isEnvDevelopment && 'cheap-module-source-map',
    entry: [ paths.appIndexJs ]

    output: {
      path: isEnvProduction ? paths.appBuild : undefined,
      pathinfo: isEnvDevelopment,
      filename: isEnvProduction
        ? 'static/js/[name].[contenthash:8].js'
        : isEnvDevelopment && 'static/js/bundle.js',
      futureEmitAssets: true,
      chunkFilename: isEnvProduction
        ? 'static/js/[name].[contenthash:8].chunk.js'
        : isEnvDevelopment && 'static/js/[name].chunk.js',
      publicPath: '/',
      devtoolModuleFilenameTemplate: isEnvProduction
        ? info =>
            path
              .relative(paths.appSrc, info.absoluteResourcePath)
              .replace(/\\/g, '/')
        : isEnvDevelopment &&
          (info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
      jsonpFunction: `webpackJsonp${appPackageJson.name}`,
      globalObject: 'this',
    },

    optimization: {
      minimize: isEnvProduction,
      minimizer: [
        new TerserPlugin({
          terserOptions: {
            parse: {
              ecma: 8,
            },
            compress: {
              ecma: 5,
              warnings: false,
              comparisons: false,
              inline: 2,
            },
            mangle: {
              safari10: true,
            },
            keep_classnames: isEnvProductionProfile,
            keep_fnames: isEnvProductionProfile,
            output: {
              ecma: 5,
              comments: false,
              ascii_only: true,
            },
          },
          sourceMap: true,
        }),
      ],
      splitChunks: {
        chunks: 'all',
        name: false,
      },
      runtimeChunk: {
        name: entrypoint => `runtime-${entrypoint.name}`,
      },
    },

    resolve: {
      modules: ['node_modules', paths.appNodeModules],
      extensions: paths.moduleFileExtensions
        .map(ext => `.${ext}`)
        .filter(ext => useTypeScript || !ext.includes('ts')),
      alias: {
        ...(isEnvProductionProfile && {
          'react-dom$': 'react-dom/profiling',
          'scheduler/tracing': 'scheduler/tracing-profiling',
        }),
      },
      plugins: [
        new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
      ],
    },

    resolveLoader: {
      plugins: [],
    },

    module: {
      strictExportPresence: true,
      rules: [
        { parser: { requireEnsure: false } },
        {
          test: /\.(js|mjs|jsx|ts|tsx)$/,
          enforce: 'pre',
          use: [
            {
              options: {
                cache: true,
                formatter: require.resolve('react-dev-utils/eslintFormatter'),
                eslintPath: require.resolve('eslint'),
                resolvePluginsRelativeTo: __dirname,

              },
              loader: require.resolve('eslint-loader'),
            },
          ],
          include: paths.appSrc,
        },
        {
          oneOf: [
            {
              test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
              loader: require.resolve('url-loader'),
              options: {
                limit: imageInlineSizeLimit,
                name: 'static/media/[name].[hash:8].[ext]',
              },
            },
            {
              test: /\.(js|mjs|jsx|ts|tsx)$/,
              include: paths.appSrc,
              loader: require.resolve('babel-loader'),
              options: {
                customize: require.resolve(
                  'babel-preset-react-app/webpack-overrides'
                ),

                plugins: [
                  [
                    require.resolve('babel-plugin-named-asset-import'),
                    {
                      loaderMap: {
                        svg: {
                          ReactComponent:
                            '@svgr/webpack?-svgo,+titleProp,+ref![path]',
                        },
                      },
                    },
                  ],
                ],
                cacheDirectory: true,
                cacheCompression: false,
                compact: isEnvProduction,
              },
            },
            {
              test: /\.(js|mjs)$/,
              exclude: /@babel(?:\/|\\{1,2})runtime/,
              loader: require.resolve('babel-loader'),
              options: {
                babelrc: false,
                configFile: false,
                compact: false,
                presets: [
                  [
                    require.resolve('babel-preset-react-app/dependencies'),
                    { helpers: true },
                  ],
                ],
                cacheDirectory: true,
                cacheCompression: false,
                sourceMaps: true,
                inputSourceMap: true,
              },
            },
            {
              loader: require.resolve('file-loader'),
              exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
              options: {
                name: 'static/media/[name].[hash:8].[ext]',
              },
            },
            // ** STOP ** Are you adding a new loader?
            // Make sure to add the new loader(s) before the "file" loader.
          ],
        },
      ],
    },

    plugins: [
      new HtmlWebpackPlugin(
        Object.assign(
          {},
          {
            inject: true,
            template: paths.appHtml,
          },
          isEnvProduction ? {
                minify: {
                  removeComments: true,
                  collapseWhitespace: true,
                  removeRedundantAttributes: true,
                  useShortDoctype: true,
                  removeEmptyAttributes: true,
                  removeStyleLinkTypeAttributes: true,
                  keepClosingSlash: true,
                  minifyJS: true,
                  minifyCSS: true,
                  minifyURLs: true,
                },
              }
            : undefined
        )
      ),
      isEnvProduction && new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]),
      new ModuleNotFoundPlugin(paths.appPath),
      new webpack.DefinePlugin(env.stringified),
      isEnvDevelopment && new webpack.HotModuleReplacementPlugin(),
      isEnvDevelopment && new CaseSensitivePathsPlugin(),
      isEnvDevelopment && new WatchMissingNodeModulesPlugin(paths.appNodeModules),
      useTypeScript && new ForkTsCheckerWebpackPlugin({
          typescript: resolve.sync('typescript', {
            basedir: paths.appNodeModules,
          }),
          async: isEnvDevelopment,
          useTypescriptIncrementalApi: true,
          checkSyntacticErrors: true,
          tsconfig: paths.appTsConfig,
          reportFiles: [
            '**',
            '!**/__tests__/**',
            '!**/?(*.)(spec|test).*',
          ],
          silent: true,
          formatter: isEnvProduction ? typescriptFormatter : undefined,
      }),
    ].filter(Boolean),

    node: {
      module: 'empty',
      dgram: 'empty',
      dns: 'mock',
      fs: 'empty',
      http2: 'empty',
      net: 'empty',
      tls: 'empty',
      child_process: 'empty',
    },

    performance: false,
  };
};
<commit_msg>minor bug<commit_after>'use strict';

const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const resolve = require('resolve');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const TerserPlugin = require('terser-webpack-plugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const paths = require('./paths');
const getClientEnvironment = require('./env');
const ModuleNotFoundPlugin = require('react-dev-utils/ModuleNotFoundPlugin');
const ForkTsCheckerWebpackPlugin = require('react-dev-utils/ForkTsCheckerWebpackPlugin');
const typescriptFormatter = require('react-dev-utils/typescriptFormatter');

const appPackageJson = require(paths.appPackageJson);

const imageInlineSizeLimit = parseInt(
  process.env.IMAGE_INLINE_SIZE_LIMIT || '10000'
);

const useTypeScript = fs.existsSync(paths.appTsConfig);

module.exports = function(webpackEnv) {
  const isEnvDevelopment = webpackEnv === 'development';
  const isEnvProduction = webpackEnv === 'production';

  const isEnvProductionProfile = isEnvProduction && process.argv.includes('--profile');

  const env = getClientEnvironment();

  return {
    mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development',
    bail: isEnvProduction,
    devtool: isEnvProduction ? 'source-map' : isEnvDevelopment && 'cheap-module-source-map',
    entry: [ paths.appIndexJs ],

    output: {
      path: isEnvProduction ? paths.appBuild : undefined,
      pathinfo: isEnvDevelopment,
      filename: isEnvProduction
        ? 'static/js/[name].[contenthash:8].js'
        : isEnvDevelopment && 'static/js/bundle.js',
      futureEmitAssets: true,
      chunkFilename: isEnvProduction
        ? 'static/js/[name].[contenthash:8].chunk.js'
        : isEnvDevelopment && 'static/js/[name].chunk.js',
      publicPath: '/',
      devtoolModuleFilenameTemplate: isEnvProduction
        ? info =>
            path
              .relative(paths.appSrc, info.absoluteResourcePath)
              .replace(/\\/g, '/')
        : isEnvDevelopment &&
          (info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
      jsonpFunction: `webpackJsonp${appPackageJson.name}`,
      globalObject: 'this',
    },

    optimization: {
      minimize: isEnvProduction,
      minimizer: [
        new TerserPlugin({
          terserOptions: {
            parse: {
              ecma: 8,
            },
            compress: {
              ecma: 5,
              warnings: false,
              comparisons: false,
              inline: 2,
            },
            mangle: {
              safari10: true,
            },
            keep_classnames: isEnvProductionProfile,
            keep_fnames: isEnvProductionProfile,
            output: {
              ecma: 5,
              comments: false,
              ascii_only: true,
            },
          },
          sourceMap: true,
        }),
      ],
      splitChunks: {
        chunks: 'all',
        name: false,
      },
      runtimeChunk: {
        name: entrypoint => `runtime-${entrypoint.name}`,
      },
    },

    resolve: {
      modules: ['node_modules', paths.appNodeModules],
      extensions: paths.moduleFileExtensions
        .map(ext => `.${ext}`)
        .filter(ext => useTypeScript || !ext.includes('ts')),
      alias: {
        ...(isEnvProductionProfile && {
          'react-dom$': 'react-dom/profiling',
          'scheduler/tracing': 'scheduler/tracing-profiling',
        }),
      },
      plugins: [
        new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
      ],
    },

    resolveLoader: {
      plugins: [],
    },

    module: {
      strictExportPresence: true,
      rules: [
        { parser: { requireEnsure: false } },
        {
          test: /\.(js|mjs|jsx|ts|tsx)$/,
          enforce: 'pre',
          use: [
            {
              options: {
                cache: true,
                formatter: require.resolve('react-dev-utils/eslintFormatter'),
                eslintPath: require.resolve('eslint'),
                resolvePluginsRelativeTo: __dirname,

              },
              loader: require.resolve('eslint-loader'),
            },
          ],
          include: paths.appSrc,
        },
        {
          oneOf: [
            {
              test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
              loader: require.resolve('url-loader'),
              options: {
                limit: imageInlineSizeLimit,
                name: 'static/media/[name].[hash:8].[ext]',
              },
            },
            {
              test: /\.(js|mjs|jsx|ts|tsx)$/,
              include: paths.appSrc,
              loader: require.resolve('babel-loader'),
              options: {
                customize: require.resolve(
                  'babel-preset-react-app/webpack-overrides'
                ),

                plugins: [
                  [
                    require.resolve('babel-plugin-named-asset-import'),
                    {
                      loaderMap: {
                        svg: {
                          ReactComponent:
                            '@svgr/webpack?-svgo,+titleProp,+ref![path]',
                        },
                      },
                    },
                  ],
                ],
                cacheDirectory: true,
                cacheCompression: false,
                compact: isEnvProduction,
              },
            },
            {
              test: /\.(js|mjs)$/,
              exclude: /@babel(?:\/|\\{1,2})runtime/,
              loader: require.resolve('babel-loader'),
              options: {
                babelrc: false,
                configFile: false,
                compact: false,
                presets: [
                  [
                    require.resolve('babel-preset-react-app/dependencies'),
                    { helpers: true },
                  ],
                ],
                cacheDirectory: true,
                cacheCompression: false,
                sourceMaps: true,
                inputSourceMap: true,
              },
            },
            {
              loader: require.resolve('file-loader'),
              exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
              options: {
                name: 'static/media/[name].[hash:8].[ext]',
              },
            },
            // ** STOP ** Are you adding a new loader?
            // Make sure to add the new loader(s) before the "file" loader.
          ],
        },
      ],
    },

    plugins: [
      new HtmlWebpackPlugin(
        Object.assign(
          {},
          {
            inject: true,
            template: paths.appHtml,
          },
          isEnvProduction ? {
                minify: {
                  removeComments: true,
                  collapseWhitespace: true,
                  removeRedundantAttributes: true,
                  useShortDoctype: true,
                  removeEmptyAttributes: true,
                  removeStyleLinkTypeAttributes: true,
                  keepClosingSlash: true,
                  minifyJS: true,
                  minifyCSS: true,
                  minifyURLs: true,
                },
              }
            : undefined
        )
      ),
      isEnvProduction && new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]),
      new ModuleNotFoundPlugin(paths.appPath),
      new webpack.DefinePlugin(env.stringified),
      isEnvDevelopment && new webpack.HotModuleReplacementPlugin(),
      isEnvDevelopment && new CaseSensitivePathsPlugin(),
      isEnvDevelopment && new WatchMissingNodeModulesPlugin(paths.appNodeModules),
      useTypeScript && new ForkTsCheckerWebpackPlugin({
          typescript: resolve.sync('typescript', {
            basedir: paths.appNodeModules,
          }),
          async: isEnvDevelopment,
          useTypescriptIncrementalApi: true,
          checkSyntacticErrors: true,
          tsconfig: paths.appTsConfig,
          reportFiles: [
            '**',
            '!**/__tests__/**',
            '!**/?(*.)(spec|test).*',
          ],
          silent: true,
          formatter: isEnvProduction ? typescriptFormatter : undefined,
      }),
    ].filter(Boolean),

    node: {
      module: 'empty',
      dgram: 'empty',
      dns: 'mock',
      fs: 'empty',
      http2: 'empty',
      net: 'empty',
      tls: 'empty',
      child_process: 'empty',
    },

    performance: false,
  };
};
<|endoftext|>


<commit_before>/**
 * test.js - Histone template engine.
 * Copyright 2012 MegaFon
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

load('Histone.js');
var testResult = 0;
var Files = require('Files');

function registerFunction(type, name, result, exception) {
	var nodeType = (
		type === 'map' ? Histone.Map :
		type === 'type' ? Histone.Type :
		type === 'number' ? Histone.Number :
		type === 'string' ? Histone.String :
		Histone.Global
	);
	nodeType[name] = function(value, args, ret) {
		if (typeof exception !== 'undefined')  {
			throw exception;
		}
		if (typeof result === 'string') {
			Histone(result).render(ret, {
				target: value,
				args: args
			});
		} else ret(result);
	};
}

function testParserExpected(input, testCase) {
	var expected = testCase.expected;
	expected = JSON.stringify(expected);
	try {
		var result = Histone(input);
		result = JSON.stringify(result.getAST());
		return (expected === result);
	} catch (e) { return false; }
}

function testParserException(input, testCase) {
	var exception = testCase.exception;
	try { Histone(input); } catch (error) {
		for (var key in exception) {
			if (!error.hasOwnProperty(key)) continue;
			if (String(error[key]) !==
				String(exception[key])) {
				return false;
			}
		}
		return true;
	}
	return false;
}

function testEvaluatorExpected(input, testCase, callback) {
	var context = testCase.context;
	var expected = testCase.expected;

	if (testCase.hasOwnProperty('function')) {
		var functionDefs = testCase.function;
		if (!(functionDefs instanceof Array)) {
			functionDefs = [functionDefs];
		}
		for (var c = 0; c < functionDefs.length; c++) {
			var functionDef = functionDefs[c];
			registerFunction(
				functionDef.node,
				functionDef.name,
				functionDef.result,
				functionDef.exception
			);
		}
	}

	try {
		var result = false;
		var template = Histone(input);
		template.render(function(result) {
			callback(expected === result);
		}, context);
	} catch (e) {
		callback(false);
	}
}

function printSuccess(message) {
	var message = JSON.stringify(message);
	message = message.substr(1);
	message = message.substr(0, message.length - 1);
	print('     [ SUCCESS ] ', message);
}

function printFail(message) {
	var message = JSON.stringify(message);
	message = message.substr(1);
	message = message.substr(0, message.length - 1);
	print('---- [ FAILING ] ', message);
}

Files.readDir('histone-acceptance-tests/src/main/acceptance', function(file) {
	//'/Users/ruslan/Sites/externals/histone-acceptance-tests.git/trunk/src/main/acceptance/'
	//histone-acceptance-tests/src/main/acceptance

	if (file.type === 'folder') {
		if (file.name === 'evaluator') return true;
		if (file.name === 'parser') return true;
		return false;
	}
	var fileType = file.name.split('.').pop();
	if (fileType !== 'json') return;
	// if (file.name !== 'global-scope.json') return;

	// if (file.name === 'constructs.json') {
	// 	var testSuites = readFile(file.path);
	// 	testSuites = JSON.parse(testSuites);
	// 	for (var i = 0; i < testSuites.length; i++) {
	// 		var testSuite = testSuites[i];
	// 		print('TESTING:', testSuite.name);
	// 		for (var j = 0; j < testSuite.cases.length; j++) {
	// 			var testCase = testSuite.cases[j];
	// 			if (!testCase.context) continue;
	// 			testCase.context = JSON.parse(testCase.context);
	// 		}
	// 	}
	//
	// 	print(JSON.stringify(testSuites));
	// }

	var testSuites = readFile(file.path);
	testSuites = JSON.parse(testSuites);

	for (var i = 0; i < testSuites.length; i++) {
		var testSuite = testSuites[i];
		print('\n[ TESTING "' + testSuite.name + '" ]\n');
		for (var j = 0; j < testSuite.cases.length; j++) {
			var testCase = testSuite.cases[j];
			var input = testCase.input;
			if (testCase.hasOwnProperty('expected')) {
				if (testCase.expected instanceof Array) {
					if (testParserExpected(input, testCase)) {
						printSuccess(input);
					} else {
						testResult = 1;
						printFail(input);
					}
				} else testEvaluatorExpected(
					input, testCase, function(result) {
						if (result) {
							printSuccess(input);
						} else {
							testResult = 1;
							printFail(input);
						}
					}
				);
			}
			else if (testCase.hasOwnProperty('exception')) {
				if (testParserException(input, testCase)) {
					printSuccess(input);
				} else {
					testResult = 1;
					printFail(input);
				}
			}
		}
	}

});

quit(testResult);<commit_msg>unregister all previously registered functions before executing the test case<commit_after>/**
 * test.js - Histone template engine.
 * Copyright 2012 MegaFon
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

load('Histone.js');
var testResult = 0;
var Files = require('Files');
var RegisterFunctions = [];

function registerFunction(type, name, result, exception) {
	var nodeType = (
		type === 'map' ? Histone.Map :
		type === 'type' ? Histone.Type :
		type === 'number' ? Histone.Number :
		type === 'string' ? Histone.String :
		Histone.Global
	);
	RegisterFunctions.push({
		name: name,
		target: nodeType,
		value: nodeType[name]
	});
	nodeType[name] = function(value, args, ret) {
		if (typeof exception !== 'undefined')  {
			throw exception;
		}
		if (typeof result === 'string') {
			Histone(result).render(ret, {
				target: value,
				args: args
			});
		} else ret(result);
	};
}

function unregisterFunctions() {
	while (RegisterFunctions.length) {
		var RegisterFunction = RegisterFunctions.shift();
		RegisterFunction.target[
			RegisterFunction.name
		] = RegisterFunction.value;
	}
}

function testParserExpected(input, testCase) {
	var expected = testCase.expected;
	expected = JSON.stringify(expected);
	try {
		var result = Histone(input);
		result = JSON.stringify(result.getAST());
		return (expected === result);
	} catch (e) { return false; }
}

function testParserException(input, testCase) {
	var exception = testCase.exception;
	try { Histone(input); } catch (error) {
		for (var key in exception) {
			if (!error.hasOwnProperty(key)) continue;
			if (String(error[key]) !==
				String(exception[key])) {
				return false;
			}
		}
		return true;
	}
	return false;
}

function testEvaluatorExpected(input, testCase, callback) {
	var context = testCase.context;
	var expected = testCase.expected;

	if (testCase.hasOwnProperty('function')) {
		var functionDefs = testCase.function;
		if (!(functionDefs instanceof Array)) {
			functionDefs = [functionDefs];
		}
		for (var c = 0; c < functionDefs.length; c++) {
			var functionDef = functionDefs[c];
			registerFunction(
				functionDef.node,
				functionDef.name,
				functionDef.result,
				functionDef.exception
			);
		}
	}

	try {
		var result = false;
		var template = Histone(input);
		template.render(function(result) {
			unregisterFunctions();
			callback(expected === result);
		}, context);
	} catch (e) {
		unregisterFunctions();
		callback(false);
	}
}

function printSuccess(message) {
	var message = JSON.stringify(message);
	message = message.substr(1);
	message = message.substr(0, message.length - 1);
	print('     [ SUCCESS ] ', message);
}

function printFail(message) {
	var message = JSON.stringify(message);
	message = message.substr(1);
	message = message.substr(0, message.length - 1);
	print('---- [ FAILING ] ', message);
}

Files.readDir('histone-acceptance-tests/src/main/acceptance', function(file) {
	//'/Users/ruslan/Sites/externals/histone-acceptance-tests.git/trunk/src/main/acceptance/'
	//histone-acceptance-tests/src/main/acceptance

	if (file.type === 'folder') {
		if (file.name === 'evaluator') return true;
		if (file.name === 'parser') return true;
		return false;
	}
	var fileType = file.name.split('.').pop();
	if (fileType !== 'json') return;
	// if (file.name !== 'global-scope.json') return;

	// if (file.name === 'constructs.json') {
	// 	var testSuites = readFile(file.path);
	// 	testSuites = JSON.parse(testSuites);
	// 	for (var i = 0; i < testSuites.length; i++) {
	// 		var testSuite = testSuites[i];
	// 		print('TESTING:', testSuite.name);
	// 		for (var j = 0; j < testSuite.cases.length; j++) {
	// 			var testCase = testSuite.cases[j];
	// 			if (!testCase.context) continue;
	// 			testCase.context = JSON.parse(testCase.context);
	// 		}
	// 	}
	//
	// 	print(JSON.stringify(testSuites));
	// }

	var testSuites = readFile(file.path);
	testSuites = JSON.parse(testSuites);

	for (var i = 0; i < testSuites.length; i++) {
		var testSuite = testSuites[i];
		print('\n[ TESTING "' + testSuite.name + '" ]\n');
		for (var j = 0; j < testSuite.cases.length; j++) {
			var testCase = testSuite.cases[j];
			var input = testCase.input;
			if (testCase.hasOwnProperty('expected')) {
				if (testCase.expected instanceof Array) {
					if (testParserExpected(input, testCase)) {
						printSuccess(input);
					} else {
						testResult = 1;
						printFail(input);
					}
				} else testEvaluatorExpected(
					input, testCase, function(result) {
						if (result) {
							printSuccess(input);
						} else {
							testResult = 1;
							printFail(input);
						}
					}
				);
			}
			else if (testCase.hasOwnProperty('exception')) {
				if (testParserException(input, testCase)) {
					printSuccess(input);
				} else {
					testResult = 1;
					printFail(input);
				}
			}
		}
	}

});

quit(testResult);<|endoftext|>


<commit_before>require.config({
  paths: {
    jsroot                    : vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/JSRootCore"),
    "jsroot/painter"          : vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/JSRootPainter"),
    "jsroot/d3"               : vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/d3.v3.min"),
    "jsroot/jquery.mousewheel": vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/jquery.mousewheel"),
    "mathjax"                 : vispa.url.dynamic("extensions/jsroot/static/vendor/mathjax/MathJax.js?config=TeX-AMS-MML_SVG" +
                                // vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/mathjax_config.js")),
                                "&delayStartupUntil=configured"),
  },
  shim: {
    jsroot: {
      exports: "JSROOT"
    },
    // "jsroot/painter": [ "jsroot", "jsroot/d3", "jsroot/jquery.mousewheel" ],
    "jsroot/painter": [ "jsroot", "jsroot/d3", "jsroot/jquery.mousewheel", "mathjax" ],
    mathjax: {
      exports: "MathJax",
      deps: ['jsroot'],
      init: function () {
        MathJax.Hub.Config({ TeX: { extensions: ["color.js"] }});
        MathJax.Hub.Register.StartupHook("SVG Jax Ready",function () {
           var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;
           VARIANT["normal"].fonts.unshift("MathJax_SansSerif");
           VARIANT["bold"].fonts.unshift("MathJax_SansSerif-bold");
           VARIANT["italic"].fonts.unshift("MathJax_SansSerif");
           VARIANT["-tex-mathit"].fonts.unshift("MathJax_SansSerif");
        });
        MathJax.Hub.Startup.onload();
        return MathJax;
      }
    }
  }
});

define([
  "vispa/extensions",
  "vispa/views/center",
  "css!../css/styles",
  "css!../vendor/jsroot/style/JSRootPainter"
], function(Extensions, CenterView) {

  var JsROOTExtension = Extensions.Extension._extend({

    init: function init() {
      init._super.call(this, "jsroot");

      var self = this;

      this.addView("jsroot", JsROOTView);

      this.addMenuEntry("Open ROOT File", {
        iconClass: "jsroot-icon-menu",
        priority : 1,
        callback : this.openViaFileSelector.bind(this)
      });

      // default preferences
      this.setDefaultPreferences(JsROOTView, {
        sidebarWidth: {
          type       : "integer",
          value      : 200,
          description: "Width of the sidebar in pixels."
        }
      });

      // tell other extensions to open root files with this jsROOTView
      this.addFileHandler("root", function(workspaceId, path) {
        self.createInstance(workspaceId, JsROOTView, { path: path });
      });

      // default fast menu entries
      this.getDefaultPreferences(JsROOTView).fastMenuEntries.value = [ "open" ];
      this.getDefaultPreferences(JsROOTView).fastMenuEntries.value = [ "help" ];

    },

    openViaFileSelector: function(workspaceId, callback) {
      var self = this;

      if (callback === undefined) {
        callback = function(workspaceId, path) {
          self.createInstance(workspaceId, JsROOTView, { path: path });
        };
      }

      var args = {
        callback: function(path) {
          // a root file?
          var ext = path.split(".").pop().toLowerCase();
          if (ext != "root") {
            vispa.messenger.alert("The selected file is not a root file. Please select a different one!");
            self.openViaFileSelector(workspaceId, callback);
          } else {
            callback(workspaceId, path);
          }
        }
      };

      vispa.extensions.createInstance(workspaceId, "file", "FileSelector", 0, args);
    }

  });

  var JsROOTView = CenterView._extend({

    init: function init(obj) {
      init._super.apply(this, arguments);

      var self = this;

      require(["jsroot", "mathjax"]);

      this.path    = (obj || {}).path;
      this.painter = null;
      this.nodes   = {};

      this.addMenuEntry("open", {
        label      : "Open File ...",
        iconClass  : "glyphicon glyphicon-folder-open",
        buttonClass: "btn-primary",
        callback: function() {
          self._extension.openViaFileSelector(self.getWorkspaceId(), function(_, path) {
            self.openFile(path);
          });
        }
      });

      this.addMenuEntry("help", {
        label      : "Help",
        iconClass  : "glyphicon glyphicon-question-sign",
        buttonClass: "btn-primary",
        callback: function() {
          self.openHelpDialog();
        }
      });

      // look if file has been deleted or modified
      this.onSocket("watch", function(data) {
        console.log(data);
        if (data.watch_id != "jsroot")
          return;
        // in case file deleting or renamings
        if (data.event == "vanish" && data.mtime == -1) {
          var filename = ((data.path).split('/')).pop();
          self.confirm("The file '" + filename +
                       "' has been deleted or renamed. \n Please open a new file or the browser is closed.",
          function(res) {
            if (!res)
              self.close();
            else {
              var callback = function() {
                self.spawnInstance("jsroot", "JSROOT", {
                  path: this.path
                });
                self.close();
              };
              self._extension.openViaFileSelector(self.getWorkspaceId(), function(_, path) {
                self.openFile(path);
              });
            }
          });
        }
        // in case up file modification
        if (data.event == "vanish" && data.mtime != -1) {
          var filename = ((data.path).split('/')).pop();
          self.confirm("The file '" + filename +
                       "' has been modified. \n Would you like to reload it?", function(res) {
            if (!res)
              self.close();
            else {
              var callback = function() {
                self.spawnInstance("jsroot", "JSROOT", {
                  path: this.path
                });
                self.close();
              };
              self.openFile(data.path);
            }
          });
        }
        if (data.event == "modify") {
          var filename = ((data.path).split('/')).pop();
          self.confirm("The file '" + filename +
                       "' has been modified. \n Would you like to reload it?", function(res) {
            if (!res)
              self.close();
            else {
              var callback = function() {
                self.spawnInstance("jsroot", "JSROOT", {
                  path: this.path
                });
                self.close();
              };
              self.openFile(data.path);
            }
          });
        }

      });

    },

    applyPreferences: function applyPreferences() {
      applyPreferences._super.call(this);

      this.layout(this.getPreference("sidebarWidth"));
    },

    render: function($node) {
      var self = this;

      // set icon for tab
      this.setIcon("jsroot-icon-tab");

      // get html template
      this.getTemplate("html/main.html", function(err, tmpl) {
        if (err) throw err;

        var $main        = $(tmpl).appendTo($node);
        var $sidebar     = $main.find(".sidebar-resize-wrapper");
        var $content     = $main.find(".content-wrapper");
        var $placeholder = $main.find(".placeholder");
        var $canvas      = $main.find(".canvas-wrapper");

        // make divs resizable
        $sidebar.resizable({
          start: function() {
            var mainWidth  = $main.width();
            $sidebar.resizable("option", "grid", [mainWidth * 0.01, 1]);
            $sidebar.resizable("option", "minWidth", 0);
            $sidebar.resizable("option", "maxWidth", mainWidth);
          },
          resize: function() {
            var mainWidth    = $main.width();
            var sidebarWidth = $sidebar.width();
            var contentWidth = mainWidth - sidebarWidth;
            $sidebar.css({
              left : 0,
              width: sidebarWidth
            });
            $content.css({
              left : sidebarWidth,
              width: contentWidth
            });
          },
          stop: function() {
            // tell the preferences about the new width
            self.setPreference("sidebarWidth", parseInt(Math.floor($sidebar.width())));
            self.pushPreferences();
          }
        });

        // make canvas wrapper resizable
        $canvas.resizable({
          start: function() {
            // set max dimensions
            $canvas.resizable("option", "maxWidth",  $content.width());
            $canvas.resizable("option", "maxHeight", $content.height());
          }
        });

        // store nodes
        self.nodes.$main        = $main;
        self.nodes.$sidebar     = $sidebar;
        self.nodes.$content     = $content;
        self.nodes.$placeholder = $placeholder;
        self.nodes.$canvas      = $canvas;

        // apply preferences
        self.applyPreferences();

        // open initial path?
        self.openFile(self.path);

      });
    },

    layout: function(sidebarWidth) {
      if (!this.nodes.$main) return;

      // limit the sidebar width
      var width = Math.min(Math.max(sidebarWidth, 0), this.nodes.$main.width());
      if (width != sidebarWidth) {
        this.setPreference("sidebarWidth", width);
        this.pushPreferences();
        return;
      }

      // set sidebar and content layout
      this.nodes.$sidebar.css({
        left : 0,
        width: sidebarWidth
      });
      this.nodes.$content.css({
        left : sidebarWidth,
        width: ""
      });

      // maybe update the canvas width
      var contentWidth = this.nodes.$content.width();
      if (this.nodes.$canvas.width() > contentWidth) {
        this.nodes.$canvas.width(contentWidth);
      }
    },

    openFile: function(path) {
      var self = this;

      if (!path || !this.nodes.$main) return;
      this.setLoading(true);
      this.path = path;
      this.setLabel(path, true);

      require(["jsroot", "jsroot/painter"], function(JSROOT) {
        JSROOT.MathJax = 2;
        self.nodes.$placeholder.hide();
        self.nodes.$canvas.show().find("> div.pad").empty();

        // set new ids
        var treeId = "tree-" + vispa.uuid();
        var padId  = "pad-"  + vispa.uuid();

        self.nodes.$main.find(".tree").attr("id", treeId);
        self.nodes.$main.find(".pad").attr("id", padId);

        // build the root file path
        var workspaceId = self.getWorkspaceId();
        path = "fs/getfile?path=" + path + "&_workspaceId=" + workspaceId;
        path = vispa.url.dynamic(path);

        // load root file
        self.painter = new JSROOT.HierarchyPainter("painter-" + vispa.uuid(), treeId);
        JSROOT.RegisterForResize(self.painter);
        self.painter.SetDisplay("simple", padId);
        self.painter.OpenRootFile(path, function() {
          self.setLoading(false);
        });
      });

      // watch
      this.POST("/ajax/fs/watch", {
        path    : this.path,
        watch_id: "jsroot"
      });

    },

    openHelpDialog: function() {
      var self    = this;
      var header  = " Help";
      var body    = "
Why are my root files not shown correctely?

VISPA adopts" +
                    " the jsroot  library to draw" +
                    " ROOT objects. Currently, the classes" +
                    "

TH1

TH2

TH3

TProfile

TGraph

TF1
" +
                    "
TPaveText

TCanvas

 are supported, as well as LaTeX strings." +
                    "
For more information, visit the jsroot  documentation site.";
      var $footer = $("
<button class='btn btn-primary'>Close</button>
");
      self.dialog({
        header  : header,
        body    : body,
        footer  : $footer,
        onRender: function() {
          var self = this;
          $footer.find("button").click(function() {
            self.close();
          });
        }
      });
    },

    onClose: function() {
      this.POST("/ajax/fs/unwatch");
    }

  });

  return JsROOTExtension;
});
<commit_msg>Do not push preferences after resizing sidebar due to platform bug<commit_after>require.config({
  paths: {
    jsroot                    : vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/JSRootCore"),
    "jsroot/painter"          : vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/JSRootPainter"),
    "jsroot/d3"               : vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/d3.v3.min"),
    "jsroot/jquery.mousewheel": vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/jquery.mousewheel"),
    "mathjax"                 : vispa.url.dynamic("extensions/jsroot/static/vendor/mathjax/MathJax.js?config=TeX-AMS-MML_SVG" +
                                // vispa.url.dynamic("extensions/jsroot/static/vendor/jsroot/scripts/mathjax_config.js")),
                                "&delayStartupUntil=configured"),
  },
  shim: {
    jsroot: {
      exports: "JSROOT"
    },
    // "jsroot/painter": [ "jsroot", "jsroot/d3", "jsroot/jquery.mousewheel" ],
    "jsroot/painter": [ "jsroot", "jsroot/d3", "jsroot/jquery.mousewheel", "mathjax" ],
    mathjax: {
      exports: "MathJax",
      deps: ['jsroot'],
      init: function () {
        MathJax.Hub.Config({ TeX: { extensions: ["color.js"] }});
        MathJax.Hub.Register.StartupHook("SVG Jax Ready",function () {
           var VARIANT = MathJax.OutputJax.SVG.FONTDATA.VARIANT;
           VARIANT["normal"].fonts.unshift("MathJax_SansSerif");
           VARIANT["bold"].fonts.unshift("MathJax_SansSerif-bold");
           VARIANT["italic"].fonts.unshift("MathJax_SansSerif");
           VARIANT["-tex-mathit"].fonts.unshift("MathJax_SansSerif");
        });
        MathJax.Hub.Startup.onload();
        return MathJax;
      }
    }
  }
});

define([
  "vispa/extensions",
  "vispa/views/center",
  "css!../css/styles",
  "css!../vendor/jsroot/style/JSRootPainter"
], function(Extensions, CenterView) {

  var JsROOTExtension = Extensions.Extension._extend({

    init: function init() {
      init._super.call(this, "jsroot");

      var self = this;

      this.addView("jsroot", JsROOTView);

      this.addMenuEntry("Open ROOT File", {
        iconClass: "jsroot-icon-menu",
        priority : 1,
        callback : this.openViaFileSelector.bind(this)
      });

      // default preferences
      this.setDefaultPreferences(JsROOTView, {
        sidebarWidth: {
          type       : "integer",
          value      : 200,
          description: "Width of the sidebar in pixels."
        }
      });

      // tell other extensions to open root files with this jsROOTView
      this.addFileHandler("root", function(workspaceId, path) {
        self.createInstance(workspaceId, JsROOTView, { path: path });
      });

      // default fast menu entries
      this.getDefaultPreferences(JsROOTView).fastMenuEntries.value = [ "open" ];
      this.getDefaultPreferences(JsROOTView).fastMenuEntries.value = [ "help" ];

    },

    openViaFileSelector: function(workspaceId, callback) {
      var self = this;

      if (callback === undefined) {
        callback = function(workspaceId, path) {
          self.createInstance(workspaceId, JsROOTView, { path: path });
        };
      }

      var args = {
        callback: function(path) {
          // a root file?
          var ext = path.split(".").pop().toLowerCase();
          if (ext != "root") {
            vispa.messenger.alert("The selected file is not a root file. Please select a different one!");
            self.openViaFileSelector(workspaceId, callback);
          } else {
            callback(workspaceId, path);
          }
        }
      };

      vispa.extensions.createInstance(workspaceId, "file", "FileSelector", 0, args);
    }

  });

  var JsROOTView = CenterView._extend({

    init: function init(obj) {
      init._super.apply(this, arguments);

      var self = this;

      require(["jsroot", "mathjax"]);

      this.path    = (obj || {}).path;
      this.painter = null;
      this.nodes   = {};

      this.addMenuEntry("open", {
        label      : "Open File ...",
        iconClass  : "glyphicon glyphicon-folder-open",
        buttonClass: "btn-primary",
        callback: function() {
          self._extension.openViaFileSelector(self.getWorkspaceId(), function(_, path) {
            self.openFile(path);
          });
        }
      });

      this.addMenuEntry("help", {
        label      : "Help",
        iconClass  : "glyphicon glyphicon-question-sign",
        buttonClass: "btn-primary",
        callback: function() {
          self.openHelpDialog();
        }
      });

      // look if file has been deleted or modified
      this.onSocket("watch", function(data) {
        console.log(data);
        if (data.watch_id != "jsroot")
          return;
        // in case file deleting or renamings
        if (data.event == "vanish" && data.mtime == -1) {
          var filename = ((data.path).split('/')).pop();
          self.confirm("The file '" + filename +
                       "' has been deleted or renamed. \n Please open a new file or the browser is closed.",
          function(res) {
            if (!res)
              self.close();
            else {
              var callback = function() {
                self.spawnInstance("jsroot", "JSROOT", {
                  path: this.path
                });
                self.close();
              };
              self._extension.openViaFileSelector(self.getWorkspaceId(), function(_, path) {
                self.openFile(path);
              });
            }
          });
        }
        // in case up file modification
        if (data.event == "vanish" && data.mtime != -1) {
          var filename = ((data.path).split('/')).pop();
          self.confirm("The file '" + filename +
                       "' has been modified. \n Would you like to reload it?", function(res) {
            if (!res)
              self.close();
            else {
              var callback = function() {
                self.spawnInstance("jsroot", "JSROOT", {
                  path: this.path
                });
                self.close();
              };
              self.openFile(data.path);
            }
          });
        }
        if (data.event == "modify") {
          var filename = ((data.path).split('/')).pop();
          self.confirm("The file '" + filename +
                       "' has been modified. \n Would you like to reload it?", function(res) {
            if (!res)
              self.close();
            else {
              var callback = function() {
                self.spawnInstance("jsroot", "JSROOT", {
                  path: this.path
                });
                self.close();
              };
              self.openFile(data.path);
            }
          });
        }

      });

    },

    applyPreferences: function applyPreferences() {
      applyPreferences._super.call(this);

      this.layout(this.getPreference("sidebarWidth"));
    },

    render: function($node) {
      var self = this;

      // set icon for tab
      this.setIcon("jsroot-icon-tab");

      // get html template
      this.getTemplate("html/main.html", function(err, tmpl) {
        if (err) throw err;

        var $main        = $(tmpl).appendTo($node);
        var $sidebar     = $main.find(".sidebar-resize-wrapper");
        var $content     = $main.find(".content-wrapper");
        var $placeholder = $main.find(".placeholder");
        var $canvas      = $main.find(".canvas-wrapper");

        // make divs resizable
        $sidebar.resizable({
          start: function() {
            var mainWidth  = $main.width();
            $sidebar.resizable("option", "grid", [mainWidth * 0.01, 1]);
            $sidebar.resizable("option", "minWidth", 0);
            $sidebar.resizable("option", "maxWidth", mainWidth);
          },
          resize: function() {
            var mainWidth    = $main.width();
            var sidebarWidth = $sidebar.width();
            var contentWidth = mainWidth - sidebarWidth;
            $sidebar.css({
              left : 0,
              width: sidebarWidth
            });
            $content.css({
              left : sidebarWidth,
              width: contentWidth
            });
          },
          stop: function() {
            // tell the preferences about the new width
            self.setPreference("sidebarWidth", parseInt(Math.floor($sidebar.width())));
            // self.pushPreferences();
          }
        });

        // make canvas wrapper resizable
        $canvas.resizable({
          start: function() {
            // set max dimensions
            $canvas.resizable("option", "maxWidth",  $content.width());
            $canvas.resizable("option", "maxHeight", $content.height());
          }
        });

        // store nodes
        self.nodes.$main        = $main;
        self.nodes.$sidebar     = $sidebar;
        self.nodes.$content     = $content;
        self.nodes.$placeholder = $placeholder;
        self.nodes.$canvas      = $canvas;

        // apply preferences
        self.applyPreferences();

        // open initial path?
        self.openFile(self.path);

      });
    },

    layout: function(sidebarWidth) {
      if (!this.nodes.$main) return;

      // limit the sidebar width
      var width = Math.min(Math.max(sidebarWidth, 0), this.nodes.$main.width());
      if (width != sidebarWidth) {
        this.setPreference("sidebarWidth", width);
        this.pushPreferences();
        return;
      }

      // set sidebar and content layout
      this.nodes.$sidebar.css({
        left : 0,
        width: sidebarWidth
      });
      this.nodes.$content.css({
        left : sidebarWidth,
        width: ""
      });

      // maybe update the canvas width
      var contentWidth = this.nodes.$content.width();
      if (this.nodes.$canvas.width() > contentWidth) {
        this.nodes.$canvas.width(contentWidth);
      }
    },

    openFile: function(path) {
      var self = this;

      if (!path || !this.nodes.$main) return;
      this.setLoading(true);
      this.path = path;
      this.setLabel(path, true);

      require(["jsroot", "jsroot/painter"], function(JSROOT) {
        JSROOT.MathJax = 2;
        self.nodes.$placeholder.hide();
        self.nodes.$canvas.show().find("> div.pad").empty();

        // set new ids
        var treeId = "tree-" + vispa.uuid();
        var padId  = "pad-"  + vispa.uuid();

        self.nodes.$main.find(".tree").attr("id", treeId);
        self.nodes.$main.find(".pad").attr("id", padId);

        // build the root file path
        var workspaceId = self.getWorkspaceId();
        path = "fs/getfile?path=" + path + "&_workspaceId=" + workspaceId;
        path = vispa.url.dynamic(path);

        // load root file
        self.painter = new JSROOT.HierarchyPainter("painter-" + vispa.uuid(), treeId);
        JSROOT.RegisterForResize(self.painter);
        self.painter.SetDisplay("simple", padId);
        self.painter.OpenRootFile(path, function() {
          self.setLoading(false);
        });
      });

      // watch
      this.POST("/ajax/fs/watch", {
        path    : this.path,
        watch_id: "jsroot"
      });

    },

    openHelpDialog: function() {
      var self    = this;
      var header  = " Help";
      var body    = "
Why are my root files not shown correctely?

VISPA adopts" +
                    " the jsroot  library to draw" +
                    " ROOT objects. Currently, the classes" +
                    "

TH1

TH2

TH3

TProfile

TGraph

TF1
" +
                    "
TPaveText

TCanvas

 are supported, as well as LaTeX strings." +
                    "
For more information, visit the jsroot  documentation site.";
      var $footer = $("
<button class='btn btn-primary'>Close</button>
");
      self.dialog({
        header  : header,
        body    : body,
        footer  : $footer,
        onRender: function() {
          var self = this;
          $footer.find("button").click(function() {
            self.close();
          });
        }
      });
    },

    onClose: function() {
      this.POST("/ajax/fs/unwatch");
    }

  });

  return JsROOTExtension;
});
<|endoftext|>


<commit_before>import test from 'ava';

export default function (title, lightflow) {
	const simpleAsync = fn => setTimeout(fn, 1);
	const randomAsync = (range, fn) => setTimeout(fn, 1 + Math.random() * (range - 1));
	const fixAsync = (timeout, fn) => setTimeout(fn, timeout);
	const label = `lightflow:${title}`;

	test(`${label}: object create`, t => {
		t.truthy(lightflow());
	});

	test(`${label}: object api check`, t => {
		const flow = lightflow();
		const check = fn => t.is(typeof flow[fn], 'function', `check .${fn} func`);

		['then', 'race', 'error', 'catch', 'done', 'loop', 'start', 'stop'].forEach(check);
	});

	test.cb(`${label}: trivial flow`, t => {
		t.plan(1);

		const ret = 3;

		lightflow()
		.then(({ next }) => next(ret))
		.done(data => {
			t.is(data, ret);
			t.end()
		})
		.start()
		;
	});

	test.cb(`${label}: trivial flow with data traverce`, t => {
		t.plan(1);

		const ret = 3;

		lightflow()
		.then(({ next, data }) => next(data))
		.done(data => {
			t.is(data, ret);
			t.end();
		})
		.start(ret)
		;
	});

	test.cb(`${label}: nested flows`, t => {
		t.plan(1);

		const ret = 3;

		lightflow()
		.then(
			lightflow()
			.then(({ next, data}) => simpleAsync(() => next(data)))
		)
		.done(data => {
			t.is(data, ret);
			t.end();
		})
		.start(ret)
		;
	});

	test.cb(`${label}: parallel tasks`, t => {
		t.plan(1);

		const ret = 3;

		lightflow()
		.then(
			lightflow()
			.then(({ next, data}) => simpleAsync(() => next(data)))
		)
		.done(data => {
			t.is(data, ret);
			t.end();
		})
		.start(ret)
		;
	});

	test.cb(`${label}: '.race' simple test`, t => {
		t.plan(3);

		lightflow()
		.race(
			// first race task
			({ next, data }) => {
				randomAsync(50, () => {
					data.t1 = true;
					next(data);
				})
			},

			// second race task
			({ next, data }) => {
				randomAsync(50, () => {
					data.t2 = true;
					next(data);
				})
			}
		)
		.then(({ data, next }) => fixAsync(60, () => next(data)))
		.then(({ next, data }) => {
			const { a, t1, t2 } = data;
			t.is(a, 1, 'check data pass through');
			t.truthy(t1 || t2, 'never a one race functions done')
			t.truthy(!(t1 && t2), 'data from both race function come here!');
			t.end();

			next();
		})
		.start({ a: 1 })
		;
	});

	test.cb(`${label}: check flow with labels`, t => {
		t.plan(1);

		lightflow()
		.then('label')
		.then(({ next }) => simpleAsync(() => next()))
		.then('another-label')
		.then(({ next }) => simpleAsync(() => next()))
		.then('last-label')
		.done(() => {
			t.pass();
			t.end();
		})
		.start()
		;
	});

	test.cb(`${label}: check single skip to label`, t => {
		t.plan(1);

		lightflow()
		.then(({ next }) => simpleAsync(() => next(null, 'label')))
		.then(({ next }) => {
			t.fail('can\'t get here');
			t.end();
			next();
		})
		.then('label')
		.then(({ next }) => {
			t.pass();
			t.end();
			next();
		})
		.start()
		;
	});

	test.cb(`${label}: '.error' with continue`, t => {
		t.plan(2);

		lightflow()
		.then(({ next }) => simpleAsync(() => next()))
		.then(({ error }) => simpleAsync(() => error()))
		.error(() => 1)
		.catch(() => {
			t.fail();
			t.end();
		})
		.then(({ next, data }) => {
			t.is(1, data);
			next();
		})
		.done(() => {
			t.pass();
			t.end();
		})
		.start()
		;
	});

	test.cb(`${label}: '.catch' api`, t => {
		t.plan(2);

		const errorMsg = 'error';

		lightflow()
		.then(({ error }) => simpleAsync(() => error(errorMsg)))
		.catch(e => {
			t.is(e, errorMsg);
		})
		.then(({ next }) => simpleAsync(() => next()))
		.catch(e => {
			t.is(e, errorMsg);
			t.end();
		})
		.done(() => {
			t.failed();
		})
		.start()
		;
	});

	test.cb(`${label}: '.loop' api`, t => {
		t.plan(1);

		let counter = 0;

		const flow = lightflow()
		.then(({ next }) => simpleAsync(() => {
			++counter;
			if (counter === 2) {
				flow.loop(false);
				t.pass();
				t.end();
			}

			next();
		}))
		.loop()
		.start()
		;
	});

	test.cb(`${label}: '.loop' api with data pass`, t => {
		t.plan(2);

		let counter = 0;
		const flow = lightflow()
		.then(({ next, data }) => simpleAsync(() => {
			t.is(data, 0, `data must be 0, but it is ${data}`);
			if (++counter === 2) {
				flow.loop(false);
				t.end();
			}

			next(data);
		}))
		.loop()
		.start(0)
		;
	});

	test.cb(`${label}: '.stop' api with callback`, t => {
		t.plan(1);

		const initial = 0;
		const final = 3;

		const flow = lightflow()
		.then(({ next, data }) => simpleAsync(() => next(++data)))
		.then(({ next, data }) => simpleAsync(() => next(++data)))
		.then(({ next, data }) => {
			simpleAsync(() => next(++data));
			flow.stop(last => {
				t.is(last, final);
				t.end();
			});
		})
		.then(({ next, data }) => simpleAsync(() => {
			t.fail('execute next task after stop called!');
			t.end();
			next(data);
		}))
		.start(initial)
		;
	});
}<commit_msg>update tests<commit_after>import test from 'ava';

export default function (title, lightflow) {
	const simpleAsync = fn => setTimeout(fn, 1);
	const randomAsync = (range, fn) => setTimeout(fn, 1 + Math.random() * (range - 1));
	const fixAsync = (timeout, fn) => setTimeout(fn, timeout);
	const label = `lightflow:${title}`;

	test(`${label}: object create`, t => {
		t.truthy(lightflow());
	});

	test(`${label}: object api check`, t => {
		const flow = lightflow();
		const check = fn => t.is(typeof flow[fn], 'function', `check .${fn} func`);

		['then', 'race', 'error', 'catch', 'done', 'loop', 'start', 'stop'].forEach(check);
	});

	test.cb(`${label}: trivial flow`, t => {
		t.plan(1);

		const ret = 3;

		lightflow()
		.then(({ next }) => next(ret))
		.done(data => {
			t.is(data, ret);
			t.end()
		})
		.start()
		;
	});

	test.cb(`${label}: trivial flow with data traverce`, t => {
		t.plan(1);

		const ret = 3;

		lightflow()
		.then(({ next, data }) => next(data))
		.done(data => {
			t.is(data, ret);
			t.end();
		})
		.start(ret)
		;
	});

	test.cb(`${label}: nested flows`, t => {
		t.plan(1);

		const ret = 3;

		lightflow()
		.then(
			lightflow()
			.then(({ next, data}) => simpleAsync(() => next(data)))
		)
		.done(data => {
			t.is(data, ret);
			t.end();
		})
		.start(ret)
		;
	});

	test.cb(`${label}: parallel tasks`, t => {
		t.plan(1);

		const ret = 3;

		lightflow()
		.then(
			lightflow()
			.then(({ next, data}) => simpleAsync(() => next(data)))
		)
		.done(data => {
			t.is(data, ret);
			t.end();
		})
		.start(ret)
		;
	});

	test.cb(`${label}: '.race' simple test`, t => {
		t.plan(3);

		lightflow()
		.race(
			// first race task
			({ next, data }) => {
				randomAsync(50, () => {
					data.t1 = true;
					next(data);
				})
			},

			// second race task
			({ next, data }) => {
				randomAsync(50, () => {
					data.t2 = true;
					next(data);
				})
			}
		)
		.then(({ data, next }) => fixAsync(60, () => next(data)))
		.then(({ next, data }) => {
			const { a, t1, t2 } = data;
			t.is(a, 1, 'check data pass through');
			t.truthy(t1 || t2, 'never a one race functions done')
			t.truthy(!(t1 && t2), 'data from both race function come here!');
			t.end();

			next();
		})
		.start({ a: 1 })
		;
	});

	test.cb(`${label}: '.then' with some parallel tasks`, t => {
		t.plan(2);

		lightflow()
		.then(
			({ next, data }) => simpleAsync(() => next({ a: data + 1 })),
			({ next, data }) => simpleAsync(() => next({ b: data + 2 }))
		)
		.done(data => {
			t.is(data.a, 2);
			t.is(data.b, 3);
			t.end();
		})
		.start(1)
		;
	});

	test.cb(`${label}: check flow with labels`, t => {
		t.plan(1);

		lightflow()
		.then('label')
		.then(({ next }) => simpleAsync(() => next()))
		.then('another-label')
		.then(({ next }) => simpleAsync(() => next()))
		.then('last-label')
		.done(() => {
			t.pass();
			t.end();
		})
		.start()
		;
	});

	test.cb(`${label}: check single skip to label`, t => {
		t.plan(1);

		lightflow()
		.then(({ next }) => simpleAsync(() => next(null, 'label')))
		.then(({ next }) => {
			t.fail('can\'t get here');
			t.end();
			next();
		})
		.then('label')
		.then(({ next }) => {
			t.pass();
			t.end();
			next();
		})
		.start()
		;
	});

	test.cb(`${label}: '.error' with continue`, t => {
		t.plan(2);

		lightflow()
		.then(({ next }) => simpleAsync(() => next()))
		.then(({ error }) => simpleAsync(() => error()))
		.error(() => 1)
		.catch(() => {
			t.fail();
			t.end();
		})
		.then(({ next, data }) => {
			t.is(1, data);
			next();
		})
		.done(() => {
			t.pass();
			t.end();
		})
		.start()
		;
	});

	test.cb(`${label}: '.catch' api`, t => {
		t.plan(2);

		const errorMsg = 'error';

		lightflow()
		.then(({ error }) => simpleAsync(() => error(errorMsg)))
		.catch(e => {
			t.is(e, errorMsg);
		})
		.then(({ next }) => simpleAsync(() => next()))
		.catch(e => {
			t.is(e, errorMsg);
			t.end();
		})
		.done(() => {
			t.failed();
		})
		.start()
		;
	});

	test.cb(`${label}: '.loop' api`, t => {
		t.plan(1);

		let counter = 0;

		const flow = lightflow()
		.then(({ next }) => simpleAsync(() => {
			++counter;
			if (counter === 2) {
				flow.loop(false);
				t.pass();
				t.end();
			}

			next();
		}))
		.loop()
		.start()
		;
	});

	test.cb(`${label}: '.loop' api with data pass`, t => {
		t.plan(2);

		let counter = 0;
		const flow = lightflow()
		.then(({ next, data }) => simpleAsync(() => {
			t.is(data, 0, `data must be 0, but it is ${data}`);
			if (++counter === 2) {
				flow.loop(false);
				t.end();
			}

			next(data);
		}))
		.loop()
		.start(0)
		;
	});

	test.cb(`${label}: '.stop' api with callback`, t => {
		t.plan(1);

		const initial = 0;
		const final = 3;

		const flow = lightflow()
		.then(({ next, data }) => simpleAsync(() => next(++data)))
		.then(({ next, data }) => simpleAsync(() => next(++data)))
		.then(({ next, data }) => {
			simpleAsync(() => next(++data));
			flow.stop(last => {
				t.is(last, final);
				t.end();
			});
		})
		.then(({ next, data }) => simpleAsync(() => {
			t.fail('execute next task after stop called!');
			t.end();
			next(data);
		}))
		.start(initial)
		;
	});
}<|endoftext|>