<commit_before>module.exports = function (grunt) {

    var browsers = [
        // chrome
        {
            browserName: "chrome",
            platform: "Windows XP",
            version: "26.0"
        }, {
            browserName: "chrome",
            platform: "OS X 10.9",
            version: "38.0"
        }, {
            browserName: "chrome",
            platform: "Windows 8.1",
            version: "30.0"
        }, {
            browserName: "chrome",
            platform: "Windows 10",
            version: "51.0"
        },
        // firefox
        {
            browserName: "firefox",
            platform: "Windows XP",
            version: "10.0"
        }, {
            browserName: "firefox",
            platform: "Windows 7",
            version: "17.0"
        }, {
            browserName: "firefox",
            platform: "Linux",
            version: "35.0"
        }
        // internet explorer
        {
            browserName: "internet explorer",
            platform: "Windows 7",
            version: "9.0"
        }, {
            browserName: "internet explorer",
            platform: "Windows 8",
            version: "10.0"
        }, {
            browserName: "internet explorer",
            platform: "Windows 8.1",
            version: "11.0"
        },
        // edge
        {
            browserName: "microsoftedge",
            platform: "Windows 10",
            version: "20.10240"
        },
        // opera
        {
            browserName: "opera",
            platform: "Windows 7",
            version: "11"
        }, {
            browserName: "opera",
            platform: "Linux",
            version: "12"
        // safari
        }, {
            browserName: "safari",
            platform: "Windows 7",
            version: "5.1"
        }, {
            browserName: "safari",
            platform: "OS X 10.8",
            version: "6.0"
        },
        // apple
        {
            browserName: "iphone",
            platform: "OS X 10.10",
            deviceName: "iPhone Simulator",
            "device-orientation": "portrait",
            version: "9.0"
        }, {
            browserName: "iphone",
            platform: "OS X 10.10",
            deviceName: "iPhone Simulator",
            "device-orientation": "portrait",
            version: "7.1"
        }, {
            browserName: "iphone",
            platform: "OS X 10.10",
            deviceName: "iPhone Simulator",
            "device-orientation": "portrait",
            version: "8.2"
        },
        // android
        {
            browserName: "android",
            platform: "Linux",
            deviceName: "LG Nexus 4 Emulator",
            version: "4.2"
        }, {
            browserName: "android",
            platform: "Linux",
            deviceName: "Android Emulator",
            version: "5.1"
        }];

    grunt.initConfig({
        uglify: {
            target: {
                files: {
                    'src/justlazy.min.js': ['src/justlazy.js']
                }
            }
        },
        jshint: {
            files: [
                "Gruntfile.js",
                "src/justlazy.js",
                "spec/**/*.js"
            ]
        },
        jasmine: {
            src: "src/justlazy.js",
            options: {
                vendor: [
                    "jasmine-standalone/lib/jasmine-jquery-2.0.7/jquery.js",
                    "jasmine-standalone/lib/jasmine-jquery-2.0.7/jasmine-jquery.js",
                    "jasmine-standalone/phantomjs-config.js"
                ],
                specs: "spec/**/*.js"
            }
        },
        connect: {
            server: {
                options: {
                    base: "",
                    port: 9999
                }
            }
        },
        "saucelabs-jasmine": {
            all: {
                options: {
                    urls: ["http://127.0.0.1:9999/jasmine-standalone/SpecRunner.html"],
                    build: process.env.TRAVIS_JOB_ID,
                    browsers: browsers,
                    testname: "justlazy.js tests",
                    "max-duration": 300,
                    tags: ["master"]
                }
            }
        },
        watch: {}
    });

    grunt.loadNpmTasks("grunt-contrib-jshint");
    grunt.loadNpmTasks("grunt-contrib-jasmine");
    grunt.loadNpmTasks("grunt-saucelabs");
    grunt.loadNpmTasks("grunt-contrib-connect");
    grunt.loadNpmTasks("grunt-contrib-watch");
    grunt.loadNpmTasks('grunt-contrib-uglify');

    grunt.registerTask("server", ["connect", "watch"]);
    grunt.registerTask("minify", ["uglify"]);
    grunt.registerTask("test-jshint", ["jshint"]);
    grunt.registerTask("test-jasmine", ["jasmine"]);
    grunt.registerTask("test-browsers", ["connect", "saucelabs-jasmine"]);
    grunt.registerTask("test-all", ["jshint", "jasmine", "connect", "saucelabs-jasmine"]);
    grunt.registerTask("travis-ci", ["test-all"]);

    grunt.registerTask("default", ["test-jshint", "test-jasmine", "minify"]);

};
<commit_msg>fix syntax<commit_after>module.exports = function (grunt) {

    var browsers = [
        // chrome
        {
            browserName: "chrome",
            platform: "Windows XP",
            version: "26.0"
        }, {
            browserName: "chrome",
            platform: "OS X 10.9",
            version: "38.0"
        }, {
            browserName: "chrome",
            platform: "Windows 8.1",
            version: "30.0"
        }, {
            browserName: "chrome",
            platform: "Windows 10",
            version: "51.0"
        },
        // firefox
        {
            browserName: "firefox",
            platform: "Windows XP",
            version: "10.0"
        }, {
            browserName: "firefox",
            platform: "Windows 7",
            version: "17.0"
        }, {
            browserName: "firefox",
            platform: "Linux",
            version: "35.0"
        },
        // internet explorer
        {
            browserName: "internet explorer",
            platform: "Windows 7",
            version: "9.0"
        }, {
            browserName: "internet explorer",
            platform: "Windows 8",
            version: "10.0"
        }, {
            browserName: "internet explorer",
            platform: "Windows 8.1",
            version: "11.0"
        },
        // edge
        {
            browserName: "microsoftedge",
            platform: "Windows 10",
            version: "20.10240"
        },
        // opera
        {
            browserName: "opera",
            platform: "Windows 7",
            version: "11"
        }, {
            browserName: "opera",
            platform: "Linux",
            version: "12"
        // safari
        }, {
            browserName: "safari",
            platform: "Windows 7",
            version: "5.1"
        }, {
            browserName: "safari",
            platform: "OS X 10.8",
            version: "6.0"
        },
        // apple
        {
            browserName: "iphone",
            platform: "OS X 10.10",
            deviceName: "iPhone Simulator",
            "device-orientation": "portrait",
            version: "9.0"
        }, {
            browserName: "iphone",
            platform: "OS X 10.10",
            deviceName: "iPhone Simulator",
            "device-orientation": "portrait",
            version: "7.1"
        }, {
            browserName: "iphone",
            platform: "OS X 10.10",
            deviceName: "iPhone Simulator",
            "device-orientation": "portrait",
            version: "8.2"
        },
        // android
        {
            browserName: "android",
            platform: "Linux",
            deviceName: "LG Nexus 4 Emulator",
            version: "4.2"
        }, {
            browserName: "android",
            platform: "Linux",
            deviceName: "Android Emulator",
            version: "5.1"
        }];

    grunt.initConfig({
        uglify: {
            target: {
                files: {
                    'src/justlazy.min.js': ['src/justlazy.js']
                }
            }
        },
        jshint: {
            files: [
                "Gruntfile.js",
                "src/justlazy.js",
                "spec/**/*.js"
            ]
        },
        jasmine: {
            src: "src/justlazy.js",
            options: {
                vendor: [
                    "jasmine-standalone/lib/jasmine-jquery-2.0.7/jquery.js",
                    "jasmine-standalone/lib/jasmine-jquery-2.0.7/jasmine-jquery.js",
                    "jasmine-standalone/phantomjs-config.js"
                ],
                specs: "spec/**/*.js"
            }
        },
        connect: {
            server: {
                options: {
                    base: "",
                    port: 9999
                }
            }
        },
        "saucelabs-jasmine": {
            all: {
                options: {
                    urls: ["http://127.0.0.1:9999/jasmine-standalone/SpecRunner.html"],
                    build: process.env.TRAVIS_JOB_ID,
                    browsers: browsers,
                    testname: "justlazy.js tests",
                    "max-duration": 300,
                    tags: ["master"]
                }
            }
        },
        watch: {}
    });

    grunt.loadNpmTasks("grunt-contrib-jshint");
    grunt.loadNpmTasks("grunt-contrib-jasmine");
    grunt.loadNpmTasks("grunt-saucelabs");
    grunt.loadNpmTasks("grunt-contrib-connect");
    grunt.loadNpmTasks("grunt-contrib-watch");
    grunt.loadNpmTasks('grunt-contrib-uglify');

    grunt.registerTask("server", ["connect", "watch"]);
    grunt.registerTask("minify", ["uglify"]);
    grunt.registerTask("test-jshint", ["jshint"]);
    grunt.registerTask("test-jasmine", ["jasmine"]);
    grunt.registerTask("test-browsers", ["connect", "saucelabs-jasmine"]);
    grunt.registerTask("test-all", ["jshint", "jasmine", "connect", "saucelabs-jasmine"]);
    grunt.registerTask("travis-ci", ["test-all"]);

    grunt.registerTask("default", ["test-jshint", "test-jasmine", "minify"]);

};
<|endoftext|>


<commit_before>var gulp = require('gulp');
var gutil = require('gulp-util');
var ts = require('gulp-typescript');
var del = require('del');
var webpack = require('webpack');
var gulpFormat = require('gulp-clang-format');
var clangFormat = require('clang-format');

gulp.task('clean', function(cb) { del('dist/', cb); });

gulp.task('es5', function() {
  var tsProject = ts.createProject('tsconfig.json', {module: 'commonjs', target: 'es5'});

  var tsResult =
      gulp.src(['node_modules/typescript/lib/lib.es6.d.ts', 'typings/tsd.d.ts', 'src/**/*.ts']).pipe(ts(tsProject));

  return tsResult.js.pipe(gulp.dest('dist/cjs'));
});

gulp.task('es6', function() {
  var tsProject = ts.createProject('tsconfig.json');

  var tsResult = gulp.src(['typings/tsd.d.ts', 'src/**/*.ts']).pipe(ts(tsProject));

  return tsResult.js.pipe(gulp.dest('dist/es6'));
});

gulp.task('umd', ['es5', 'es6'], function(cb) {
  webpack(
      {
        entry: './dist/cjs/core.js',
        output: {filename: 'dist/global/ng-bootstrap.js', libraryTarget: 'umd'},
        externals: {'angular2/angular2': 'angular2/angular2'}
      },
      function(err, stats) {
        if (err) throw new gutil.PluginError('webpack', err);
        gutil.log("[webpack]", stats.toString());
        cb();
      })
});

gulp.task('check-format', function() {
  return doCheckFormat().on(
      'warning', function(e) { console.log("NOTE: this will be promoted to an ERROR in the continuous build"); });
});

gulp.task('enforce-format', function() {
  return doCheckFormat().on('warning', function(e) {
    console.log("ERROR: You forgot to run clang-format on your change.");
    console.log("See https://github.com/ng-bootstrap/core/blob/master/DEVELOPER.md#clang-format");
    process.exit(1);
  });
});

gulp.task('build', ['clean', 'umd', 'check-format']);
gulp.task('default', ['build']);

// formatting
function doCheckFormat() {
  return gulp.src(['gulpfile.js', 'src/**/*.ts']).pipe(gulpFormat.checkFormat('file', clangFormat));
}<commit_msg>chore: fix umd for ES5<commit_after>var gulp = require('gulp');
var gutil = require('gulp-util');
var ts = require('gulp-typescript');
var del = require('del');
var webpack = require('webpack');
var gulpFormat = require('gulp-clang-format');
var clangFormat = require('clang-format');

