<commit_before>(function(){

module('call-remote-callbacks', {
  setup: function() {
    $('#qunit-fixture').append($('<form />', {
      action: '/echo', method: 'get', 'data-remote': 'true'
    }));
  },
  teardown: function() {
    $('form[data-remote]').die('ajax:beforeSend');
  }
});

function submit(fn) {
  var form = $('form')
    .bind('ajax:complete', function(){
      ok(true, 'ajax:complete');
      start();
    });

  if (fn) fn(form);
  form.trigger('submit');
}

asyncTest('modifying form fields with "ajax:before" sends modified data in request', 4, function(){
  $('form[data-remote]')
		.append($('<input type="text" name="user_name" value="john">'))
		.append($('<input type="text" name="removed_user_name" value="john">'))
		.live('ajax:before', function() {
			var form = $(this);
    	form
				.append($('<input />',{name: 'other_user_name',value: 'jonathan'}))
				.find('input[name="removed_user_name"]').remove();
			form
				.find('input[name="user_name"]').val('steve');
  	});

  submit(function(form) {
    form.bind('ajax:success', function(e, data, status, xhr) {
			equal(data.params.user_name, 'steve', 'modified field value should have been submitted');
			equal(data.params.other_user_name, 'jonathan', 'added field value should have been submitted');
			equal(data.params.removed_user_name, undefined, 'removed field value should be undefined');
		});
  });
});

asyncTest('stopping the "ajax:beforeSend" event aborts the request', 1, function() {
  submit(function(form) {
    form.bind('ajax:beforeSend', function() {
      ok(true, 'aborting request in ajax:beforeSend')
      return false;
    });
    form.unbind('ajax:complete').bind('ajax:complete', function() {
      ok(false, 'ajax:complete should not run');
    });
    form.bind('ajax:error', function(e, xhr, status, error) {
      ok(false, 'ajax:error should not run');
    });
    form.bind('ajaxStop', function() {
      start();
    });
  });
});

asyncTest('blank required form input field should abort request', 1, function() {
  var form = $('form[data-remote]')
    .append($('<input type="text" name="user_name" required="required">'))
    .bind('ajax:beforeSend', function() {
      ok(false, 'ajax:beforeSend should not run');
    })
    .bind('iframe:loading', function() {
      ok(false, 'form should not get submitted');
    })
    .trigger('submit');

  setTimeout(function() {
    form.find('input[required]').val('Tyler');
    form.unbind('ajax:beforeSend');
    submit();
  }, 13);
});

asyncTest('"ajax:beforeSend" can be observed and stopped with event delegation', 1, function() {
  $('form[data-remote]').live('ajax:beforeSend', function() {
    ok(true, 'ajax:beforeSend observed with event delegation');
    return false;
  });

  submit(function(form) {
    form.unbind('ajax:complete').bind('ajax:complete', function() {
      ok(false, 'ajax:complete should not run');
    });
    form.bind('ajaxStop', function() {
      start();
    });
  });
});

asyncTest('"ajax:beforeSend", "ajax:success" and "ajax:complete" are triggered', 8, function() {
  submit(function(form) {
    form.bind('ajax:beforeSend', function(e, xhr, settings) {
      ok(xhr.setRequestHeader, 'first argument to "ajax:beforeSend" should be an XHR object');
      equal(settings.url, '/echo', 'second argument to "ajax:beforeSend" should be a settings object');
    });
    form.bind('ajax:success', function(e, data, status, xhr) {
      ok(data.REQUEST_METHOD, 'first argument to ajax:success should be a data object');
      equal(status, 'success', 'second argument to ajax:success should be a status string');
      ok(xhr.getResponseHeader, 'third argument to "ajax:success" should be an XHR object');
    });
    form.bind('ajax:complete', function(e, xhr, status) {
      ok(xhr.getResponseHeader, 'first argument to "ajax:complete" should be an XHR object');
      equal(status, 'success', 'second argument to ajax:complete should be a status string');
    });
  });
});

asyncTest('"ajax:beforeSend", "ajax:error" and "ajax:complete" are triggered on error', 6, function() {
  submit(function(form) {
    form.attr('action', '/error');
    form.bind('ajax:beforeSend', function(arg) { ok(true, 'ajax:beforeSend') });
    form.bind('ajax:error', function(e, xhr, status, error) {
      ok(xhr.getResponseHeader, 'first argument to "ajax:error" should be an XHR object');
      equal(status, 'error', 'second argument to ajax:error should be a status string');
      if (jQuery().jquery.indexOf('1.4') === 0) strictEqual(error, undefined)
      else equal(error, 'Forbidden', 'third argument to ajax:error should be an HTTP status response');
      // Opera returns "0" for HTTP code
      equal(xhr.status, window.opera ? 0 : 403, 'status code should be 403');
    });
  });
});

})();
<commit_msg>Fixed failing test with cleanup in teardown. Rejustified spacing.<commit_after>(function(){

module('call-remote-callbacks', {
  setup: function() {
    $('#qunit-fixture').append($('<form />', {
      action: '/echo', method: 'get', 'data-remote': 'true'
    }));
  },
  teardown: function() {
    $('form[data-remote]').die('ajax:beforeSend');
    $('form[data-remote]').die('ajax:before');
  }
});

function submit(fn) {
  var form = $('form')
    .bind('ajax:complete', function(){
      ok(true, 'ajax:complete');
      start();
    });

  if (fn) fn(form);
  form.trigger('submit');
}

asyncTest('modifying form fields with "ajax:before" sends modified data in request', 4, function(){
  $('form[data-remote]')
    .append($('<input type="text" name="user_name" value="john">'))
    .append($('<input type="text" name="removed_user_name" value="john">'))
    .live('ajax:before', function() {
      var form = $(this);
      form
        .append($('<input />',{name: 'other_user_name',value: 'jonathan'}))
        .find('input[name="removed_user_name"]').remove();
      form
        .find('input[name="user_name"]').val('steve');
    });

  submit(function(form) {
    form.bind('ajax:success', function(e, data, status, xhr) {
      equal(data.params.user_name, 'steve', 'modified field value should have been submitted');
      equal(data.params.other_user_name, 'jonathan', 'added field value should have been submitted');
      equal(data.params.removed_user_name, undefined, 'removed field value should be undefined');
    });
  });
});

asyncTest('stopping the "ajax:beforeSend" event aborts the request', 1, function() {
  submit(function(form) {
    form.bind('ajax:beforeSend', function() {
      ok(true, 'aborting request in ajax:beforeSend')
      return false;
    });
    form.unbind('ajax:complete').bind('ajax:complete', function() {
      ok(false, 'ajax:complete should not run');
    });
    form.bind('ajax:error', function(e, xhr, status, error) {
      ok(false, 'ajax:error should not run');
    });
    form.bind('ajaxStop', function() {
      start();
    });
  });
});

asyncTest('blank required form input field should abort request', 1, function() {
  var form = $('form[data-remote]')
    .append($('<input type="text" name="user_name" required="required">'))
    .bind('ajax:beforeSend', function() {
      ok(false, 'ajax:beforeSend should not run');
    })
    .bind('iframe:loading', function() {
      ok(false, 'form should not get submitted');
    })
    .trigger('submit');

  setTimeout(function() {
    form.find('input[required]').val('Tyler');
    form.unbind('ajax:beforeSend');
    submit();
  }, 13);
});

asyncTest('"ajax:beforeSend" can be observed and stopped with event delegation', 1, function() {
  $('form[data-remote]').live('ajax:beforeSend', function() {
    ok(true, 'ajax:beforeSend observed with event delegation');
    return false;
  });

  submit(function(form) {
    form.unbind('ajax:complete').bind('ajax:complete', function() {
      ok(false, 'ajax:complete should not run');
    });
    form.bind('ajaxStop', function() {
      start();
    });
  });
});

asyncTest('"ajax:beforeSend", "ajax:success" and "ajax:complete" are triggered', 8, function() {
  submit(function(form) {
    form.bind('ajax:beforeSend', function(e, xhr, settings) {
      ok(xhr.setRequestHeader, 'first argument to "ajax:beforeSend" should be an XHR object');
      equal(settings.url, '/echo', 'second argument to "ajax:beforeSend" should be a settings object');
    });
    form.bind('ajax:success', function(e, data, status, xhr) {
      ok(data.REQUEST_METHOD, 'first argument to ajax:success should be a data object');
      equal(status, 'success', 'second argument to ajax:success should be a status string');
      ok(xhr.getResponseHeader, 'third argument to "ajax:success" should be an XHR object');
    });
    form.bind('ajax:complete', function(e, xhr, status) {
      ok(xhr.getResponseHeader, 'first argument to "ajax:complete" should be an XHR object');
      equal(status, 'success', 'second argument to ajax:complete should be a status string');
    });
  });
});

asyncTest('"ajax:beforeSend", "ajax:error" and "ajax:complete" are triggered on error', 6, function() {
  submit(function(form) {
    form.attr('action', '/error');
    form.bind('ajax:beforeSend', function(arg) { ok(true, 'ajax:beforeSend') });
    form.bind('ajax:error', function(e, xhr, status, error) {
      ok(xhr.getResponseHeader, 'first argument to "ajax:error" should be an XHR object');
      equal(status, 'error', 'second argument to ajax:error should be a status string');
      if (jQuery().jquery.indexOf('1.4') === 0) strictEqual(error, undefined)
      else equal(error, 'Forbidden', 'third argument to ajax:error should be an HTTP status response');
      // Opera returns "0" for HTTP code
      equal(xhr.status, window.opera ? 0 : 403, 'status code should be 403');
    });
  });
});

})();
<|endoftext|>


<commit_before>// NodeRESTHost.js
// A simple REST host in Node.js with using Express.js framework.
//
// All data stored in memory, requests are handled in particular routes.
//
// Created in 2014 by Radek Tomasek / SeaCat Ltd.

var express = require('express');<commit_msg>Updated basic structure of NodeRESTHost.js application<commit_after>// NodeRESTHost.js
// A simple REST host in Node.js with using Express.js framework.
//
// All data stored in memory, requests are handled in particular routes.
//
// Created in 2014 by Radek Tomasek / SeaCat Ltd.

// Include Express.js framework scripts.
var express = require('express');

// Initialize app by using Express framework.
var app = express();

// Set default port 1337 or custom if defined by user externally.
app.set('port', process.env.PORT || 1337);

// Start listening on defined port, this keep running the application until hit Ctrl + C key combination.
app.listen(app.get('port'), function(){
  console.log("Host is running and listening on http://localhost:" + app.get('port') + '; press Ctrl-C to terminate.');
});<|endoftext|>


