<commit_before>'use strict'
var init = require('./init')
var sauce = require('./sauce')

module.exports = {
  beforeEach: function (browser, done) {
    try {
      init(browser, function () {
        done()
      })
    } catch (e) {
      var mes = 'error ' + e.message
      console.log(mes)
      done(mes)
    }
  },

  'vmdebugger': function (browser) {
    loadTraceNotFound(browser)
    .click('#unload')
    loadTrace(browser)
    .click('#unload')
    panels(browser)
    .click('#unload')
    slider(browser)
    .click('#unload')
    stepping(browser)
    .click('#unload')
    stepdetail(browser)
    .end()
  },

  tearDown: sauce
}

function loadTraceNotFound (browser) {
  browser
    .clearValue('#txinput')
    .setValue('#txinput', '0x20ef65b8b186ca942zcccd634f37074dde49b541c27994fc7596740ef44cfd51')
    .click('#load')
    .click('#txinfo .title')
    .click('#txinfo .dropdownpanel .btn')
    .expect.element('#txinfo .dropdownpanel .dropdownrawcontent').text.to.contain('<not found>')
  return browser
}

function loadTrace (browser) {
  browser
    .clearValue('#txinput')
    .setValue('#txinput', '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51')
    .click('#load')
    .click('#txinfo .title')
    .click('#txinfo .dropdownpanel .btn')
    .expect.element('#txinfo .dropdownpanel .dropdownrawcontent').text.to.contain('0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51')
  browser.click('#unload')
    .waitForElementNotVisible('#vmdebugger', 1000)
  return browser
}

function panels (browser) {
  browser
    .clearValue('#txinput')
    .setValue('#txinput', '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51')
    .click('#load')
    .multipleClick('#intoforward', 63)
    .assertStack(['0:0x', '1:0x60', '2:0x65', '3:0x38', '4:0x55', '5:0x60fe47b1'])
    .assertStorageChanges([
      '0x0000000000000000000000000000000000000000000000000000000000000000:Objectkey:0x0000000000000000000000000000000000000000000000000000000000000000value:0x0000000000000000000000000000000000000000000000000000000000000000',
      '0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563:ObjecthashedKey:0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563key:0x00value:0x38'])
    .assertCallData(['0:0x60fe47b10000000000000000000000000000000000000000000000000000000000000038'])
    .assertCallStack(['0:0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5'])
    .assertStackValue(1, '1:0x60')
    .assertMemoryValue(6, '0x60:60606040526040516020806045833981????R??Q????E?9?')
    .assertMemoryValue(7, '0x70:01604052808051906020019091905050???R??Q???????PP')
    .assertMemoryValue(8, '0x80:5b806001016000600050819055505b50?????????P??UP?P')
    .click('#intoforward') // CREATE
    .assertStack([''])
    .assertStorageChanges(['0x0000000000000000000000000000000000000000000000000000000000000000:Objectkey:0x0000000000000000000000000000000000000000000000000000000000000000value:0x0000000000000000000000000000000000000000000000000000000000000000'])
    .assertMemory([''])
    .assertCallData(['0:0x0000000000000000000000000000000000000000000000000000000000000000000000000000006060606040526040516020806045833981016040528080519060200190919050505b806001016000600050819055'])
    .assertCallStack(['0:0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5', '1:(ContractCreation-Step63)'])
  return browser
}

function slider (browser) {
  browser
    .clearValue('#txinput')
    .setValue('#txinput', '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51')
    .click('#load')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    /*
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.LEFT_ARROW)
    */
    .assertCurrentSelectedItem('041 PUSH4 60fe47b1')
  return browser
}

function stepping (browser) {
  browser
    .clearValue('#txinput')
    .setValue('#txinput', '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51')
    .click('#load')
    .click('#intoforward')
    .click('#intoforward')
    .assertCurrentSelectedItem('004 MSTORE')
    .click('#intoforward')
    .click('#intoback')
    .click('#intoback')
    .assertCurrentSelectedItem('002 PUSH1 40')
    .multipleClick('#intoforward', 62)
    .assertCurrentSelectedItem('181 CREATE')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#overforward')
    .assertCurrentSelectedItem('007 MLOAD')
    .click('#intoback')
    .click('#intoback')
    .click('#intoback')
    .click('#intoback')
    .click('#intoback')
    .click('#overforward')
    .assertCurrentSelectedItem('182 PUSH1 01')
    .click('#overforward')
    .assertCurrentSelectedItem('184 PUSH1 00')
    .click('#intoback')
    .click('#intoback')
    .click('#overback')
    .assertCurrentSelectedItem('181 CREATE')
  return browser
}