gulp.task('clean', function(cb) { del('dist/', cb); });

gulp.task('es5', function() {
  var tsProject = ts.createProject('tsconfig.json', {module: 'commonjs', target: 'es5'});

  var tsResult =
      gulp.src(['node_modules/typescript/lib/lib.es6.d.ts', 'typings/tsd.d.ts', 'src/**/*.ts']).pipe(ts(tsProject));

  return tsResult.js.pipe(gulp.dest('dist/cjs'));
});

gulp.task('es6', function() {
  var tsProject = ts.createProject('tsconfig.json');

  var tsResult = gulp.src(['typings/tsd.d.ts', 'src/**/*.ts']).pipe(ts(tsProject));

  return tsResult.js.pipe(gulp.dest('dist/es6'));
});

gulp.task('umd', ['es5', 'es6'], function(cb) {
  webpack(
      {
        entry: './dist/cjs/core.js',
        output: {filename: 'dist/global/ng-bootstrap.js', library: 'ngb', libraryTarget: 'umd'},
        externals: {
          'angular2/angular2':
              {root: 'ng', commonjs: 'angular2/angular2', commonjs2: 'angular2/angular2', amd: 'angular2/angular2'}
        }
      },
      function(err, stats) {
        if (err) throw new gutil.PluginError('webpack', err);
        gutil.log("[webpack]", stats.toString());
        cb();
      })
});

gulp.task('check-format', function() {
  return doCheckFormat().on(
      'warning', function(e) { console.log("NOTE: this will be promoted to an ERROR in the continuous build"); });
});

gulp.task('enforce-format', function() {
  return doCheckFormat().on('warning', function(e) {
    console.log("ERROR: You forgot to run clang-format on your change.");
    console.log("See https://github.com/ng-bootstrap/core/blob/master/DEVELOPER.md#clang-format");
    process.exit(1);
  });
});

gulp.task('build', ['clean', 'umd', 'check-format']);
gulp.task('default', ['build']);

// formatting
function doCheckFormat() {
  return gulp.src(['gulpfile.js', 'src/**/*.ts']).pipe(gulpFormat.checkFormat('file', clangFormat));
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      questions: [
        { text: "I have found a meaningful career", answer: 1 },
        { text: "I view my work as contributing to my personal growth.", answer: 1 },
        { text: "My work really makes no difference to the world.", answer: 1 },
        { text: "I understand how my work contributes to my life's meaning.", answer: 1 },
        { text: "I have a good sense of what makes my job meaningful.", answer: 1 },
        { text: "I know my work makes a positive difference in the world.", answer: 1 },
        { text: "My work helps me better understand myself.", answer: 1 },
        { text: "I have discovered work that has a satisfying purpose.", answer: 1 },
        { text: "My work helps me make sense of the world around me.", answer: 1 },
        { text: "The work I do serves a greater purpose.", answer: 1 },
      ],
      results: {
        positiveMeaning: {
          name: "Positive Meaning",
          text: "The Positive Meaning scale reflects the degree to which people find their work to hold personal meaning, significance, or purpose.",
          result: 0,
          max: 20
        },
        meaningMakingThroughWork: {
          name: "Meaning-Making through Work",
          text: "The Meaning-Making through Work score reflects the fact that work is often a source of broader meaning in life for people, helping them to make sense of their live experience.",
          result: 0,
          max: 15
        },
        greaterGoodMotivations: {
          name: "Greater Good Motivations",
          text: "The Greater Good Motivations score reflects the degree to which people see that their effort at work makes a positive contribution and benefits others or society.",
          result: 0,
          max: 15
        },
        meaningfulWork: {
          name: "Meaningful Work",
          text: "The Meaningful Work score reflects the depth to which people experience their work as meaningful, as something they are personally invested in, and which is a source of flourishing in their lives.",
          result: 0,
          max: 50
        }
      },
    };

    this.updateAnswer = this.updateAnswer.bind(this);
  }

  updateAnswer(event) {
    var newValue = Number.parseInt(event.target.value, 10);
    var answerIndex = event.target.id.slice(6);
    var newState = this.state;
    newState.questions[answerIndex].answer = newValue;
    newState.results.positiveMeaning.result = newState.questions[0].answer + newState.questions[3].answer + newState.questions[4].answer + newState.questions[7].answer;
    newState.results.meaningMakingThroughWork.result = newState.questions[1].answer + newState.questions[6].answer + newState.questions[8].answer;
    newState.results.greaterGoodMotivations.result = 6 - newState.questions[2].answer + newState.questions[5].answer + newState.questions[9].answer;
    newState.results.meaningfulWork.result = newState.results.positiveMeaning.result + newState.results.meaningMakingThroughWork.result + newState.results.greaterGoodMotivations.result;
    this.setState(newState);
  }

  render() {
    return (

The Work and Meaning Inventory

          The Work and Meaning Inventory (WAMI) estimates your feelings of meaning in work. It was created by Dr. Steger. The original PDF may be found here and the research summary may be found here.

Questions

        {
          this.state.questions.map((question, index) =>

              {question.text}
              <input id={"answer" + index} type="range" min="1" max="5" step="1" defaultValue="1" onChange={this.updateAnswer} />
              {question.answer}

          )
        }
        { //this.state.results.meaningfulWork.result > 0 &&

Results

              {
                [ "positiveMeaning", "meaningMakingThroughWork", "greaterGoodMotivations", "meaningfulWork" ].map((name) =>

{this.state.results[name].name}: {this.state.results[name].result} out of {this.state.results[name].max} ({((this.state.results[name].result / this.state.results[name].max) * 100).toFixed(2)}%)

                )
              }

        }

Source code at https://github.com/kevgrig/wami-react

    );
  }
}

export default App;
<commit_msg>Add a few comments<commit_after>import React, { Component } from 'react';
import './App.css';

class App extends Component {
  constructor(props) {
    super(props);

    this.state = {
      questions: [
        { text: "I have found a meaningful career", answer: 1 },
        { text: "I view my work as contributing to my personal growth.", answer: 1 },
        { text: "My work really makes no difference to the world.", answer: 1 },
        { text: "I understand how my work contributes to my life's meaning.", answer: 1 },
        { text: "I have a good sense of what makes my job meaningful.", answer: 1 },
        { text: "I know my work makes a positive difference in the world.", answer: 1 },
        { text: "My work helps me better understand myself.", answer: 1 },
        { text: "I have discovered work that has a satisfying purpose.", answer: 1 },
        { text: "My work helps me make sense of the world around me.", answer: 1 },
        { text: "The work I do serves a greater purpose.", answer: 1 },
      ],
      results: {
        positiveMeaning: {
          name: "Positive Meaning",
          text: "The Positive Meaning scale reflects the degree to which people find their work to hold personal meaning, significance, or purpose.",
          result: 0,
          max: 20
        },
        meaningMakingThroughWork: {
          name: "Meaning-Making through Work",
          text: "The Meaning-Making through Work score reflects the fact that work is often a source of broader meaning in life for people, helping them to make sense of their live experience.",
          result: 0,
          max: 15
        },
        greaterGoodMotivations: {
          name: "Greater Good Motivations",
          text: "The Greater Good Motivations score reflects the degree to which people see that their effort at work makes a positive contribution and benefits others or society.",
          result: 0,
          max: 15
        },
        meaningfulWork: {
          name: "Meaningful Work",
          text: "The Meaningful Work score reflects the depth to which people experience their work as meaningful, as something they are personally invested in, and which is a source of flourishing in their lives.",
          result: 0,
          max: 50
        }
      },
    };

    this.updateAnswer = this.updateAnswer.bind(this);
  }

  updateAnswer(event) {
    var newValue = Number.parseInt(event.target.value, 10);

    // Extract the question index from the identifier (created in render)
    var answerIndex = event.target.id.slice(6);

    var newState = this.state;
    newState.questions[answerIndex].answer = newValue;

    // Calculations from http://www.michaelfsteger.com/wp-content/uploads/2012/08/WAMI.pdf
    // Answers array is 0-indexed so "item 1" from the PDF is index 0 in the questions array
    newState.results.positiveMeaning.result = newState.questions[0].answer + newState.questions[3].answer + newState.questions[4].answer + newState.questions[7].answer;
    newState.results.meaningMakingThroughWork.result = newState.questions[1].answer + newState.questions[6].answer + newState.questions[8].answer;
    newState.results.greaterGoodMotivations.result = 6 - newState.questions[2].answer + newState.questions[5].answer + newState.questions[9].answer;
    newState.results.meaningfulWork.result = newState.results.positiveMeaning.result + newState.results.meaningMakingThroughWork.result + newState.results.greaterGoodMotivations.result;

    this.setState(newState);
  }

  render() {
    return (

The Work and Meaning Inventory

          The Work and Meaning Inventory (WAMI) estimates your feelings of meaning in work. It was created by Dr. Steger. The original PDF may be found here and the research summary may be found here.

Questions

        {
          this.state.questions.map((question, index) =>

              {question.text}
              <input id={"answer" + index} type="range" min="1" max="5" step="1" defaultValue="1" onChange={this.updateAnswer} />
              {question.answer}

          )
        }

Results

            {
              [ "positiveMeaning", "meaningMakingThroughWork", "greaterGoodMotivations", "meaningfulWork" ].map((name) =>

{this.state.results[name].name}: {this.state.results[name].result} out of {this.state.results[name].max} ({((this.state.results[name].result / this.state.results[name].max) * 100).toFixed(2)}%)

              )
            }

Source code at https://github.com/kevgrig/wami-react

    );
  }
}

export default App;
<|endoftext|>


<commit_before>"use strict";

var keys = null;
var testUrl = 'http://localhost:43091/demo';
var numErrors = 0;

function getInfo(elemId) {
    return JSON.parse(casper.page.evaluate(function(id) {
        var theElement = document.getElementById(id);
        var rect = theElement.getBoundingClientRect();
        return JSON.stringify({
            value: 'getTypedValue' in theElement?theElement.getTypedValue():'not adapted',
            cx: Math.floor((rect.left+rect.right)/2),
            cy: Math.floor((rect.top+rect.bottom)/2),
            isActive: document.activeElement === theElement
        })
    }, elemId));
}

function sendKey(keysOrKey){
    if(typeof keysOrKey === "string"){
        casper.page.sendEvent('keypress', keysOrKey);
    }else{
        var sendEvent = casper.page.sendEvent;
        sendEvent('keydown', keysOrKey);
        sendEvent('keyup', keysOrKey);
    }
}

function sendFocus(elem) {
    casper.page.evaluate(function(id) {
       var theElement = document.getElementById(id);
       theElement.focus();
    }, elem);
}

function testSendKeyAndCompare(test, elementId, key, expected, description){
    sendKey(key);
    var info = getInfo(elementId);
    test.assertEquals(info.value, expected, description );
};

function testSendClickAndCompare(test, elementId, expected, description){
    var info = getInfo(elementId);
    casper.page.sendEvent('click', info.cx, info.cy);
    info = getInfo(elementId);
    //casper.echo("exp:"+expected+" real:"+info.value)
    test.assertEquals(info.value, expected, description);
};