<commit_before>import wrapModule from "../../helpers/wrapModule";
import chunkedBundleBuilder from "../../../src/bundler/chunkedBundleBuilder";
import chunkedBundlePrelude from "../../../src/bundler/chunkedBundlePrelude";
import combineSourceMap from "combine-source-map";
import { expect } from "chai";

const prelude = chunkedBundlePrelude.toString();

describe("Bundle builder test suite", function() {
  describe("When bundling a hello world module with no entry", function() {
    var input, result;

    beforeEach(function() {
      input = "module.exports = console.log('hello world');";

      result = chunkedBundleBuilder.buildBundle({
        1: { source: input }
      });
    });

    it("then the bundler generates the correct result", function() {
      var expected = (
`require=_bb$iter=(${prelude})({
${wrapModule(input, 1)}
},[]);

`);
      expect(combineSourceMap.removeComments(result)).to.equal(expected);
    });
  });

  describe("When bundling a hello world module with an entry", function() {
    var input, result;

    beforeEach(function() {
      input = "module.exports = console.log('hello world');";

      result = chunkedBundleBuilder.buildBundle({
        1: { source: input, entry: true }
      });
    });

    it("then the bundler generates the correct result", function() {
      var expected = (
`require=_bb$iter=(${prelude})({
${wrapModule(input, 1)}
},[1]);

`);

      expect(combineSourceMap.removeComments(result)).to.equal(expected);
    });
  });

  describe("When bundling a hello world module with an entry and two dependency", function() {
    var input, dep1, dep2, result;

    beforeEach(function() {
      input = "require('path');require('process');module.exports = console.log('hello world');";
      dep1 = "console.log('the path');";
      dep2 = "console.log('the process');";

      result = chunkedBundleBuilder.buildBundle({
        1: { source: input, entry: true, deps: [{ id: 2, name: "path" }, { id: 3, name: "process" }] },
        2: { source: dep1 },
        3: { source: dep2 }
      });
    });

    it("then the bundler generates the correct result", function() {
      var expected = (
`require=_bb$iter=(${prelude})({
${wrapModule(input, 1, {"path": 2, "process": 3})},
${wrapModule(dep1, 2)},
${wrapModule(dep2, 3)}
},[1]);

`);

      expect(combineSourceMap.removeComments(result)).to.equal(expected);
    });
  });
});
<commit_msg>adding unit test to test the bundle builder with ES2015 import/export statements, including dynamic imports<commit_after>import wrapModule from "../../helpers/wrapModule";
import chunkedBundleBuilder from "../../../src/bundler/chunkedBundleBuilder";
import chunkedBundlePrelude from "../../../src/bundler/chunkedBundlePrelude";
import combineSourceMap from "combine-source-map";
import { expect } from "chai";

const prelude = chunkedBundlePrelude.toString();

describe("Bundle builder test suite", function() {
  describe("When bundling a hello world module with no entry", function() {
    var input, result;

    beforeEach(function() {
      input = "module.exports = console.log('hello world');";

      result = chunkedBundleBuilder.buildBundle({
        1: { source: input }
      });
    });

    it("then the bundler generates the correct result", function() {
      var expected = (
`require=_bb$iter=(${prelude})({
${wrapModule(input, 1)}
},[]);

`);
      expect(combineSourceMap.removeComments(result)).to.equal(expected);
    });
  });

  describe("When bundling a hello world module with an entry", function() {
    var input, result;

    beforeEach(function() {
      input = "module.exports = console.log('hello world');";

      result = chunkedBundleBuilder.buildBundle({
        1: { source: input, entry: true }
      });
    });

    it("then the bundler generates the correct result", function() {
      var expected = (
`require=_bb$iter=(${prelude})({
${wrapModule(input, 1)}
},[1]);

`);

      expect(combineSourceMap.removeComments(result)).to.equal(expected);
    });
  });

  describe("When bundling a hello world module with an entry and two dependency", function() {
    var input, dep1, dep2, result;

    beforeEach(function() {
      input = "require('path');require('process');module.exports = console.log('hello world');";
      dep1 = "console.log('the path');";
      dep2 = "console.log('the process');";

      result = chunkedBundleBuilder.buildBundle({
        1: { source: input, entry: true, deps: [{ id: 2, name: "path" }, { id: 3, name: "process" }] },
        2: { source: dep1 },
        3: { source: dep2 }
      });
    });

    it("then the bundler generates the correct result", function() {
      var expected = (
`require=_bb$iter=(${prelude})({
${wrapModule(input, 1, {"path": 2, "process": 3})},
${wrapModule(dep1, 2)},
${wrapModule(dep2, 3)}
},[1]);

`);

      expect(combineSourceMap.removeComments(result)).to.equal(expected);
    });
  });

  describe("When bundling a hello world module with an ES6 dependency", function() {
    var input, dep1, result;

    beforeEach(function() {
      input = "import './X';\nimport('./X');\nexport default 'hello world';";
      dep1 = "console.log('from X.js');";

      result = chunkedBundleBuilder.buildBundle({
        1: { source: input, entry: true, deps: [{ id: 2, name: "./X" }] },
        2: { source: dep1 }
      });
    });

    it("then the bundler generates the correct result", function() {
      var expected = (
`require=_bb$iter=(${prelude})({
${wrapModule(input, 1, {"./X": 2})},
${wrapModule(dep1, 2)}
},[1]);

`);

      expect(combineSourceMap.removeComments(result)).to.equal(expected);
    });
  });

});
<|endoftext|>


<commit_before>'use strict';

var constants = require('./../config/constants'),
	config = require('./../config/config'),
	redis = require('redis').createClient(config.databasePort, config.databaseDomain),
	logger = require('./../util/logger'),
	Q = require('q');

redis.on('connect', function () {
	logger.notice('Redis connection established');
});
redis.on('reconnecting', function () {
	logger.notice('Reconnecting to Redis...');
});
redis.on('error', function redisError (error) {
	var message = String(error),
			logType = /connection/.test(message) ? 'emergency' : 'critical';
	logger[logType](message);
});
redis.on('end', function () {
	logger.notice('Redis connection closed');
});

module.exports = {
	set: function(key, value){
		if(key && value){
			// all redis entries are deleted after a certain time
			redis.set(key, value, 'PX', constants.AUTH_MAX_AGE);
		} else {
			logger.error('Error options for redis SET', key, value);
		}
	},
	get: function(key){
		var defer = Q.defer();

		redis.get(key, function(err, reply){
			if(! err){
				defer.resolve(reply);
			} else {
				defer.reject(err);
			}
		});

		return defer.promise;
	},
	del: function(key){
		redis.del(key || null);
	},
	exists: function(key){
		var defer = Q.defer();

		redis.exists(key, function(err, reply){
			if(!err){
				defer.resolve(reply);
			} else {
				defer.reject(err);
			}
		});

		return defer.promise;
	}
};<commit_msg>Updated error message for invalid redis.set call.<commit_after>'use strict';

var constants = require('./../config/constants'),
	config = require('./../config/config'),
	redis = require('redis').createClient(config.databasePort, config.databaseDomain),
	logger = require('./../util/logger'),
	Q = require('q');

redis.on('connect', function () {
	logger.notice('Redis connection established');
});
redis.on('reconnecting', function () {
	logger.notice('Reconnecting to Redis...');
});
redis.on('error', function redisError (error) {
	var message = String(error),
			logType = /connection/.test(message) ? 'emergency' : 'critical';
	logger[logType](message);
});
redis.on('end', function () {
	logger.notice('Redis connection closed');
});

module.exports = {
	set: function(key, value){
		if (key && value) {
			// all redis entries are deleted after a certain time
			redis.set(key, value, 'PX', constants.AUTH_MAX_AGE);
		} else {
			logger.error('Invalid arguments for redis SET command. (key: "' + key + '", value: "' + value + '")');
		}
	},
	get: function(key){
		var defer = Q.defer();

		redis.get(key, function(err, reply){
			if(! err){
				defer.resolve(reply);
			} else {
				defer.reject(err);
			}
		});

		return defer.promise;
	},
	del: function(key){
		redis.del(key || null);
	},
	exists: function(key){
		var defer = Q.defer();

		redis.exists(key, function(err, reply){
			if(!err){
				defer.resolve(reply);
			} else {
				defer.reject(err);
			}
		});

		return defer.promise;
	}
};<|endoftext|>


<commit_before>import 'isomorphic-fetch';

function parseResponseBody(response) {
  return response.text().then(textString => {
    const contentType =
      response.headers.get('content-type') || 'application/json';

    if (contentType.includes('application/json') && textString) {
      response.jsonData = JSON.parse(textString);
    }

    response.textString = textString;
    return response;
  });
}

function rejectOnHttpErrors(response) {
  if (response.ok) {
    return response;
  }

  const error = new Error(`HTTP ${response.status}`);
  error.response = response;
  throw error;
}

export function stringifyBody(requestOptions: Object) {
  const { body, json } = requestOptions;

  if (typeof body === 'string') {
    return body;
  }

  if (typeof body === 'object' && json !== false) {
    return JSON.stringify(body);
  }

  return null;
}

function makeFormData(files, rawBody) {
  const body = new FormData();

  if (rawBody) {
    Object.keys(rawBody).forEach(prop => {
      body.append(prop, rawBody[prop]);
    });
  }

  body.append('file', files[0]);
  return body;
}

function timeoutPromise(ms = 0) {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  }).then(() => {
    throw new Error('HTTP request timed out.');
  });
}

export default function fetchJSON(path, requestOptions = { headers: [] }) {
  const {
    files = [],
    retryDelays = [1000, 3000],
    timeout = 15000,
    ...options
  } = requestOptions;

  let body;
  if (files.length > 0) {
    body = makeFormData(files, options.body);
  } else {
    body = stringifyBody(options);
    options.headers['Content-Type'] = 'application/json';
  }

  const createRequest = () =>
    new Request(path, {
      ...options,
      body,
      headers: new Headers({
        Accept: 'application/json',
        ...options.headers
      })
    });

  return new Promise((resolve, reject) => {
    let requestsAttempted = 0;

    const wrappedFetch = () => {
      const request = createRequest();
      requestsAttempted++;
      return Promise.race([
        timeoutPromise(timeout),
        fetch(request)
          .then(parseResponseBody)
          .then(rejectOnHttpErrors)
          .then(resolve)
      ]).catch(error => {
        if (!retryDelays || requestsAttempted > retryDelays.length) {
          return reject(error);
        }

        setTimeout(() => {
          wrappedFetch();
        }, retryDelays[requestsAttempted - 1]);
      });
    };

    wrappedFetch();
  });
}
<commit_msg>Update retry logic in fetchJSON (#415)<commit_after>import 'isomorphic-fetch';

function parseResponseBody(response) {
  return response.text().then(textString => {
    const contentType =
      response.headers.get('content-type') || 'application/json';

    if (contentType.includes('application/json') && textString) {
      response.jsonData = JSON.parse(textString);
    }

    response.textString = textString;
    return response;
  });
}

function rejectOnHttpErrors(response) {
  if (response.ok) {
    return response;
  }

  const error = new Error(`HTTP ${response.status}`);
  error.response = response;
  throw error;
}

export function stringifyBody(requestOptions: Object) {
  const { body, json } = requestOptions;

  if (typeof body === 'string') {
    return body;
  }

  if (typeof body === 'object' && json !== false) {
    return JSON.stringify(body);
  }

  return null;
}

function makeFormData(files, rawBody) {
  const body = new FormData();

  if (rawBody) {
    Object.keys(rawBody).forEach(prop => {
      body.append(prop, rawBody[prop]);
    });
  }

  body.append('file', files[0]);
  return body;
}

function timeoutPromise(ms = 0) {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  }).then(() => {
    throw new Error('HTTP request timed out.');
  });
}