function stepdetail (browser) {
  browser
    .clearValue('#txinput')
    .setValue('#txinput', '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51')
    .click('#load')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    /*
    .fireEvent('#slider', browser.debugerKeyCode.Right, 4, function () {
      browser.assertSticker('6', '6', '', '3', '84476', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5')
        .click('#nextcall')
        .assertSticker('63', '63', '', '32000', '79283', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5')
        .click('#intoforward')
        .click('#overforward')
        .assertSticker('108', '44', '', '0', '27145', '(Contract Creation - Step 63)')
        .click('#intoforward')
        .assertSticker('109', '64', '', '3', '25145', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5')
        .end()
    })
    */
    .assertStepDetail('6', '6', '', '3', '84476', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5')
    .multipleClick('#intoforward', 57)
    .assertStepDetail('63', '63', '', '32000', '79283', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5')
    .click('#overforward')
    .click('#intoback')
    .assertStepDetail('108', '44', '', '0', '27145', '(ContractCreation-Step63)')
    .click('#intoforward')
    .assertStepDetail('109', '64', '', '3', '25145', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5')
  return browser
}
<commit_msg>fix test<commit_after>'use strict'
var init = require('./init')
var sauce = require('./sauce')

module.exports = {
  beforeEach: function (browser, done) {
    try {
      init(browser, function () {
        done()
      })
    } catch (e) {
      var mes = 'error ' + e.message
      console.log(mes)
      done(mes)
    }
  },

  'vmdebugger': function (browser) {
    loadTraceNotFound(browser)
    .click('#unload')
    loadTrace(browser)
    .click('#unload')
    panels(browser)
    .click('#unload')
    slider(browser)
    .click('#unload')
    stepping(browser)
    .click('#unload')
    stepdetail(browser)
    .end()
  },

  tearDown: sauce
}

function loadTraceNotFound (browser) {
  browser
    .clearValue('#txinput')
    .setValue('#txinput', '0x20ef65b8b186ca942zcccd634f37074dde49b541c27994fc7596740ef44cfd51')
    .click('#load')
    .click('#txinfo .title')
    .click('#txinfo .dropdownpanel .btn')
    .expect.element('#txinfo .dropdownpanel .dropdownrawcontent').text.to.contain('<not found>')
  return browser
}

function loadTrace (browser) {
  browser
    .clearValue('#txinput')
    .setValue('#txinput', '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51')
    .click('#load')
    .click('#txinfo .title')
    .click('#txinfo .dropdownpanel .btn')
    .expect.element('#txinfo .dropdownpanel .dropdownrawcontent').text.to.contain('0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51')
  browser.click('#unload')
    .waitForElementNotVisible('#vmdebugger', 1000)
  return browser
}

function panels (browser) {
  browser
    .clearValue('#txinput')
    .setValue('#txinput', '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51')
    .click('#load')
    .multipleClick('#intoforward', 63)
    .assertStack(['0:0x', '1:0x60', '2:0x65', '3:0x38', '4:0x55', '5:0x60fe47b1'])
    .assertStorageChanges(['0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563:Objectkey:0x00value:0x38'])
    .assertCallData(['0:0x60fe47b10000000000000000000000000000000000000000000000000000000000000038'])
    .assertCallStack(['0:0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5'])
    .assertStackValue(1, '1:0x60')
    .assertMemoryValue(6, '0x60:60606040526040516020806045833981????R??Q????E?9?')
    .assertMemoryValue(7, '0x70:01604052808051906020019091905050???R??Q???????PP')
    .assertMemoryValue(8, '0x80:5b806001016000600050819055505b50?????????P??UP?P')
    .click('#intoforward') // CREATE
    .assertStack([''])
    .assertStorageChanges([])
    .assertMemory([''])
    .assertCallData(['0:0x0000000000000000000000000000000000000000000000000000000000000000000000000000006060606040526040516020806045833981016040528080519060200190919050505b806001016000600050819055'])
    .assertCallStack(['0:0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5', '1:(ContractCreation-Step63)'])
  return browser
}

function slider (browser) {
  browser
    .clearValue('#txinput')
    .setValue('#txinput', '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51')
    .click('#load')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    /*
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.RIGHT_ARROW)
    .sendKeys('#slider', browser.Keys.LEFT_ARROW)
    */
    .assertCurrentSelectedItem('041 PUSH4 60fe47b1')
  return browser
}

function stepping (browser) {
  browser
    .clearValue('#txinput')
    .setValue('#txinput', '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51')
    .click('#load')
    .click('#intoforward')
    .click('#intoforward')
    .assertCurrentSelectedItem('004 MSTORE')
    .click('#intoforward')
    .click('#intoback')
    .click('#intoback')
    .assertCurrentSelectedItem('002 PUSH1 40')
    .multipleClick('#intoforward', 62)
    .assertCurrentSelectedItem('181 CREATE')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#overforward')
    .assertCurrentSelectedItem('007 MLOAD')
    .click('#intoback')
    .click('#intoback')
    .click('#intoback')
    .click('#intoback')
    .click('#intoback')
    .click('#overforward')
    .assertCurrentSelectedItem('182 PUSH1 01')
    .click('#overforward')
    .assertCurrentSelectedItem('184 PUSH1 00')
    .click('#intoback')
    .click('#intoback')
    .click('#overback')
    .assertCurrentSelectedItem('181 CREATE')
  return browser
}

function stepdetail (browser) {
  browser
    .clearValue('#txinput')
    .setValue('#txinput', '0x20ef65b8b186ca942fcccd634f37074dde49b541c27994fc7596740ef44cfd51')
    .click('#load')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    .click('#intoforward')
    /*
    .fireEvent('#slider', browser.debugerKeyCode.Right, 4, function () {
      browser.assertSticker('6', '6', '', '3', '84476', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5')
        .click('#nextcall')
        .assertSticker('63', '63', '', '32000', '79283', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5')
        .click('#intoforward')
        .click('#overforward')
        .assertSticker('108', '44', '', '0', '27145', '(Contract Creation - Step 63)')
        .click('#intoforward')
        .assertSticker('109', '64', '', '3', '25145', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5')
        .end()
    })
    */
    .assertStepDetail('6', '6', '', '3', '84476', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5')
    .multipleClick('#intoforward', 57)
    .assertStepDetail('63', '63', '', '32000', '79283', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5')
    .click('#overforward')
    .click('#intoback')
    .assertStepDetail('108', '44', '', '0', '27145', '(ContractCreation-Step63)')
    .click('#intoforward')
    .assertStepDetail('109', '64', '', '3', '25145', '0x0d3a18d64dfe4f927832ab58d6451cecc4e517c5')
  return browser
}
<|endoftext|>


<commit_before>"use strict";
var Configuration = require("../lib/Configuration");
var Environment   = require("apparition").Environment;
var expect        = require("chai").expect;

describe("A configuration helper", function () {
	var configuration;

	before(function () {
		configuration = new Configuration();
	});

	describe("looking up the server hostname", function () {
		describe("with the HOST environment variable", function () {
			var hostname = "example.com";

			var environment;

			before(function () {
				environment = new Environment();
				environment.set("host", hostname);
			});

			it("returns the HOST value", function () {
				expect(configuration.server.hostname(), "hostname")
				.to.equal(hostname);
			});
		});

		describe("without the HOST environment variable", function () {
			var environment;

			before(function () {
				environment = new Environment();
				environment.delete("host");
			});

			after(function () {
				environment.restore();
			});

			it("returns null", function () {
				expect(configuration.server.hostname(), "hostname").to.be.null;
			});
		});
	});

	describe("looking up the server port", function () {
		describe("with the PORT environment variable", function () {
			var port = 8080;

			var environment;

			before(function () {
				environment = new Environment();
				environment.set("port", port);
			});

			after(function () {
				environment.restore();
			});

			it("returns the PORT value", function () {
				var value = configuration.server.port();

				expect(value, "type").to.be.a("number");
				expect(value, "value").to.equal(8080);
			});
		});

		describe("without the PORT environment variable", function () {
			var environment;

			before(function () {
				environment = new Environment();
				environment.delete("port");
			});

			after(function () {
				environment.restore();
			});

			it("returns 0", function () {
				var value = configuration.server.port();

				expect(value, "type").to.be.a("number");
				expect(value, "value").to.equal(0);
			});
		});
	});

	describe("looking up the InfluxDB URL", function () {
		describe("with the INFLUXDB_URL environment variable", function () {
			var url = "http://example.com:8086/db/test/series?u=foo&p=bar";

			var environment;

			before(function () {
				environment = new Environment();
				environment.set("influxdb_url", url);
			});

			after(function () {
				environment.restore();
			});

			it("returns the INFLUXDB_URL value", function () {
				expect(configuration.database.url(), "database").to.equal(url);
			});
		});

		describe("without the INFLUXDB_URL environment variable", function () {
			var environment;

			before(function () {
				environment = new Environment();
				environment.delete("influxdb_url");
			});

			after(function () {
				environment.restore();
			});

			it("returns a local database URL", function () {
				expect(configuration.database.url(), "database")
				.to.equal(
					"http://localhost:8086/db/lurker/series?u=lurker&p=test"
				);
			});
		});
	});

	describe("looking up the GitHub shared secret", function () {
		describe("with the GITHUB_SECRET environment variable", function () {
			var secret = "asuperdupersecret";

			var environment;

			before(function () {
				environment = new Environment();
				environment.set("github_secret", secret);
			});

			after(function () {
				environment.restore();
			});

			it("returns the GITHUB_SECRET value", function () {
				expect(configuration.github.secret(), "secret")
				.to.equal(secret);
			});
		});

		describe("without the GITHUB_SECRET environment variable", function () {
			var environment;

			before(function () {
				environment = new Environment();
				environment.delete("github_secret");
			});

			after(function () {
				environment.restore();
			});

			it("returns null", function () {
				expect(configuration.github.secret(), "secret").to.be.null;
			});
		});
	});

	describe("looking up the GitHub organization", function () {
		describe(
			"with the GITHUB_ORGANIZATION environment variable",
			function () {
				var organization = "octocats";

				var environment;

				before(function () {
					environment = new Environment();
					environment.set("github_organization", organization);
				});

				after(function () {
					environment.restore();
				});

				it("returns the GITHUB_ORGANIZATION value", function () {
					expect(configuration.github.organization(), "organization")
					.to.equal(organization);
				});
			}
		);

		describe(
			"without the GITHUB_ORGANIZATION environment variable",
			function () {
				var environment;

				before(function () {
					environment = new Environment();
					environment.delete("github_organization");
				});

				after(function () {
					environment.restore();
				});

				it("returns null", function () {
					expect(configuration.github.organization(), "organization")
					.to.be.null;
				});
			}
		);
	});
});
<commit_msg>Reduce duplication in configuration tests.<commit_after>"use strict";
var Configuration = require("../lib/Configuration");
var Environment   = require("apparition").Environment;
var expect        = require("chai").expect;

describe("A configuration helper", function () {
	var configuration;

	function describeOption (options) {
		var key = options.key.toUpperCase();

		describe("looking up the " + options.description, function () {
			describe("with the " + key + " environment variable", function () {
				var environment;

				before(function () {
					environment = new Environment();
					environment.set(key, options.testValue);
				});

				after(function () {
					environment.restore();
				});

				it("returns the " + key + " value", function () {
					expect(options.getter(), "value")
					.to.equal(options.testValue);
				});
			});

			describe(
				"without the " + key + " environment variable",
				function () {
					var environment;

					before(function () {
						environment = new Environment();
						environment.delete(key);
					});

					after(function () {
						environment.restore();
					});

					it("returns " + options.defaultValue, function () {
						expect(options.getter(), "default")
						.to.equal(options.defaultValue);
					});
				}
			);
		});
	}

	before(function () {
		configuration = new Configuration();
	});

	describeOption({
		defaultValue : null,
		description  : "server hostname",
		key          : "host",
		testValue    : "example.com",

		getter : function () {
			return configuration.server.hostname();
		},
	});

	describeOption({
		defaultValue : 0,
		description  : "server port",
		key          : "port",
		testValue    : 8080,

		getter : function () {
			return configuration.server.port();
		}
	});

	describeOption({
		defaultValue : "http://localhost:8086/db/lurker/series?u=lurker&p=test",
		description  : "InfluxDB URL",
		key          : "influxdb_url",
		testValue    : "http://example.com:8086/db/test/series?u=foo&p=bar",

		getter : function () {
			return configuration.database.url();
		}
	});

	describeOption({
		defaultValue : null,
		description  : "GitHub organization",
		key          : "github_organization",
		testValue    : "octocats",

		getter : function () {
			return configuration.github.organization();
		}
	});

	describeOption({
		defaultValue : null,
		description  : "GitHub shared secret",
		key          : "github_secret",
		testValue    : "asuperdupersecret",

		getter : function () {
			return configuration.github.secret();
		}
	});
});
<|endoftext|>


<commit_before>/**
 * Takes a command line and converts it to something that can
 * be evaluated on the host side.
 *
 * Host commands are defined by creating a method called
 * hostcommand_<command name here>. The command method has the following
 * signature
 *
 * void hostcommand(object token, object[] tokenlist)
 *
 * The first argument contains a token object with keys for
 * "type" and "value". The type is (FIXME: int/enum or string tbd)
 *
 * Value contains the string representation of the token. The token
 * objects are passed by reference, so any changes made to them are
 * propagated back when the string representation of the command line
 * is generated.
 *
 * The "tokenlist" argument contains the entire list of tokens generated
 * from parsing the command line. This array is also passed by reference,
 * so any changes will be seen by all host command methods.
 *
 * Host command methods are expected to directly manipulate the token,
 * and/or the token list. A command handler may ask for the entire
 * token list to be re-processed, by returning true. This may be
 * useful if a handler inserts something that is itself a host command.
 *
 */
window.cls = window.cls || {};
cls.HostCommandTransformer = function() {
  this.parser = null;
  this.client_command_map = {};
  this.df_command_map = {};
  this.transform_map = {};

  //local copy of token types, local vars have better performance. :
  const
  WHITESPACE = window.cls.SimpleJSParser.WHITESPACE,
  LINETERMINATOR = window.cls.SimpleJSParser.LINETERMINATOR,
  IDENTIFIER = window.cls.SimpleJSParser.IDENTIFIER,
  NUMBER = window.cls.SimpleJSParser.NUMBER,
  STRING = window.cls.SimpleJSParser.STRING,
  PUNCTUATOR = window.cls.SimpleJSParser.PUNCTUATOR,
  DIV_PUNCTUATOR = window.cls.SimpleJSParser.DIV_PUNCTUATOR,
  REG_EXP = window.cls.SimpleJSParser.REG_EXP,
  COMMENT = window.cls.SimpleJSParser.COMMENT;

  this.init = function() {
    // window.simple_js_parser is default location for the parser instance
    // in dragonfly. Use it if it exists.
    this.parser = window.simple_js_parser || new window.cls.SimpleJSParser();

    for (var methodname in this) {
      var type = methodname.split("_", 1)[0];
      if (type == "hostcommand")
      {
        var name = methodname.split("hostcommand_")[1];
        this.transform_map[name] = this[methodname];
      }
      else if (type == "clientcommand")
      {
        var name = methodname.split("clientcommand_")[1];
        this.client_command_map[name] = this[methodname];
      }
      else if (type == "dfcommand")
      {
        var name = methodname.split("dfcommand_")[1];
        this.df_command_map[name] = this[methodname];
      }
    }
  };

  this.transform = function(source)
  {
    var types = [];
    var values = [];
    var tokens = [];
    this.parser.parse(source, values, types);

    // make a more straightforward representation of tokens. Command line
    // stuff is small, so the cost of this doesn't matter much.
    tokens = this.zip_tokens(types, values);

    dirty: // we jump back here if we need to re-process all tokens
    for (var n=0, token; token=tokens[n]; n++) {
      if (token.type == IDENTIFIER && this.transform_map.hasOwnProperty(token.value)) {
        var fun = this.transform_map[token.value];
        if (fun.call(this, token, tokens)) {
          break dirty;
        }
      }
    }
    return tokens.map(function(e) {return e.value;}).join("");
  };

  this.get_command = function(source)
  {
    var types = [];
    var values = [];
    var tokens = [];
    this.parser.parse(source, values, types);

    // make a more straightforward representation of tokens. Command line
    // stuff is small, so the cost of this doesn't matter much.
    tokens = this.zip_tokens(types, values);

    if (!tokens.length)
    {
      return null;
    }
    else if (this.is_call(tokens, 0) && tokens[0].value in this.client_command_map)
    {
      return this.client_command_map[tokens[0].value];
    }

    if (tokens[0].type == COMMENT)
    {
      // regex matches "// command()" . Whitespace is allowed inbetween most tokens
      var match = tokens[0].value.match(/\s*\/\/\s*(\w+)\s*\(\s*\)\s*/);
      if (match)
      {
        var command = match[1];
        if (command in this.df_command_map)
        {
          return this.df_command_map[command];
        }
      }
    }
    return null;
  };

  this.zip_tokens = function(types, values) {
    var tokens = [];
    for (var n=0; n<types.length; n++) {
      tokens.push({type: types[n], value: values[n]});
    }
    return tokens;
  };

  /**
   * Check if the token at index looks like it's a function/method being
   * called by looking at the following tokens.
   */
  this.is_call = function(tokens, index) {
    if (!tokens[index] || tokens[index].type != IDENTIFIER) {
      return false;
    }

    for (var n=index+1, token; token=tokens[n]; n++) {
      switch (token.type) {
        case WHITESPACE:
          continue;
        case PUNCTUATOR:
        if (token.value == "(") { return true; }
        default:
          return false;
      }
    }
    return false;
  };

  /**
   * Check if the token at index is a property of name
   */
  this.is_property_of = function(name, tokens, index) {
    if (!tokens[index] || tokens[index].type != IDENTIFIER) {
      return false;
    }

    var n = index-1;

    for (var token; token=tokens[n]; n--) {
      if (token.type == WHITESPACE)
      {
        continue;
      }
      else if (token.type == PUNCTUATOR && token.value == ".")
      {
        break;
      }
      else
      {
        return false;
      }
    }

    n--; // if the break triggered n didn't decr

    for (var token; token=tokens[n]; n--) {
      switch (token.type) {
        case WHITESPACE:
          break;
        case IDENTIFIER:
          if (token.value == name) { return true; }
        default:
          return false;
      }
    }

    return false;
  };

  // Host commands:

  this.hostcommand_dir = function(token, tokenlist) {
    var index = tokenlist.indexOf(token);
    if (!this.is_call(tokenlist, index) ||
         this.is_property_of("console", tokenlist, index)) {
      return;
    }

    token.value = "(window.dir || function(e) { return console.dir(e)})";
  };

  this.hostcommand_dirxml = function(token, tokenlist) {
    var index = tokenlist.indexOf(token);

    if (!this.is_call(tokenlist, index) ||
         this.is_property_of("console", tokenlist, index)) {
      return;
    }

    token.value = "(window.dirxml || function(e) { return console.dirxml(e)})";
  };

  this.hostcommand_$ = function(token, tokenlist) {
    var index = tokenlist.indexOf(token);

    if (this.is_call(tokenlist, index)) {
      token.value = "(window.$ || function(e) { return document.getElementById(e)})";
    }
  };

  this.hostcommand_$$ = function(token, tokenlist) {
    var index = tokenlist.indexOf(token);

    if (this.is_call(tokenlist, index)) {
      token.value = "(window.$$ || function(e) { return document.querySelectorAll(e)})";
    }
  };

  this.hostcommand_$x = function(token, tokenlist) {
    var funstr = "(window.$x || function(e)\
                  {\
                    var res = document.evaluate(e, document, null, XPathResult.ANY_TYPE, null);\
                    var ret = [];\
                    var ele = res.iterateNext();\
                    while (ele) { ret.push(ele); ele=res.iterateNext() };\
                    return ret;\
                  })";
    token.value = funstr;
  };

  this.hostcommand_keys = function(token, tokenlist) {
    var funstr = "(window.keys || function(o) {var arr=[], key; for (key in o) {arr.push(key)}; return arr})";
    token.value = funstr;
  };

  this.hostcommand_values = function(token, tokenlist) {
    var funstr = "(window.values || function(o) {var arr=[], key; for (key in o) {arr.push(o[key])}; return arr})";
    token.value = funstr;
  };

  this.clientcommand_clear = function(view, data, input)
  {
    view._handle_action_clear();
  };

  // TODO: these special client commands should be defined outside of this class here.
  this.dfcommand_help = function(view, data, service)
  {
    data.add_message("Available commands:");
    var names = [];
    for (var key in this.df_command_map) { names.push(key) }
    names.sort();
    for (var n=0, name; name=names[n]; n++)
    {
      var cmd = this.df_command_map[name];
      data.add_message(name + (cmd.description ? ": " + cmd.description : ""));
    }
    data.add_message("\n");
    data.add_message(ui_strings.S_SETTINGS_HEADER_KEYBOARD_SHORTCUTS + ":");
    data.add_message("\n");
    const CMD_LINE_VIEW_ID = 'command_line';
    var broker = ActionBroker.get_instance();
    var shortcuts = broker.get_shortcuts();
    shortcuts = shortcuts && shortcuts[CMD_LINE_VIEW_ID];
    var label_map = {};
    var all_keys = [];
    for (var mode in shortcuts)
    {
      mode_label = broker.get_label_with_handler_id_and_mode(CMD_LINE_VIEW_ID, mode);
      if (mode_label)
      {
        var mode_shortcuts = shortcuts[mode];
        var keys = [];
        for (var mode_shortcut in mode_shortcuts)
        {
          keys.push(mode_shortcut);
        }
        keys.sort();
        all_keys.extend(keys)
        label_map[mode] = {label: mode_label, keys: keys};
      }
    }
    var width = Math.max.apply(Math, all_keys.map(function(k)
    {
      return k.length;
    }));
    for (mode in label_map)
    {
      data.add_message(label_map[mode].label);
      label_map[mode].keys.forEach(function(key)
      {
        data.add_message("    " + key.ljust(width + 4) + shortcuts[mode][key]);
      });
      data.add_message("\n");
    }
  };

  this.dfcommand_help.description = ui_strings.S_REPL_HELP_COMMAND_DESC;

  this.dfcommand_man = this.dfcommand_help; // man is alias for help

  this.dfcommand_jquery = function(view, data, service)
  {
    var url = "http://code.jquery.com/jquery.min.js";
    var code = ["(function(){",
                "  var script = document.createElement('script');",
                "  script.setAttribute('src', '" + url + "');",
                "  var cb = function() {",
                "    script.parentNode.removeChild(script);",
                "    console.log('jquery loaded');",
                "  };",
                "  script.addEventListener('load', cb, false);",
                "  document.body.appendChild(script);",
                "  return 'Loading jquery'",
                "})();"].join("\n");
    service.evaluate_input(code);
  }
  this.dfcommand_jquery.description = ui_strings.S_REPL_JQUERY_COMMAND_DESC;

  this.init();
};
<commit_msg>Fixed minor issue where in-built Console commands where taken as a function call even if it was missing an ending ')'.<commit_after>/**
 * Takes a command line and converts it to something that can
 * be evaluated on the host side.
 *
 * Host commands are defined by creating a method called
 * hostcommand_<command name here>. The command method has the following
 * signature
 *
 * void hostcommand(object token, object[] tokenlist)
 *
 * The first argument contains a token object with keys for
 * "type" and "value". The type is (FIXME: int/enum or string tbd)
 *
 * Value contains the string representation of the token. The token
 * objects are passed by reference, so any changes made to them are
 * propagated back when the string representation of the command line
 * is generated.
 *
 * The "tokenlist" argument contains the entire list of tokens generated
 * from parsing the command line. This array is also passed by reference,
 * so any changes will be seen by all host command methods.
 *
 * Host command methods are expected to directly manipulate the token,
 * and/or the token list. A command handler may ask for the entire
 * token list to be re-processed, by returning true. This may be
 * useful if a handler inserts something that is itself a host command.
 *
 */
window.cls = window.cls || {};
cls.HostCommandTransformer = function() {
  this.parser = null;
  this.client_command_map = {};
  this.df_command_map = {};
  this.transform_map = {};

  //local copy of token types, local vars have better performance. :
  const
  WHITESPACE = window.cls.SimpleJSParser.WHITESPACE,
  LINETERMINATOR = window.cls.SimpleJSParser.LINETERMINATOR,
  IDENTIFIER = window.cls.SimpleJSParser.IDENTIFIER,
  NUMBER = window.cls.SimpleJSParser.NUMBER,
  STRING = window.cls.SimpleJSParser.STRING,
  PUNCTUATOR = window.cls.SimpleJSParser.PUNCTUATOR,
  DIV_PUNCTUATOR = window.cls.SimpleJSParser.DIV_PUNCTUATOR,
  REG_EXP = window.cls.SimpleJSParser.REG_EXP,
  COMMENT = window.cls.SimpleJSParser.COMMENT;

  this.init = function() {
    // window.simple_js_parser is default location for the parser instance
    // in dragonfly. Use it if it exists.
    this.parser = window.simple_js_parser || new window.cls.SimpleJSParser();

    for (var methodname in this) {
      var type = methodname.split("_", 1)[0];
      if (type == "hostcommand")
      {
        var name = methodname.split("hostcommand_")[1];
        this.transform_map[name] = this[methodname];
      }
      else if (type == "clientcommand")
      {
        var name = methodname.split("clientcommand_")[1];
        this.client_command_map[name] = this[methodname];
      }
      else if (type == "dfcommand")
      {
        var name = methodname.split("dfcommand_")[1];
        this.df_command_map[name] = this[methodname];
      }
    }
  };

  this.transform = function(source)
  {
    var types = [];
    var values = [];
    var tokens = [];
    this.parser.parse(source, values, types);

    // make a more straightforward representation of tokens. Command line
    // stuff is small, so the cost of this doesn't matter much.
    tokens = this.zip_tokens(types, values);

    dirty: // we jump back here if we need to re-process all tokens
    for (var n=0, token; token=tokens[n]; n++) {
      if (token.type == IDENTIFIER && this.transform_map.hasOwnProperty(token.value)) {
        var fun = this.transform_map[token.value];
        if (fun.call(this, token, tokens)) {
          break dirty;
        }
      }
    }
    return tokens.map(function(e) {return e.value;}).join("");
  };

  this.get_command = function(source)
  {
    var types = [];
    var values = [];
    var tokens = [];
    this.parser.parse(source, values, types);

    // make a more straightforward representation of tokens. Command line
    // stuff is small, so the cost of this doesn't matter much.
    tokens = this.zip_tokens(types, values);

    if (!tokens.length)
    {
      return null;
    }
    else if (this.is_call(tokens, 0) && tokens[0].value in this.client_command_map)
    {
      return this.client_command_map[tokens[0].value];
    }

    if (tokens[0].type == COMMENT)
    {
      // regex matches "// command()" . Whitespace is allowed inbetween most tokens
      var match = tokens[0].value.match(/\s*\/\/\s*(\w+)\s*\(\s*\)\s*/);
      if (match)
      {
        var command = match[1];
        if (command in this.df_command_map)
        {
          return this.df_command_map[command];
        }
      }
    }
    return null;
  };

  this.zip_tokens = function(types, values) {
    var tokens = [];
    for (var n=0; n<types.length; n++) {
      tokens.push({type: types[n], value: values[n]});
    }
    return tokens;
  };

  /**
   * Check if the token at index looks like it's a function/method being
   * called by looking at the following tokens. This is a naïve check, but
   * should work fine in most cases.
   */
  this.is_call = function(tokens, index) {
    if (!tokens[index] || tokens[index].type != IDENTIFIER) {
      return false;
    }

    var open_paren_seen = false;
    for (var n=index+1, token; token=tokens[n]; n++) {
      switch (token.type) {
        case WHITESPACE:
          continue;
        case PUNCTUATOR:
          if (token.value == "(")
          {
            open_paren_seen = true;
          }
          else if (token.value == ")" && open_paren_seen)
          {
            // if there's no junk after, assume it's fine
            return !tokens[n+1];
          }
          break;
      }
    }
    return false;
  };

  /**
   * Check if the token at index is a property of name
   */
  this.is_property_of = function(name, tokens, index) {
    if (!tokens[index] || tokens[index].type != IDENTIFIER) {
      return false;
    }

    var n = index-1;

    for (var token; token=tokens[n]; n--) {
      if (token.type == WHITESPACE)
      {
        continue;
      }
      else if (token.type == PUNCTUATOR && token.value == ".")
      {
        break;
      }
      else
      {
        return false;
      }
    }

    n--; // if the break triggered n didn't decr

    for (var token; token=tokens[n]; n--) {
      switch (token.type) {
        case WHITESPACE:
          break;
        case IDENTIFIER:
          if (token.value == name) { return true; }
        default:
          return false;
      }
    }

    return false;
  };

  // Host commands:

  this.hostcommand_dir = function(token, tokenlist) {
    var index = tokenlist.indexOf(token);
    if (!this.is_call(tokenlist, index) ||
         this.is_property_of("console", tokenlist, index)) {
      return;
    }

    token.value = "(window.dir || function(e) { return console.dir(e)})";
  };

  this.hostcommand_dirxml = function(token, tokenlist) {
    var index = tokenlist.indexOf(token);

    if (!this.is_call(tokenlist, index) ||
         this.is_property_of("console", tokenlist, index)) {
      return;
    }

    token.value = "(window.dirxml || function(e) { return console.dirxml(e)})";
  };

  this.hostcommand_$ = function(token, tokenlist) {
    var index = tokenlist.indexOf(token);

    if (this.is_call(tokenlist, index)) {
      token.value = "(window.$ || function(e) { return document.getElementById(e)})";
    }
  };

  this.hostcommand_$$ = function(token, tokenlist) {
    var index = tokenlist.indexOf(token);

    if (this.is_call(tokenlist, index)) {
      token.value = "(window.$$ || function(e) { return document.querySelectorAll(e)})";
    }
  };

  this.hostcommand_$x = function(token, tokenlist) {
    var funstr = "(window.$x || function(e)\
                  {\
                    var res = document.evaluate(e, document, null, XPathResult.ANY_TYPE, null);\
                    var ret = [];\
                    var ele = res.iterateNext();\
                    while (ele) { ret.push(ele); ele=res.iterateNext() };\
                    return ret;\
                  })";
    token.value = funstr;
  };

  this.hostcommand_keys = function(token, tokenlist) {
    var funstr = "(window.keys || function(o) {var arr=[], key; for (key in o) {arr.push(key)}; return arr})";
    token.value = funstr;
  };

  this.hostcommand_values = function(token, tokenlist) {
    var funstr = "(window.values || function(o) {var arr=[], key; for (key in o) {arr.push(o[key])}; return arr})";
    token.value = funstr;
  };

  this.clientcommand_clear = function(view, data, input)
  {
    view._handle_action_clear();
  };

  // TODO: these special client commands should be defined outside of this class here.
  this.dfcommand_help = function(view, data, service)
  {
    data.add_message("Available commands:");
    var names = [];
    for (var key in this.df_command_map) { names.push(key) }
    names.sort();
    for (var n=0, name; name=names[n]; n++)
    {
      var cmd = this.df_command_map[name];
      data.add_message(name + (cmd.description ? ": " + cmd.description : ""));
    }
    data.add_message("\n");
    data.add_message(ui_strings.S_SETTINGS_HEADER_KEYBOARD_SHORTCUTS + ":");
    data.add_message("\n");
    const CMD_LINE_VIEW_ID = 'command_line';
    var broker = ActionBroker.get_instance();
    var shortcuts = broker.get_shortcuts();
    shortcuts = shortcuts && shortcuts[CMD_LINE_VIEW_ID];
    var label_map = {};
    var all_keys = [];
    for (var mode in shortcuts)
    {
      mode_label = broker.get_label_with_handler_id_and_mode(CMD_LINE_VIEW_ID, mode);
      if (mode_label)
      {
        var mode_shortcuts = shortcuts[mode];
        var keys = [];
        for (var mode_shortcut in mode_shortcuts)
        {
          keys.push(mode_shortcut);
        }
        keys.sort();
        all_keys.extend(keys)
        label_map[mode] = {label: mode_label, keys: keys};
      }
    }
    var width = Math.max.apply(Math, all_keys.map(function(k)
    {
      return k.length;
    }));
    for (mode in label_map)
    {
      data.add_message(label_map[mode].label);
      label_map[mode].keys.forEach(function(key)
      {
        data.add_message("    " + key.ljust(width + 4) + shortcuts[mode][key]);
      });
      data.add_message("\n");
    }
  };

  this.dfcommand_help.description = ui_strings.S_REPL_HELP_COMMAND_DESC;

  this.dfcommand_man = this.dfcommand_help; // man is alias for help

  this.dfcommand_jquery = function(view, data, service)
  {
    var url = "http://code.jquery.com/jquery.min.js";
    var code = ["(function(){",
                "  var script = document.createElement('script');",
                "  script.setAttribute('src', '" + url + "');",
                "  var cb = function() {",
                "    script.parentNode.removeChild(script);",
                "    console.log('jquery loaded');",
                "  };",
                "  script.addEventListener('load', cb, false);",
                "  document.body.appendChild(script);",
                "  return 'Loading jquery'",
                "})();"].join("\n");
    service.evaluate_input(code);
  }
  this.dfcommand_jquery.description = ui_strings.S_REPL_JQUERY_COMMAND_DESC;

  this.init();
};
<|endoftext|>


<commit_before>'use strict';

var path = require('path');

var cache = Object.create(null);

module.exports = function nodeModulePaths(start) {
    start = path.resolve(start);

    if (start in cache) {
        return cache[start];
    }

    var parts = start.split(path.sep);
    if (parts[0] === '') {
        parts[0] = path.sep;
    }

    var root = Math.max(parts.indexOf('node_modules'), 0);
    var i = parts.length - 1;
    var dirs = [];

    while (i > root) {
        if (parts[i] !== 'node_modules') {
            dirs.push(path.join.apply(path, parts.slice(0, i + 1).concat('node_modules')));
        }
        --i;
    }

    cache[start] = dirs;
    return dirs;
};
<commit_msg>fix nodeModulePaths<commit_after>'use strict';

var path = require('path');

var cache = Object.create(null);

module.exports = function nodeModulePaths(start) {
    start = path.resolve(start);

    if (start in cache) {
        return cache[start];
    }

    var parts = start.split(path.sep);
    if (parts[0] === '') {
        parts[0] = path.sep;
    }

    var i = parts.length - 1;
    var dirs = [];

    while (i >= 0) {
        if (parts[i] !== 'node_modules') {
            dirs.push(path.join.apply(path, parts.slice(0, i + 1).concat('node_modules')));
        }
        --i;
    }

    cache[start] = dirs;
    return dirs;
};
<|endoftext|>


<commit_before>'use strict';

var assert = require('assert');
var testHelper = require('../helper');

describe('closest', function () {

    var QUERY_SOURCE = 'select * from airbnb_rooms';
    var QUERY_TARGET = 'select * from atm_machines';

    var analysisDefinition = {
        type: 'closest',
        params: {
            source: {
                type: 'source',
                params: {
                    query: QUERY_SOURCE
                }
            },
            target: {
                type: 'source',
                params: {
                    query: QUERY_TARGET
                }
            },
            responses: 2,
            category: 'bank'
        }
    };

    it('basic CLOSEST test', function (done) {
        testHelper.createAnalyses(analysisDefinition, function (err, closest) {

            assert.ifError(err);

            var rootNode = closest.getRoot();

            testHelper.getRows(rootNode.getQuery(), function (err, rows) {
                assert.ifError(err);
                rows.forEach(function (row) {
                    assert.ok(typeof row.cartodb_id === 'number');
                    assert.ok(typeof row.the_geom === 'string');
                });
                return done();
            });
        });
    });

    it('check CLOSEST number of responses', function (done) {
        testHelper.createAnalyses(analysisDefinition, function (err, closest) {

            assert.ifError(err);

            var rootNode = closest.getRoot();

            testHelper.getRows(rootNode.getQuery(), function (err, rows) {
                var checker = {};
                var checked;
                assert.ifError(err);
                rows.forEach(function (row) {
                    checker[row.bank] = (!checker[row.bank])?  1 : checker[row.bank] + 1;
                });
                checked = Object.keys(checker).filter(function(key) {
                    /*
                    in the corner case that the number of responses requested is
                    bigger than the available items within a category, the number of
                    responses will below the requested value
                    */
                    return checker[key] > analysisDefinition.params.responses;
                });
                assert.ok(checked.length == 0);
                return done();
            });
        });
    });

});
<commit_msg>Add tests for closest analysis<commit_after>'use strict';

var assert = require('assert');
var testHelper = require('../helper');

describe('closest analysis', function () {

    var QUERY_SOURCE = [
        'WITH sources AS (',
        '   select i as cartodb_id, st_setsrid(st_makepoint(i,0), 4326) as the_geom',
        '   from generate_series(1,3) as i',
        ')',
        'select *, st_x(the_geom) as x, st_y(the_geom) as y from sources'
    ].join('\n');
    /**
     * cartodb_id,x,y
     * 1,1,0
     * 2,2,0
     * 3,3,0
     */

    var QUERY_TARGET = [
        'WITH s as (',
        QUERY_SOURCE,
        '),',
        'targets AS (',
        'select',
        '   row_number() over() as cartodb_id,',
        '   chr(64 + (i % 4)) as category,',
        '   st_translate(the_geom, 0, i*.1) as the_geom',
        'from s, generate_series(1,3) as i',
        ')',
        'select *, st_x(the_geom) as x, st_y(the_geom) as y from targets'
    ].join('\n');
    /**
     * cartodb_id,category,x,y
     * 1,A,1,0.1
     * 2,B,1,0.2
     * 3,C,1,0.3
     * 4,A,2,0.1
     * 5,B,2,0.2
     * 6,C,2,0.3
     * 7,A,3,0.1
     * 8,B,3,0.2
     * 9,C,3,0.3
     */

    /**
     *   C                   C                  C  \
     *   B                   B                  B  | <= TARGETS
     *   A                   A                  A  /
     *   *                   *                  *    <= SOURCES
     * (1,0)               (2,0)              (3,0)
     */

    function closestAnalysisDefinition(responses, category) {
        return {
            type: 'closest',
            params: {
                source: {
                    type: 'source',
                    params: {
                        query: QUERY_SOURCE
                    }
                },
                target: {
                    type: 'source',
                    params: {
                        query: QUERY_TARGET
                    }
                },
                responses: responses || 1,
                category: category
            }
        };
    }

    it('basic (1 target per source)', function (done) {
        testHelper.getResult(closestAnalysisDefinition(), function(err, rows) {
            assert.ifError(err);
            assert.equal(rows.length, 3);
            testHelper.checkCartoDBIsSorted(rows);

            assert.equal(rows[0].source_cartodb_id, 1);
            assert.equal(rows[0].x, 1);
            assert.equal(rows[0].y, 0.1);
            assert.equal(rows[0].category, 'A');

            assert.equal(rows[1].source_cartodb_id, 2);
            assert.equal(rows[1].x, 2);
            assert.equal(rows[1].y, 0.1);
            assert.equal(rows[1].category, 'A');

            assert.equal(rows[2].source_cartodb_id, 3);
            assert.equal(rows[2].x, 3);
            assert.equal(rows[2].y, 0.1);
            assert.equal(rows[2].category, 'A');

            return done();
        });
    });

    it('2 targets per source', function (done) {
        testHelper.getResult(closestAnalysisDefinition(2), function(err, rows) {
            assert.ifError(err);
            assert.equal(rows.length, 6);
            testHelper.checkCartoDBIsSorted(rows);

            assert.equal(rows[0].source_cartodb_id, 1);
            assert.equal(rows[0].x, 1);
            assert.equal(rows[0].y, 0.1);
            assert.equal(rows[0].category, 'A');
            assert.equal(rows[1].source_cartodb_id, 1);
            assert.equal(rows[1].x, 1);
            assert.equal(rows[1].y, 0.2);
            assert.equal(rows[1].category, 'B');

            assert.equal(rows[2].source_cartodb_id, 2);
            assert.equal(rows[2].x, 2);
            assert.equal(rows[2].y, 0.1);
            assert.equal(rows[2].category, 'A');
            assert.equal(rows[3].source_cartodb_id, 2);
            assert.equal(rows[3].x, 2);
            assert.equal(rows[3].y, 0.2);
            assert.equal(rows[3].category, 'B');

            assert.equal(rows[4].source_cartodb_id, 3);
            assert.equal(rows[4].x, 3);
            assert.equal(rows[4].y, 0.1);
            assert.equal(rows[4].category, 'A');
            assert.equal(rows[5].source_cartodb_id, 3);
            assert.equal(rows[5].x, 3);
            assert.equal(rows[5].y, 0.2);
            assert.equal(rows[5].category, 'B');

            return done();
        });
    });

    it('4 targets per source, only checks for source=1', function (done) {
        testHelper.getResult(closestAnalysisDefinition(4), function(err, rows) {
            assert.ifError(err);
            assert.equal(rows.length, 12);

            assert.equal(rows[0].source_cartodb_id, 1);
            assert.equal(rows[0].x, 1);
            assert.equal(rows[0].y, 0.1);
            assert.equal(rows[0].category, 'A');
            assert.equal(rows[1].source_cartodb_id, 1);
            assert.equal(rows[1].x, 1);
            assert.equal(rows[1].y, 0.2);
            assert.equal(rows[1].category, 'B');
            assert.equal(rows[2].source_cartodb_id, 1);
            assert.equal(rows[2].x, 1);
            assert.equal(rows[2].y, 0.3);
            assert.equal(rows[2].category, 'C');

            assert.equal(rows[3].source_cartodb_id, 1);
            assert.equal(rows[3].x, 2);
            assert.equal(rows[3].y, 0.1);
            assert.equal(rows[3].category, 'A');

            return done();
        });
    });

    it('does not return more points than existing ones for big responses param', function (done) {
        testHelper.getResult(closestAnalysisDefinition(10), function(err, rows) {
            assert.ifError(err);
            // max 9 targets per source
            assert.equal(rows.length, 27);
            return done();
        });
    });

    describe('category', function() {
        it('basic category (1 target per source and category)', function (done) {
            testHelper.getResult(closestAnalysisDefinition(1, 'category'), function(err, rows) {
                assert.ifError(err);
                assert.equal(rows.length, 9);
                testHelper.checkCartoDBIsSorted(rows);

                assert.equal(rows[0].source_cartodb_id, 1);
                assert.equal(rows[0].x, 1);
                assert.equal(rows[0].y, 0.1);
                assert.equal(rows[0].category, 'A');

                assert.equal(rows[1].source_cartodb_id, 1);
                assert.equal(rows[1].x, 1);
                assert.equal(rows[1].y, 0.2);
                assert.equal(rows[1].category, 'B');

                assert.equal(rows[2].source_cartodb_id, 1);
                assert.equal(rows[2].x, 1);
                assert.equal(rows[2].y, 0.3);
                assert.equal(rows[2].category, 'C');

                return done();
            });
        });

        it('2 results per category per source', function (done) {
            testHelper.getResult(closestAnalysisDefinition(2, 'category'), function(err, rows) {
                assert.ifError(err);
                assert.equal(rows.length, 18);

                assert.equal(rows[0].source_cartodb_id, 1);
                assert.equal(rows[0].x, 1);
                assert.equal(rows[0].y, 0.1);
                assert.equal(rows[0].category, 'A');
                assert.equal(rows[1].source_cartodb_id, 1);
                assert.equal(rows[1].x, 2);
                assert.equal(rows[1].y, 0.1);
                assert.equal(rows[1].category, 'A');

                assert.equal(rows[2].source_cartodb_id, 1);
                assert.equal(rows[2].x, 1);
                assert.equal(rows[2].y, 0.2);
                assert.equal(rows[2].category, 'B');
                assert.equal(rows[3].source_cartodb_id, 1);
                assert.equal(rows[3].x, 2);
                assert.equal(rows[3].y, 0.2);
                assert.equal(rows[3].category, 'B');

                assert.equal(rows[4].source_cartodb_id, 1);
                assert.equal(rows[4].x, 1);
                assert.equal(rows[4].y, 0.3);
                assert.equal(rows[4].category, 'C');
                assert.equal(rows[5].source_cartodb_id, 1);
                assert.equal(rows[5].x, 2);
                assert.equal(rows[5].y, 0.3);
                assert.equal(rows[5].category, 'C');

                assert.equal(rows[6].source_cartodb_id, 2);
                assert.equal(rows[6].x, 2);
                assert.equal(rows[6].y, 0.1);
                assert.equal(rows[6].category, 'A');

                return done();
            });
        });

        it('does not return more results per category than existing ones', function (done) {
            testHelper.getResult(closestAnalysisDefinition(4, 'category'), function(err, rows) {
                assert.ifError(err);
                assert.equal(rows.length, 27);

                assert.equal(rows[0].source_cartodb_id, 1);
                assert.equal(rows[0].x, 1);
                assert.equal(rows[0].y, 0.1);
                assert.equal(rows[0].category, 'A');
                assert.equal(rows[1].source_cartodb_id, 1);
                assert.equal(rows[1].x, 2);
                assert.equal(rows[1].y, 0.1);
                assert.equal(rows[1].category, 'A');
                assert.equal(rows[2].source_cartodb_id, 1);
                assert.equal(rows[2].x, 3);
                assert.equal(rows[2].y, 0.1);
                assert.equal(rows[2].category, 'A');

                assert.equal(rows[3].source_cartodb_id, 1);
                assert.equal(rows[3].x, 1);
                assert.equal(rows[3].y, 0.2);
                assert.equal(rows[3].category, 'B');

                assert.equal(rows[9].source_cartodb_id, 2);
                assert.equal(rows[9].x, 2);
                assert.equal(rows[9].y, 0.1);
                assert.equal(rows[9].category, 'A');

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


<commit_before>"use strict";
const assert = require('assert');
const jsc = require('jsverify');
const lazyseq = require("lazy-seq");

const {commands} = require('../../src/arbitrary/commands');

const GENSIZE = 10;
var fakeJscCommand = function(ClassType) {
    return jsc.bless({
        generator: size => new Object({ command: new ClassType(), parameters: [] }),
        shrink: lazyseq.nil,
        show: t => "fake"
    });
};
var fakeClass = function() {
    return function() {};
};
var FakeSuccessCommand = function() {};
var FakeFailureCommand = function() {};
var FakeDoNotRunCommand = function() {};

describe('commands', function() {
    describe('generator', function() {
        it('should instantiate an array', function() {
            jsc.assert(jsc.forall(jsc.integer(1, 1024), function(num) {
                const classes = [...Array(num).keys()].map(fakeClass);
                const arbs = classes.map(fakeJscCommand);
                const arb = commands.apply(this, arbs);
                var v = arb.generator(GENSIZE);
                return Array.isArray(v);
            }));
        });

        it('should instantiate command elements', function() {
            jsc.assert(jsc.forall(jsc.integer(1, 1024), function(num) {
                const classes = [...Array(num).keys()].map(fakeClass);
                const arbs = classes.map(fakeJscCommand);
                const arb = commands.apply(this, arbs);
                var v = arb.generator(GENSIZE);
                return v.every(cmd => classes.find(c => cmd.command instanceof c) !== undefined);
            }));
        });
    });
    describe('shrink', function() {
        const classes = [FakeSuccessCommand, FakeDoNotRunCommand, FakeFailureCommand];
        const oneOfClasses = jsc.oneof(classes.map(c => jsc.constant({Cls: c, name: c.name})));
        var fakeCommandsAfterRun = function(classesToGenerate) {
            var fakeGenerated = classesToGenerate.map(c => new Object({command: new c.Cls(), parameters: [], name: c.name}));
            for (var idx = 0 ; idx != fakeGenerated.length ; ++idx) {
                var c = fakeGenerated[idx].command;
                c.hasStarted = !(c instanceof FakeDoNotRunCommand);
                if (c instanceof FakeFailureCommand) {
                    break;
                }
            }
            return fakeGenerated;
        };

        it('should replay only played commands', function() {
            jsc.assert(jsc.forall(jsc.array(oneOfClasses), function(classesToGenerate) {
                const arbs = classes.map(fakeJscCommand);
                const arb = commands.apply(this, arbs);
                const fakeGenerated = fakeCommandsAfterRun(classesToGenerate);
                const generatedContainFailures = fakeGenerated.find(c => c.command instanceof FakeFailureCommand) !== undefined;
                const onlyPlayedCommands = function(arr) {
                    if (arr.length === 0) {
                        return true;
                    }
                    if (generatedContainFailures) {
                        const lastItem = arr.slice(-1)[0].command;
                        return (lastItem instanceof FakeSuccessCommand || lastItem instanceof FakeFailureCommand)
                                && arr.slice(0, -1).every(c => c.command instanceof FakeSuccessCommand);
                    }
                    return arr.slice(0, -1).every(c => c.command instanceof FakeSuccessCommand);
                };
                return arb.shrink(fakeGenerated).every(onlyPlayedCommands);
            }));
        });

        it('should replay less commands', function() {
            jsc.assert(jsc.forall(jsc.array(oneOfClasses), function(classesToGenerate) {
                const arbs = classes.map(fakeJscCommand);
                const arb = commands.apply(this, arbs);
                const fakeGenerated = fakeCommandsAfterRun(classesToGenerate);
                const numStarted = fakeGenerated.filter(c => c.hasStarted === true).length;
                return arb.shrink(fakeGenerated).every(a => a.length <= numStarted);
            }));
        });

        /*it('should not reorder commands', function() {
            jsc.assert(jsc.forall(jsc.array(jsc.oneof(classes)), function(classesToGenerate) {
                //TODO
            }));
        });*/

        it('should remove hasStarted flags', function() {
            jsc.assert(jsc.forall(jsc.array(oneOfClasses), function(classesToGenerate) {
                const arbs = classes.map(fakeJscCommand);
                const arb = commands.apply(this, arbs);
                const fakeGenerated = fakeCommandsAfterRun(classesToGenerate);
                return arb.shrink(fakeGenerated).every(a => a.every(c => !c.hasOwnProperty('hasStarted')));
            }));
        });
    });
});<commit_msg>[test] check commands.shrink do not change the ordering<commit_after>"use strict";
const assert = require('assert');
const jsc = require('jsverify');
const lazyseq = require("lazy-seq");

const {commands} = require('../../src/arbitrary/commands');

const GENSIZE = 10;
var fakeJscCommand = function(ClassType) {
    return jsc.bless({
        generator: size => new Object({ command: new ClassType(), parameters: [] }),
        shrink: lazyseq.nil,
        show: t => "fake"
    });
};
var fakeClass = function() {
    return function() {};
};
var FakeSuccessCommand = function(id) { this.id = id; };
var FakeFailureCommand = function(id) { this.id = id; };
var FakeDoNotRunCommand = function(id) { this.id = id; };

describe('commands', function() {
    describe('generator', function() {
        it('should instantiate an array', function() {
            jsc.assert(jsc.forall(jsc.integer(1, 1024), function(num) {
                const classes = [...Array(num).keys()].map(fakeClass);
                const arbs = classes.map(fakeJscCommand);
                const arb = commands.apply(this, arbs);
                var v = arb.generator(GENSIZE);
                return Array.isArray(v);
            }));
        });

        it('should instantiate command elements', function() {
            jsc.assert(jsc.forall(jsc.integer(1, 1024), function(num) {
                const classes = [...Array(num).keys()].map(fakeClass);
                const arbs = classes.map(fakeJscCommand);
                const arb = commands.apply(this, arbs);
                var v = arb.generator(GENSIZE);
                return v.every(cmd => classes.find(c => cmd.command instanceof c) !== undefined);
            }));
        });
    });
    describe('shrink', function() {
        const classes = [FakeSuccessCommand, FakeDoNotRunCommand, FakeFailureCommand];
        const oneOfClasses = jsc.oneof(classes.map(c => jsc.constant({Cls: c, name: c.name})));
        var fakeCommandsAfterRun = function(classesToGenerate) {
            var fakeGenerated = classesToGenerate.map((c, idx) => new Object({command: new c.Cls(idx), parameters: [], name: c.name}));
            for (var idx = 0 ; idx != fakeGenerated.length ; ++idx) {
                var c = fakeGenerated[idx].command;
                c.hasStarted = !(c instanceof FakeDoNotRunCommand);
                if (c instanceof FakeFailureCommand) {
                    break;
                }
            }
            return fakeGenerated;
        };

        it('should replay only played commands', function() {
            jsc.assert(jsc.forall(jsc.array(oneOfClasses), function(classesToGenerate) {
                const arbs = classes.map(fakeJscCommand);
                const arb = commands.apply(this, arbs);
                const fakeGenerated = fakeCommandsAfterRun(classesToGenerate);
                const generatedContainFailures = fakeGenerated.find(c => c.command instanceof FakeFailureCommand) !== undefined;
                const onlyPlayedCommands = function(arr) {
                    if (arr.length === 0) {
                        return true;
                    }
                    if (generatedContainFailures) {
                        const lastItem = arr.slice(-1)[0].command;
                        return (lastItem instanceof FakeSuccessCommand || lastItem instanceof FakeFailureCommand)
                                && arr.slice(0, -1).every(c => c.command instanceof FakeSuccessCommand);
                    }
                    return arr.slice(0, -1).every(c => c.command instanceof FakeSuccessCommand);
                };
                return arb.shrink(fakeGenerated).every(onlyPlayedCommands);
            }));
        });

        it('should replay less commands', function() {
            jsc.assert(jsc.forall(jsc.array(oneOfClasses), function(classesToGenerate) {
                const arbs = classes.map(fakeJscCommand);
                const arb = commands.apply(this, arbs);
                const fakeGenerated = fakeCommandsAfterRun(classesToGenerate);
                const numStarted = fakeGenerated.filter(c => c.hasStarted === true).length;
                return arb.shrink(fakeGenerated).every(a => a.length <= numStarted);
            }));
        });

        it('should not reorder commands', function() {
            jsc.assert(jsc.forall(jsc.array(oneOfClasses), function(classesToGenerate) {
                const arbs = classes.map(fakeJscCommand);
                const arb = commands.apply(this, arbs);
                const fakeGenerated = fakeCommandsAfterRun(classesToGenerate);
                return arb.shrink(fakeGenerated).every(a => {
                    for (var idx = 1 ; idx < a.length ; ++idx) {
                        if (a[idx-1].command.id >= a[idx].command.id) {
                            return false;
                        }
                    }
                    return true;
                });
            }));
        });

        it('should remove hasStarted flags', function() {
            jsc.assert(jsc.forall(jsc.array(oneOfClasses), function(classesToGenerate) {
                const arbs = classes.map(fakeJscCommand);
                const arb = commands.apply(this, arbs);
                const fakeGenerated = fakeCommandsAfterRun(classesToGenerate);
                return arb.shrink(fakeGenerated).every(a => a.every(c => !c.hasOwnProperty('hasStarted')));
            }));
        });
    });
});<|endoftext|>


<commit_before>import _ from 'lodash';
import { delay } from 'redux-saga';
import { take, race, call, put, takeLatest, all } from 'redux-saga/effects';
import { AUTH_SUCCESS } from '../ducks/authenticate';
import { calendarUpdated } from '../ducks/calendar';
import { ROOM_BOOKED } from '../actions';
import calendars from '../calendars.json';

const gapi = window.gapi;

function fetchEventsForCal(calendar) {
  return gapi.client.calendar.events.list({
    calendarId: calendar,
    timeMin: (new Date()).toISOString(),
    showDeleted: false,
    singleEvents: true,
    maxResults: 2,
    orderBy: 'startTime',
  });
}

function* eventsTick(events) {
  // 10 min max between updates
  const MAX_TICK = 600000;
  let nextTick = MAX_TICK;
  if (events.length > 0) {
    const eventStart = new Date(events[0].start.dateTime);
    const eventEnd = new Date(events[0].end.dateTime);
    const now = new Date();
    if (eventStart > now) {
      // event not started yet
      if (eventStart - now < MAX_TICK) {
        // event starts before next max tick, so update then
        nextTick = eventStart - now;
      }
    } else if (eventEnd - now < MAX_TICK) {
      // event ends before next max tick, so update then
      nextTick = eventEnd - now;
    }
  }
  yield delay(nextTick);
}

function* watchCalendar(calendar) {
  while (true) {
    const response = yield call(fetchEventsForCal, calendar.id);
    yield put(calendarUpdated(calendar.id, response.result.summary, response.result.items));
    yield race([
      // fetch again if room was booked
      take((action) => action.type === ROOM_BOOKED && action.calendarId === calendar.id),
      // or at next event tick
      call(eventsTick, response.result.items),
    ]);
  }
}

function* fetchCalendars() {
  yield all(_.map(calendars, (calendar) => call(watchCalendar, calendar)));
}

export default function* calendarEventSaga() {
  yield takeLatest(AUTH_SUCCESS, fetchCalendars);
}
<commit_msg>Don't break all calendars when gapi returns an error for one<commit_after>import _ from 'lodash';
import { delay } from 'redux-saga';
import { take, race, call, put, takeLatest, all } from 'redux-saga/effects';
import { AUTH_SUCCESS } from '../ducks/authenticate';
import { calendarUpdated } from '../ducks/calendar';
import { ROOM_BOOKED } from '../actions';
import calendars from '../calendars.json';

const gapi = window.gapi;

function fetchEventsForCal(calendar) {
  return gapi.client.calendar.events.list({
    calendarId: calendar,
    timeMin: (new Date()).toISOString(),
    showDeleted: false,
    singleEvents: true,
    maxResults: 2,
    orderBy: 'startTime',
  }).then(
    (response) => ({ response }),
    (error) => ({ error }),
  );
}

function* eventsTick(events) {
  // 10 min max between updates
  const MAX_TICK = 600000;
  let nextTick = MAX_TICK;
  if (events.length > 0) {
    const eventStart = new Date(events[0].start.dateTime);
    const eventEnd = new Date(events[0].end.dateTime);
    const now = new Date();
    if (eventStart > now) {
      // event not started yet
      if (eventStart - now < MAX_TICK) {
        // event starts before next max tick, so update then
        nextTick = eventStart - now;
      }
    } else if (eventEnd - now < MAX_TICK) {
      // event ends before next max tick, so update then
      nextTick = eventEnd - now;
    }
  }
  yield delay(nextTick);
}

function* watchCalendar(calendar) {
  while (true) {
    const { response } = yield call(fetchEventsForCal, calendar.id);
    if (response) {
      yield put(calendarUpdated(calendar.id, response.result.summary, response.result.items));
      yield race([
        // fetch again if room was booked
        take((action) => action.type === ROOM_BOOKED && action.calendarId === calendar.id),
        // or at next event tick
        call(eventsTick, response.result.items),
      ]);
    } else {
      yield call(eventsTick, []);
    }
  }
}

function* fetchCalendars() {
  yield all(_.map(calendars, (calendar) => call(watchCalendar, calendar)));
}

export default function* calendarEventSaga() {
  yield takeLatest(AUTH_SUCCESS, fetchCalendars);
}
<|endoftext|>


<commit_before>/*!
 * ${copyright}
 */

/**
 * Initialization Code and shared classes of library sap.f.
 */
sap.ui.define(["sap/ui/Global",
	"sap/ui/core/library", "sap/m/library"], // library dependency
	function() {

	"use strict";

	// delegate further initialization of this library to the Core
	sap.ui.getCore().initLibrary({
		name : "sap.f",
		version: "${version}",
		dependencies : ["sap.ui.core", "sap.m"],
		types: [
			"sap.f.LayoutType",
			"sap.f.DynamicPageTitleArea"
		],
		controls: [
			"sap.f.Avatar",
			"sap.f.DynamicPage",
			"sap.f.DynamicPageHeader",
			"sap.f.DynamicPageTitle",
			"sap.f.FlexibleColumnLayout",
			"sap.f.semantic.SemanticPage"
		],
		elements: [
			"sap.f.semantic.AddAction",
			"sap.f.semantic.CloseAction",
			"sap.f.semantic.CopyAction",
			"sap.f.semantic.DeleteAction",
			"sap.f.semantic.DiscussInJamAction",
			"sap.f.semantic.EditAction",
			"sap.f.semantic.ExitFullScreenAction",
			"sap.f.semantic.FavoriteAction",
			"sap.f.semantic.FlagAction",
			"sap.f.semantic.FooterMainAction",
			"sap.f.semantic.FullScreenAction",
			"sap.f.semantic.MessagesIndicator",
			"sap.f.semantic.NegativeAction",
			"sap.f.semantic.PositiveAction",
			"sap.f.semantic.PrintAction",
			"sap.f.semantic.SemanticButton",
			"sap.f.semantic.SemanticControl",
			"sap.f.semantic.SemanticToggleButton",
			"sap.f.semantic.SendEmailAction",
			"sap.f.semantic.SendMessageAction",
			"sap.f.semantic.ShareInJamAction",
			"sap.f.semantic.TitleMainAction"
		],
		extensions: {
			flChangeHandlers: {
				"sap.f.DynamicPageHeader" : {
					"hideControl": "default",
					"unhideControl": "default",
					"moveControls": "default"
				},
				"sap.f.DynamicPageTitle" : "sap/f/flexibility/DynamicPageTitle"
			}
		}
	});

	/**
	 * SAPUI5 library with controls specialized for SAP Fiori apps.
	 *
	 * @namespace
	 * @alias sap.f
	 * @author SAP SE
	 * @version ${version}
	 * @public
	 */
	var thisLib = sap.f;

	/**
	* Defines the areas within the sap.f.DynamicPageTitle.
	*
	* @enum {string}
	* @public
	* @since 1.50
	* @ui5-metamodel This enumeration also will be described in the UI5 (legacy) designtime metamodel
	*/
	thisLib.DynamicPageTitleArea = {
		/**
		* The area includes the heading, expandedContent and snappedContent aggregations,
		* positioned in the beginning area of the {@link sap.f.DynamicPageTitle}.
		*
		* @public
		*/
		Begin: "Begin",

		/**
		* The area includes the content aggregation,
		* positioned in the middle part of the {@link sap.f.DynamicPageTitle}.
		*
		* @public
		*/
		Middle: "Middle"
	};

	/**
	 * Layouts, representing the number of columns to be displayed and their relative widths for a {@link sap.f.FlexibleColumnLayout} control.
	 *
	 * Each layout has a predefined ratio for the three columns, depending on device size. Based on the device and layout, some columns are hidden.
	 * For more information, refer to the ratios (in %) for each value, listed below: (dash "-" means non-accessible columns).
	 *
	 * Note: Please note that on a phone device, due to the limited screen size, only one column can be displayed at a time.
	 * For all two-column layouts, this column is the Mid column, and for all three-column layouts - the End column,
	 * even though the respective column may be hidden on desktop and tablet for that particular layout.
	 *
	 * For more information, see {@link topic:3b9f760da5b64adf8db7f95247879086 Types of Layout} in the documentation.
	 *
	 * @enum {string}
	 * @public
	 * @since 1.46
	 * @ui5-metamodel This enumeration also will be described in the UI5 (legacy) designtime metamodel
	 */
	thisLib.LayoutType = {

		/**
		 * Desktop: 100/-/-  only the Begin column is displayed
		 *
		 * Tablet:  100/-/-  only the Begin column is displayed
		 *
		 * Phone:   100/-/-  only the Begin column is displayed
		 *
		 * Use to start with a master page.
		 *
		 * @public
		 */
		OneColumn: "OneColumn",

		/**
		 * Desktop: 67/33/-  Begin (expanded) and Mid columns are displayed
		 *
		 * Tablet:  67/33/-  Begin (expanded) and Mid columns are displayed
		 *
		 * Phone:   -/100/-  only the Mid column is displayed
		 *
		 * Use to display both a master and a detail page when the user should focus on the master page.
		 *
		 * @public
		 */
		TwoColumnsBeginExpanded: "TwoColumnsBeginExpanded",

		/**
		 * Desktop: 33/67/-  Begin and Mid (expanded) columns are displayed
		 *
		 * Tablet:  33/67/-  Begin and Mid (expanded) columns are displayed
		 *
		 * Phone:   -/100/-  only the Mid column is displayed
		 *
		 * Use to display both a master and a detail page when the user should focus on the detail page.
		 *
		 * @public
		 */
		TwoColumnsMidExpanded: "TwoColumnsMidExpanded",

		/**
		 * Desktop: -/100/-  only the Mid column is displayed
		 *
		 * Tablet:  -/100/-  only the Mid column is displayed
		 *
		 * Phone:   -/100/-  only the Mid column is displayed
		 *
		 * Use to display a detail page only, when the user should focus entirely on it.
		 *
		 * @public
		 */
		MidColumnFullScreen: "MidColumnFullScreen",

		/**
		 * Desktop: 25/50/25 Begin, Mid (expanded) and End columns are displayed
		 *
		 * Tablet:  0/67/33  Mid (expanded) and End columns are displayed, Begin is accessible by a layout arrow
		 *
		 * Phone:   -/-/100  only the End column is displayed
		 *
		 * Use to display all three pages (master, detail, detail-detail) when the user should focus on the detail.
		 *
		 * @public
		 */
		ThreeColumnsMidExpanded: "ThreeColumnsMidExpanded",

		/**
		 * Desktop: 25/25/50 Begin, Mid and End (expanded) columns are displayed
		 *
		 * Tablet:  0/33/67  Mid and End (expanded) columns are displayed, Begin is accessible by layout arrows
		 *
		 * Phone:   -/-/100  (only the End column is displayed)
		 *
		 * Use to display all three pages (master, detail, detail-detail) when the user should focus on the detail-detail.
		 *
		 * @public
		 */
		ThreeColumnsEndExpanded: "ThreeColumnsEndExpanded",

		/**
		 * Desktop: 33/67/0  Begin and Mid (expanded) columns are displayed, End is accessible by a layout arrow
		 *
		 * Tablet:  33/67/0  Begin and Mid (expanded) columns are displayed, End is accessible by a layout arrow
		 *
		 * Phone:   -/-/100  only the End column is displayed
		 *
		 * Use to display the master and detail pages when the user should focus on the detail.
		 * The detail-detail is still loaded and easily accessible with a layout arrow.
		 *
		 * @public
		 */
		ThreeColumnsMidExpandedEndHidden: "ThreeColumnsMidExpandedEndHidden",

		/**
		 * Desktop: 67/33/0  Begin (expanded) and Mid columns are displayed, End is accessible by layout arrows
		 *
		 * Tablet:  67/33/0  Begin (expanded) and Mid columns are displayed, End is accessible by layout arrows
		 *
		 * Phone:   -/-/100  only the End column is displayed
		 *
		 * Use to display the master and detail pages when the user should focus on the master.
		 * The detail-detail is still loaded and easily accessible with layout arrows.
		 *
		 * @public
		 */
		ThreeColumnsBeginExpandedEndHidden: "ThreeColumnsBeginExpandedEndHidden",

		/**
		 * Desktop: -/-/100  only the End column is displayed
		 *
		 * Tablet:  -/-/100  only the End column is displayed
		 *
		 * Phone:   -/-/100  only the End column is displayed
		 *
		 * Use to display a detail-detail page only, when the user should focus entirely on it.
		 *
		 * @public
		 */
		EndColumnFullScreen: "EndColumnFullScreen"
	};

	sap.ui.lazyRequire("sap.f.routing.Router");
	sap.ui.lazyRequire("sap.f.routing.Target");
	sap.ui.lazyRequire("sap.f.routing.TargetHandler");
	sap.ui.lazyRequire("sap.f.routing.Targets");

	/**
	 * Types of shape for the {@link sap.f.Avatar} control.
	 *
	 * @enum {string}
	 * @public
	 * @since 1.46
	 * @ui5-metamodel This enumeration also will be described in the UI5 (legacy) designtime metamodel
	 */
	thisLib.AvatarShape = {
		/**
		 * Circular shape.
		 * @public
		 */
		Circle: "Circle",

		/**
		 * Square shape.
		 * @public
		 */
		Square: "Square"
	};

	/**
	 * Predefined sizes for the {@link sap.f.Avatar} control.
	 *
	 * @enum {string}
	 * @public
	 * @since 1.46
	 * @ui5-metamodel This enumeration also will be described in the UI5 (legacy) designtime metamodel
	 */
	thisLib.AvatarSize = {
		/**
		 * Control size - 2rem
		 * Font size - 0.75rem
		 * @public
		 */
		XS: "XS",

		/**
		 * Control size - 3rem
		 * Font size - 1.125rem
		 * @public
		 */
		S: "S",

		/**
		 * Control size - 4rem
		 * Font size - 1.625rem
		 * @public
		 */
		M: "M",

		/**
		 * Control size - 5rem
		 * Font size - 2rem
		 * @public
		 */
		L: "L",

		/**
		 * Control size - 7rem
		 * Font size - 2.75rem
		 * @public
		 */
		XL: "XL",

		/**
		 * Custom size
		 * @public
		 */
		Custom: "Custom"
	};

	/**
	 * Types of {@link sap.f.Avatar} based on the displayed content.
	 *
	 * @enum {string}
	 * @public
	 * @since 1.46
	 * @ui5-metamodel This enumeration also will be described in the UI5 (legacy) designtime metamodel
	 */
	thisLib.AvatarType = {
		/**
		 * The displayed content is an icon.
		 * @public
		 */
		Icon: "Icon",
		/**
		 * The displayed content is an image.
		 * @public
		 */
		Image: "Image",
		/**
		 * The displayed content is initials.
		 * @public
		 */
		Initials: "Initials"
	};
	/**
	 * Types of image size and position that determine how an image fits in the {@link sap.f.Avatar} control area.
	 *
	 * @enum {string}
	 * @public
	 * @since 1.46
	 * @ui5-metamodel This enumeration also will be described in the UI5 (legacy) designtime metamodel
	 */
	thisLib.AvatarImageFitType = {
		/**
		 * The image is scaled to be large enough so that the control area is completely covered.
		 * @public
		 */
		Cover: "Cover",
		/**
		 * The image is scaled to the largest size so that both its width and height can fit in the control area.
		 * @public
		 */
		Contain: "Contain"
	};

	return thisLib;

});
<commit_msg>[INTERNAL] sap.f.LayoutType - documentation improved<commit_after>/*!
 * ${copyright}
 */

/**
 * Initialization Code and shared classes of library sap.f.
 */
sap.ui.define(["sap/ui/Global",
	"sap/ui/core/library", "sap/m/library"], // library dependency
	function() {

	"use strict";

	// delegate further initialization of this library to the Core
	sap.ui.getCore().initLibrary({
		name : "sap.f",
		version: "${version}",
		dependencies : ["sap.ui.core", "sap.m"],
		types: [
			"sap.f.LayoutType",
			"sap.f.DynamicPageTitleArea"
		],
		controls: [
			"sap.f.Avatar",
			"sap.f.DynamicPage",
			"sap.f.DynamicPageHeader",
			"sap.f.DynamicPageTitle",
			"sap.f.FlexibleColumnLayout",
			"sap.f.semantic.SemanticPage"
		],
		elements: [
			"sap.f.semantic.AddAction",
			"sap.f.semantic.CloseAction",
			"sap.f.semantic.CopyAction",
			"sap.f.semantic.DeleteAction",
			"sap.f.semantic.DiscussInJamAction",
			"sap.f.semantic.EditAction",
			"sap.f.semantic.ExitFullScreenAction",
			"sap.f.semantic.FavoriteAction",
			"sap.f.semantic.FlagAction",
			"sap.f.semantic.FooterMainAction",
			"sap.f.semantic.FullScreenAction",
			"sap.f.semantic.MessagesIndicator",
			"sap.f.semantic.NegativeAction",
			"sap.f.semantic.PositiveAction",
			"sap.f.semantic.PrintAction",
			"sap.f.semantic.SemanticButton",
			"sap.f.semantic.SemanticControl",
			"sap.f.semantic.SemanticToggleButton",
			"sap.f.semantic.SendEmailAction",
			"sap.f.semantic.SendMessageAction",
			"sap.f.semantic.ShareInJamAction",
			"sap.f.semantic.TitleMainAction"
		],
		extensions: {
			flChangeHandlers: {
				"sap.f.DynamicPageHeader" : {
					"hideControl": "default",
					"unhideControl": "default",
					"moveControls": "default"
				},
				"sap.f.DynamicPageTitle" : "sap/f/flexibility/DynamicPageTitle"
			}
		}
	});

	/**
	 * SAPUI5 library with controls specialized for SAP Fiori apps.
	 *
	 * @namespace
	 * @alias sap.f
	 * @author SAP SE
	 * @version ${version}
	 * @public
	 */
	var thisLib = sap.f;

	/**
	* Defines the areas within the sap.f.DynamicPageTitle.
	*
	* @enum {string}
	* @public
	* @since 1.50
	* @ui5-metamodel This enumeration also will be described in the UI5 (legacy) designtime metamodel
	*/
	thisLib.DynamicPageTitleArea = {
		/**
		* The area includes the heading, expandedContent and snappedContent aggregations,
		* positioned in the beginning area of the {@link sap.f.DynamicPageTitle}.
		*
		* @public
		*/
		Begin: "Begin",

		/**
		* The area includes the content aggregation,
		* positioned in the middle part of the {@link sap.f.DynamicPageTitle}.
		*
		* @public
		*/
		Middle: "Middle"
	};

	/**
	 * Layouts, representing the number of columns to be displayed and their relative widths for a {@link sap.f.FlexibleColumnLayout} control.
	 *
	 * Each layout has a predefined ratio for the three columns, depending on device size. Based on the device and layout, some columns are hidden.
	 * For more information, refer to the ratios (in %) for each value, listed below: (dash "-" means non-accessible columns).
	 *
	 * Note: Please note that on a phone device, due to the limited screen size, only one column can be displayed at a time.
	 * For all two-column layouts, this column is the Mid column, and for all three-column layouts - the End column,
	 * even though the respective column may be hidden on desktop and tablet for that particular layout. Therefore some of the names
	 * (such as ThreeColumnsMidExpandedEndHidden for example) are representative of the desktop scenario only.
	 *
	 * For more information, see {@link topic:3b9f760da5b64adf8db7f95247879086 Types of Layout} in the documentation.
	 *
	 * @enum {string}
	 * @public
	 * @since 1.46
	 * @ui5-metamodel This enumeration also will be described in the UI5 (legacy) designtime metamodel
	 */
	thisLib.LayoutType = {

		/**
		 * Desktop: 100/-/-  only the Begin column is displayed
		 *
		 * Tablet:  100/-/-  only the Begin column is displayed
		 *
		 * Phone:   100/-/-  only the Begin column is displayed
		 *
		 * Use to start with a master page.
		 *
		 * @public
		 */
		OneColumn: "OneColumn",

		/**
		 * Desktop: 67/33/-  Begin (expanded) and Mid columns are displayed
		 *
		 * Tablet:  67/33/-  Begin (expanded) and Mid columns are displayed
		 *
		 * Phone:   -/100/-  only the Mid column is displayed
		 *
		 * Use to display both a master and a detail page when the user should focus on the master page.
		 *
		 * @public
		 */
		TwoColumnsBeginExpanded: "TwoColumnsBeginExpanded",

		/**
		 * Desktop: 33/67/-  Begin and Mid (expanded) columns are displayed
		 *
		 * Tablet:  33/67/-  Begin and Mid (expanded) columns are displayed
		 *
		 * Phone:   -/100/-  only the Mid column is displayed
		 *
		 * Use to display both a master and a detail page when the user should focus on the detail page.
		 *
		 * @public
		 */
		TwoColumnsMidExpanded: "TwoColumnsMidExpanded",

		/**
		 * Desktop: -/100/-  only the Mid column is displayed
		 *
		 * Tablet:  -/100/-  only the Mid column is displayed
		 *
		 * Phone:   -/100/-  only the Mid column is displayed
		 *
		 * Use to display a detail page only, when the user should focus entirely on it.
		 *
		 * @public
		 */
		MidColumnFullScreen: "MidColumnFullScreen",

		/**
		 * Desktop: 25/50/25 Begin, Mid (expanded) and End columns are displayed
		 *
		 * Tablet:  0/67/33  Mid (expanded) and End columns are displayed, Begin is accessible by a layout arrow
		 *
		 * Phone:   -/-/100  only the End column is displayed
		 *
		 * Use to display all three pages (master, detail, detail-detail) when the user should focus on the detail.
		 *
		 * @public
		 */
		ThreeColumnsMidExpanded: "ThreeColumnsMidExpanded",

		/**
		 * Desktop: 25/25/50 Begin, Mid and End (expanded) columns are displayed
		 *
		 * Tablet:  0/33/67  Mid and End (expanded) columns are displayed, Begin is accessible by layout arrows
		 *
		 * Phone:   -/-/100  (only the End column is displayed)
		 *
		 * Use to display all three pages (master, detail, detail-detail) when the user should focus on the detail-detail.
		 *
		 * @public
		 */
		ThreeColumnsEndExpanded: "ThreeColumnsEndExpanded",

		/**
		 * Desktop: 33/67/0  Begin and Mid (expanded) columns are displayed, End is accessible by a layout arrow
		 *
		 * Tablet:  33/67/0  Begin and Mid (expanded) columns are displayed, End is accessible by a layout arrow
		 *
		 * Phone:   -/-/100  only the End column is displayed
		 *
		 * Use to display the master and detail pages when the user should focus on the detail.
		 * The detail-detail is still loaded and easily accessible with a layout arrow.
		 *
		 * @public
		 */
		ThreeColumnsMidExpandedEndHidden: "ThreeColumnsMidExpandedEndHidden",

		/**
		 * Desktop: 67/33/0  Begin (expanded) and Mid columns are displayed, End is accessible by layout arrows
		 *
		 * Tablet:  67/33/0  Begin (expanded) and Mid columns are displayed, End is accessible by layout arrows
		 *
		 * Phone:   -/-/100  only the End column is displayed
		 *
		 * Use to display the master and detail pages when the user should focus on the master.
		 * The detail-detail is still loaded and easily accessible with layout arrows.
		 *
		 * @public
		 */
		ThreeColumnsBeginExpandedEndHidden: "ThreeColumnsBeginExpandedEndHidden",

		/**
		 * Desktop: -/-/100  only the End column is displayed
		 *
		 * Tablet:  -/-/100  only the End column is displayed
		 *
		 * Phone:   -/-/100  only the End column is displayed
		 *
		 * Use to display a detail-detail page only, when the user should focus entirely on it.
		 *
		 * @public
		 */
		EndColumnFullScreen: "EndColumnFullScreen"
	};

	sap.ui.lazyRequire("sap.f.routing.Router");
	sap.ui.lazyRequire("sap.f.routing.Target");
	sap.ui.lazyRequire("sap.f.routing.TargetHandler");
	sap.ui.lazyRequire("sap.f.routing.Targets");

	/**
	 * Types of shape for the {@link sap.f.Avatar} control.
	 *
	 * @enum {string}
	 * @public
	 * @since 1.46
	 * @ui5-metamodel This enumeration also will be described in the UI5 (legacy) designtime metamodel
	 */
	thisLib.AvatarShape = {
		/**
		 * Circular shape.
		 * @public
		 */
		Circle: "Circle",

		/**
		 * Square shape.
		 * @public
		 */
		Square: "Square"
	};

	/**
	 * Predefined sizes for the {@link sap.f.Avatar} control.
	 *
	 * @enum {string}
	 * @public
	 * @since 1.46
	 * @ui5-metamodel This enumeration also will be described in the UI5 (legacy) designtime metamodel
	 */
	thisLib.AvatarSize = {
		/**
		 * Control size - 2rem
		 * Font size - 0.75rem
		 * @public
		 */
		XS: "XS",

		/**
		 * Control size - 3rem
		 * Font size - 1.125rem
		 * @public
		 */
		S: "S",

		/**
		 * Control size - 4rem
		 * Font size - 1.625rem
		 * @public
		 */
		M: "M",

		/**
		 * Control size - 5rem
		 * Font size - 2rem
		 * @public
		 */
		L: "L",

		/**
		 * Control size - 7rem
		 * Font size - 2.75rem
		 * @public
		 */
		XL: "XL",

		/**
		 * Custom size
		 * @public
		 */
		Custom: "Custom"
	};

	/**
	 * Types of {@link sap.f.Avatar} based on the displayed content.
	 *
	 * @enum {string}
	 * @public
	 * @since 1.46
	 * @ui5-metamodel This enumeration also will be described in the UI5 (legacy) designtime metamodel
	 */
	thisLib.AvatarType = {
		/**
		 * The displayed content is an icon.
		 * @public
		 */
		Icon: "Icon",
		/**
		 * The displayed content is an image.
		 * @public
		 */
		Image: "Image",
		/**
		 * The displayed content is initials.
		 * @public
		 */
		Initials: "Initials"
	};
	/**
	 * Types of image size and position that determine how an image fits in the {@link sap.f.Avatar} control area.
	 *
	 * @enum {string}
	 * @public
	 * @since 1.46
	 * @ui5-metamodel This enumeration also will be described in the UI5 (legacy) designtime metamodel
	 */
	thisLib.AvatarImageFitType = {
		/**
		 * The image is scaled to be large enough so that the control area is completely covered.
		 * @public
		 */
		Cover: "Cover",
		/**
		 * The image is scaled to the largest size so that both its width and height can fit in the control area.
		 * @public
		 */
		Contain: "Contain"
	};

	return thisLib;

});
<|endoftext|>