function testCompareUpdate(test, winVar, winSource, sourceId, expectedVar, description){
    var myVar=casper.page.evaluate(function(wVar) {
        return window[wVar];
    }, winVar);
    var mySourceElement=casper.page.evaluate(function(wVar) {
        return window[wVar];
    }, winSource);
    var mySourceId = casper.page.evaluate(function(id) {
        return document.getElementById(id);
    }, sourceId);
    test.assertEquals(myVar, expectedVar);
    test.assertEquals(mySourceElement, mySourceId);
};

casper.test.on("fail", function () {
    ++numErrors;
});

// hooks para errores
casper.on("remote.message", function(msg) {
    this.echo("Console: " + msg);
});

casper.on("page.error", function(msg, trace) {
    this.echo("page Error: " + msg);
    for(var t in trace) {
        var tra = trace[t];
        this.echo("  ["+tra.file+":"+tra.line+"] "+tra.function)
    }
});

casper.on("resource.error", function(msg, trace) {
    this.echo("Res.Error: " + msg);
});

// Una sola vez
casper.test.begin('Setup', function(test) {
    casper.start(testUrl, function() {
        keys = casper.page.event.key;
        test.done();
    }).run(function() {
        test.done();
    });
});

// Inicio de los tests
casper.test.begin("Test checkbox", function suite(test) {
    casper.start(testUrl, function() {
        var elementId =  'bool1';
        test.assertTitle('tedede demo', 'titulo correcto');
        test.assertExists('#bool1', 'tengo bool1');
        var bool1 = getInfo(elementId);
        test.assertEquals(bool1.value, false, "default value is false");

        var testClick = testSendClickAndCompare.bind(null, test, elementId);
        testClick(true, "one click sets it to true");
        testClick(false, "one click sets it to false");
        testClick(true, "one click sets it back to true");

        var testKey = testSendKeyAndCompare.bind(null, test, elementId);
        testKey(keys.Space, false, "space sets to false");
        testKey(keys.Delete, null, "delete sets null");
        testKey(keys.Space, false, "space sets to false (2)");
        testKey(keys.Backspace, null, "backspace sets null");
        testKey(keys.Space, false, "space sets to false (3)");
        testKey(keys.Minus, null, "minus sets null");
        testKey(keys.Space, false, "space sets to false (4)");
        testKey(keys.Period, null, "period sets null");

    }).run(function() {
        test.done();
    });
});

casper.test.begin("Test Text", function(test) {
    casper.start(testUrl, function() {
        test.assertExists('#text1', 'tengo text1');
        var elementId =  'text1';
        var text1 = getInfo(elementId);
        var testKey = testSendKeyAndCompare.bind(null, test, elementId);
        test.assertEquals(text1.isActive,false);
        test.assert(! text1.value, "default value to null");
        sendFocus(elementId);
        text1 = getInfo(elementId);
        test.assertEquals(text1.isActive,true, "should be active if it has focus");
        testKey('ab', 'ab', 'should set text');
        testKey(keys.Backspace, 'a' ,'should erase the last key');
        testKey(keys.Backspace, null ,'because the control has two chars the double backspace should set to null');
        testKey(keys.Space, '', 'space in a null input should set to emtpy string');
        testKey(keys.Left, '', 'left should not alter the value');
        testKey(keys.A, 'A', 'should set to "A"');
        testKey(keys.Left,'A', 'left should not alter the value (2)');
        testKey(keys.B,'BA', 'should set to "BA"');
        testKey(keys.Delete, 'B', 'delete should erase one character');
        testKey(keys.Backspace, null, 'backspace should set to null');
        testKey(keys.Space, '', 'space in a null input should set to emtpy string (2)');
    }).run(function() {
        test.done();
    });
});

casper.test.begin("Test text with custom event", function(test) {
    casper.start(testUrl, function() {
        var elementId='txtEmiter';
        sendFocus(elementId);
        test.assertExists('#txtEmiter', 'tengo emmiter');
        casper.page.evaluate(function() {
            window.myUpdateEventResult='.';
            window.mySourceElement = null;
            txtEmiter.addEventListener("update", function updateEvent(e){
                window.myUpdateEventResult+='ok';
                window.mySourceElement = e.target;
            }, false);
        });
        var testKey = testSendKeyAndCompare.bind(null, test, elementId);
        testKey(keys.A, 'A');
        testKey(keys.Tab, 'A'); // esto debe disparar el evento
        var myUpdateEventResult=casper.page.evaluate(function() {
            return window.myUpdateEventResult;
        });
        var mySourceElement=casper.page.evaluate(function() {
            return window.mySourceElement;
        });
        var txtEmiter = casper.page.evaluate(function(id) {
            return document.getElementById(id);
        }, elementId);
        test.assertEquals(myUpdateEventResult,'.ok');
        test.assertEquals(mySourceElement, txtEmiter);
    }).run(function() {
        this.test.done();
    });
});

casper.test.begin("Test checkbox with custom event", function(test) {
    casper.start(testUrl, function() {
        var elementId =  'bool1';
        test.assertExists('#'+elementId, 'tengo bool1');
        sendFocus(elementId);

        casper.page.evaluate(function() {
            window.myCounter=0;
            window.mySourceElement = null;
            bool1.addEventListener("update", function updateEvent(e){
                ++window.myCounter;
                window.mySourceElement = e.target;
            }, false);
        });

        var testClick = testSendClickAndCompare.bind(null, test, elementId);
        var compareUpdate = testCompareUpdate.bind(null, test, 'myCounter', 'mySourceElement', elementId);

        testClick(true, "click should change value to TRUE and fire update");
        compareUpdate(1, 'should set to 1')

        testClick(false, "another click should change value to FALSE and fire update");
        compareUpdate(2, 'should set to 2')

        testClick(true, "another click should change value BACK TO TRUE and fire update");
        compareUpdate(3, 'should set to 3')

        var testKey = testSendKeyAndCompare.bind(null, test, elementId);
        testKey(keys.Space, false, 'SPACE should change value to FALSE and fire update');
        compareUpdate(4, 'should set to 4')

        testKey(keys.Space, true, 'SPACE should change value BACK to TRUE and fire update');
        compareUpdate(5, 'should set to 5')

        testKey(keys.Space, false, 'SPACE should change value BACK to FALSE and fire update');
        compareUpdate(6, 'should set to 6')

    }).run(function() {
        this.test.done();
    });
});

casper.test.begin("Test bool with options", function(test) {
    casper.start(testUrl, function() {
        test.assertExists('#bool2', 'tengo bool2');

        var elementId =  'bool2';

        var testKey = testSendKeyAndCompare.bind(null, test, elementId);
        var bool2 = getInfo(elementId);
        this.echo(bool2.value);
/*

        test.assertEquals(bool2.value, null, "default value to null");

        var labelTrue = getInfo('label-bool2-true');
        casper.page.sendEvent('click', labelTrue.cx, labelTrue.cy);
        bool2 = getInfo(elementId);
        test.assertEquals(bool2.value,true);

        var labelFalse=getInfo('bool2-false');
        casper.page.sendEvent('click', labelFalse.cx,labelFalse.cy);
        var bool2=getInfo(elementId);
        test.assertEquals(bool2.value,false);

        //este test da como resultado 'element not adapted'
        var radioButton=getInfo('bool2-true');
        casper.page.sendEvent('click',radioButton.cx, radioButton.cy);
       // console.log("############   radioButton", radioButton.value);
        var bool2=getInfo(elementId);
        test.assertEquals(bool2.value,true);
*/
    }).run(function() {
        test.done();
    });
});

// checkeo de tests funcionará al actualizar CasperJS!
casper.test.begin("Finish", function(test) {
    casper.start(testUrl, function() {
        this.echo("# errores: "+numErrors)
    }).run(function() {
        this.test.done(numErrors === 0);
    });
});<commit_msg>Refactorizo test de checkbox/update event para que sea más light<commit_after>"use strict";

var keys = null;
var testUrl = 'http://localhost:43091/demo';
var numErrors = 0;

function getInfo(elemId) {
    return JSON.parse(casper.page.evaluate(function(id) {
        var theElement = document.getElementById(id);
        var rect = theElement.getBoundingClientRect();
        return JSON.stringify({
            value: 'getTypedValue' in theElement?theElement.getTypedValue():'not adapted',
            cx: Math.floor((rect.left+rect.right)/2),
            cy: Math.floor((rect.top+rect.bottom)/2),
            isActive: document.activeElement === theElement
        })
    }, elemId));
}

function sendKey(keysOrKey){
    if(typeof keysOrKey === "string"){
        casper.page.sendEvent('keypress', keysOrKey);
    }else{
        var sendEvent = casper.page.sendEvent;
        sendEvent('keydown', keysOrKey);
        sendEvent('keyup', keysOrKey);
    }
}

function sendFocus(elem) {
    casper.page.evaluate(function(id) {
       var theElement = document.getElementById(id);
       theElement.focus();
    }, elem);
}

function testSendKeyAndCompare(test, elementId, key, expected, description){
    sendKey(key);
    var info = getInfo(elementId);
    test.assertEquals(info.value, expected, description );
};

function testSendClickAndCompare(test, elementId, expected, description){
    var info = getInfo(elementId);
    casper.page.sendEvent('click', info.cx, info.cy);
    info = getInfo(elementId);
    //casper.echo("exp:"+expected+" real:"+info.value)
    test.assertEquals(info.value, expected, description);
};

function testCompareUpdatedVar(test, winVar, expectedVar, description){
    var myVar=casper.page.evaluate(function(wVar) {
        return window[wVar];
    }, winVar);
    test.assertEquals(myVar, expectedVar, description);
};

function testCompareSender(test, sourceId, expectedSource, description){
    var mySourceElement=casper.page.evaluate(function(wVar) {
        return window[wVar];
    }, sourceId);
    var mySourceId = casper.page.evaluate(function(id) {
        return document.getElementById(id);
    }, expectedSource);
    test.assertEquals(mySourceElement, mySourceId, description);
};

casper.test.on("fail", function () {
    ++numErrors;
});

// hooks para errores
casper.on("remote.message", function(msg) {
    this.echo("Console: " + msg);
});

casper.on("page.error", function(msg, trace) {
    this.echo("page Error: " + msg);
    for(var t in trace) {
        var tra = trace[t];
        this.echo("  ["+tra.file+":"+tra.line+"] "+tra.function)
    }
});

casper.on("resource.error", function(msg, trace) {
    this.echo("Res.Error: " + msg);
});

// Una sola vez
casper.test.begin('Setup', function(test) {
    casper.start(testUrl, function() {
        keys = casper.page.event.key;
        test.done();
    }).run(function() {
        test.done();
    });
});

// Inicio de los tests
casper.test.begin("Test checkbox", function suite(test) {
    casper.start(testUrl, function() {
        var elementId =  'bool1';
        test.assertTitle('tedede demo', 'titulo correcto');
        test.assertExists('#bool1', 'tengo bool1');
        var bool1 = getInfo(elementId);
        test.assertEquals(bool1.value, false, "default value is false");

        var testClick = testSendClickAndCompare.bind(null, test, elementId);
        testClick(true, "one click sets it to true");
        testClick(false, "one click sets it to false");
        testClick(true, "one click sets it back to true");

        var testKey = testSendKeyAndCompare.bind(null, test, elementId);
        testKey(keys.Space, false, "space sets to false");
        testKey(keys.Delete, null, "delete sets null");
        testKey(keys.Space, false, "space sets to false (2)");
        testKey(keys.Backspace, null, "backspace sets null");
        testKey(keys.Space, false, "space sets to false (3)");
        testKey(keys.Minus, null, "minus sets null");
        testKey(keys.Space, false, "space sets to false (4)");
        testKey(keys.Period, null, "period sets null");

    }).run(function() {
        test.done();
    });
});