export default function fetchJSON(path, requestOptions = { headers: [] }) {
  const {
    files = [],
    retryDelays = [1000, 3000],
    timeout = 15000,
    ...options
  } = requestOptions;

  let body;
  if (files.length > 0) {
    body = makeFormData(files, options.body);
  } else {
    body = stringifyBody(options);
    options.headers['Content-Type'] = 'application/json';
  }

  const createRequest = () =>
    new Request(path, {
      ...options,
      body,
      headers: new Headers({
        Accept: 'application/json',
        ...options.headers
      })
    });

  return new Promise((resolve, reject) => {
    let requestsAttempted = 0;

    const wrappedFetch = () => {
      const request = createRequest();
      requestsAttempted++;
      return Promise.race([
        timeoutPromise(timeout),
        fetch(request)
          .then(parseResponseBody)
          .then(rejectOnHttpErrors)
          .then(resolve)
      ]).catch(error => {
        if (
          (error.response && error.response.status < 500) ||
          !retryDelays ||
          requestsAttempted > retryDelays.length
        ) {
          return reject(error);
        }

        setTimeout(() => {
          wrappedFetch();
        }, retryDelays[requestsAttempted - 1]);
      });
    };

    wrappedFetch();
  });
}
<|endoftext|>


<commit_before>const app = require('../app');
const flame = app.locals.flame;

//module config

//keeping this synchronous due to how small the data is. pass this to the event loop
function transformModuleConfig (info, next) {
    //expecting only one module config
    const base = info.base[0];
    const retrySeconds = info.retrySeconds.map(function (secondObj) {
        return secondObj.seconds;
    });

    next(null, {
        "preloaded_pt": base.preloaded_pt,
        "exchange_after_x_ignition_cycles": base.exchange_after_x_ignition_cycles,
        "exchange_after_x_kilometers": base.exchange_after_x_kilometers,
        "exchange_after_x_days": base.exchange_after_x_days,
        "timeout_after_x_seconds": base.timeout_after_x_seconds,
        "seconds_between_retries": retrySeconds,
        "endpoints": {
            "0x07": {
                default: [base.endpoint_0x07]
            },
            "0x04": {
                default: [base.endpoint_0x04]
            },
            "queryAppsUrl": {
                default: [base.query_apps_url]
            },
            "lock_screen_icon_url": {
                default: [base.lock_screen_default_url]
            }
        },
        "notifications_per_minute_by_priority": {
            "EMERGENCY": base.emergency_notifications,
            "NAVIGATION": base.navigation_notifications,
            "VOICECOM": base.voicecom_notifications,
            "COMMUNICATION": base.communication_notifications,
            "NORMAL": base.normal_notifications,
            "NONE": base.none_notifications
        }
    });
}

//consumer messages

function transformMessages (info, cb) {
    const allMessages = info.messageStatuses;
    const groups = info.messageGroups;

    const transformFlow = flame.flow([
        //hash the message groups by message_category
        flame.async.groupBy.bind(null, groups, function (group, callback) {
            callback(null, group.message_category);
        }),
        //filter out messages that don't exist in the hashed message groups
        function (hashedGroups, next) {
            flame.async.filter(allMessages, function (message, callback) {
                callback(null, hashedGroups[message.message_category]);
            }, next);
        },
        //finish constructing the consumer messages object
        function (finalMessages, next) {
            let messageObj = {};
            flame.async.map(finalMessages, function (msg, next) {
                if (!messageObj[msg.message_category]) {
                    messageObj[msg.message_category] = {};
                    messageObj[msg.message_category].languages = {};
                }
                if (!messageObj[msg.message_category].languages[msg.language_id]) {
                    messageObj[msg.message_category].languages[msg.language_id] = {};
                }
                const langObj = messageObj[msg.message_category].languages[msg.language_id];
                langObj.tts = msg.tts ? msg.tts : undefined;
                langObj.line1 = msg.line1 ? msg.line1 : undefined;
                langObj.line2 = msg.line2 ? msg.line2 : undefined;
                langObj.textBody = msg.text_body ? msg.text_body : undefined;
                langObj.label = msg.label ? msg.label : undefined;
                next();
            }, function () {
                next(null, {
                    "version": "000.000.001", //TODO: what to do with the versioning?
                    "messages": messageObj
                });
            });
        }
    ], {method: 'waterfall'});

    transformFlow(cb);
}

//functional groups

function transformFunctionalGroups (isProduction, info, next) {
    const baseInfo = info.base;
    const hmiLevels = info.hmiLevels;
    const parameters = info.parameters;
    const consentPrompts = info.messageGroups;

    //hashes to get hmiLevels and parameters by function group id
    const groupedData = {};
    const hashIdToPropertyName = {};

    //set up the top level objects for these hashes
    for (let i = 0; i < baseInfo.length; i++) {
        groupedData[baseInfo[i].id] = {};

        const selectedPrompt = consentPrompts.find(function (prompt) {
            return prompt.message_category === baseInfo[i].user_consent_prompt;
        });
        //the prompt must exist at least in staging and must be in production mode if isProduction is true
        if (selectedPrompt
            && (!isProduction || selectedPrompt.status === "PRODUCTION")
            && !selectedPrompt.is_deleted) {
            groupedData[baseInfo[i].id].user_consent_prompt = selectedPrompt.message_category;
        }
        groupedData[baseInfo[i].id].rpcs = null;
        hashIdToPropertyName[baseInfo[i].id] = baseInfo[i].property_name;
    }

    //begin asynchronous logic below

    //populate the hash above, using the functional group id as a key
    //include the hmi levels and parameter data
    const groupUpData = flame.flow([
        flame.async.map.bind(null, hmiLevels, function (hmiLevel, next) {
            const funcId = hmiLevel.function_group_id;
            if (!groupedData[funcId].rpcs) {
                groupedData[funcId].rpcs = {};
            }
            if (!groupedData[funcId].rpcs[hmiLevel.permission_name]) {
                groupedData[funcId].rpcs[hmiLevel.permission_name] = {};
                groupedData[funcId].rpcs[hmiLevel.permission_name].hmi_levels = {};
                groupedData[funcId].rpcs[hmiLevel.permission_name].parameters = {};
            }
            groupedData[funcId].rpcs[hmiLevel.permission_name].hmi_levels[hmiLevel.hmi_level] = true;
            next();
        }),
        flame.async.map.bind(null, parameters, function (parameter, next) {
            const funcId = parameter.function_group_id;
            groupedData[funcId].rpcs[parameter.rpc_name].parameters[parameter.parameter] = true;
            next();
        }),
    ], {method: 'series', eventLoop: true});

    //transform groupedData into valid functional group rpc objects under the keys
    //modifies the original object
    function hashToRpcObject (_, next) {
        //asynchronously iterate over groupedData
        flame.async.map(groupedData, function (group, callback) {
            for (let rpc in group.rpcs) {
                //hmi_levels and parameters property needs to be an array
                const data = group.rpcs[rpc];
                let hmiLevels = [];
                let parameters = [];
                //manually insert hmi levels. preserve order of BACKGROUND, FULL, LIMITED, NONE
                if (data.hmi_levels.BACKGROUND) {
                    hmiLevels.push("BACKGROUND");
                }
                if (data.hmi_levels.FULL) {
                    hmiLevels.push("FULL");
                }
                if (data.hmi_levels.LIMITED) {
                    hmiLevels.push("LIMITED");
                }
                if (data.hmi_levels.NONE) {
                    hmiLevels.push("NONE");
                }
                for (let parameter in data.parameters) {
                    parameters.push(parameter);
                }
                //erase and replace
                delete data.hmi_levels;
                delete data.parameters;
                if (hmiLevels.length > 0) {
                    data.hmi_levels = hmiLevels;
                }
                if (parameters.length > 0) {
                    //sort the parameters array
                    data.parameters = parameters.sort();
                }
            }
            callback();
        }, next);
    }

    function constructFullObject (_, next) {
        let functionalGroupings = {};
        for (let id in groupedData) {
            const propertyName = hashIdToPropertyName[id];
            functionalGroupings[propertyName] = groupedData[id];
        }
        next(null, functionalGroupings);
    }

    //combine all the steps above
    const constructFunctionalGroupFlow = flame.flow([
        groupUpData,
        hashToRpcObject,
        constructFullObject
    ], {method: 'waterfall', eventLoop: true});

    constructFunctionalGroupFlow(next); //run it
}

//application policies

function constructAppPolicy (appObj, res, next) {
    const displayNames = res.displayNames.map(function (elem) {
        return elem.display_text;
    });
    const moduleNames = res.moduleNames.map(function (elem) {
        return elem.permission_name;
    });
    const funcGroupNames = res.funcGroupNames.map(function (elem) {
        return elem.property_name;
    });

    const appPolicyObj = {};
    appPolicyObj[appObj.app_uuid] = {
        nicknames: displayNames,
        keep_context: true,
        steal_focus: appObj.can_steal_focus,
        priority: "NONE",
        default_hmi: appObj.default_hmi_level.split("_")[1], //trim the HMI_ prefix
        groups: funcGroupNames,
        moduleType: moduleNames
    };

    next(null, appPolicyObj);
}

function aggregateResults (res, next) {
    const policyObjs = res.policyObjs;
    const defaultFuncGroups = res.defaultFuncGroups.map(function (obj) {
        return obj.property_name;
    });
    const preDataConsentFuncGroups = res.preDataConsentFuncGroups.map(function (obj) {
        return obj.property_name;
    });
    const deviceFuncGroups = res.deviceFuncGroups.map(function (obj) {
        return obj.property_name;
    });

    const appPolicy = {};

    // set all requested apps to default permissions
    for (let i = 0; i < res.requestedUuids.length; i++) {
        appPolicy[res.requestedUuids[i]] = {
            "keep_context": false,
            "steal_focus": false,
            "priority": "NONE",
            "default_hmi": "NONE",
            "groups": defaultFuncGroups
        };
    }

    // overwrite available apps with their granted permissions
    for (let i = 0; i < policyObjs.length; i++) {
        const key = Object.keys(policyObjs[i])[0];
        appPolicy[key] = policyObjs[i][key];
    }

    //setup defaults after the app ids are populated
    appPolicy.default = {
        "keep_context": false,
        "steal_focus": false,
        "priority": "NONE",
        "default_hmi": "NONE",
        "groups": defaultFuncGroups
    };
    //DataConsent-2 functional group removed
    appPolicy.device = {
        "keep_context": false,
        "steal_focus": false,
        "priority": "NONE",
        "default_hmi": "NONE",
        "groups": deviceFuncGroups
    };
    //BaseBeforeDataConsent functional group removed
    appPolicy.pre_DataConsent = {
        "keep_context": false,
        "steal_focus": false,
        "priority": "NONE",
        "default_hmi": "NONE",
        "groups": preDataConsentFuncGroups
    };
    next(null, appPolicy);
}

module.exports = {
    transformModuleConfig: transformModuleConfig,
    transformMessages: transformMessages,
    transformFunctionalGroups: transformFunctionalGroups,
    constructAppPolicy: constructAppPolicy,
    aggregateResults: aggregateResults
}<commit_msg>+ explicitly give all apps default permissions by default<commit_after>const app = require('../app');
const flame = app.locals.flame;

//module config

//keeping this synchronous due to how small the data is. pass this to the event loop
function transformModuleConfig (info, next) {
    //expecting only one module config
    const base = info.base[0];
    const retrySeconds = info.retrySeconds.map(function (secondObj) {
        return secondObj.seconds;
    });

    next(null, {
        "preloaded_pt": base.preloaded_pt,
        "exchange_after_x_ignition_cycles": base.exchange_after_x_ignition_cycles,
        "exchange_after_x_kilometers": base.exchange_after_x_kilometers,
        "exchange_after_x_days": base.exchange_after_x_days,
        "timeout_after_x_seconds": base.timeout_after_x_seconds,
        "seconds_between_retries": retrySeconds,
        "endpoints": {
            "0x07": {
                default: [base.endpoint_0x07]
            },
            "0x04": {
                default: [base.endpoint_0x04]
            },
            "queryAppsUrl": {
                default: [base.query_apps_url]
            },
            "lock_screen_icon_url": {
                default: [base.lock_screen_default_url]
            }
        },
        "notifications_per_minute_by_priority": {
            "EMERGENCY": base.emergency_notifications,
            "NAVIGATION": base.navigation_notifications,
            "VOICECOM": base.voicecom_notifications,
            "COMMUNICATION": base.communication_notifications,
            "NORMAL": base.normal_notifications,
            "NONE": base.none_notifications
        }
    });
}

//consumer messages

function transformMessages (info, cb) {
    const allMessages = info.messageStatuses;
    const groups = info.messageGroups;

    const transformFlow = flame.flow([
        //hash the message groups by message_category
        flame.async.groupBy.bind(null, groups, function (group, callback) {
            callback(null, group.message_category);
        }),
        //filter out messages that don't exist in the hashed message groups
        function (hashedGroups, next) {
            flame.async.filter(allMessages, function (message, callback) {
                callback(null, hashedGroups[message.message_category]);
            }, next);
        },
        //finish constructing the consumer messages object
        function (finalMessages, next) {
            let messageObj = {};
            flame.async.map(finalMessages, function (msg, next) {
                if (!messageObj[msg.message_category]) {
                    messageObj[msg.message_category] = {};
                    messageObj[msg.message_category].languages = {};
                }
                if (!messageObj[msg.message_category].languages[msg.language_id]) {
                    messageObj[msg.message_category].languages[msg.language_id] = {};
                }
                const langObj = messageObj[msg.message_category].languages[msg.language_id];
                langObj.tts = msg.tts ? msg.tts : undefined;
                langObj.line1 = msg.line1 ? msg.line1 : undefined;
                langObj.line2 = msg.line2 ? msg.line2 : undefined;
                langObj.textBody = msg.text_body ? msg.text_body : undefined;
                langObj.label = msg.label ? msg.label : undefined;
                next();
            }, function () {
                next(null, {
                    "version": "000.000.001", //TODO: what to do with the versioning?
                    "messages": messageObj
                });
            });
        }
    ], {method: 'waterfall'});

    transformFlow(cb);
}

//functional groups

function transformFunctionalGroups (isProduction, info, next) {
    const baseInfo = info.base;
    const hmiLevels = info.hmiLevels;
    const parameters = info.parameters;
    const consentPrompts = info.messageGroups;

    //hashes to get hmiLevels and parameters by function group id
    const groupedData = {};
    const hashIdToPropertyName = {};

    //set up the top level objects for these hashes
    for (let i = 0; i < baseInfo.length; i++) {
        groupedData[baseInfo[i].id] = {};

        const selectedPrompt = consentPrompts.find(function (prompt) {
            return prompt.message_category === baseInfo[i].user_consent_prompt;
        });
        //the prompt must exist at least in staging and must be in production mode if isProduction is true
        if (selectedPrompt
            && (!isProduction || selectedPrompt.status === "PRODUCTION")
            && !selectedPrompt.is_deleted) {
            groupedData[baseInfo[i].id].user_consent_prompt = selectedPrompt.message_category;
        }
        groupedData[baseInfo[i].id].rpcs = null;
        hashIdToPropertyName[baseInfo[i].id] = baseInfo[i].property_name;
    }

    //begin asynchronous logic below

    //populate the hash above, using the functional group id as a key
    //include the hmi levels and parameter data
    const groupUpData = flame.flow([
        flame.async.map.bind(null, hmiLevels, function (hmiLevel, next) {
            const funcId = hmiLevel.function_group_id;
            if (!groupedData[funcId].rpcs) {
                groupedData[funcId].rpcs = {};
            }
            if (!groupedData[funcId].rpcs[hmiLevel.permission_name]) {
                groupedData[funcId].rpcs[hmiLevel.permission_name] = {};
                groupedData[funcId].rpcs[hmiLevel.permission_name].hmi_levels = {};
                groupedData[funcId].rpcs[hmiLevel.permission_name].parameters = {};
            }
            groupedData[funcId].rpcs[hmiLevel.permission_name].hmi_levels[hmiLevel.hmi_level] = true;
            next();
        }),
        flame.async.map.bind(null, parameters, function (parameter, next) {
            const funcId = parameter.function_group_id;
            groupedData[funcId].rpcs[parameter.rpc_name].parameters[parameter.parameter] = true;
            next();
        }),
    ], {method: 'series', eventLoop: true});

    //transform groupedData into valid functional group rpc objects under the keys
    //modifies the original object
    function hashToRpcObject (_, next) {
        //asynchronously iterate over groupedData
        flame.async.map(groupedData, function (group, callback) {
            for (let rpc in group.rpcs) {
                //hmi_levels and parameters property needs to be an array
                const data = group.rpcs[rpc];
                let hmiLevels = [];
                let parameters = [];
                //manually insert hmi levels. preserve order of BACKGROUND, FULL, LIMITED, NONE
                if (data.hmi_levels.BACKGROUND) {
                    hmiLevels.push("BACKGROUND");
                }
                if (data.hmi_levels.FULL) {
                    hmiLevels.push("FULL");
                }
                if (data.hmi_levels.LIMITED) {
                    hmiLevels.push("LIMITED");
                }
                if (data.hmi_levels.NONE) {
                    hmiLevels.push("NONE");
                }
                for (let parameter in data.parameters) {
                    parameters.push(parameter);
                }
                //erase and replace
                delete data.hmi_levels;
                delete data.parameters;
                if (hmiLevels.length > 0) {
                    data.hmi_levels = hmiLevels;
                }
                if (parameters.length > 0) {
                    //sort the parameters array
                    data.parameters = parameters.sort();
                }
            }
            callback();
        }, next);
    }

    function constructFullObject (_, next) {
        let functionalGroupings = {};
        for (let id in groupedData) {
            const propertyName = hashIdToPropertyName[id];
            functionalGroupings[propertyName] = groupedData[id];
        }
        next(null, functionalGroupings);
    }

    //combine all the steps above
    const constructFunctionalGroupFlow = flame.flow([
        groupUpData,
        hashToRpcObject,
        constructFullObject
    ], {method: 'waterfall', eventLoop: true});

    constructFunctionalGroupFlow(next); //run it
}

//application policies

function constructAppPolicy (appObj, res, next) {
    const displayNames = res.displayNames.map(function (elem) {
        return elem.display_text;
    });
    const moduleNames = res.moduleNames.map(function (elem) {
        return elem.permission_name;
    });
    const funcGroupNames = res.funcGroupNames.map(function (elem) {
        return elem.property_name;
    });

    const appPolicyObj = {};
    appPolicyObj[appObj.app_uuid] = {
        nicknames: displayNames,
        keep_context: true,
        steal_focus: appObj.can_steal_focus,
        priority: "NONE",
        default_hmi: appObj.default_hmi_level.split("_")[1], //trim the HMI_ prefix
        groups: funcGroupNames,
        moduleType: moduleNames
    };

    next(null, appPolicyObj);
}

function aggregateResults (res, next) {
    const policyObjs = res.policyObjs;
    const defaultFuncGroups = res.defaultFuncGroups.map(function (obj) {
        return obj.property_name;
    });
    const preDataConsentFuncGroups = res.preDataConsentFuncGroups.map(function (obj) {
        return obj.property_name;
    });
    const deviceFuncGroups = res.deviceFuncGroups.map(function (obj) {
        return obj.property_name;
    });

    const appPolicy = {};

    // set all requested apps to default permissions
    for (let i = 0; i < res.requestedUuids.length; i++) {
        appPolicy[res.requestedUuids[i]] = "default";
    }

    // overwrite available apps with their granted permissions
    for (let i = 0; i < policyObjs.length; i++) {
        const key = Object.keys(policyObjs[i])[0];
        appPolicy[key] = policyObjs[i][key];
    }

    //setup defaults after the app ids are populated
    appPolicy.default = {
        "keep_context": false,
        "steal_focus": false,
        "priority": "NONE",
        "default_hmi": "NONE",
        "groups": defaultFuncGroups
    };
    //DataConsent-2 functional group removed
    appPolicy.device = {
        "keep_context": false,
        "steal_focus": false,
        "priority": "NONE",
        "default_hmi": "NONE",
        "groups": deviceFuncGroups
    };
    //BaseBeforeDataConsent functional group removed
    appPolicy.pre_DataConsent = {
        "keep_context": false,
        "steal_focus": false,
        "priority": "NONE",
        "default_hmi": "NONE",
        "groups": preDataConsentFuncGroups
    };
    next(null, appPolicy);
}