casper.test.begin("Test Text", function(test) {
    casper.start(testUrl, function() {
        test.assertExists('#text1', 'tengo text1');
        var elementId =  'text1';
        var text1 = getInfo(elementId);
        var testKey = testSendKeyAndCompare.bind(null, test, elementId);
        test.assertEquals(text1.isActive,false);
        test.assert(! text1.value, "default value to null");
        sendFocus(elementId);
        text1 = getInfo(elementId);
        test.assertEquals(text1.isActive,true, "should be active if it has focus");
        testKey('ab', 'ab', 'should set text');
        testKey(keys.Backspace, 'a' ,'should erase the last key');
        testKey(keys.Backspace, null ,'because the control has two chars the double backspace should set to null');
        testKey(keys.Space, '', 'space in a null input should set to emtpy string');
        testKey(keys.Left, '', 'left should not alter the value');
        testKey(keys.A, 'A', 'should set to "A"');
        testKey(keys.Left,'A', 'left should not alter the value (2)');
        testKey(keys.B,'BA', 'should set to "BA"');
        testKey(keys.Delete, 'B', 'delete should erase one character');
        testKey(keys.Backspace, null, 'backspace should set to null');
        testKey(keys.Space, '', 'space in a null input should set to emtpy string (2)');
    }).run(function() {
        test.done();
    });
});

casper.test.begin("Test text with custom event", function(test) {
    casper.start(testUrl, function() {
        var elementId='txtEmiter';
        sendFocus(elementId);
        test.assertExists('#txtEmiter', 'tengo emiter');
        casper.page.evaluate(function() {
            window.myUpdateEventResult='.';
            window.mySourceElement = null;
            txtEmiter.addEventListener("update", function updateEvent(e){
                window.myUpdateEventResult+='ok';
                window.mySourceElement = e.target;
            }, false);
        });
        var testKey = testSendKeyAndCompare.bind(null, test, elementId);
        testKey(keys.A, 'A', 'value should be set to "A"');
        testKey(keys.Tab, 'A', 'value should not change but fire the update event'); // esto debe disparar el evento
        var myUpdateEventResult=casper.page.evaluate(function() {
            return window.myUpdateEventResult;
        });
        var mySourceElement=casper.page.evaluate(function() {
            return window.mySourceElement;
        });
        var txtEmiter = casper.page.evaluate(function(id) {
            return document.getElementById(id);
        }, elementId);
        test.assertEquals(myUpdateEventResult,'.ok', 'result should be updated');
        test.assertEquals(mySourceElement, txtEmiter, 'update sender should be "'+elementId+'"');
    }).run(function() {
        this.test.done();
    });
});

casper.test.begin("Test checkbox with custom event", function(test) {
    casper.start(testUrl, function() {
        var elementId =  'bool1';
        test.assertExists('#'+elementId, 'tengo bool1');
        sendFocus(elementId);

        casper.page.evaluate(function() {
            window.myCounter=0;
            window.mySourceElement = null;
            bool1.addEventListener("update", function updateEvent(e){
                ++window.myCounter;
                window.mySourceElement = e.target;
            }, false);
        });

        var testClick = testSendClickAndCompare.bind(null, test, elementId);
        var compareSender = testCompareSender.bind(null, test, 'mySourceElement');
        var compareVar = testCompareUpdatedVar.bind(null, test, 'myCounter');

        testClick(true, "click should change value to TRUE and fire update");
        compareVar(1, 'should set to 1');

        testClick(false, "another click should change value to FALSE and fire update");
        compareVar(2, 'should set to 2');

        testClick(true, "another click should change value BACK TO TRUE and fire update");
        compareVar(3, 'should set to 3');

        compareSender(elementId, "sender should be '"+elementId+"'");

        var testKey = testSendKeyAndCompare.bind(null, test, elementId);
        testKey(keys.Space, false, 'SPACE should change value to FALSE and fire update');
        compareVar(4, 'should set to 4');

        testKey(keys.Space, true, 'SPACE should change value BACK to TRUE and fire update');
        compareVar(5, 'should set to 5');

        testKey(keys.Space, false, 'SPACE should change value BACK to FALSE and fire update');
        compareVar(6, 'should set to 6');

        compareSender(elementId, "sender should be '"+elementId+"'");

    }).run(function() {
        this.test.done();
    });
});

casper.test.begin("Test bool with options", function(test) {
    casper.start(testUrl, function() {
        test.assertExists('#bool2', 'tengo bool2');

        var elementId =  'bool2';

        var testKey = testSendKeyAndCompare.bind(null, test, elementId);
        var bool2 = getInfo(elementId);
        this.echo(bool2.value);
/*

        test.assertEquals(bool2.value, null, "default value to null");

        var labelTrue = getInfo('label-bool2-true');
        casper.page.sendEvent('click', labelTrue.cx, labelTrue.cy);
        bool2 = getInfo(elementId);
        test.assertEquals(bool2.value,true);

        var labelFalse=getInfo('bool2-false');
        casper.page.sendEvent('click', labelFalse.cx,labelFalse.cy);
        var bool2=getInfo(elementId);
        test.assertEquals(bool2.value,false);

        //este test da como resultado 'element not adapted'
        var radioButton=getInfo('bool2-true');
        casper.page.sendEvent('click',radioButton.cx, radioButton.cy);
       // console.log("############   radioButton", radioButton.value);
        var bool2=getInfo(elementId);
        test.assertEquals(bool2.value,true);
*/
    }).run(function() {
        test.done();
    });
});

// checkeo de tests funcionará al actualizar CasperJS!
casper.test.begin("Finish", function(test) {
    casper.start(testUrl, function() {
        this.echo("# errores: "+numErrors)
    }).run(function() {
        this.test.done(numErrors === 0);
    });
});<|endoftext|>


<commit_before>/* @flow */

import { cleanPath } from '../util/path'
import { createRoute, isSameRoute, isIncludedRoute } from '../util/route'
import { normalizeLocation } from '../util/location'

// work around weird flow bug
const toTypes: Array<Function> = [String, Object]

export default {
  name: 'router-link',
  props: {
    to: {
      type: toTypes,
      required: true
    },
    tag: {
      type: String,
      default: 'a'
    },
    exact: Boolean,
    append: Boolean,
    replace: Boolean,
    activeClass: String
  },
  render (h: Function) {
    const router = this.$router
    const current = this.$route
    const to = normalizeLocation(this.to, current, this.append)
    const resolved = router.match(to)
    const fullPath = resolved.redirectedFrom || resolved.fullPath
    const base = router.history.base
    const href = base ? cleanPath(base + fullPath) : fullPath
    const classes = {}
    const activeClass = this.activeClass || router.options.linkActiveClass || 'router-link-active'
    const compareTarget = to.path ? createRoute(null, to) : resolved
    classes[activeClass] = this.exact
      ? isSameRoute(current, compareTarget)
      : isIncludedRoute(current, compareTarget)

    const data: any = {
      class: classes,
      on: {
        click: (e) => {
          e.preventDefault()
          if (this.replace) {
            router.replace(to)
          } else {
            router.push(to)
          }
        }
      }
    }

    if (this.tag === 'a') {
      data.attrs = { href }
    } else {
      // find the first <a> child and apply href
      const a = findAnchor(this.$slots.default)
      if (a) {
        const aData = a.data || (a.data = {})
        const aAttrs = aData.attrs || (aData.attrs = {})
        aAttrs.href = href
      }
    }

    return h(this.tag, data, this.$slots.default)
  }
}

function findAnchor (children) {
  if (children) {
    let child
    for (let i = 0; i < children.length; i++) {
      child = children[i]
      if (child.tag === 'a') {
        return child
      }
      if (child.children && (child = findAnchor(child.children))) {
        return child
      }
    }
  }
}
<commit_msg>adjust <router-link> click listener target when wrapping <a><commit_after>/* @flow */

import { cleanPath } from '../util/path'
import { createRoute, isSameRoute, isIncludedRoute } from '../util/route'
import { normalizeLocation } from '../util/location'

// work around weird flow bug
const toTypes: Array<Function> = [String, Object]

export default {
  name: 'router-link',
  props: {
    to: {
      type: toTypes,
      required: true
    },
    tag: {
      type: String,
      default: 'a'
    },
    exact: Boolean,
    append: Boolean,
    replace: Boolean,
    activeClass: String
  },
  render (h: Function) {
    const router = this.$router
    const current = this.$route
    const to = normalizeLocation(this.to, current, this.append)
    const resolved = router.match(to)
    const fullPath = resolved.redirectedFrom || resolved.fullPath
    const base = router.history.base
    const href = base ? cleanPath(base + fullPath) : fullPath
    const classes = {}
    const activeClass = this.activeClass || router.options.linkActiveClass || 'router-link-active'
    const compareTarget = to.path ? createRoute(null, to) : resolved
    classes[activeClass] = this.exact
      ? isSameRoute(current, compareTarget)
      : isIncludedRoute(current, compareTarget)

    const on = {
      click: (e) => {
        e.preventDefault()
        if (this.replace) {
          router.replace(to)
        } else {
          router.push(to)
        }
      }
    }

    const data: any = {
      class: classes
    }

    if (this.tag === 'a') {
      data.on = on
      data.attrs = { href }
    } else {
      // find the first <a> child and apply listener and href
      const a = findAnchor(this.$slots.default)
      if (a) {
        const aData = a.data || (a.data = {})
        aData.on = on
        const aAttrs = aData.attrs || (aData.attrs = {})
        aAttrs.href = href
      }
    }

    return h(this.tag, data, this.$slots.default)
  }
}

function findAnchor (children) {
  if (children) {
    let child
    for (let i = 0; i < children.length; i++) {
      child = children[i]
      if (child.tag === 'a') {
        return child
      }
      if (child.children && (child = findAnchor(child.children))) {
        return child
      }
    }
  }
}
<|endoftext|>


<commit_before>const project = require("pillars");
const i18n = require("textualization");

project.services.get("http").configure({port:3001}).start();

i18n.load("vanity","./languages");
i18n.languages = ["es","en","fr"];

project.routes.add(new Route({
	iPath: 'vanity.paths.greeting'
},
function(gw){
	gw.render("./index.pug");
}));<commit_msg>un poco narrado<commit_after>const project = require("pillars");
const i18n = require("textualization");

project.services.get("http").configure({port:3001}).start();

// En un nombre de nodo, en este caso: vanity, cargamos el contenido del directorio
// Donde estarán las hojas de traducciones, que tan sólo es un fichero por idioma, con extensión js.
i18n.load("vanity","./languages");
// Declaramos los idiomas disponibles en la aplicación, el primero será el por defecto
i18n.languages = ["es","en","fr"];

// Agregamos iPath, el cual nos permite traducir también las rutas
project.routes.add(new Route({
	iPath: 'vanity.paths.greeting'
},
function(gw){
	gw.render("./index.pug");
}));<|endoftext|>


<commit_before>var ExchangeScraper = function() {
    var reader      = require('fs').readFileSync;
    this.url_format = require('url').format;
    this.js_scraper = require('jsdom').env;
    this.request    = require('request');

    this.printer    = require('./printer');

    this.xe = {
        protocol:   'http:',
        host:       'www.xe.com',
        pathname:   '/currencyconverter/convert/',
    };
    this.jquery = [reader('./lib/jquery-2.1.3.min.js', 'utf-8')];
};