module.exports = {
    transformModuleConfig: transformModuleConfig,
    transformMessages: transformMessages,
    transformFunctionalGroups: transformFunctionalGroups,
    constructAppPolicy: constructAppPolicy,
    aggregateResults: aggregateResults
}<|endoftext|>


<commit_before>import Immutable from 'immutable'
import { clearJSON, json, stubAnnouncementNotification } from '../../support/stubs'
import * as selector from '../../../src/selectors/notifications'

describe('announcement selectors', () => {
  const gui = Immutable.Map({ lastAnnouncementSeen: '333' })
  let announcement
  let state
  beforeEach(() => {
    announcement = stubAnnouncementNotification()
    state = { gui, json }
  })

  afterEach(() => {
    clearJSON()
  })

  context('#selectAnnouncements', () => {
    it('returns announcements model out of json', () => {
      expect(selector.selectAnnouncements(state)).to.deep.equal(state.json.get('announcements'))
    })
  })

  context('#selectAnnouncement', () => {
    it('returns the first announcement in the model', () => {
      expect(selector.selectAnnouncement(state)).to.deep.equal(state.json.getIn(['announcements', '8']))
    })

    it('returns an empty Map if announcements have been read', () => {
      expect(selector.selectAnnouncement({ json: Immutable.Map() })).to.deep.equal(Immutable.Map())
    })
  })

  context('#selectAnnouncementBody', () => {
    it('returns the announcement.body property', () => {
      const result = selector.selectAnnouncementBody(state)
      expect(result).to.equal(announcement.get('body'))
    })
  })

  context('#selectAnnouncementCTACaption', () => {
    it('returns the announcement.ctaCaption property', () => {
      const result = selector.selectAnnouncementCTACaption(state)
      expect(result).to.equal(announcement.get('ctaCaption'))
    })
  })

  context('#selectAnnouncementCTAHref', () => {
    it('returns the announcement.ctaHref property', () => {
      const result = selector.selectAnnouncementCTAHref(state)
      expect(result).to.equal(announcement.get('ctaHref'))
    })
  })

  context('#selectAnnouncementId', () => {
    it('returns the announcement.id property', () => {
      const result = selector.selectAnnouncementId(state)
      expect(result).to.equal(announcement.get('id'))
    })
  })

  context('#selectAnnouncementImage', () => {
    it('returns the announcement.image property', () => {
      const result = selector.selectAnnouncementImage(state)
      expect(result).to.deep.equal(announcement.getIn(['image', 'hdpi', 'url']))
    })
  })

  context('#selectAnnouncementTitle', () => {
    it('returns the announcement.header property', () => {
      const result = selector.selectAnnouncementTitle(state)
      expect(result).to.equal(announcement.get('header'))
    })
  })

  context('#selectAnnouncementIsStaffPreview', () => {
    it('returns if the announcement is staff preview (false)', () => {
      const result = selector.selectAnnouncementIsStaffPreview(state)
      expect(result).to.equal(false)
    })

    it('returns if the announcement is staff preview (true)', () => {
      state.json = state.json.setIn(['announcements', '8', 'isStaffPreview'], true)
      console.log(state.json.toJS())
      expect(selector.selectAnnouncementIsStaffPreview(state)).to.equal(true)
    })
  })

  context('#selectAnnouncementIsEmpty', () => {
    it('returns if the announcement is empty (false)', () => {
      const result = selector.selectAnnouncementIsEmpty(state)
      expect(result).to.equal(false)
    })

    it('returns if the announcement is empty (true)', () => {
      expect(selector.selectAnnouncementIsEmpty({ json: Immutable.Map() })).to.equal(true)
    })
  })

  context('#selectAnnouncementIsUnread', () => {
    it('returns if the announcements is empty (true)', () => {
      const result = selector.selectAnnouncementIsUnread(state)
      expect(result).to.equal(true)
    })

    it('returns if the announcements is empty (false)', () => {
      expect(selector.selectAnnouncementIsUnread({ json: Immutable.Map() })).to.equal(false)
    })
  })

  context('#selectAnnouncementHasBeenViewed', () => {
    it('returns if the announcements has been viewed (false)', () => {
      const result = selector.selectAnnouncementHasBeenViewed(state)
      expect(result).to.equal(false)
    })

    it('returns if the announcements has been viewed after opening the notifications', () => {
      state = { gui: state.gui.set('lastAnnouncementSeen', '8'), json }
      const result = selector.selectAnnouncementHasBeenViewed(state)
      expect(result).to.equal(true)
    })

    it('returns if the announcements has been viewed after marking read', () => {
      state = {
        gui: state.gui.set('lastAnnouncementSeen', '8'),
        json: state.json.delete('announcements'),
      }
      const result = selector.selectAnnouncementHasBeenViewed(state)
      expect(result).to.equal(true)
    })
  })
})

<commit_msg>Remove a console statement<commit_after>import Immutable from 'immutable'
import { clearJSON, json, stubAnnouncementNotification } from '../../support/stubs'
import * as selector from '../../../src/selectors/notifications'

describe('announcement selectors', () => {
  const gui = Immutable.Map({ lastAnnouncementSeen: '333' })
  let announcement
  let state
  beforeEach(() => {
    announcement = stubAnnouncementNotification()
    state = { gui, json }
  })

  afterEach(() => {
    clearJSON()
  })

  context('#selectAnnouncements', () => {
    it('returns announcements model out of json', () => {
      expect(selector.selectAnnouncements(state)).to.deep.equal(state.json.get('announcements'))
    })
  })

  context('#selectAnnouncement', () => {
    it('returns the first announcement in the model', () => {
      expect(selector.selectAnnouncement(state)).to.deep.equal(state.json.getIn(['announcements', '8']))
    })

    it('returns an empty Map if announcements have been read', () => {
      expect(selector.selectAnnouncement({ json: Immutable.Map() })).to.deep.equal(Immutable.Map())
    })
  })

  context('#selectAnnouncementBody', () => {
    it('returns the announcement.body property', () => {
      const result = selector.selectAnnouncementBody(state)
      expect(result).to.equal(announcement.get('body'))
    })
  })

  context('#selectAnnouncementCTACaption', () => {
    it('returns the announcement.ctaCaption property', () => {
      const result = selector.selectAnnouncementCTACaption(state)
      expect(result).to.equal(announcement.get('ctaCaption'))
    })
  })

  context('#selectAnnouncementCTAHref', () => {
    it('returns the announcement.ctaHref property', () => {
      const result = selector.selectAnnouncementCTAHref(state)
      expect(result).to.equal(announcement.get('ctaHref'))
    })
  })

  context('#selectAnnouncementId', () => {
    it('returns the announcement.id property', () => {
      const result = selector.selectAnnouncementId(state)
      expect(result).to.equal(announcement.get('id'))
    })
  })

  context('#selectAnnouncementImage', () => {
    it('returns the announcement.image property', () => {
      const result = selector.selectAnnouncementImage(state)
      expect(result).to.deep.equal(announcement.getIn(['image', 'hdpi', 'url']))
    })
  })

  context('#selectAnnouncementTitle', () => {
    it('returns the announcement.header property', () => {
      const result = selector.selectAnnouncementTitle(state)
      expect(result).to.equal(announcement.get('header'))
    })
  })

  context('#selectAnnouncementIsStaffPreview', () => {
    it('returns if the announcement is staff preview (false)', () => {
      const result = selector.selectAnnouncementIsStaffPreview(state)
      expect(result).to.equal(false)
    })

    it('returns if the announcement is staff preview (true)', () => {
      state.json = state.json.setIn(['announcements', '8', 'isStaffPreview'], true)
      expect(selector.selectAnnouncementIsStaffPreview(state)).to.equal(true)
    })
  })

  context('#selectAnnouncementIsEmpty', () => {
    it('returns if the announcement is empty (false)', () => {
      const result = selector.selectAnnouncementIsEmpty(state)
      expect(result).to.equal(false)
    })

    it('returns if the announcement is empty (true)', () => {
      expect(selector.selectAnnouncementIsEmpty({ json: Immutable.Map() })).to.equal(true)
    })
  })

  context('#selectAnnouncementIsUnread', () => {
    it('returns if the announcements is empty (true)', () => {
      const result = selector.selectAnnouncementIsUnread(state)
      expect(result).to.equal(true)
    })

    it('returns if the announcements is empty (false)', () => {
      expect(selector.selectAnnouncementIsUnread({ json: Immutable.Map() })).to.equal(false)
    })
  })

  context('#selectAnnouncementHasBeenViewed', () => {
    it('returns if the announcements has been viewed (false)', () => {
      const result = selector.selectAnnouncementHasBeenViewed(state)
      expect(result).to.equal(false)
    })

    it('returns if the announcements has been viewed after opening the notifications', () => {
      state = { gui: state.gui.set('lastAnnouncementSeen', '8'), json }
      const result = selector.selectAnnouncementHasBeenViewed(state)
      expect(result).to.equal(true)
    })

    it('returns if the announcements has been viewed after marking read', () => {
      state = {
        gui: state.gui.set('lastAnnouncementSeen', '8'),
        json: state.json.delete('announcements'),
      }
      const result = selector.selectAnnouncementHasBeenViewed(state)
      expect(result).to.equal(true)
    })
  })
})

<|endoftext|>


<commit_before>var urlUtils = require('url');

var Watai			= require('../helpers/subject'),
	ConfigLoader	= require('mattisg.configloader'),
	stdoutSpy		= require('../helpers/StdoutSpy'),
	SauceLabsView	= require(Watai.path + '/view/Runner/SauceLabs');