ExchangeScraper.prototype.getRate = function(payload, callback) {
    var self = this;

    self.xe.query = {
        'Amount':   1,
        'From':     payload.from,
        'To':       payload.to
    };
    var xe_url = self.url_format(self.xe);

    self.printer('Scraping URL: ' + xe_url);
    self.request(xe_url, function(error, response, body) {
        var data = {};
        if (error || response.statusCode !== 200)
            callback(false, data);
        else {
            self.js_scraper({
                html:   body,
                src:    self.jquery,
                done:   function(error, window) {
                            var $ = window.$;
                            var query = $('tr.uccRes td.rightCol');
                            var rate = parseFloat(query
                                .text()
                                .match(/\d[\d\.\,]*/)[0]
                                .replace(',', ''))
                                .toFixed(2)
                                .toString();

                            if (!isNaN(rate)) {
                                data.from =         payload.from;
                                data.to =           payload.to;
                                data.created_at =   new Date();
                                data.rate =         rate;
                            }
                            callback(true, data);
                        }
            });
        }
    });
};

module.exports = ExchangeScraper;
<commit_msg>Final<commit_after>var ExchangeScraper = function() {
    var reader      = require('fs').readFileSync;
    this.url_format = require('url').format;
    this.js_scraper = require('jsdom').env;
    this.request    = require('request');

    this.printer    = require('./printer');

    this.xe = {
        protocol:   'http:',
        host:       'www.xe.com',
        pathname:   '/currencyconverter/convert/',
    };
    this.jquery = [reader('./lib/jquery-2.1.3.min.js', 'utf-8')];
};

ExchangeScraper.prototype.getRate = function(payload, callback) {
    var self = this;

    self.xe.query = {
        'Amount':   1,
        'From':     payload.from,
        'To':       payload.to
    };
    var xe_url = self.url_format(self.xe);

    self.printer('Scraping URL: ' + xe_url);
    self.request(xe_url, function(error, response, body) {
        var data = {};
        if (error || response.statusCode !== 200)
            callback(false, data);
        else {
            self.js_scraper({
                html:   body,
                src:    self.jquery,
                done:   function(error, window) {
                            var $ = window.$;
                            var query = $('tr.uccRes td.rightCol');
                            var rate = parseFloat(query
                                .text()
                                .match(/\d[\d\.\,]*/)[0]
                                .replace(',', ''))
                                .toFixed(2)
                                .toString();

                            if (!isNaN(rate)) {
                                data.from       = payload.from;
                                data.to         = payload.to;
                                data.created_at = new Date();
                                data.rate       = rate;
                            }
                            callback(true, data);
                        }
            });
        }
    });
};

module.exports = ExchangeScraper;
<|endoftext|>


<commit_before>'use strict';

import express from 'express';
import passport from 'passport';
import User from "../../api/user/user.model";
import {signToken} from '../auth.service';

var router = express.Router();

router.post('/', function(req, res, next) {
  var studentOnly = req.query.studentOnly;
  var instructorOnly = req.query.instructorOnly;
  passport.authenticate('local', function(err, user, info) {
    var error = err || info;
    if (error) {
      return res.status(401).json(error);
    }
    if (!user) {
      return res.status(404).json({message: 'Something went wrong, please try again.'});
    }

    var profile = user.profile;
    User.findById(profile._id).then((user) => {
      if (studentOnly === true && profile.isInstructor){
        res.status(401).json({"message": "user is not a student"});
      }else if (instructorOnly === true && !profile.isInstructor){
        res.status(401).json({"message": "user is not an instructor"});
      }
      var token = signToken(user._id, user.role);
      res.json({ token, profile });
    });
  })(req, res, next)
});

export default router;
<commit_msg>fixed double response problem<commit_after>'use strict';

import express from 'express';
import passport from 'passport';
import User from "../../api/user/user.model";
import {signToken} from '../auth.service';

var router = express.Router();

router.post('/', function(req, res, next) {
  var studentOnly = req.query.studentOnly;
  var instructorOnly = req.query.instructorOnly;
  passport.authenticate('local', function(err, user, info) {
    var error = err || info;
    if (error) {
      return res.status(401).json(error);
    }
    if (!user) {
      return res.status(404).json({message: 'Something went wrong, please try again.'});
    }

    var profile = user.profile;
    User.findById(profile._id).then((user) => {
      if (studentOnly === true && profile.isInstructor){
        res.status(401).json({"message": "user is not a student"});
        return;
      }else if (instructorOnly === true && !profile.isInstructor){
        res.status(401).json({"message": "user is not an instructor"});
        return;
      }
      var token = signToken(user._id, user.role);
      res.json({ token, profile });
    });
  })(req, res, next)
});

export default router;
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

/*
 * This is a worker doing the encode/decode transformations to add end-to-end
 * encryption to a WebRTC PeerConnection using the Insertable Streams API.
 */

'use strict';
let currentCryptoKey;
let useCryptoOffset;
let currentKeyIdentifier = 0;

// If using crypto offset (controlled by a checkbox):
// Do not encrypt the first couple of bytes of the payload. This allows
// a middle to determine video keyframes or the opus mode being used.
// For VP8 this is the content described in
//   https://tools.ietf.org/html/rfc6386#section-9.1
// which is 10 bytes for key frames and 3 bytes for delta frames.
// For opus (where chunk.type is not set) this is the TOC byte from
//   https://tools.ietf.org/html/rfc6716#section-3.1
//
// It makes the (encrypted) video and audio much more fun to watch and listen to
// as the decoder does not immediately throw a fatal error.
const frameTypeToCryptoOffset = {
  key: 10,
  delta: 3,
  undefined: 1,
};

function dump(chunk, direction, max = 16) {
  const data = new Uint8Array(chunk.data);
  let bytes = '';
  for (let j = 0; j < data.length && j < max; j++) {
    bytes += (data[j] < 16 ? '0' : '') + data[j].toString(16) + ' ';
  }
  console.log(performance.now().toFixed(2), direction, bytes.trim(),
      'len=' + chunk.data.byteLength,
      'type=' + (chunk.type || 'audio'),
      'ts=' + chunk.timestamp,
      'ssrc=' + chunk.synchronizationSource
  );
}

let scount = 0;
function encodeFunction(chunk, controller) {
  if (scount++ < 30) { // dump the first 30 packets.
    dump(chunk, 'send');
  }
  if (currentCryptoKey) {
    const view = new DataView(chunk.data);
    // Any length that is needed can be used for the new buffer.
    const newData = new ArrayBuffer(chunk.data.byteLength + 5);
    const newView = new DataView(newData);

    const cryptoOffset = useCryptoOffset? frameTypeToCryptoOffset[chunk.type] : 0;
    for (let i = 0; i < cryptoOffset && i < chunk.data.byteLength; ++i) {
      newView.setInt8(i, view.getInt8(i));
    }
    // This is a bitwise xor of the key with the payload. This is not strong encryption, just a demo.
    for (let i = cryptoOffset; i < chunk.data.byteLength; ++i) {
      const keyByte = currentCryptoKey.charCodeAt(i % currentCryptoKey.length);
      newView.setInt8(i, view.getInt8(i) ^ keyByte);
    }
    // Append keyIdentifier.
    newView.setUint8(chunk.data.byteLength, currentKeyIdentifier % 0xff);
    // Append checksum
    newView.setUint32(chunk.data.byteLength + 1, 0xDEADBEEF);

    chunk.data = newData;
  }
  controller.enqueue(chunk);
}

let rcount = 0;
function decodeFunction(chunk, controller) {
  if (rcount++ < 30) { // dump the first 30 packets
    dump(chunk, 'recv');
  }
  const view = new DataView(chunk.data);
  const checksum = chunk.data.byteLength > 4 ? view.getUint32(chunk.data.byteLength - 4) : false;
  if (currentCryptoKey) {
    if (checksum !== 0xDEADBEEF) {
      console.log('Corrupted frame received, checksum ' +
                  checksum.toString(16));
      return; // This can happen when the key is set and there is an unencrypted frame in-flight.
    }
    const keyIdentifier = view.getUint8(chunk.data.byteLength - 5);
    if (keyIdentifier !== currentKeyIdentifier) {
      console.log(`Key identifier mismatch, got ${keyIdentifier} expected ${currentKeyIdentifier}.`);
      return;
    }

    const newData = new ArrayBuffer(chunk.data.byteLength - 5);
    const newView = new DataView(newData);
    const cryptoOffset = useCryptoOffset? frameTypeToCryptoOffset[chunk.type] : 0;

    for (let i = 0; i < cryptoOffset; ++i) {
      newView.setInt8(i, view.getInt8(i));
    }
    for (let i = cryptoOffset; i < chunk.data.byteLength - 5; ++i) {
      const keyByte = currentCryptoKey.charCodeAt(i % currentCryptoKey.length);
      newView.setInt8(i, view.getInt8(i) ^ keyByte);
    }
    chunk.data = newData;
  } else if (checksum === 0xDEADBEEF) {
    return; // encrypted in-flight frame but we already forgot about the key.
  }
  controller.enqueue(chunk);
}