/** This test suite is written with [Mocha](http://visionmedia.github.com/mocha/) and [Should](https://github.com/visionmedia/should.js).
*/
describe('SauceLabs view', function() {
	var subject,
		runner;

	before(function() {
		var config = new ConfigLoader({
			from		: __dirname,
			appName		: 'watai',
			override	: { quit: 'always' },
			visitAlso	: '../../src'
		}).load('config');

		this.timeout(config.browserWarmupTime);

		runner = new Watai.Runner(config);

		subject = new SauceLabsView(runner);
	});

	after(function(done) {
		runner.quitBrowser().finally(done);
	});

	describe('#getAuth', function() {
		describe('when there is no way to get the data', function() {
			before(stdoutSpy.reset);
			beforeEach(stdoutSpy.mute);
			afterEach(stdoutSpy.unmute);

			it('should throw', function() {
				(subject.getAuth.bind(subject)).should.throw(ReferenceError);
			});

			it('should provide information to the user', function() {
				stdoutSpy.printed().should.include('SauceLabs authentication');
				stdoutSpy.printed().should.include('config');
				stdoutSpy.printed().should.include('SAUCE_USERNAME');
				stdoutSpy.printed().should.include('SAUCE_ACCESS_KEY');
			});
		});

		function checkMatch(username, accessKey) {
			var data = subject.getAuth();
			data.username.should.equal(username);
			data.password.should.equal(accessKey);
		}

		describe('when auth is set through environment variables', function() {
			before(function() {
				process.env.SAUCE_USERNAME = 'user-env';
				process.env.SAUCE_ACCESS_KEY = 'pass-env';
			});

			it('should obtain auth data from environment variables', function() {
				checkMatch('user-env', 'pass-env')
			});
		});

		describe('when auth is set through config', function() {
			before(function() {
				var seleniumServerURL = urlUtils.parse(runner.config.seleniumServerURL);
				seleniumServerURL.auth = 'user-config:pass-config';
				runner.config.seleniumServerURL = urlUtils.format(seleniumServerURL);
			});

			it('should obtain auth data from configuration', function() {
				checkMatch('user-config', 'pass-config');
			});
		});

		describe('when auth is set through both env and config', function() {
			before(function() {
				var seleniumServerURL = urlUtils.parse(runner.config.seleniumServerURL);
				seleniumServerURL.auth = 'user-config:';
				runner.config.seleniumServerURL = urlUtils.format(seleniumServerURL);
				process.env.SAUCE_ACCESS_KEY = 'pass-env';
			});

			it('should obtain auth data half from configuration, half from environment variables', function() {
				checkMatch('user-config', 'pass-env');
			});
		});
	});

	describe('when not set to always quit', function() {
		before(function() {
			runner.config.quit = 'never';
		});

		after(function() {
			runner.config.quit = 'always';
		});

		before(stdoutSpy.reset);
		beforeEach(stdoutSpy.mute);
		afterEach(stdoutSpy.unmute);

		it('should provide information to the user', function() {
			subject.showStart();
			stdoutSpy.printed().should.include('quit');
			stdoutSpy.printed().should.include('always');
			stdoutSpy.printed().should.match(/wast.* 90 ?s/);	// wasting, wastes, waste, 90 seconds, 90s… doesn't matter
		});
	});
});
<commit_msg>Fix SauceLabs view test<commit_after>var urlUtils = require('url');

var Watai			= require('../helpers/subject'),
	ConfigLoader	= require('mattisg.configloader'),
	stdoutSpy		= require('../helpers/StdoutSpy'),
	SauceLabsView	= require(Watai.path + '/view/Runner/SauceLabs');

/** This test suite is written with [Mocha](http://visionmedia.github.com/mocha/) and [Should](https://github.com/visionmedia/should.js).
*/
describe('SauceLabs view', function() {
	var subject,
		runner;

	before(function() {
		var config = new ConfigLoader({
			from		: __dirname,
			appName		: 'watai',
			override	: { quit: 'always' },
			visitAlso	: '../../src'
		}).load('config');

		this.timeout(config.browserWarmupTime);

		runner = new Watai.Runner(config);

		subject = new SauceLabsView(runner);
	});

	after(function(done) {
		this.timeout(10 * 1000);

		runner.quitBrowser().finally(done);
	});

	describe('#getAuth', function() {
		describe('when there is no way to get the data', function() {
			before(stdoutSpy.reset);
			beforeEach(stdoutSpy.mute);
			afterEach(stdoutSpy.unmute);

			it('should throw', function() {
				(subject.getAuth.bind(subject)).should.throw(ReferenceError);
			});

			it('should provide information to the user', function() {
				stdoutSpy.printed().should.include('SauceLabs authentication');
				stdoutSpy.printed().should.include('config');
				stdoutSpy.printed().should.include('SAUCE_USERNAME');
				stdoutSpy.printed().should.include('SAUCE_ACCESS_KEY');
			});
		});

		function checkMatch(username, accessKey) {
			var data = subject.getAuth();
			data.username.should.equal(username);
			data.password.should.equal(accessKey);
		}

		describe('when auth is set through environment variables', function() {
			before(function() {
				process.env.SAUCE_USERNAME = 'user-env';
				process.env.SAUCE_ACCESS_KEY = 'pass-env';
			});

			it('should obtain auth data from environment variables', function() {
				checkMatch('user-env', 'pass-env')
			});
		});

		describe('when auth is set through config', function() {
			before(function() {
				var seleniumServerURL = urlUtils.parse(runner.config.seleniumServerURL);
				seleniumServerURL.auth = 'user-config:pass-config';
				runner.config.seleniumServerURL = urlUtils.format(seleniumServerURL);
			});

			it('should obtain auth data from configuration', function() {
				checkMatch('user-config', 'pass-config');
			});
		});

		describe('when auth is set through both env and config', function() {
			before(function() {
				var seleniumServerURL = urlUtils.parse(runner.config.seleniumServerURL);
				seleniumServerURL.auth = 'user-config:';
				runner.config.seleniumServerURL = urlUtils.format(seleniumServerURL);
				process.env.SAUCE_ACCESS_KEY = 'pass-env';
			});

			it('should obtain auth data half from configuration, half from environment variables', function() {
				checkMatch('user-config', 'pass-env');
			});
		});
	});

	describe('when not set to always quit', function() {
		before(function() {
			process.env.SAUCE_USERNAME = 'user-env';
			process.env.SAUCE_ACCESS_KEY = 'pass-env';

			runner.config.quit = 'never';
		});

		after(function() {
			runner.config.quit = 'always';
		});

		before(stdoutSpy.reset);
		beforeEach(stdoutSpy.mute);
		afterEach(stdoutSpy.unmute);

		it('should provide information to the user', function() {
			subject.showStart();
			stdoutSpy.printed().should.include('quit');
			stdoutSpy.printed().should.include('always');
			stdoutSpy.printed().should.match(/wast.* 90 ?s/);	// wasting, wastes, waste, 90 seconds, 90s… doesn't matter
		});
	});
});
<|endoftext|>


<commit_before>/* global angular Phaser */

'use strict'

angular.module('myApp.game', ['ngRoute'])

.config(['$routeProvider', function ($routeProvider) {
  $routeProvider.when('/game', {
    templateUrl: 'app/views/game/game.html',
    controller: 'GameCtrl'
  })
}])

.controller('GameCtrl', ['Photos', '$scope', '$rootScope', '$timeout', 'Game.Preloader', 'Game.Logic', function (Photos, $scope, $rootScope, $timeout, Preloader, Logic) {

  $scope.assetsLoaded = false

  Photos.fetch()
    .then(function (data) {
      return data.photos.map(function (obj) {
        return obj.image_url
      })
    })
    .then(function (photosURL) {

      var game = new Phaser.Game('100%', '100%', Phaser.CANVAS, 'game', null, true)

      game.state.add('Preloader', Preloader(photosURL), true)
      game.state.add('Game', Logic)

      $scope.assetsLoaded = false

      $rootScope.$on('loaded', function (event) {
        $scope.$apply(function () {
          $scope.assetsLoaded = true
        })

        $timeout(
          function () {
            $scope.$apply(function () {
              $scope.hidePreloader = true
              game.state.start('Game')
            })
          }
          , 2000)
      })
    })

  $rootScope.$on('tips', function (event, data) {
    $scope.$apply(function () {
      $scope.tips = data
    })
  })

  $scope.onSelect = function (selection) {
    $rootScope.$broadcast('selection', selection)
  }
}])

.factory('Game.Preloader', ['$rootScope', function ($rootScope) {

  var _photosURL

  var Preloader = function () {}

  Preloader.prototype = {

    init: function () {
      this.input.maxPointers = 1
      this.scale.pageAlignHorizontally = true
    },

    preload: function () {

      this.load.path = 'app/assets/'

      this.load.bitmapFont('fat-and-tiny')
      this.load.bitmapFont('digits')

      this.load.images(_photosURL)
    },

    create: function () {
      $rootScope.$broadcast('loaded')
    }
  }

  return function (photosURL) {

    _photosURL = photosURL

    return Preloader
  }
}])