onmessage = async (event) => {
  const {operation} = event.data;
  if (operation === 'encode') {
    const {readableStream, writableStream} = event.data;
    const transformStream = new TransformStream({
      transform: encodeFunction,
    });
    readableStream
        .pipeThrough(transformStream)
        .pipeTo(writableStream);
  } else if (operation === 'decode') {
    const {readableStream, writableStream} = event.data;
    const transformStream = new TransformStream({
      transform: decodeFunction,
    });
    readableStream
        .pipeThrough(transformStream)
        .pipeTo(writableStream);
  } else if (operation === 'setCryptoKey') {
    if (event.data.currentCryptoKey !== currentCryptoKey) {
      currentKeyIdentifier++;
    }
    currentCryptoKey = event.data.currentCryptoKey;
    useCryptoOffset = event.data.useCryptoOffset;
  }
};
<commit_msg>e2ee: fix initial setting of useCryptoOffset (#1288)<commit_after>/*
 *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

/*
 * This is a worker doing the encode/decode transformations to add end-to-end
 * encryption to a WebRTC PeerConnection using the Insertable Streams API.
 */

'use strict';
let currentCryptoKey;
let useCryptoOffset = true;
let currentKeyIdentifier = 0;

// If using crypto offset (controlled by a checkbox):
// Do not encrypt the first couple of bytes of the payload. This allows
// a middle to determine video keyframes or the opus mode being used.
// For VP8 this is the content described in
//   https://tools.ietf.org/html/rfc6386#section-9.1
// which is 10 bytes for key frames and 3 bytes for delta frames.
// For opus (where chunk.type is not set) this is the TOC byte from
//   https://tools.ietf.org/html/rfc6716#section-3.1
//
// It makes the (encrypted) video and audio much more fun to watch and listen to
// as the decoder does not immediately throw a fatal error.
const frameTypeToCryptoOffset = {
  key: 10,
  delta: 3,
  undefined: 1,
};

function dump(chunk, direction, max = 16) {
  const data = new Uint8Array(chunk.data);
  let bytes = '';
  for (let j = 0; j < data.length && j < max; j++) {
    bytes += (data[j] < 16 ? '0' : '') + data[j].toString(16) + ' ';
  }
  console.log(performance.now().toFixed(2), direction, bytes.trim(),
      'len=' + chunk.data.byteLength,
      'type=' + (chunk.type || 'audio'),
      'ts=' + chunk.timestamp,
      'ssrc=' + chunk.synchronizationSource
  );
}

let scount = 0;
function encodeFunction(chunk, controller) {
  if (scount++ < 30) { // dump the first 30 packets.
    dump(chunk, 'send');
  }
  if (currentCryptoKey) {
    const view = new DataView(chunk.data);
    // Any length that is needed can be used for the new buffer.
    const newData = new ArrayBuffer(chunk.data.byteLength + 5);
    const newView = new DataView(newData);

    const cryptoOffset = useCryptoOffset? frameTypeToCryptoOffset[chunk.type] : 0;
    for (let i = 0; i < cryptoOffset && i < chunk.data.byteLength; ++i) {
      newView.setInt8(i, view.getInt8(i));
    }
    // This is a bitwise xor of the key with the payload. This is not strong encryption, just a demo.
    for (let i = cryptoOffset; i < chunk.data.byteLength; ++i) {
      const keyByte = currentCryptoKey.charCodeAt(i % currentCryptoKey.length);
      newView.setInt8(i, view.getInt8(i) ^ keyByte);
    }
    // Append keyIdentifier.
    newView.setUint8(chunk.data.byteLength, currentKeyIdentifier % 0xff);
    // Append checksum
    newView.setUint32(chunk.data.byteLength + 1, 0xDEADBEEF);

    chunk.data = newData;
  }
  controller.enqueue(chunk);
}

let rcount = 0;
function decodeFunction(chunk, controller) {
  if (rcount++ < 30) { // dump the first 30 packets
    dump(chunk, 'recv');
  }
  const view = new DataView(chunk.data);
  const checksum = chunk.data.byteLength > 4 ? view.getUint32(chunk.data.byteLength - 4) : false;
  if (currentCryptoKey) {
    if (checksum !== 0xDEADBEEF) {
      console.log('Corrupted frame received, checksum ' +
                  checksum.toString(16));
      return; // This can happen when the key is set and there is an unencrypted frame in-flight.
    }
    const keyIdentifier = view.getUint8(chunk.data.byteLength - 5);
    if (keyIdentifier !== currentKeyIdentifier) {
      console.log(`Key identifier mismatch, got ${keyIdentifier} expected ${currentKeyIdentifier}.`);
      return;
    }

    const newData = new ArrayBuffer(chunk.data.byteLength - 5);
    const newView = new DataView(newData);
    const cryptoOffset = useCryptoOffset? frameTypeToCryptoOffset[chunk.type] : 0;

    for (let i = 0; i < cryptoOffset; ++i) {
      newView.setInt8(i, view.getInt8(i));
    }
    for (let i = cryptoOffset; i < chunk.data.byteLength - 5; ++i) {
      const keyByte = currentCryptoKey.charCodeAt(i % currentCryptoKey.length);
      newView.setInt8(i, view.getInt8(i) ^ keyByte);
    }
    chunk.data = newData;
  } else if (checksum === 0xDEADBEEF) {
    return; // encrypted in-flight frame but we already forgot about the key.
  }
  controller.enqueue(chunk);
}

onmessage = async (event) => {
  const {operation} = event.data;
  if (operation === 'encode') {
    const {readableStream, writableStream} = event.data;
    const transformStream = new TransformStream({
      transform: encodeFunction,
    });
    readableStream
        .pipeThrough(transformStream)
        .pipeTo(writableStream);
  } else if (operation === 'decode') {
    const {readableStream, writableStream} = event.data;
    const transformStream = new TransformStream({
      transform: decodeFunction,
    });
    readableStream
        .pipeThrough(transformStream)
        .pipeTo(writableStream);
  } else if (operation === 'setCryptoKey') {
    if (event.data.currentCryptoKey !== currentCryptoKey) {
      currentKeyIdentifier++;
    }
    currentCryptoKey = event.data.currentCryptoKey;
    useCryptoOffset = event.data.useCryptoOffset;
  }
};
<|endoftext|>


<commit_before>// @flow
import * as Constants from '../../../../constants/chat'
import Header from '.'
import {compose} from 'recompose'
import {connect} from 'react-redux'
import {CommonConversationMembersType} from '../../../../constants/types/flow-types-chat'

import type {TypedState} from '../../../../constants/reducer'
import type {OwnProps} from './container'

const mapStateToProps = (state: TypedState, {messageKey}: OwnProps) => {
  const conversationState = Constants.getSelectedConversationStates(state)
  const moreToLoad = conversationState && conversationState.get('moreToLoad')
  const inbox = Constants.getSelectedInbox(state)

  // If it's a multi-user chat that isn't a team, offer to make a new team.
  const showTeamOffer =
    inbox &&
    inbox.info &&
    inbox.membersType !== CommonConversationMembersType.team &&
    inbox.get('participants').size > 2

  return {
    moreToLoad,
    showTeamOffer,
  }
}

export default compose(connect(mapStateToProps, () => ({})))(Header)
<commit_msg>membersType is on info<commit_after>// @flow
import * as Constants from '../../../../constants/chat'
import Header from '.'
import {compose} from 'recompose'
import {connect} from 'react-redux'
import {CommonConversationMembersType} from '../../../../constants/types/flow-types-chat'

import type {TypedState} from '../../../../constants/reducer'
import type {OwnProps} from './container'

const mapStateToProps = (state: TypedState, {messageKey}: OwnProps) => {
  const conversationState = Constants.getSelectedConversationStates(state)
  const moreToLoad = conversationState && conversationState.get('moreToLoad')
  const inbox = Constants.getSelectedInbox(state)

  // If it's a multi-user chat that isn't a team, offer to make a new team.
  const showTeamOffer =
    inbox &&
    inbox.info &&
    inbox.info.membersType !== CommonConversationMembersType.team &&
    inbox.get('participants').size > 2

  return {
    moreToLoad,
    showTeamOffer,
  }
}

export default compose(connect(mapStateToProps, () => ({})))(Header)
<|endoftext|>


<commit_before>import { toQueryString, getUrlVars, sleep } from './utils.js';

window.visualize = visualize; // Add function to global scope.

/**
 * Get the simulation metadata encoded as a query string, iterate over all rounds and visualize
 * the real and estimated board state at each round (with a 1000 ms delay between two consecutive rounds).
 */
async function visualize() {
    const realBoardElementId = 'real-board-table';
    const estimatedBoardElementId = 'estimated-board-table';
    var simulation = getUrlVars();
    var mainHeader = document.getElementById('simulation-visualization-header');
    var roundHeader = document.getElementById('current-round-header');
    var delay;
    mainHeader.innerText = 'Visualizing Simulation\n' + simulation.id;
    var params = {};
    params['simulationId'] = simulation.id;
    for (var round = 0; round < simulation.roundsNum; round++) {
        roundHeader.innerText = 'Current Round: ' + round;
        params['round'] = round;

        // Request real board state.
        params['isReal'] = true;
        await fetchReadBoardState(params, realBoardElementId);

        // Request estimated board state.
        params['isReal'] = false;
        await fetchReadBoardState(params, estimatedBoardElementId);

        // Delay.
        delay = 1/document.getElementById('speed-controller').value;
        await sleep(delay);
    }
    displayStats(params);
}

/**
 * Fetch board state from servlet by given parameters, and update an HTML table corresponding to given
 * board element id to visualize the board's state.
 * @param {Object} params is an object storing parameters for http request.
 * @param {String} boardElementId is the id of the html table element to be updated.
 */
async function fetchReadBoardState(params, boardElementId) {
    const queryString = toQueryString(params);
    fetch(`/read-board-state?${queryString}`)
    .then(response => response.json())
    .then(boardState => visualizeBoardState(boardState.array, boardElementId));
}

/**
 * Given a board state and an id of an html table element, update the table to display the board state.
 * @param {String[][]} board is the board state to visualize.
 * @param {String} tableId is the id of the html table element to be updated.
 */
function visualizeBoardState(board, tableId) {

    // Set table and table body
    var boardTable = document.getElementById(tableId);
    var boardTableBody = document.createElement('tbody');

    // Change cells' classes according to board.
    board.forEach(function(rowData) {

        var row = document.createElement('tr');
        row.classList.add('board-tr')

        rowData.forEach(function(cellData) {
            var cell = document.createElement('td');
            cell.classList.add('board-td');
            updateCell(cell, cellData);
            row.appendChild(cell);
        });

        boardTableBody.appendChild(row);
    });

    // Clear last state of table (if table body exists).
    var oldTableBodies = boardTable.tBodies;
    if (oldTableBodies.length > 0) {
        boardTable.removeChild(oldTableBodies[0]);
    }

    // Append updated table body.
    boardTable.appendChild(boardTableBody);
}

/**
 * Update the cell according to the agents inside it.
 * @param {HTMLTableDataCellElement} cell is an HTML element from type <td>, representing a cell on the board.
 * @param {String[]} agents is a list of agents ids located inside the cell.
 */
function updateCell(cell, agents) {
    var beaconsIdsInsideCell = extractBeaconsIds(agents);
    cell.setAttribute('title', beaconsIdsInsideCell.join(","));

    var beaconToFocusOn = document.getElementById("beacon-id").value;
    var isBeaconToFocusOnInCell = beaconToFocusOn != "" && beaconsIdsInsideCell.includes(beaconToFocusOn);
    cell.classList.add(determineCellClass(agents, beaconsIdsInsideCell.length, isBeaconToFocusOnInCell));
}

/**
 * return the css class name representing the correct state of the cell (empty/contains beacons/observers only).
 * @param {String[]} agents a list of agents ids located in the same cell of the board.
 * @returns {String} the correct css class name.
 */
function determineCellClass(agents, numberOfBeacons, isBeaconToFocusOnInCell) {
    if (agents.length === 0) {
        return 'board-td-empty';
    }
    if (isBeaconToFocusOnInCell) {
        return 'board-td-contains-wanted-beacon';
    }
    if (numberOfBeacons > 0) {
       return 'board-td-contains-beacon';
    }
    return 'board-td-observers-only';
}

/**
 * Returns a sorted list of all the beacons' ids in the given list.
 * @param {String[]} agents is a list of agents ids located in the same cell of the board.
 */
function extractBeaconsIds(agents) {
    var beaconsIds = agents.filter(agent => agent.charAt(0) === 'B')
                    .map(agent => agent.slice(6));
    return beaconsIds.sort((a, b) => parseInt(a) - parseInt(b));
}

/**
 * Display the statistical data of a simulation.
 * @param {Object*} params is an object storing parameters for http request.
 */
function displayStats(params) {
    const queryString = toQueryString(params);
    fetch(`/read-stats?${queryString}`)
    .then(response => response.json())
    .then(stats => Object.keys(stats).forEach(kind => createStatsTable(kind, stats[kind])))
    .then(() => clearVisualizationElements());
}

/**
 * Create an HTML table element add fill it with statistical data.
 * @param {String} kind is the statistical data kind (distance or beacon observed percent).
 * @param {Object} stats is an object storing the simulations' stats of a specific kind.
 */
function createStatsTable(kind, stats) {
    var title = document.createElement('h4');
    title.innerText = kind;
    var table = document.createElement('table');
    table.classList.add('stats-table');
    var header = table.createTHead();
    var headerRow = header.insertRow(0);
    var dataRow = table.insertRow(1);
    var i = 0;
    Object.keys(stats).forEach(measure => {
        headerRow.insertCell(i).innerText = measure;
        dataRow.insertCell(i).innerText = stats[measure];
        i++;
    });
    document.body.appendChild(title);
    document.body.appendChild(table);
}

/** Clear all HTML element used for visualization. */
function clearVisualizationElements() {
    document.getElementsByClassName('boards')[0].innerHTML = '';
    document.getElementsByClassName('choose-beacon')[0].innerHTML = '';
    document.getElementsByClassName('speed-controller')[0].innerHTML = '';
}<commit_msg>add prefix to beacon observed percent stats measures.<commit_after>import { toQueryString, getUrlVars, sleep } from './utils.js';

window.visualize = visualize; // Add function to global scope.

/**
 * Get the simulation metadata encoded as a query string, iterate over all rounds and visualize
 * the real and estimated board state at each round (with a 1000 ms delay between two consecutive rounds).
 */
async function visualize() {
    const realBoardElementId = 'real-board-table';
    const estimatedBoardElementId = 'estimated-board-table';
    var simulation = getUrlVars();
    var mainHeader = document.getElementById('simulation-visualization-header');
    var roundHeader = document.getElementById('current-round-header');
    var delay;
    mainHeader.innerText = 'Visualizing Simulation\n' + simulation.id;
    var params = {};
    params['simulationId'] = simulation.id;
    for (var round = 0; round < simulation.roundsNum; round++) {
        roundHeader.innerText = 'Current Round: ' + round;
        params['round'] = round;

        // Request real board state.
        params['isReal'] = true;
        await fetchReadBoardState(params, realBoardElementId);

        // Request estimated board state.
        params['isReal'] = false;
        await fetchReadBoardState(params, estimatedBoardElementId);

        // Delay.
        delay = 1/document.getElementById('speed-controller').value;
        await sleep(delay);
    }
    displayStats(params);
}

/**
 * Fetch board state from servlet by given parameters, and update an HTML table corresponding to given
 * board element id to visualize the board's state.
 * @param {Object} params is an object storing parameters for http request.
 * @param {String} boardElementId is the id of the html table element to be updated.
 */
async function fetchReadBoardState(params, boardElementId) {
    const queryString = toQueryString(params);
    fetch(`/read-board-state?${queryString}`)
    .then(response => response.json())
    .then(boardState => visualizeBoardState(boardState.array, boardElementId));
}

/**
 * Given a board state and an id of an html table element, update the table to display the board state.
 * @param {String[][]} board is the board state to visualize.
 * @param {String} tableId is the id of the html table element to be updated.
 */
function visualizeBoardState(board, tableId) {

    // Set table and table body
    var boardTable = document.getElementById(tableId);
    var boardTableBody = document.createElement('tbody');

    // Change cells' classes according to board.
    board.forEach(function(rowData) {

        var row = document.createElement('tr');
        row.classList.add('board-tr')

        rowData.forEach(function(cellData) {
            var cell = document.createElement('td');
            cell.classList.add('board-td');
            updateCell(cell, cellData);
            row.appendChild(cell);
        });

        boardTableBody.appendChild(row);
    });

    // Clear last state of table (if table body exists).
    var oldTableBodies = boardTable.tBodies;
    if (oldTableBodies.length > 0) {
        boardTable.removeChild(oldTableBodies[0]);
    }

    // Append updated table body.
    boardTable.appendChild(boardTableBody);
}

/**
 * Update the cell according to the agents inside it.
 * @param {HTMLTableDataCellElement} cell is an HTML element from type <td>, representing a cell on the board.
 * @param {String[]} agents is a list of agents ids located inside the cell.
 */
function updateCell(cell, agents) {
    var beaconsIdsInsideCell = extractBeaconsIds(agents);
    cell.setAttribute('title', beaconsIdsInsideCell.join(","));

    var beaconToFocusOn = document.getElementById("beacon-id").value;
    var isBeaconToFocusOnInCell = beaconToFocusOn != "" && beaconsIdsInsideCell.includes(beaconToFocusOn);
    cell.classList.add(determineCellClass(agents, beaconsIdsInsideCell.length, isBeaconToFocusOnInCell));
}

/**
 * return the css class name representing the correct state of the cell (empty/contains beacons/observers only).
 * @param {String[]} agents a list of agents ids located in the same cell of the board.
 * @returns {String} the correct css class name.
 */
function determineCellClass(agents, numberOfBeacons, isBeaconToFocusOnInCell) {
    if (agents.length === 0) {
        return 'board-td-empty';
    }
    if (isBeaconToFocusOnInCell) {
        return 'board-td-contains-wanted-beacon';
    }
    if (numberOfBeacons > 0) {
       return 'board-td-contains-beacon';
    }
    return 'board-td-observers-only';
}

/**
 * Returns a sorted list of all the beacons' ids in the given list.
 * @param {String[]} agents is a list of agents ids located in the same cell of the board.
 */
function extractBeaconsIds(agents) {
    var beaconsIds = agents.filter(agent => agent.charAt(0) === 'B')
                    .map(agent => agent.slice(6));
    return beaconsIds.sort((a, b) => parseInt(a) - parseInt(b));
}

/**
 * Display the statistical data of a simulation.
 * @param {Object*} params is an object storing parameters for http request.
 */
function displayStats(params) {
    const queryString = toQueryString(params);
    fetch(`/read-stats?${queryString}`)
    .then(response => response.json())
    .then(stats => Object.keys(stats).forEach(kind => createStatsTable(kind, stats[kind])))
    .then(() => clearVisualizationElements());
}

/**
 * Create an HTML table element add fill it with statistical data.
 * @param {String} kind is the statistical data kind (distance or beacon observed percent).
 * @param {Object} stats is an object storing the simulations' stats of a specific kind.
 */
function createStatsTable(kind, stats) {
    var title = document.createElement('h4');
    title.innerText = kind;
    var table = document.createElement('table');
    table.classList.add('stats-table');
    var header = table.createTHead();
    var headerRow = header.insertRow(0);
    var dataRow = table.insertRow(1);

    // For beacon observed stats add the prefix 'beacon' to each measure name.
    var prefix = kind === 'BeaconsObservedPercentStats' ? 'beacon #' : '';

    var i = 0;
    Object.keys(stats).forEach(measure => {
        headerRow.insertCell(i).innerText = prefix + measure;
        dataRow.insertCell(i).innerText = stats[measure];
        i++;
    });
    document.body.appendChild(title);
    document.body.appendChild(table);
}

/** Clear all HTML element used for visualization. */
function clearVisualizationElements() {
    document.getElementsByClassName('boards')[0].innerHTML = '';
    document.getElementsByClassName('choose-beacon')[0].innerHTML = '';
    document.getElementsByClassName('speed-controller')[0].innerHTML = '';
}<|endoftext|>


<commit_before>import getElementById from '../../common/getElement';
import querySelectorAll from '../../common/querySelectorAll';

const calcHeight = (collection) => collection.length * 22;

const byLink = (type) => calcHeight(
  getElementById(`nav-${type}`).nextElementSibling.children,
);

const bySection = (section) => calcHeight(
  querySelectorAll(`#nav-${section} > ul li`),
);

export default function adjustHeight(theNav, myNav) {
  // first the closed saved variables
  // eslint-disable-next-line no-param-reassign
  myNav.heights = [
    null,
    null,
    byLink('character'),
    bySection('actions'),
    bySection('guild'),
    bySection('toprated'),
    bySection('upgrades'),
    byLink('resources'),
    null,
  ];
  if (Number(myNav.state) !== -1) {
    // and now the open one
    // eslint-disable-next-line no-param-reassign
    theNav.children[myNav.state].children[1].style
      .height = `${myNav.heights[myNav.state]}px`;
  }
}
<commit_msg>remove hard coded values v2 #194<commit_after>import querySelectorArray from '../../common/querySelectorArray';

export default function adjustHeight(theNav, myNav) {
  // first the closed saved variables
  // eslint-disable-next-line no-param-reassign
  myNav.heights = querySelectorArray('#nav > li')
    .map((li) => (querySelectorArray('li', li).length * 22) || null);
  if (Number(myNav.state) !== -1) {
    // and now the open one
    // eslint-disable-next-line no-param-reassign
    theNav.children[myNav.state].children[1].style
      .height = `${myNav.heights[myNav.state]}px`;
  }
}
<|endoftext|>


<commit_before>import {
  CREATE_REPLY,
  DELETE_TICKET,
  FETCH_TICKETS,
  FILTER_TICKETS,
  RECEIVE_TICKETS,
  SELECT_TICKET,
  SET_MESSAGES_TO_READ,
  SORT_TICKETS,
  TICKET_STATUS_OPEN,
  UPDATE_TICKET
} from '../constants/tickets';
import { STATUSES } from '../components/tickets/util';
import { API_FAIL } from '../constants/api';
import { ADD_NOTIFICATION } from '../constants';
import fetch from 'cross-fetch';

const getCsrf = () => document.querySelector("meta[name='csrf-token']").getAttribute('content');

export const notifyOfMessage = body => async (dispatch) => {
  try {
    const response = await fetch('/tickets/notify_owner', {
      body: JSON.stringify(body),
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
        'X-CSRF-Token': getCsrf()
      },
      method: 'POST'
    });
    if (!response.ok) {
      const json = await response.json();
      dispatch({ type: API_FAIL, data: { statusText: json.message } });
    } else {
      dispatch({
        type: ADD_NOTIFICATION,
        notification: {
          message: 'Email was sent to the owner.',
          status: 'success'
        }
      });
    }
  } catch (error) {
    const message = 'Email could not be sent.';
    dispatch({ type: API_FAIL, data: { statusText: message } });
  }
};

export const createReply = (body, status) => async (dispatch) => {
  let notificationBody;
  try {
    const response = await fetch('/td/tickets/replies', {
      body: JSON.stringify({ ...body, read: true, status }),
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
        'X-CSRF-Token': getCsrf()
      },
      method: 'POST'
    });

    const message = await response.json();
    notificationBody = {
      sender_id: body.sender_id,
      message_id: message.id
    };
  } catch (error) {
    const message = 'Creation of message failed. Please try again.';
    dispatch({ type: API_FAIL, data: { statusText: message } });
  }

  try {
    const response = await fetch('/tickets/notify', {
      body: JSON.stringify(notificationBody),
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
        'X-CSRF-Token': getCsrf()
      },
      method: 'POST'
    });
    if (!response.ok) {
      const json = await response.json();
      dispatch({ type: API_FAIL, data: { statusText: json.message } });
    }
  } catch (error) {
    const message = 'Message was created but email could not be sent.';
    dispatch({ type: API_FAIL, data: { statusText: message } });
  }

  dispatch({ type: CREATE_REPLY });
};

export const readAllMessages = ticket => async (dispatch) => {
  const unreadMessages = ticket.messages.some(message => !message.read);
  if (!unreadMessages) return false;

  const response = await fetch('/td/read_all_messages', {
    body: JSON.stringify({ ticket_id: ticket.id }),
    credentials: 'include',
    headers: {
      'Content-Type': 'application/json',
      'X-CSRF-Token': getCsrf()
    },
    method: 'PUT'
  });
  const json = await response.json();
  dispatch({ type: SET_MESSAGES_TO_READ, data: json });
};

export const fetchTickets = () => async (dispatch) => {
  dispatch({ type: FETCH_TICKETS });

  const response = await fetch('/td/tickets');
  const json = await response.json();

  dispatch({ type: RECEIVE_TICKETS, data: json.tickets });
};

export const selectTicket = ticket => ({ type: SELECT_TICKET, ticket });

export const fetchTicket = id => async (dispatch) => {
  const response = await fetch(`/td/tickets/${id}`);
  const data = await response.json();
  dispatch(selectTicket(data.ticket));
};