.factory('Game.Logic', ['Photos', '$rootScope', '$location', 'GameResults', function (Photos, $rootScope, $location, GameResults) {

  var KEYS = ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm']

  var Game = function () {

    this.score = 0
    this.scoreText = null
  }

  Game.prototype = {

    init: function () {

      this.score = 0

      $rootScope.$on('selection', function (ev, data) {
        this.selectKey(data)
      }.bind(this))
    },

    create: function () {

      this.scoreText = this.add.bitmapText(64, 12, 'fat-and-tiny', 'SCORE: 0', 32)
      this.scoreText.smoothed = false
      this.scoreText.tint = 0x000000

      this.rawPhotoData = Photos.get()

      this.playing = true
      this.speed = 1
      this.totalKeys = []
      this.successfulTags = []
      this.totalTags = []

      this.showNextPhoto()
    },

    update: function () {

      if (this.playing && this.input.keyboard.pressEvent) {

        var ev = this.input.keyboard.pressEvent
        var success = this.currentTags.filter(function (value) {
          return value.indexOf(ev.key) === 0
        })

        this.keysPressed.push(ev.key)
        this.totalKeys.push(ev.key)

        if (success.length > 0) {
          this.success(success)
        }

        this.input.keyboard.pressEvent = null
      }
    },

    success: function (tags) {

      this.playing = false

      this.successfulTags = (this.successfulTags || []).concat(tags)
      this.totalTags = (this.totalTags || []).concat(this.currentTags)

      this.add.tween(this.currentPhoto).to({
        x: this.world.centerX,
        y: this.world.centerY,
        width: 10000,
        height: 10000,
        alpha: 0
      }, 300, 'Sine.easeOut', true, 100)

      var style = { font: 'bold 200px Arial', fill: '#fff', boundsAlignH: 'center', boundsAlignV: 'middle' }
      var text = this.game.add.text(0, 0, tags.toString(), style)
      text.setShadow(3, 3, 'rgba(0,0,0,0.5)', 2)
      text.anchor.set(0.5)
      text.x = this.world.width / 2
      text.y = this.world.height / 2
      var tween = this.add.tween(text).to({
        alpha: 0,
        width: 0,
        height: 0
      }, 300, 'Sine.easeOut', true, 300)

      tween.onComplete.add(this.addScore, this)
    },

    calcPoints: function () {

      var worldWidth = this.world.width
      var photoRightCorner = this.currentPhoto.x
      var percentageOfScreen = (worldWidth - photoRightCorner) / worldWidth
      var positionScore = Math.floor(percentageOfScreen * 10)

      var speedScore = Math.floor(this.speed)

      var keysNeeded = this.keysPressed.length
      var keysNeededScore = Math.max(10 - keysNeeded, 0)

      this.totalPhotos = (this.totalPhotos || 0) + 1

      return positionScore + speedScore + keysNeededScore
    },

    addScore: function (tween) {

      this.score += this.calcPoints()
      this.scoreText.text = 'SCORE: ' + this.score

      this.showNextPhoto()
    },

    showNextPhoto: function () {

      if (this.photoTween) {
        this.photoTween.stop()
      }

      var photo = Phaser.ArrayUtils.getRandomItem(this.rawPhotoData)

      this.currentPhoto = this.add.image(0, this.world.centerY, photo.image_url)
      this.currentPhoto.anchor.set(0.5)
      this.currentPhoto.x -= this.currentPhoto.width / 2
      this.currentTags = photo.tags
      this.currentPhoto.alpha = 0

      this.speed *= 1.2

      this.playing = true
      this.keysPressed = []

      this.add.tween(this.currentPhoto).to({alpha: 1}, 1000, 'Sine.easeOut', true, 100)
      this.photoTween = this.add.tween(this.currentPhoto).to({x: this.world.width + (this.currentPhoto.width / 2)}, 10000 / this.speed, 'Linear', true, 100)
      this.photoTween.onComplete.add(this.gameOver, this)

      if (!Phaser.Device.desktop) {
        var tips = this.updateTips()
        $rootScope.$broadcast('tips', tips)
      }

      console.log(this.currentTags)
    },

    updateTips: function () {
      var tips = [this.currentTags[this.game.rnd.integerInRange(0, this.currentTags.length - 1)].substr(0, 1)]
      tips.push(KEYS[this.game.rnd.integerInRange(0, 10)])
      tips.push(KEYS[this.game.rnd.integerInRange(10, 20)])
      tips.push(KEYS[this.game.rnd.integerInRange(20, KEYS.length - 1)])

      return Phaser.ArrayUtils.shuffle(tips)
    },

    selectKey: function (k) {

      var success = this.currentTags.filter(function (value) {
        return value.indexOf(k) === 0
      })

      this.keysPressed.push(k)
      this.totalKeys.push(k)

      if (success.length > 0) {
        this.success(success)
      } else {
        this.updateTips()
      }
    },

    gameOver: function () {

      GameResults.set({
        score: this.score,
        keysPressed: this.totalKeys,
        maxSpeed: this.speed,
        tags: {
          successful: this.successfulTags,
          total: this.totalTags
        }
      })

      this.game.destroy()

      $rootScope.$apply(function () {
        $location.path('/results')
      })
    }
  }

  return Game
}])
<commit_msg>Fixed removing photo after tween issue<commit_after>/* global angular Phaser */

'use strict'

angular.module('myApp.game', ['ngRoute'])

.config(['$routeProvider', function ($routeProvider) {
  $routeProvider.when('/game', {
    templateUrl: 'app/views/game/game.html',
    controller: 'GameCtrl'
  })
}])

.controller('GameCtrl', ['Photos', '$scope', '$rootScope', '$timeout', 'Game.Preloader', 'Game.Logic', function (Photos, $scope, $rootScope, $timeout, Preloader, Logic) {

  $scope.assetsLoaded = false

  Photos.fetch()
    .then(function (data) {
      return data.photos.map(function (obj) {
        return obj.image_url
      })
    })
    .then(function (photosURL) {

      var game = new Phaser.Game('100%', '100%', Phaser.CANVAS, 'game', null, true)

      game.state.add('Preloader', Preloader(photosURL), true)
      game.state.add('Game', Logic)

      $scope.assetsLoaded = false

      $rootScope.$on('loaded', function (event) {
        $scope.$apply(function () {
          $scope.assetsLoaded = true
        })

        $timeout(
          function () {
            $scope.$apply(function () {
              $scope.hidePreloader = true
              game.state.start('Game')
            })
          }
          , 2000)
      })
    })

  $rootScope.$on('tips', function (event, data) {
    $scope.$apply(function () {
      $scope.tips = data
    })
  })

  $scope.onSelect = function (selection) {
    $rootScope.$broadcast('selection', selection)
  }
}])

.factory('Game.Preloader', ['$rootScope', function ($rootScope) {

  var _photosURL

  var Preloader = function () {}

  Preloader.prototype = {

    init: function () {
      this.input.maxPointers = 1
      this.scale.pageAlignHorizontally = true
    },

    preload: function () {

      this.load.path = 'app/assets/'

      this.load.bitmapFont('fat-and-tiny')
      this.load.bitmapFont('digits')

      this.load.images(_photosURL)
    },

    create: function () {
      $rootScope.$broadcast('loaded')
    }
  }

  return function (photosURL) {

    _photosURL = photosURL

    return Preloader
  }
}])

.factory('Game.Logic', ['Photos', '$rootScope', '$location', 'GameResults', function (Photos, $rootScope, $location, GameResults) {

  var KEYS = ['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm']

  var Game = function () {

    this.score = 0
    this.scoreText = null
  }

  Game.prototype = {

    init: function () {

      this.score = 0

      $rootScope.$on('selection', function (ev, data) {
        this.selectKey(data)
      }.bind(this))
    },

    create: function () {

      this.scoreText = this.add.bitmapText(64, 12, 'fat-and-tiny', 'SCORE: 0', 32)
      this.scoreText.smoothed = false
      this.scoreText.tint = 0x000000

      this.rawPhotoData = Photos.get()

      this.playing = true
      this.speed = 1
      this.totalKeys = []
      this.successfulTags = []
      this.totalTags = []

      this.showNextPhoto()
    },

    update: function () {

      if (this.playing && this.input.keyboard.pressEvent) {

        var ev = this.input.keyboard.pressEvent
        var success = this.currentTags.filter(function (value) {
          return value.indexOf(ev.key) === 0
        })

        this.keysPressed.push(ev.key)
        this.totalKeys.push(ev.key)

        if (success.length > 0) {
          this.success(success)
        }

        this.input.keyboard.pressEvent = null
      }
    },

    success: function (tags) {

      this.playing = false

      this.successfulTags = (this.successfulTags || []).concat(tags)
      this.totalTags = (this.totalTags || []).concat(this.currentTags)

      this.add.tween(this.currentPhoto).to({
        x: this.world.centerX,
        y: this.world.centerY,
        width: 10000,
        height: 10000,
        alpha: 0
      }, 300, 'Sine.easeOut', true, 100)

      var style = { font: 'bold 70px Arial', fill: '#fff', boundsAlignH: 'center', boundsAlignV: 'center' }
      var text = this.game.add.text(0, 0, tags.join('\n').toString(), style)
      text.setShadow(3, 3, 'rgba(0,0,0,0.5)', 2)
      text.anchor.set(0.5)
      text.x = this.world.width / 2
      text.y = this.world.height / 2
      var tween = this.add.tween(text).to({
        alpha: 0,
        width: 0,
        height: 0
      }, 300, 'Sine.easeOut', true, 300)

      tween.onComplete.add(this.addScore, this)
    },

    calcPoints: function () {

      var worldWidth = this.world.width
      var photoRightCorner = this.currentPhoto.x
      var percentageOfScreen = (worldWidth - photoRightCorner) / worldWidth
      var positionScore = Math.floor(percentageOfScreen * 10)

      var speedScore = Math.floor(this.speed)

      var keysNeeded = this.keysPressed.length
      var keysNeededScore = Math.max(10 - keysNeeded, 0)

      this.totalPhotos = (this.totalPhotos || 0) + 1

      return positionScore + speedScore + keysNeededScore
    },

    addScore: function (tween) {

      this.score += this.calcPoints()
      this.scoreText.text = 'SCORE: ' + this.score

      this.currentPhoto.destroy()

      this.showNextPhoto()
    },

    showNextPhoto: function () {

      if (this.photoTween) {
        this.photoTween.stop()
      }

      var photo = Phaser.ArrayUtils.getRandomItem(this.rawPhotoData)

      this.currentPhoto = this.add.image(0, this.world.centerY, photo.image_url)
      this.currentPhoto.anchor.set(0.5)
      this.currentPhoto.x -= this.currentPhoto.width / 2
      this.currentTags = photo.tags
      this.currentPhoto.alpha = 0

      this.speed *= 1.2

      this.playing = true
      this.keysPressed = []

      this.add.tween(this.currentPhoto).to({alpha: 1}, 1000, 'Sine.easeOut', true, 100)
      this.photoTween = this.add.tween(this.currentPhoto).to({x: this.world.width + (this.currentPhoto.width / 2)}, 10000 / this.speed, 'Linear', true, 100)
      this.photoTween.onComplete.add(this.gameOver, this)

      if (!Phaser.Device.desktop) {
        var tips = this.updateTips()
        $rootScope.$broadcast('tips', tips)
      }
    },

    updateTips: function () {

      var tags = this.currentTags[this.game.rnd.integerInRange(0, this.currentTags.length - 1)]

      var tips = []

      if (tags) {
        tips.push(tags.substr(0, 1))
      } else {
        tips.push(KEYS[this.game.rnd.integerInRange(0, 10)])
      }
      tips.push(KEYS[this.game.rnd.integerInRange(0, 10)])
      tips.push(KEYS[this.game.rnd.integerInRange(10, 20)])
      tips.push(KEYS[this.game.rnd.integerInRange(20, KEYS.length - 1)])

      return Phaser.ArrayUtils.shuffle(tips)
    },

    selectKey: function (k) {

      var success = this.currentTags.filter(function (value) {
        return value.indexOf(k) === 0
      })

      this.keysPressed.push(k)
      this.totalKeys.push(k)

      if (success.length > 0) {
        this.success(success)
      } else {
        this.updateTips()
      }
    },

    gameOver: function () {

      GameResults.set({
        score: this.score,
        keysPressed: this.totalKeys,
        maxSpeed: this.speed,
        tags: {
          successful: this.successfulTags,
          total: this.totalTags
        }
      })

      this.game.destroy()

      $rootScope.$apply(function () {
        $location.path('/results')
      })
    }
  }

  return Game
}])
<|endoftext|>