export const sortTickets = key => ({ type: SORT_TICKETS, key });

const updateTicket = async (id, ticket, dispatch) => {
  const response = await fetch(`/td/tickets/${id}`, {
    body: JSON.stringify(ticket),
    credentials: 'include',
    headers: {
      'Content-Type': 'application/json',
      'X-CSRF-Token': getCsrf()
    },
    method: 'PATCH'
  });
  const json = await response.json();
  dispatch({ type: UPDATE_TICKET, id, data: json });
};

export const updateTicketStatus = (id, status) => (dispatch) => {
  updateTicket(id, { status }, dispatch);
};

export const updateTicketOwner = (id, owner_id) => (dispatch) => {
  updateTicket(id, { owner_id }, dispatch);
};

export const deleteTicket = id => async (dispatch) => {
  await fetch(`/td/tickets/${id}`, {
    credentials: 'include',
    headers: {
      'Content-Type': 'application/json',
      'X-CSRF-Token': getCsrf()
    },
    method: 'DELETE'
  });

  dispatch({ type: DELETE_TICKET, id });
};

export const setTicketOwnersFilter = filters => ({ type: FILTER_TICKETS, filters: { owners: filters } });
export const setTicketStatusesFilter = filters => ({ type: FILTER_TICKETS, filters: { statuses: filters } });

export const setInitialTicketFilters = () => (dispatch, getState) => {
  // Open tickets only
  dispatch(setTicketStatusesFilter([{ value: TICKET_STATUS_OPEN, label: STATUSES[TICKET_STATUS_OPEN] }]));

  // Owned by current user, or no one
  const state = getState();
  const currentUserId = state.currentUserFromHtml.id;
  const [label, value] = state.admins.find(([_username, id]) => id === currentUserId);
  const currentUserOption = { label, value };
  const unassignedOption = { label: 'unassigned', value: null };
  dispatch(setTicketOwnersFilter([currentUserOption, unassignedOption]));
};

<commit_msg>Update notification message on Email Owner<commit_after>import {
  CREATE_REPLY,
  DELETE_TICKET,
  FETCH_TICKETS,
  FILTER_TICKETS,
  RECEIVE_TICKETS,
  SELECT_TICKET,
  SET_MESSAGES_TO_READ,
  SORT_TICKETS,
  TICKET_STATUS_OPEN,
  UPDATE_TICKET
} from '../constants/tickets';
import { STATUSES } from '../components/tickets/util';
import { API_FAIL } from '../constants/api';
import { ADD_NOTIFICATION } from '../constants';
import fetch from 'cross-fetch';

const getCsrf = () => document.querySelector("meta[name='csrf-token']").getAttribute('content');

export const notifyOfMessage = body => async (dispatch) => {
  try {
    const response = await fetch('/tickets/notify_owner', {
      body: JSON.stringify(body),
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
        'X-CSRF-Token': getCsrf()
      },
      method: 'POST'
    });
    if (!response.ok) {
      const json = await response.json();
      dispatch({ type: API_FAIL, data: { statusText: json.message } });
    } else {
      dispatch({
        type: ADD_NOTIFICATION,
        notification: {
          message: 'Email was sent to the owner.',
          type: 'success',
          closable: true
        }
      });
    }
  } catch (error) {
    const message = 'Email could not be sent.';
    dispatch({ type: API_FAIL, data: { statusText: message } });
  }
};

export const createReply = (body, status) => async (dispatch) => {
  let notificationBody;
  try {
    const response = await fetch('/td/tickets/replies', {
      body: JSON.stringify({ ...body, read: true, status }),
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
        'X-CSRF-Token': getCsrf()
      },
      method: 'POST'
    });

    const message = await response.json();
    notificationBody = {
      sender_id: body.sender_id,
      message_id: message.id
    };
  } catch (error) {
    const message = 'Creation of message failed. Please try again.';
    dispatch({ type: API_FAIL, data: { statusText: message } });
  }

  try {
    const response = await fetch('/tickets/notify', {
      body: JSON.stringify(notificationBody),
      credentials: 'include',
      headers: {
        'Content-Type': 'application/json',
        'X-CSRF-Token': getCsrf()
      },
      method: 'POST'
    });
    if (!response.ok) {
      const json = await response.json();
      dispatch({ type: API_FAIL, data: { statusText: json.message } });
    }
  } catch (error) {
    const message = 'Message was created but email could not be sent.';
    dispatch({ type: API_FAIL, data: { statusText: message } });
  }

  dispatch({ type: CREATE_REPLY });
};

export const readAllMessages = ticket => async (dispatch) => {
  const unreadMessages = ticket.messages.some(message => !message.read);
  if (!unreadMessages) return false;

  const response = await fetch('/td/read_all_messages', {
    body: JSON.stringify({ ticket_id: ticket.id }),
    credentials: 'include',
    headers: {
      'Content-Type': 'application/json',
      'X-CSRF-Token': getCsrf()
    },
    method: 'PUT'
  });
  const json = await response.json();
  dispatch({ type: SET_MESSAGES_TO_READ, data: json });
};

export const fetchTickets = () => async (dispatch) => {
  dispatch({ type: FETCH_TICKETS });

  const response = await fetch('/td/tickets');
  const json = await response.json();

  dispatch({ type: RECEIVE_TICKETS, data: json.tickets });
};

export const selectTicket = ticket => ({ type: SELECT_TICKET, ticket });

export const fetchTicket = id => async (dispatch) => {
  const response = await fetch(`/td/tickets/${id}`);
  const data = await response.json();
  dispatch(selectTicket(data.ticket));
};

export const sortTickets = key => ({ type: SORT_TICKETS, key });

const updateTicket = async (id, ticket, dispatch) => {
  const response = await fetch(`/td/tickets/${id}`, {
    body: JSON.stringify(ticket),
    credentials: 'include',
    headers: {
      'Content-Type': 'application/json',
      'X-CSRF-Token': getCsrf()
    },
    method: 'PATCH'
  });
  const json = await response.json();
  dispatch({ type: UPDATE_TICKET, id, data: json });
};

export const updateTicketStatus = (id, status) => (dispatch) => {
  updateTicket(id, { status }, dispatch);
};

export const updateTicketOwner = (id, owner_id) => (dispatch) => {
  updateTicket(id, { owner_id }, dispatch);
};

export const deleteTicket = id => async (dispatch) => {
  await fetch(`/td/tickets/${id}`, {
    credentials: 'include',
    headers: {
      'Content-Type': 'application/json',
      'X-CSRF-Token': getCsrf()
    },
    method: 'DELETE'
  });

  dispatch({ type: DELETE_TICKET, id });
};

export const setTicketOwnersFilter = filters => ({ type: FILTER_TICKETS, filters: { owners: filters } });
export const setTicketStatusesFilter = filters => ({ type: FILTER_TICKETS, filters: { statuses: filters } });

export const setInitialTicketFilters = () => (dispatch, getState) => {
  // Open tickets only
  dispatch(setTicketStatusesFilter([{ value: TICKET_STATUS_OPEN, label: STATUSES[TICKET_STATUS_OPEN] }]));

  // Owned by current user, or no one
  const state = getState();
  const currentUserId = state.currentUserFromHtml.id;
  const [label, value] = state.admins.find(([_username, id]) => id === currentUserId);
  const currentUserOption = { label, value };
  const unassignedOption = { label: 'unassigned', value: null };
  dispatch(setTicketOwnersFilter([currentUserOption, unassignedOption]));
};

<|endoftext|>


<commit_before>var utils = require('../lib/utils.js');
var DIRECTIONS = ['north', 'east', 'south', 'west'];

var getShortestDirection = (start, endArray) => {
  var reducedArray = endArray.reduce((reduced, currentPosition) => {
    if (reduced[0] === -1 || utils.getDistance(start, currentPosition) < reduced[0]) {
      reduced[0] = utils.getDistance(start, currentPosition);
      reduced[1] = currentPosition;
    }

    return reduced;
  }, [-1, 0]);

  return utils.fastGetDirection(start, reducedArray[1]);
};

var turnToKill = (originalPosition, positionArray) => {
  return DIRECTIONS.reduce((result, currentDirection) => {
    if (result) return result;
    return positionArray.reduce((resultPositions, currentEnemyPosition) => {
      if (resultPositions) return resultPositions;
      return utils.isVisible(originalPosition, currentEnemyPosition, currentDirection) ? currentDirection : null;
    }, null);
  }, null);
};

var HITLER = {
  info: {
    name: 'Yuno',
    style: 9
  },
  ai: (playerState, enemiesStates, gameEnvironment) => {
    var directionToAmmo;
    var directionToPlayer;

    if (utils.canKill(playerState, enemiesStates) && playerState.ammo) return 'shoot';

    if (playerState.ammo) {
      directionToPlayer = turnToKill(playerState.position, enemiesStates.map(el => el.position));
      if (directionToPlayer) {
        return directionToPlayer;
      }

      directionToPlayer = getShortestDirection(playerState.position, enemiesStates.map(el => el.position));
      if (directionToPlayer !== playerState.direction) return directionToPlayer;
      return 'move';
    }

    if (gameEnvironment.ammoPosition.length) {
      directionToAmmo = getShortestDirection(playerState.position, gameEnvironment.ammoPosition);

      if (directionToAmmo !== playerState.direction) return directionToAmmo;
      return 'move';
    }

    return utils.safeRandomMove();
  }
};

module.exports = HITLER;
<commit_msg>Reformat Yuno<commit_after>var utils = require("../lib/utils.js");
var DIRECTIONS = ["north", "east", "south", "west"];

var getShortestDirection = (start, endArray) => {
  var reducedArray = endArray.reduce(
    (reduced, currentPosition) => {
      if (reduced[0] === -1 || utils.getDistance(start, currentPosition) < reduced[0]) {
        reduced[0] = utils.getDistance(start, currentPosition);
        reduced[1] = currentPosition;
      }

      return reduced;
    },
    [-1, 0]
  );

  return utils.fastGetDirection(start, reducedArray[1]);
};

var turnToKill = (originalPosition, positionArray) => {
  return DIRECTIONS.reduce((result, currentDirection) => {
    if (result) return result;
    return positionArray.reduce((resultPositions, currentEnemyPosition) => {
      if (resultPositions) return resultPositions;
      return utils.isVisible(originalPosition, currentEnemyPosition, currentDirection) ? currentDirection : null;
    }, null);
  }, null);
};

var Yuno = {
  info: {
    name: "Yuno",
    style: 9
  },
  ai: (playerState, enemiesStates, gameEnvironment) => {
    var directionToAmmo;
    var directionToPlayer;

    if (utils.canKill(playerState, enemiesStates) && playerState.ammo) return "shoot";

    if (playerState.ammo) {
      directionToPlayer = turnToKill(playerState.position, enemiesStates.map(el => el.position));
      if (directionToPlayer) {
        return directionToPlayer;
      }

      directionToPlayer = getShortestDirection(playerState.position, enemiesStates.map(el => el.position));
      if (directionToPlayer !== playerState.direction) return directionToPlayer;
      return "move";
    }

    if (gameEnvironment.ammoPosition.length) {
      directionToAmmo = getShortestDirection(playerState.position, gameEnvironment.ammoPosition);

      if (directionToAmmo !== playerState.direction) return directionToAmmo;
      return "move";
    }

    return utils.safeRandomMove();
  }
};

module.exports = Yuno;
<|endoftext|>