<commit_before>// Ionic Starter App

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
angular.module('headcount', [
  'ionic',
  'headcount.AppController',
  'headcount.services',
  'headcount.events',
  'headcount.accounts',
  'headcount.auth',
  'ngMaterial'
])
.run(function($ionicPlatform, $rootScope, Auth, $state ) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    // if(window.cordova && window.cordova.plugins.Keyboard) {
    //   cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    // }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });

  $rootScope.$on('$stateChangeStart', function (e, toState, toParams, fromState, fromParams) {

    if (toState && toState.authenticate && !Auth.isAuth()) {
      setTimeout(function(){
        $state.go('signin');
      });

    }
  });
})
.config(function($stateProvider, $urlRouterProvider){
  $stateProvider
  // adds menu
    .state('app', {
      url: '/app',
      templateUrl: '../www/templates/app.html',
      // for development on phone add www/ as beginning route path
      // for development on web browser, take out www/
      controller: 'AppController'
    })
    .state('signin', {
      url: '/signin',
      templateUrl: '../www/templates/signin.html',
      controller: 'AuthController',
    })
    .state('signup', {
      url: '/signup',
      templateUrl: '../www/templates/signup.html',
      controller: 'AuthController'
    })
    .state('app.event', {
      url: '/event',
      views: {
        'menuContent': {
          templateUrl: '../www/templates/event.html',
          controller: 'EventsController'
        }
      },
      authenticate: true,
    })
    .state('app.events', {
      url: '/events',
      views: {
        'menuContent': {
          templateUrl: '../www/templates/eventslist.html',
          controller: 'EventsController'
        }
      },
      authenticate: true
    })
    .state('app.newevent', {
      url: '/newevent',
      views: {
        'menuContent': {
          templateUrl: '../www/templates/newevent.html',
          controller: 'EventsController'
        }
      },
      authenticate: true
    })
    .state('app.accounts', {
      url: '/accounts',
      views: {
        'menuContent': {
          templateUrl: '../www/templates/accounts.html',
          controller: 'AccountsController'
        }
      },
      authenticate: true
    });

    // $mdThemingProvider.theme('default')
    //   .primaryPalette('blue')
    //   .accentPalette('red');

    $urlRouterProvider.otherwise('/signin');
})
.factory('EventsFactory', function ($rootScope) {
  var eventServices = {};

  eventServices.shouldNotBeCreatable = false;
  eventServices.shouldNotBeClickable = false;

  eventServices.currentEvent = {};
  return eventServices;
})
.factory('AttachTokens', function ($window, $location) {
  // this is an $httpInterceptor
  // its job is to stop all out going request
  // then look in local storage and find the user's token
  // then add it to the header so the server can validate the request
  // TODO: Make this more secure, use passport or bcrypt.
  var attach = {
    request: function (object) {
      var username = $window.localStorage.getItem('user');
      if (username) {
        object.headers['x-access-token'] = username;
      }
      object.headers['Allow-Control-Allow-Origin'] = '*';
      return object;
    }
  };
  return attach;
})
<commit_msg>adds minimal material design<commit_after>// Ionic Starter App

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
angular.module('headcount', [
  'ionic',
  'headcount.AppController',
  'headcount.services',
  'headcount.events',
  'headcount.accounts',
  'headcount.auth',
  'ngMaterial'
])
.run(function($ionicPlatform, $rootScope, Auth, $state ) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    // if(window.cordova && window.cordova.plugins.Keyboard) {
    //   cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    // }
    if(window.StatusBar) {
      StatusBar.styleDefault();
    }
  });

  $rootScope.$on('$stateChangeStart', function (e, toState, toParams, fromState, fromParams) {

    if (toState && toState.authenticate && !Auth.isAuth()) {
      setTimeout(function(){
        $state.go('signin');
      });

    }
  });
})
.config(function($stateProvider, $urlRouterProvider){
  $stateProvider
  // adds menu
    .state('app', {
      url: '/app',
      templateUrl: '../www/templates/app.html',
      // for development on phone add www/ as beginning route path
      // for development on web browser, take out www/
      controller: 'AppController'
    })
    .state('signin', {
      url: '/signin',
      templateUrl: '../www/templates/signin.html',
      controller: 'AuthController',
    })
    .state('signup', {
      url: '/signup',
      templateUrl: '../www/templates/signup.html',
      controller: 'AuthController'
    })
    .state('app.event', {
      url: '/event',
      views: {
        'menuContent': {
          templateUrl: '../www/templates/event.html',
          controller: 'EventsController'
        }
      },
      authenticate: true,
    })
    .state('app.events', {
      url: '/events',
      views: {
        'menuContent': {
          templateUrl: '../www/templates/eventslist.html',
          controller: 'EventsController'
        }
      },
      authenticate: true
    })
    .state('app.newevent', {
      url: '/newevent',
      views: {
        'menuContent': {
          templateUrl: '../www/templates/newevent.html',
          controller: 'EventsController'
        }
      },
      authenticate: true
    })
    .state('app.accounts', {
      url: '/accounts',
      views: {
        'menuContent': {
          templateUrl: '../www/templates/accounts.html',
          controller: 'AccountsController'
        }
      },
      authenticate: true
    });

    $mdThemingProvider.theme('default')
      .primaryPalette('blue')
      .accentPalette('red');

    $urlRouterProvider.otherwise('/signin');
})
.factory('EventsFactory', function ($rootScope) {
  var eventServices = {};

  eventServices.shouldNotBeCreatable = false;
  eventServices.shouldNotBeClickable = false;

  eventServices.currentEvent = {};
  return eventServices;
})
.factory('AttachTokens', function ($window, $location) {
  // this is an $httpInterceptor
  // its job is to stop all out going request
  // then look in local storage and find the user's token
  // then add it to the header so the server can validate the request
  // TODO: Make this more secure, use passport or bcrypt.
  var attach = {
    request: function (object) {
      var username = $window.localStorage.getItem('user');
      if (username) {
        object.headers['x-access-token'] = username;
      }
      object.headers['Allow-Control-Allow-Origin'] = '*';
      return object;
    }
  };
  return attach;
})
<|endoftext|>


<commit_before>/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0

ABOUT THIS NODE.JS EXAMPLE: This example works with AWS SDK for JavaScript version 3 (v3),
which is available at https://github.com/aws/aws-sdk-js-v3. This example is in the 'AWS SDK for JavaScript v3 Developer Guide' at
https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/dynamodb-example-dynamodb-utilities.html.

Purpose:
ddbdoc_put_item.js demonstrates how to use the Amazon DynamoDB document client to create or replace an item in an Amazon DynamoDB table.

Inputs (replace in code):
- TABLE_NAME
- primaryKey - The name of the primary key. For example, "id".
- VALUE_1: Value for the primary key (The format for the datatype must match the schema. For example, if the primaryKey is a number, VALUE_1 has no inverted commas.)
- sortKey - The name of the sort key. Only required if table has sort key. For example, "firstName".
- VALUE_2: Value for the primary key (The format for the datatype must match the schema.)
- NEW_ATTRIBUTE_1
- NEW_ATTRIBUTE_1_VALUE

Running the code:
ts-node ddbdoc_put_item.js
*/
// snippet-start:[dynamodb.JavaScript.docClient.putV3]

import { PutCommand } from "@aws-sdk/lib-dynamodb";
import { ddbDocClient } from "./libs/ddbDocClient.js";

// Set the parameters.
const params = {
  TableName: "TABLE_NAME",
  /*
    Convert the key JavaScript object you are adding to the
    required Amazon DynamoDB record. The format of values specifies
    the datatype. The following list demonstrates different
    datatype formatting requirements:
    String: "String",
    NumAttribute: 1,
    BoolAttribute: true,
    ListAttribute: [1, "two", false],
    MapAttribute: { foo: "bar" },
    NullAttribute: null
     */
  Item: {
    primaryKey: "VALUE_1", // For example, 'Season': 2
    sortKey: "VALUE_2", // For example,  'Episode': 2 (only required if table has sort key)
    NEW_ATTRIBUTE_1: "NEW_ATTRIBUTE_1_VALUE", //For example 'Title': 'The Beginning'
  },
};

const run = async () => {
  try {
    const data = await ddbDocClient.send(new PutCommand(params));
    console.log("Success - item added or updated", data);
    return data;
  } catch (err) {
    console.log("Error", err);
  }
};
run();
// snippet-end:[dynamodb.JavaScript.docClient.putV3]
// For unit tests only.
// module.exports = { run, params };
<commit_msg>Fix incorrect description<commit_after>/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0

ABOUT THIS NODE.JS EXAMPLE: This example works with AWS SDK for JavaScript version 3 (v3),
which is available at https://github.com/aws/aws-sdk-js-v3. This example is in the 'AWS SDK for JavaScript v3 Developer Guide' at
https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/dynamodb-example-dynamodb-utilities.html.

Purpose:
ddbdoc_put_item.js demonstrates how to use the Amazon DynamoDB document client to create or replace an item in an Amazon DynamoDB table.

Inputs (replace in code):
- TABLE_NAME
- primaryKey - The name of the primary key. For example, "id".
- VALUE_1: Value for the primary key (The format for the datatype must match the schema. For example, if the primaryKey is a number, VALUE_1 has no inverted commas.)
- sortKey - The name of the sort key. Only required if table has sort key. For example, "firstName".
- VALUE_2: Value for the sort key (The format for the datatype must match the schema.)
- NEW_ATTRIBUTE_1
- NEW_ATTRIBUTE_1_VALUE

Running the code:
ts-node ddbdoc_put_item.js
*/
// snippet-start:[dynamodb.JavaScript.docClient.putV3]

import { PutCommand } from "@aws-sdk/lib-dynamodb";
import { ddbDocClient } from "./libs/ddbDocClient.js";

// Set the parameters.
const params = {
  TableName: "TABLE_NAME",
  /*
    Convert the key JavaScript object you are adding to the
    required Amazon DynamoDB record. The format of values specifies
    the datatype. The following list demonstrates different
    datatype formatting requirements:
    String: "String",
    NumAttribute: 1,
    BoolAttribute: true,
    ListAttribute: [1, "two", false],
    MapAttribute: { foo: "bar" },
    NullAttribute: null
     */
  Item: {
    primaryKey: "VALUE_1", // For example, 'Season': 2
    sortKey: "VALUE_2", // For example,  'Episode': 2 (only required if table has sort key)
    NEW_ATTRIBUTE_1: "NEW_ATTRIBUTE_1_VALUE", //For example 'Title': 'The Beginning'
  },
};

const run = async () => {
  try {
    const data = await ddbDocClient.send(new PutCommand(params));
    console.log("Success - item added or updated", data);
    return data;
  } catch (err) {
    console.log("Error", err);
  }
};
run();
// snippet-end:[dynamodb.JavaScript.docClient.putV3]
// For unit tests only.
// module.exports = { run, params };
<|endoftext|>