<commit_before>var QueueWorker = require('./lib/queue_worker');

/**
 * @constructor
 * @param {Firebase} ref A firebase reference to the queue.
 * @param {Object} (optional) Object containing keys for jobId: the current job ID.
     and numWorkers: The number of workers to create for this job.
 * @param {Function} processingFunction A function that is called each time to
 *   process the queue item. This function is passed three parameters:
 *     - data {Object} The current data at the location.
 *     - resolve {Function} An asychronous callback function - call this
 *         function when the processingFunction completes successfully. This
 *         takes an optional Object parameter that, if passed, will overwrite
 *         the data at the queue item location
 *     - reject {Function} An asynchronous callback function - call this
 *         function if the processingFunction encounters an error. This takes
 *         an optional String or Object parameter that will be stored in the
 *         '_error_details/error' location in the queue item.
 */
module.exports = Queue;
var DEFAULT_JOB_STATE_FINISHED = "finished";
var DEFAULT_JOB_STATE_IN_PROGRESS = "in_progress";
var DEFAULT_NUM_WORKERS = 1;
var DEFAULT_TIMEOUT = 360000;
function Queue() {
  var ref, options, jobId, numWorkers, processingFunction;
  if (arguments.length === 2) {
    ref = arguments[0];
    numWorkers = DEFAULT_NUM_WORKERS;
    processingFunction = arguments[1];
  } else if (arguments.length === 3) {
    ref = arguments[0];
    options = arguments[1];
    if (typeof(options.jobId) === 'string') {
      jobId = options.jobId;
    }
    if (typeof(options.numWorkers) === 'number' && options.numWorkers % 1 === 0 && options.numWorkers > 0) {
      numWorkers = options.numWorkers;
    } else {
      numWorkers = DEFAULT_NUM_WORKERS;
    }
    processingFunction = arguments[2];
  } else {
    throw new Error('Queue must at least have the queueRef and processingFunction arguments.');
  }
  var self = this;
  self.ref = ref;
  self.workers = [];
  for (var i = 0; i < numWorkers; i++) {
    self.workers.push(QueueWorker(self.ref.child('queue'), i, processingFunction));
  }
  if (jobId !== undefined) {
    self.ref.child('jobs').child(jobId).on('value',
      function(jobSpecSnap) {
        if (jobSpecSnap.val() === null) {
          throw new Error('No job specified for this worker');
        }
        finishedState = jobSpecSnap.child('state_finished').val();
        if (finishedState === null) {
          throw new Error('No state_finished specified for this job');
        }
        inProgressState = jobSpecSnap.child('state_in_progress').val();
        if (inProgressState === null) {
          throw new Error('No state_in_progress specified for this job');
        }
        var jobSpec = {
          startState: jobSpecSnap.child('state_start').val(),
          inProgressState: inProgressState,
          finishedState: finishedState,
          jobTimeout: jobSpecSnap.child('timeout').val()
        };
        for (var i = 0; i < numWorkers; i++) {
          self.workers[i].resetJob(jobSpec);
        }
      },
      function(error) {
        throw error;
      });
  } else {
    jobSpec = {
      startState: null,
      inProgressState: DEFAULT_JOB_STATE_IN_PROGRESS,
      finishedState: DEFAULT_JOB_STATE_FINISHED,
      jobTimeout: DEFAULT_TIMEOUT
    };
    for (var j = 0; j < numWorkers; j++) {
      self.workers[j].resetJob(jobSpec);
    }
  }
  return self;
}<commit_msg>two tiny style changes<commit_after>var QueueWorker = require('./lib/queue_worker');

/**
 * @constructor
 * @param {Firebase} ref A firebase reference to the queue.
 * @param {Object} (optional) Object containing keys for jobId: the current job ID.
     and numWorkers: The number of workers to create for this job.
 * @param {Function} processingFunction A function that is called each time to
 *   process the queue item. This function is passed three parameters:
 *     - data {Object} The current data at the location.
 *     - resolve {Function} An asychronous callback function - call this
 *         function when the processingFunction completes successfully. This
 *         takes an optional Object parameter that, if passed, will overwrite
 *         the data at the queue item location
 *     - reject {Function} An asynchronous callback function - call this
 *         function if the processingFunction encounters an error. This takes
 *         an optional String or Object parameter that will be stored in the
 *         '_error_details/error' location in the queue item.
 */
module.exports = Queue;
var DEFAULT_JOB_STATE_FINISHED = "finished";
var DEFAULT_JOB_STATE_IN_PROGRESS = "in_progress";
var DEFAULT_NUM_WORKERS = 1;
var DEFAULT_TIMEOUT = 360000;
function Queue() {
  var ref, options, jobId, numWorkers, processingFunction;
  if (arguments.length === 2) {
    ref = arguments[0];
    numWorkers = DEFAULT_NUM_WORKERS;
    processingFunction = arguments[1];
  } else if (arguments.length === 3) {
    ref = arguments[0];
    options = arguments[1];
    if (typeof(options.jobId) === 'string') {
      jobId = options.jobId;
    }
    if (typeof(options.numWorkers) === 'number' && options.numWorkers % 1 === 0 && options.numWorkers > 0) {
      numWorkers = options.numWorkers;
    } else {
      numWorkers = DEFAULT_NUM_WORKERS;
    }
    processingFunction = arguments[2];
  } else {
    throw new Error('Queue must at least have the queueRef and processingFunction arguments.');
  }
  var self = this;
  self.ref = ref;
  self.workers = [];
  for (var i = 0; i < numWorkers; i++) {
    self.workers.push(QueueWorker(self.ref.child('queue'), i, processingFunction));
  }
  if (typeof(jobId) !== 'undefined') {
    self.ref.child('jobs').child(jobId).on('value',
      function(jobSpecSnap) {
        if (jobSpecSnap.val() === null) {
          throw new Error('No job specified for this worker');
        }
        finishedState = jobSpecSnap.child('state_finished').val();
        if (finishedState === null) {
          throw new Error('No state_finished specified for this job');
        }
        inProgressState = jobSpecSnap.child('state_in_progress').val();
        if (inProgressState === null) {
          throw new Error('No state_in_progress specified for this job');
        }
        var jobSpec = {
          startState: jobSpecSnap.child('state_start').val(),
          inProgressState: inProgressState,
          finishedState: finishedState,
          jobTimeout: jobSpecSnap.child('timeout').val()
        };
        for (var i = 0; i < numWorkers; i++) {
          self.workers[i].resetJob(jobSpec);
        }
      },
      function(error) {
        throw error;
      });
  } else {
    jobSpec = {
      startState: null,
      inProgressState: DEFAULT_JOB_STATE_IN_PROGRESS,
      finishedState: DEFAULT_JOB_STATE_FINISHED,
      jobTimeout: DEFAULT_TIMEOUT
    };
    for (var j = 0; j < numWorkers; j++) {
      self.workers[j].resetJob(jobSpec);
    }
  }
  return self;
}
<|endoftext|>


<commit_before>var superagent = require('superagent'),urlencode = require('urlencode'),Job = require('./models/job'),config = require('./config')
function InsertDB(Data) {
    for (var i = 0; i < Data.length; i++) {
        var job =Data[i];
        var newjob = new Job({
            positionId:job.positionId,
            positionName: job.positionName,
            positionAdvantage: job.positionAdvantage,
            salary: job.salary,
            companyName: job.companyName,
            companySize: job.companySize,
            companyLabelList: job.companyLabelList,
            industryField:job.industryField,
            education: job.education,
            workYear: job.workYear,
            createTime: job.createTime
        })
        newjob.save(function(err,data) {
           // console.log(err);
        });
    }
}
function getJobs(pageNo,city,kd) {
    var args = process.argv.slice(2);
    var url = '';
    if (pageNo === 1) {
        url = 'http://www.lagou.com/jobs/positionAjax.json?city=' + urlencode(city) + '&first=true&kd=' + urlencode(kd) + '&pn=' + pageNo;
    } else {
        url = 'http://www.lagou.com/jobs/positionAjax.json?city=' + urlencode(city) + '&first=false&kd=' + urlencode(kd) + '&pn=' + pageNo;
    }
    superagent.get(url).end(function(err, sres) {
        if (err) {
            hasNextPage = false;
            console.log(err);
        }
        var jobjson = JSON.parse(sres.text);
        if (jobjson.success) {
            InsertDB(jobjson.content.result);
            if (pageNo<jobjson.content.totalPageCount) {
                getJobs(pageNo + 1,city,kd);
            } else {
                console.log('抓取完毕，共抓取' + pageNo + '页数据');
                console.log('结束时间:'+new Date().toLocaleTimeString());
            }
        } else {
            console.log(jobjson.msg);
        }
    });
}
(function () {
    Job.removeAll(function(err,params) {
        if(!err){
            console.log("清空数据库...");
        }
       console.log(new Date().toLocaleTimeString() +'开始抓取'+config.city+'的'+config.kd+'职位' );
       getJobs(1,config.city,config.kd);
    });
})();
<commit_msg>拉勾网JSON数据更新和解决工资转换大小写问题<commit_after>var superagent = require('superagent'),urlencode = require('urlencode'),Job = require('./models/job'),config = require('./config')
function InsertDB(Data) {
    for (var i = 0; i < Data.length; i++) {
        var job =Data[i];
        var newjob = new Job({
            positionId:job.positionId,
            positionName: job.positionName,
            positionAdvantage: job.positionAdvantage,
            salary: job.salary.toLowerCase(),
            companyName: job.companyFullName,
            companySize: job.companySize,
            companyLabelList: job.companyLabelList,
            industryField:job.industryField,
            education: job.education,
            workYear: job.workYear,
            createTime: job.createTime
        })
        newjob.save(function(err,data) {
           // console.log(err);
        });
    }
}
function getJobs(pageNo,city,kd) {
    var args = process.argv.slice(2);
    var url = '';
    if (pageNo === 1) {
        url = 'http://www.lagou.com/jobs/positionAjax.json?city=' + urlencode(city) + '&first=true&kd=' + urlencode(kd) + '&pn=' + pageNo;
    } else {
        url = 'http://www.lagou.com/jobs/positionAjax.json?city=' + urlencode(city) + '&first=false&kd=' + urlencode(kd) + '&pn=' + pageNo;
    }

    superagent.get(url).end(function(err, sres) {
        if (err) {
            hasNextPage = false;
            console.log(err);
        }

        var jobjson = JSON.parse(sres.text);

        if (jobjson.success) {
            InsertDB(jobjson.content.positionResult.result);
            if (pageNo<jobjson.content.positionResult.totalCount) {
                getJobs(pageNo + 1,city,kd);
            } else {
                console.log('抓取完毕，共抓取' + pageNo + '页数据');
                console.log('结束时间:'+new Date().toLocaleTimeString());
            }
        } else {
            console.log(jobjson.msg);
        }
    });
}
(function () {
    Job.removeAll(function(err,params) {
        if(!err){
            console.log("清空数据库...");
        }
       console.log(new Date().toLocaleTimeString() +'开始抓取'+config.city+'的'+config.kd+'职位' );
       getJobs(1,config.city,config.kd);
    });
})();
<|endoftext|>


<commit_before>var express = require('express'),
fs = require('fs'),
path = require('path'),
url = require('url'),
request = require('request'),
dns = require('dns'),
jimp = require('jimp'),
tmp = require("tmp"),
common;

var metahub_srv = "bokeh-metahub.service.consul."
var photohub_srv = "bokeh-photohub-3000.service.consul."
var thumbhub_srv = "bokeh-thumbhub.service.consul."

function pickupSRV(name, cb) {
	dns.resolveSrv(name, function (err, results) {
		if (results instanceof Array) {
			// Pickup a random result from the different resolved names
			result = results[Math.floor(Math.random()*results.length)];
			cb(result);
		}
	});
}

function getMetaData(hash, cb) {
	pickupSRV(metahub_srv, function(record) {
		var myurl = 'http://' + record.name + ':' + record.port + '/photos?hash=' + hash;
		console.log("Requesting Metahub: "+ myurl);
		request({uri: myurl}).on('response', function(response) {
			var str = '';
			response.on('data', function (chunk) { str += chunk; });
			response.on('end', function () {
				console.log("Got answer from Metahub: " + str);
				var resp = JSON.parse(str);
				if (resp) {
					myPhoto = resp['photos'][0];
					type = myPhoto['type'];
					url = myPhoto['url'];
					cb(false, url, type);
				} else {
					console.log('Bad response from Metahub');
					cb('error', '', '');
				}
			});
		}).on('error', function (error) {
			console.log('Error while requesting Metahub');
			cb('error', '', '');
		});
	});
}

function getPhoto(hash, path, cb) {
	pickupSRV(photohub_srv, function(record) {
		var myurl = 'http://' + record.name + ':' + record.port + '/photos/hash/' + hash;
		console.log('Uploading photo from PhotoHub: '+myurl);
		request(myurl)
		.on('error', function(err) {
			cb(err);
		})
		.on('response', function(response) {
			console.log("Reply from photohub: " + response.statusCode);
			response.on('end', function () {
				console.log("Written file: " + path);
				cb('');
			});
		}).pipe(fs.createWriteStream(path));
	});
}

module.exports = function(config){
	var app = express(),
	staticFiles = config.staticFiles,
	common = require('./common')(config);

//	app.get(/.+\.(jpg|bmp|jpeg|gif|png|tif)$/i, function(req, res, next){
	app.get(/.+$/i, function(req, res, next){
		var filePath, fstream;
		var hash = path.basename(req.path);
		var hashPath =  path.join(staticFiles + "/" + hash);

		console.log("Got request for " + config.urlRoot + req.path);
		getMetaData(hash, function (e, p, type) {
			if (e) {
				console.log("Unable to get MIME type on MetaHub");
				return common.error(req, res, next, 404, 'File not found', err);
			}
			console.log("Got from MetaHub type: " + type)
			fs.stat(hashPath, function(err){
				if (err){
					console.log("Thumb not found: " + hashPath);
					filePath = path.join(staticFiles + "/" + p);
					getPhoto(hash, filePath, function (err) {
						if (err) {
							console.log("Cannot download: " + err);
							return common.error(req, res, next, 404, 'File not found', err1);
						}
						jimp.read(filePath, function(err1, img) {
							if (err1) {
								console.log("Cannot read: " + err);
								return common.error(req, res, next, 404, 'File not found', err1);
							}
							img.resize(256, jimp.AUTO)
							console.log("Img ext: " + img.getExtension());
							console.log("Img MIME: " + img.getMIME());
							img.write(hashPath, function(err3, i) {
								if (err3) {
									console.log("Cannot write final thumb: " + hashPath + " err3: " + err3);
									return common.error(req, res, next, 404, 'File not found', err3);
								}
								console.log("Successfully created thumb: " + hashPath);
								fstream = fs.createReadStream(hashPath);
								return fstream.pipe(res);
							});
						});
					});
				} else {
					fstream = fs.createReadStream(filePath);
					fstream.on('error', function(err){
						console.log("Cannot read thumb: " + req.path);
						return common.error(req, res, next, 404, 'File not found', err);
					});
					return fstream.pipe(res);
				}
			});
		});
	});

	return app;
}<commit_msg>TH: add log<commit_after>var express = require('express'),
fs = require('fs'),
path = require('path'),
url = require('url'),
request = require('request'),
dns = require('dns'),
jimp = require('jimp'),
tmp = require("tmp"),
common;

var metahub_srv = "bokeh-metahub.service.consul."
var photohub_srv = "bokeh-photohub-3000.service.consul."
var thumbhub_srv = "bokeh-thumbhub.service.consul."

function pickupSRV(name, cb) {
	dns.resolveSrv(name, function (err, results) {
		if (results instanceof Array) {
			// Pickup a random result from the different resolved names
			result = results[Math.floor(Math.random()*results.length)];
			cb(result);
		}
	});
}

function getMetaData(hash, cb) {
	pickupSRV(metahub_srv, function(record) {
		var myurl = 'http://' + record.name + ':' + record.port + '/photos?hash=' + hash;
		console.log("Requesting Metahub: "+ myurl);
		request({uri: myurl}).on('response', function(response) {
			var str = '';
			response.on('data', function (chunk) { str += chunk; });
			response.on('end', function () {
				console.log("Got answer from Metahub: " + str);
				var resp = JSON.parse(str);
				if (resp) {
					myPhoto = resp['photos'][0];
					type = myPhoto['type'];
					url = myPhoto['url'];
					cb(false, url, type);
				} else {
					console.log('Bad response from Metahub');
					cb('error', '', '');
				}
			});
		}).on('error', function (error) {
			console.log('Error while requesting Metahub');
			cb('error', '', '');
		});
	});
}

function getPhoto(hash, path, cb) {
	pickupSRV(photohub_srv, function(record) {
		var myurl = 'http://' + record.name + ':' + record.port + '/photos/hash/' + hash;
		console.log('Uploading photo from PhotoHub: '+myurl);
		request(myurl)
		.on('error', function(err) {
			cb(err);
		})
		.on('response', function(response) {
			console.log("Reply from photohub: " + response.statusCode);
			response.on('end', function () {
				console.log("Written file: " + path);
				cb('');
			});
		}).pipe(fs.createWriteStream(path));
	});
}

module.exports = function(config){
	var app = express(),
	staticFiles = config.staticFiles,
	common = require('./common')(config);

//	app.get(/.+\.(jpg|bmp|jpeg|gif|png|tif)$/i, function(req, res, next){
	app.get(/.+$/i, function(req, res, next){
		var filePath, fstream;
		var hash = path.basename(req.path);
		var hashPath =  path.join(staticFiles + "/" + hash);

		console.log("Got request for " + config.urlRoot + req.path);
		getMetaData(hash, function (e, p, type) {
			if (e) {
				console.log("Unable to get MIME type on MetaHub");
				return common.error(req, res, next, 404, 'File not found', err);
			}
			console.log("Got from MetaHub type: " + type)
			fs.stat(hashPath, function(err){
				if (err){
					console.log("Thumb not found: " + hashPath);
					filePath = path.join(staticFiles + "/" + p);
					getPhoto(hash, filePath, function (err) {
						if (err) {
							console.log("Cannot download: " + err);
							return common.error(req, res, next, 404, 'File not found', err1);
						}
						jimp.read(filePath, function(err1, img) {
							if (err1) {
								console.log("Cannot read: " + err1);
								return common.error(req, res, next, 404, 'File not found', err1);
							}
							img.resize(256, jimp.AUTO)
							console.log("Img ext: " + img.getExtension());
							console.log("Img MIME: " + img.getMIME());
							img.write(hashPath, function(err3, i) {
								if (err3) {
									console.log("Cannot write final thumb: " + hashPath + " err3: " + err3);
									return common.error(req, res, next, 404, 'File not found', err3);
								}
								console.log("Successfully created thumb: " + hashPath);
								fstream = fs.createReadStream(hashPath);
								return fstream.pipe(res);
							});
						});
					});
				} else {
					fstream = fs.createReadStream(filePath);
					fstream.on('error', function(err){
						console.log("Cannot read thumb: " + req.path);
						return common.error(req, res, next, 404, 'File not found', err);
					});
					return fstream.pipe(res);
				}
			});
		});
	});

	return app;
}<|endoftext|>


<commit_before>// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

'use strict'

const assert = require('assert')
const test = require('../lib/test')
const { By } = require('..')
const { UnknownCommandError } = require('../lib/error')

test.suite(function (env) {
  let driver

  before(async function () {
    driver = await env.builder().build()
  })
  after(function () {
    return driver.quit()
  })

  beforeEach(function () {
    return driver.switchTo().defaultContent()
  })

  it('can set size of the current window', async function () {
    await driver.get(test.Pages.echoPage)
    await changeSizeBy(-20, -20)
  })

  it('can set size of the current window from frame', async function () {
    await driver.get(test.Pages.framesetPage)

    var frame = await driver.findElement({ css: 'frame[name="fourth"]' })
    await driver.switchTo().frame(frame)
    await changeSizeBy(-20, -20)
  })

  it('can set size of the current window from iframe', async function () {
    await driver.get(test.Pages.iframePage)

    var frame = await driver.findElement({ css: 'iframe[name="iframe1-name"]' })
    await driver.switchTo().frame(frame)
    await changeSizeBy(-20, -20)
  })

  it('can switch to a new window', async function () {
    await driver.get(test.Pages.xhtmlTestPage)

    await driver.getWindowHandle()
    let originalHandles = await driver.getAllWindowHandles()

    await driver.findElement(By.linkText('Open new window')).click()
    await driver.wait(forNewWindowToBeOpened(originalHandles), 2000)
    assert.strictEqual(await driver.getTitle(), 'XHTML Test Page')

    let newHandle = await getNewWindowHandle(originalHandles)

    await driver.switchTo().window(newHandle)
    assert.strictEqual(await driver.getTitle(), 'We Arrive Here')
  })

  it('can set the window position of the current window', async function () {
    let { x, y } = await driver.manage().window().getRect()
    let newX = x + 10
    let newY = y + 10

    await driver.manage().window().setRect({
      x: newX,
      y: newY,
      width: 640,
      height: 480,
    })

    return driver.wait(forPositionToBe(newX, newY), 1000)
  })

  it('can set the window position from a frame', async function () {
    await driver.get(test.Pages.iframePage)

    let frame = await driver.findElement(By.name('iframe1-name'))
    await driver.switchTo().frame(frame)

    let { x, y } = await driver.manage().window().getRect()
    x += 10
    y += 10

    await driver.manage().window().setRect({ width: 640, height: 480, x, y })
    return driver.wait(forPositionToBe(x, y), 1000)
  })

  it('can open a new window', async function () {
    let originalHandles = await driver.getAllWindowHandles()
    let originalHandle = await driver.getWindowHandle()

    let newHandle
    try {
      newHandle = await driver.switchTo().newWindow()
    } catch (ex) {
      if (ex instanceof UnknownCommandError) {
        console.warn(
          Error(
            `${env.browser.name}: aborting test due to unsupported command: ${ex}`
          ).stack
        )
        return
      }
    }

    assert.strictEqual(
      (await driver.getAllWindowHandles()).length,
      originalHandles.length + 1
    )
    assert.notEqual(originalHandle, newHandle)
  })

  async function changeSizeBy(dx, dy) {
    let { width, height } = await driver.manage().window().getRect()
    width += dx
    height += dy

    let rect = await driver.manage().window().setRect({ width, height })
    if (rect.width === width && rect.height === height) {
      return
    }
    return driver.wait(forSizeToBe(width, height), 1000)
  }

  function forSizeToBe(w, h) {
    return async function () {
      let { width, height } = await driver.manage().window().getRect()
      return width === w && height === h
    }
  }

  function forPositionToBe(x, y) {
    return async function () {
      let position = await driver.manage().window().getRect()
      return (
        position.x === x &&
        // On OSX, the window height may be bumped down 22px for the top
        // status bar.
        // On Linux, Opera's window position will be off by 28px.
        position.y >= y &&
        position.y <= y + 28
      )
    }
  }

  function forNewWindowToBeOpened(originalHandles) {
    return function () {
      return driver.getAllWindowHandles().then(function (currentHandles) {
        return currentHandles.length > originalHandles.length
      })
    }
  }

  function getNewWindowHandle(originalHandles) {
    // Note: this assumes there's just one new window.
    return driver.getAllWindowHandles().then(function (currentHandles) {
      return currentHandles.filter(function (i) {
        return originalHandles.indexOf(i) < 0
      })[0]
    })
  }
})
<commit_msg>[JS] Fix window test in firefox<commit_after>// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

'use strict'

const assert = require('assert')
const test = require('../lib/test')
const { By } = require('..')
const { UnknownCommandError } = require('../lib/error')

test.suite(function (env) {
  let driver

  before(async function () {
    driver = await env.builder().build()
  })
  after(function () {
    return driver.quit()
  })

  beforeEach(function () {
    return driver.switchTo().defaultContent()
  })

  it('can set size of the current window', async function () {
    await driver.get(test.Pages.echoPage)
    await changeSizeBy(-20, -20)
  })

  it('can set size of the current window from frame', async function () {
    await driver.get(test.Pages.framesetPage)

    const frame = await driver.findElement({ css: 'frame[name="fourth"]' })
    await driver.switchTo().frame(frame)
    await changeSizeBy(-20, -20)
  })

  it('can set size of the current window from iframe', async function () {
    await driver.get(test.Pages.iframePage)

    const frame = await driver.findElement({ css: 'iframe[name="iframe1-name"]' })
    await driver.switchTo().frame(frame)
    await changeSizeBy(-20, -20)
  })

  it('can switch to a new window', async function () {
    await driver.get(test.Pages.xhtmlTestPage)

    await driver.getWindowHandle()
    let originalHandles = await driver.getAllWindowHandles()

    await driver.findElement(By.linkText('Open new window')).click()
    await driver.wait(forNewWindowToBeOpened(originalHandles), 2000)
    assert.strictEqual(await driver.getTitle(), 'XHTML Test Page')

    let newHandle = await getNewWindowHandle(originalHandles)

    await driver.switchTo().window(newHandle)
    assert.strictEqual(await driver.getTitle(), 'We Arrive Here')
  })

  it('can set the window position of the current window', async function () {
    let { x, y } = await driver.manage().window().getRect()
    let newX = x + 10
    let newY = y + 10

    await driver.manage().window().setRect({
      x: newX,
      y: newY,
      width: 640,
      height: 480,
    })

    await driver.wait(forPositionToBe(newX, newY), 1000)
  })

  it('can set the window position from a frame', async function () {
    await driver.get(test.Pages.iframePage)

    let frame = await driver.findElement(By.name('iframe1-name'))
    await driver.switchTo().frame(frame)

    let { x, y } = await driver.manage().window().getRect()
    x += 10
    y += 10

    await driver.manage().window().setRect({ width: 640, height: 480, x, y })
    await driver.wait(forPositionToBe(x, y), 1000)
  })

  it('can open a new window', async function () {
    let originalHandles = await driver.getAllWindowHandles()
    let originalHandle = await driver.getWindowHandle()

    let newHandle
    try {
      newHandle = await driver.switchTo().newWindow()
    } catch (ex) {
      if (ex instanceof UnknownCommandError) {
        console.warn(
          Error(
            `${env.browser.name}: aborting test due to unsupported command: ${ex}`
          ).stack
        )
        return
      }
    }

    assert.strictEqual(
      (await driver.getAllWindowHandles()).length,
      originalHandles.length + 1
    )
    assert.notEqual(originalHandle, newHandle)
  })

  async function changeSizeBy(dx, dy) {
    let { width, height } = await driver.manage().window().getRect()
    width += dx
    height += dy

    let rect = await driver.manage().window().setRect({ width, height })
    if (rect.width === width && rect.height === height) {
      return
    }
    return await driver.wait(forSizeToBe(width, height), 1000)
  }

  function forSizeToBe(w, h) {
    return async function () {
      let { width, height } = await driver.manage().window().getRect()
      return width === w && height === h
    }
  }

  function forPositionToBe(x, y) {
    return async function () {
      let position = await driver.manage().window().getRect()
      return (
        position.x === x &&
        // On OSX, the window height may be bumped down 22px for the top
        // status bar.
        // On Linux, Opera's window position will be off by 28px.
        position.y >= y &&
        position.y <= y + 28
      )
    }
  }

  function forNewWindowToBeOpened(originalHandles) {
    return function () {
      return driver.getAllWindowHandles().then(function (currentHandles) {
        return currentHandles.length > originalHandles.length
      })
    }
  }

  function getNewWindowHandle(originalHandles) {
    // Note: this assumes there's just one new window.
    return driver.getAllWindowHandles().then(function (currentHandles) {
      return currentHandles.filter(function (i) {
        return originalHandles.indexOf(i) < 0
      })[0]
    })
  }
})
<|endoftext|>


<commit_before>/*
 * This file has been created by Ergosign GmbH - All rights reserved - http://www.ergosign.de
 * DO NOT ALTER OR REMOVE THIS COPYRIGHT NOTICE OR THIS FILE HEADER.
 *
 * This file and the code contained in it are subject to the agreed contractual terms and conditions,
 * in particular with regard to resale and publication.
 */

/**
 * This class represents ...
 *
 * Class history:
 *  - 0.1: First release, working (frankb)
 *
 * @author frankb
 * @date 22.10.15
 * @constructor
 */

$(document).ready(function()
{
    var modifierContainer = $('.modifier-select').next('div').find('.kss-modifier__container');
    //modifierContainer.hide();
    $('.kss-modifier__wrapper .modifier-select').change(function(ev)
    {
        var selector = $(this).val();
        var offset = $('body').scrollTop();

        if (selector === 'all')
        {
            $(this).next('div').find('.kss-modifier__container').show();
        }
        else
        {
            console.log("open " + selector);
            modifierContainer.hide();
            //$(this).next('div').find(selector).parents('.kss-modifier__container').show();
            var idx = this.selectedIndex;
            if(idx > 1)
                $(this).next('div').children().eq(parseInt(idx-2)).show();
        }

        $('body').scrollTop(offset);
    });
});<commit_msg>fix variations select scroll bug<commit_after>/*
 * This file has been created by Ergosign GmbH - All rights reserved - http://www.ergosign.de
 * DO NOT ALTER OR REMOVE THIS COPYRIGHT NOTICE OR THIS FILE HEADER.
 *
 * This file and the code contained in it are subject to the agreed contractual terms and conditions,
 * in particular with regard to resale and publication.
 */

/**
 * This class represents ...
 *
 * Class history:
 *  - 0.1: First release, working (frankb)
 *
 * @author frankb
 * @date 22.10.15
 * @constructor
 */

$(document).ready(function()
{
    var modifierContainer = $('.modifier-select').next('div').find('.kss-modifier__container');
    //modifierContainer.hide();
    $('.kss-modifier__wrapper .modifier-select').change(function(ev)
    {
        var selector = $(this).val();
        var offset = $('body').scrollTop();

        if (selector === 'all')
        {
            $(this).next('div').find('.kss-modifier__container').show();
        }
        else
        {
            console.log("open " + selector);
            $(this).next('div').children().hide();
            //$(this).next('div').find(selector).parents('.kss-modifier__container').show();
            var idx = this.selectedIndex;
            if(idx > 1)
                $(this).next('div').children().eq(parseInt(idx-2)).show();
        }

        $('body').scrollTop(offset);
    });
});<|endoftext|>


<commit_before>import React, {PropTypes} from 'react'
import buildInfluxQLQuery from 'utils/influxql'
import classNames from 'classnames'
import AutoRefresh from 'shared/components/AutoRefresh'
import LineGraph from 'shared/components/LineGraph'
import SingleStat from 'shared/components/SingleStat'
import Table from './Table'
import VisHeader from 'src/data_explorer/components/VisHeader'

const RefreshingLineGraph = AutoRefresh(LineGraph)
const RefreshingSingleStat = AutoRefresh(SingleStat)

const GRAPH = 'graph'
const TABLE = 'table'
const VIEWS = [GRAPH, TABLE]

const {
  func,
  arrayOf,
  number,
  shape,
  string,
} = PropTypes

const Visualization = React.createClass({
  propTypes: {
    cellName: string,
    cellType: string,
    autoRefresh: number.isRequired,
    timeRange: shape({
      upper: string,
      lower: string,
    }).isRequired,
    queryConfigs: arrayOf(shape({})).isRequired,
    activeQueryIndex: number,
    height: string,
    heightPixels: number,
    onEditRawStatus: func.isRequired,
  },

  contextTypes: {
    source: PropTypes.shape({
      links: PropTypes.shape({
        proxy: PropTypes.string.isRequired,
      }).isRequired,
    }).isRequired,
  },

  getInitialState() {
    const {queryConfigs, activeQueryIndex} = this.props
    if (!queryConfigs.length || activeQueryIndex === null) {
      return {
        view: GRAPH,
      }
    }

    return {
      view: typeof queryConfigs[activeQueryIndex].rawText === 'string' ? TABLE : GRAPH,
    }
  },

  componentWillReceiveProps(nextProps) {
    const {queryConfigs, activeQueryIndex} = nextProps
    if (!queryConfigs.length || activeQueryIndex === null || activeQueryIndex === this.props.activeQueryIndex) {
      return
    }

    const activeQuery = queryConfigs[activeQueryIndex]
    if (activeQuery && typeof activeQuery.rawText === 'string') {
      return this.setState({view: TABLE})
    }
  },

  handleToggleView(view) {
    this.setState({view})
  },

  render() {
    const {queryConfigs, timeRange, height, heightPixels, onEditRawStatus, activeQueryIndex} = this.props
    const {source} = this.context
    const proxyLink = source.links.proxy
    const {view} = this.state

    const statements = queryConfigs.map((query) => {
      const text = query.rawText || buildInfluxQLQuery(timeRange, query)
      return {text, id: query.id}
    })
    const queries = statements.filter((s) => s.text !== null).map((s) => {
      return {host: [proxyLink], text: s.text, id: s.id}
    })

    return (

        <VisHeader views={VIEWS} view={view} onToggleView={this.handleToggleView} name={name || 'Graph'}/>

          {this.renderVisualization(view, queries, heightPixels, onEditRawStatus, activeQueryIndex)}

    )
  },

  renderVisualization(view, queries, heightPixels, onEditRawStatus, activeQueryIndex) {
    const activeQuery = queries[activeQueryIndex]
    const defaultQuery = queries[0]
    const q = activeQuery || defaultQuery

    switch (view) {
      case GRAPH:
        return this.renderGraph(queries)
      case TABLE:
        return (q ?
 :
Enter your query below
)
      default:
        this.renderGraph(queries)
    }
  },

  renderGraph(queries) {
    const {cellType, autoRefresh, activeQueryIndex} = this.props
    const isInDataExplorer = true

    if (cellType === 'single-stat') {
      return <RefreshingSingleStat queries={[queries[0]]} autoRefresh={autoRefresh} />
    }

    const displayOptions = {
      stepPlot: cellType === 'line-stepplot',
      stackedGraph: cellType === 'line-stacked',
    }
    return (
      <RefreshingLineGraph
        queries={queries}
        autoRefresh={autoRefresh}
        activeQueryIndex={activeQueryIndex}
        isInDataExplorer={isInDataExplorer}
        showSingleStat={cellType === "line-plus-single-stat"}
        displayOptions={displayOptions}
      />
    )
  },
})

export default Visualization
<commit_msg>Consolidate switch statement<commit_after>import React, {PropTypes} from 'react'
import buildInfluxQLQuery from 'utils/influxql'
import classNames from 'classnames'
import AutoRefresh from 'shared/components/AutoRefresh'
import LineGraph from 'shared/components/LineGraph'
import SingleStat from 'shared/components/SingleStat'
import Table from './Table'
import VisHeader from 'src/data_explorer/components/VisHeader'

const RefreshingLineGraph = AutoRefresh(LineGraph)
const RefreshingSingleStat = AutoRefresh(SingleStat)

const GRAPH = 'graph'
const TABLE = 'table'
const VIEWS = [GRAPH, TABLE]

const {
  func,
  arrayOf,
  number,
  shape,
  string,
} = PropTypes

const Visualization = React.createClass({
  propTypes: {
    cellName: string,
    cellType: string,
    autoRefresh: number.isRequired,
    timeRange: shape({
      upper: string,
      lower: string,
    }).isRequired,
    queryConfigs: arrayOf(shape({})).isRequired,
    activeQueryIndex: number,
    height: string,
    heightPixels: number,
    onEditRawStatus: func.isRequired,
  },

  contextTypes: {
    source: PropTypes.shape({
      links: PropTypes.shape({
        proxy: PropTypes.string.isRequired,
      }).isRequired,
    }).isRequired,
  },

  getInitialState() {
    const {queryConfigs, activeQueryIndex} = this.props
    if (!queryConfigs.length || activeQueryIndex === null) {
      return {
        view: GRAPH,
      }
    }

    return {
      view: typeof queryConfigs[activeQueryIndex].rawText === 'string' ? TABLE : GRAPH,
    }
  },

  componentWillReceiveProps(nextProps) {
    const {queryConfigs, activeQueryIndex} = nextProps
    if (!queryConfigs.length || activeQueryIndex === null || activeQueryIndex === this.props.activeQueryIndex) {
      return
    }

    const activeQuery = queryConfigs[activeQueryIndex]
    if (activeQuery && typeof activeQuery.rawText === 'string') {
      return this.setState({view: TABLE})
    }
  },

  handleToggleView(view) {
    this.setState({view})
  },

  render() {
    const {queryConfigs, timeRange, height, heightPixels, onEditRawStatus, activeQueryIndex} = this.props
    const {source} = this.context
    const proxyLink = source.links.proxy
    const {view} = this.state

    const statements = queryConfigs.map((query) => {
      const text = query.rawText || buildInfluxQLQuery(timeRange, query)
      return {text, id: query.id}
    })
    const queries = statements.filter((s) => s.text !== null).map((s) => {
      return {host: [proxyLink], text: s.text, id: s.id}
    })

    return (

        <VisHeader views={VIEWS} view={view} onToggleView={this.handleToggleView} name={name || 'Graph'}/>

          {this.renderVisualization(view, queries, heightPixels, onEditRawStatus, activeQueryIndex)}

    )
  },

  renderVisualization(view, queries, heightPixels, onEditRawStatus, activeQueryIndex) {
    const activeQuery = queries[activeQueryIndex]
    const defaultQuery = queries[0]
    const q = activeQuery || defaultQuery

    switch (view) {
      case TABLE:
        return (q ?
 :
Enter your query below
)
      case GRAPH:
      default:
        this.renderGraph(queries)
    }
  },

  renderGraph(queries) {
    const {cellType, autoRefresh, activeQueryIndex} = this.props
    const isInDataExplorer = true

    if (cellType === 'single-stat') {
      return <RefreshingSingleStat queries={[queries[0]]} autoRefresh={autoRefresh} />
    }

    const displayOptions = {
      stepPlot: cellType === 'line-stepplot',
      stackedGraph: cellType === 'line-stacked',
    }
    return (
      <RefreshingLineGraph
        queries={queries}
        autoRefresh={autoRefresh}
        activeQueryIndex={activeQueryIndex}
        isInDataExplorer={isInDataExplorer}
        showSingleStat={cellType === "line-plus-single-stat"}
        displayOptions={displayOptions}
      />
    )
  },
})

export default Visualization
<|endoftext|>


<commit_before>/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */

'use strict';

/* Benchmarks can automatically be created from the django command line
 * using the following command (deprecated):
 *
 * python manage.py makebenchmarks <script_id ...>
 *
 * Steps to benchmarking:
 *
 * 1) Record and save script 'foo'.
 * 2) Run learning and benchmarks on script.
 *
 *    runSynthesizeBenchmarksLoop(names, numRuns)
 */

/* Paramaterizable, but should only need to use singleton object */
var Benchmarker = (function BenchmarkerClosure() {
  var log = getLog('benchmark');

  function Benchmarker(ports, record, scriptServer, controller) {
    this.ports = ports;
    this.record = record;
    this.scriptServer = scriptServer;
    this.controller = controller;
  }

  Benchmarker.prototype = {
    resetParams: function _resetParams() {
      params = jQuery.extend(true, {}, defaultParams);
      this.updateParams();
    },
    updateParams: function _updateParams() {
      this.controller.updateParams();
    },
    getBenchmarks: function _getBenchmarks(cont) {
      var scriptServer = this.scriptServer;
      scriptServer.getBenchmarks(function(benchmarks) {
        return cont(null, benchmarks)
      });
    },
    getBenchmarkByName: function _getBenchmarkByName(name, cont) {
      this.getBenchmarks(function(err, benchmarks) {
        if (err)
          return cont(err, null);

        var filtered = benchmarks.filter(function(b) {
          return benchmark.name == name;
        });

        return cont(null, filtered);
      });
    },
    /* Runs a set of benchmarks
     * @param benchmarks[array] a list of objects, with each object containing
     *     the following fields: benchmark, init, notes
     */
    runBenchmarks: function _runBenchmarks(benchmarks, numRuns, cont) {
      var scriptServer = this.scriptServer;
      var b = this;

      function helper(index) {
        if (index >= benchmarks.length) {
          if (cont)
            return cont(null);
          return;
        }

        var info = benchmarks[index];
        var benchmark = info.benchmark;
        var init = info.init;
        var notes = info.notes;

        b.runBenchmark(benchmark, init, notes, numRuns, function(err) {
          if (err)
            return cont(err);
          helper(index + 1);
        });
      }
      helper(0);
    },
    runBenchmark: function _runBenchmark(benchmark, init, notes, numRuns,
        cont) {
      var b = this;

      if (!notes)
        notes = {};

      this.resetParams();
      // params.replay.eventTimeout = 60;
      params.panel.enableEdit = false;
      params.replay.saveReplay = true;
      params.replay.defaultWaitNewTab = 100;
      params.replay.defaultWaitNextEvent = 100;
      params.replay.snapshot = true;
      params.logging.saved = false;
      params.logging.level = 4;

      if (init)
        init();

      this.updateParams();
      this.controller.clearMessages();

      scriptServer.getScript(benchmark.script.id, function(err, script) {
        log.debug('Starting benchmark:', benchmark.script.id, events);

        function replayOnce(pastRuns) {
          if (pastRuns >= numRuns) {
            if (cont)
              cont(null);
            return;
          }

          var timeoutId = -1;

          /* save a file indicating that the benchmark started */
          saveText(notes, benchmark.name);

          var r = b.controller.replayScript(script.events,
              {scriptId: script.id}, function(replay) {
            clearTimeout(timeoutId);

            /* remove all the tabs created during execution */
            var events = replay.record.events;
            var allTabs = [];
            for (var i = 0, ii = events.length; i < ii; ++i) {
              var e = events[i];
              var tab = "";
              /* tabs from DOM events */
              if (e.frame && e.frame.tab)
                tab = e.frame.tab;
              /* tabs from web requests */
              if (e.data && e.data.tabId)
                tab = e.data.tabId;

              if (tab && allTabs.indexOf(tab) < 0)
                allTabs.push(tab);
            }

            /* Remove all tabs seen during demonstration */
            for (var i = 0, ii = allTabs.length; i < ii; ++i) {
              var tabId = parseInt(allTabs[i]);
              if (tabId >= 0) {
                chrome.tabs.get(tabId, function(tabInfo) {
                  if (chrome.runtime.lastError)
                    log.info('Tab does not exists');
                  else
                    chrome.tabs.remove(tabId);
                });
              }
            }

            /* Check if captures match */
            var rcaptures = benchmark.successCaptures;
            var captures = replay.captures;

            var correctCaptures = [];
            for (var i = 0, ii = rcaptures.length; i < ii; ++i) {
              if (i < captures.length) {
                var c = rcaptures[i].trim() == captures[i].trim();
                correctCaptures.push({
                    correct: rcaptures[i],
                    actual: captures[i],
                    match: c
                });
              } else {
                correctCaptures.push({
                  correct: rcaptures[i],
                  actual: '',
                  match: false
                });
              }
            }

            /* define success as capturing the correct text */
            // var success = replay.events.length == replay.index;
            var success = true;
            for (var i = 0, ii = correctCaptures.length; i < ii; ++i) {
              if (!correctCaptures[i].match)
                success = false;
            }

            var time = replay.time;
            var error = replay.errorMsg;

            saveText("", JSON.stringify(success));

            log.debug('Finished benchmark');
            scriptServer.saveBenchmarkRun(benchmark.id, success, replay.index,
                replay.events.length, time, notes, correctCaptures, error);

            replayOnce(pastRuns + 1);
          });

          controller.replay = r;

          // kill script after timeout period
          timeoutId = setTimeout(function() {
            r.finish();
          }, params.benchmark.timeout * 1000);
        }
        replayOnce(0);
      });
    }
  };

  return Benchmarker;
})();

/* singleton object */
var b = new Benchmarker(ports, record, scriptServer, controller);

/* set of benchmarks for the paper */
var paperBenchmarks = ['allrecipes','gmail','drugs','goodreads','google translate','myfitnesspal','thesaurus','xe','yahoo finance','yelp','zillow','mapquest','google','opentable','target','walmart','facebook','booking','expedia','hotels','southwest','trip advisor'];

function runAllBenchmarks(numRuns) {
  b.getBenchmarks(function(err, matches) {
    var benchmarks = [];
    for (var i = 0, ii = matches.length; i < ii; ++i) {
      benchmarks.push({benchmark: matches[i]});
    }
    b.runBenchmarks(benchmarks, numRuns)
  });
}

function runBenchmark(name, numRuns) {
  b.getBenchmarkByName(name, function(err, matches) {
    if (matches.length > 0) {
      var benchmark = matches[0];
      var benchmarks = [];
      benchmarks.push({benchmark: benchmark});
      b.runBenchmarks(benchmarks, numRuns);
    }
  });
}

function makeSynthesizedBenchmarks(name, callback) {
  scriptServer.getScripts(name, function(err, scripts) {
    var whitelist = ['original', 'original-nowait', 'original-triggers',
                     'initial-triggers', 'final', 'final-triggers'];

    var numBenchmarks = 0;
    for (var i = 0, ii = scripts.length; i < ii; ++i) {
      /* create local scope */
      (function() {
        var s = scripts[i];
        var notes = JSON.parse(s.notes);
        /* find scripts that contain whitelisted type, and are not replays */
        if (whitelist.indexOf(notes.state) >= 0 && !notes.replay) {
          numBenchmarks += 1;
          scriptServer.getScript(s.id, function(err, script) {
            var captures = script.events.filter(function(e) {
              return e.type == "capture";
            });

            var success = captures.map(function(c) {
              return c.target.snapshot.prop.innerText;
            });

            scriptServer.saveBenchmark(s.name + '-' + notes.state, s.id,
                success, true, callbackReady);
          });
        }
      })();
    }

    /* if no benchmarks matched, then immediately return to callback */
    if (numBenchmarks == 0)
      return callback(null, []);

    var ids = [];
    function callbackReady(id) {
      ids.push(id);
      if (callback && ids.length == numBenchmarks)
        return callback(null, ids);
    }
  });
}

function runSynthesizeBenchmarkLoop(names, numRuns) {
  function helper(index) {
    if (index >= names.length)
      return;

    runSynthesizeBenchmark(names[index], numRuns, function(err) {
      if (err)
        log.error('Error in runSynthesizeBenchmarkLoop:', err);
      helper(index + 1);
    });
  }
  helper(0);
}

function runSynthesizeBenchmark(name, numRuns, cont) {
  synthesizeTriggers(name, function(err, timestampName) {
    scriptServer.finishedProcessing(function() {
      makeSynthesizedBenchmarks(timestampName, function(err, benchmarkIds) {
        log.log(benchmarkIds);
        scriptServer.finishedProcessing(function() {
          b.getBenchmarks(function(err, benchmarks) {
            benchmarks = benchmarks.filter(function(b) {
              return benchmarkIds.indexOf(b.id) >= 0;
            });
            benchmarks =  benchmarks.map(function(b) {
              return {benchmark: b};
            });
            log.log(benchmarks);
            b.runBenchmarks(benchmarks, numRuns, cont)
          });
        });
      });
    });
  });
}

<commit_msg>Fixed but with closure<commit_after>/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */

'use strict';

/* Benchmarks can automatically be created from the django command line
 * using the following command (deprecated):
 *
 * python manage.py makebenchmarks <script_id ...>
 *
 * Steps to benchmarking:
 *
 * 1) Record and save script 'foo'.
 * 2) Run learning and benchmarks on script.
 *
 *    runSynthesizeBenchmarksLoop(names, numRuns)
 */

/* Paramaterizable, but should only need to use singleton object */
var Benchmarker = (function BenchmarkerClosure() {
  var log = getLog('benchmark');

  function Benchmarker(ports, record, scriptServer, controller) {
    this.ports = ports;
    this.record = record;
    this.scriptServer = scriptServer;
    this.controller = controller;
  }

  Benchmarker.prototype = {
    resetParams: function _resetParams() {
      params = jQuery.extend(true, {}, defaultParams);
      this.updateParams();
    },
    updateParams: function _updateParams() {
      this.controller.updateParams();
    },
    getBenchmarks: function _getBenchmarks(cont) {
      var scriptServer = this.scriptServer;
      scriptServer.getBenchmarks(function(benchmarks) {
        return cont(null, benchmarks)
      });
    },
    getBenchmarkByName: function _getBenchmarkByName(name, cont) {
      this.getBenchmarks(function(err, benchmarks) {
        if (err)
          return cont(err, null);

        var filtered = benchmarks.filter(function(b) {
          return b.name == name;
        });

        return cont(null, filtered);
      });
    },
    /* Runs a set of benchmarks
     * @param benchmarks[array] a list of objects, with each object containing
     *     the following fields: benchmark, init, notes
     */
    runBenchmarks: function _runBenchmarks(benchmarks, numRuns, cont) {
      var scriptServer = this.scriptServer;
      var b = this;

      function helper(index) {
        if (index >= benchmarks.length) {
          if (cont)
            return cont(null);
          return;
        }

        var info = benchmarks[index];
        var benchmark = info.benchmark;
        var init = info.init;
        var notes = info.notes;

        b.runBenchmark(benchmark, init, notes, numRuns, function(err) {
          if (err)
            return cont(err);
          helper(index + 1);
        });
      }
      helper(0);
    },
    runBenchmark: function _runBenchmark(benchmark, init, notes, numRuns,
        cont) {
      var b = this;

      if (!notes)
        notes = {};

      this.resetParams();
      // params.replay.eventTimeout = 60;
      params.panel.enableEdit = false;
      params.replay.saveReplay = true;
      params.replay.defaultWaitNewTab = 100;
      params.replay.defaultWaitNextEvent = 100;
      params.replay.snapshot = true;
      params.logging.saved = false;
      params.logging.level = 4;

      if (init)
        init();

      this.updateParams();
      this.controller.clearMessages();

      scriptServer.getScript(benchmark.script.id, function(err, script) {
        log.debug('Starting benchmark:', benchmark.script.id, events);

        function replayOnce(pastRuns) {
          if (pastRuns >= numRuns) {
            if (cont)
              cont(null);
            return;
          }

          var timeoutId = -1;

          /* save a file indicating that the benchmark started */
          saveText(notes, benchmark.name);

          var r = b.controller.replayScript(script.events,
              {scriptId: script.id}, function(replay) {
            clearTimeout(timeoutId);

            /* remove all the tabs created during execution */
            var events = replay.record.events;
            var allTabs = [];
            for (var i = 0, ii = events.length; i < ii; ++i) {
              var e = events[i];
              var tab = "";
              /* tabs from DOM events */
              if (e.frame && e.frame.tab)
                tab = e.frame.tab;
              /* tabs from web requests */
              if (e.data && e.data.tabId)
                tab = e.data.tabId;

              if (tab && allTabs.indexOf(tab) < 0)
                allTabs.push(tab);
            }

            /* Remove all tabs seen during demonstration */
            for (var i = 0, ii = allTabs.length; i < ii; ++i) {
              var tabId = parseInt(allTabs[i]);
              if (tabId >= 0) {
                chrome.tabs.get(tabId, function(tabInfo) {
                  if (chrome.runtime.lastError)
                    log.info('Tab does not exists');
                  else
                    chrome.tabs.remove(tabId);
                });
              }
            }

            /* Check if captures match */
            var rcaptures = benchmark.successCaptures;
            var captures = replay.captures;

            var correctCaptures = [];
            for (var i = 0, ii = rcaptures.length; i < ii; ++i) {
              if (i < captures.length) {
                var c = rcaptures[i].trim() == captures[i].trim();
                correctCaptures.push({
                    correct: rcaptures[i],
                    actual: captures[i],
                    match: c
                });
              } else {
                correctCaptures.push({
                  correct: rcaptures[i],
                  actual: '',
                  match: false
                });
              }
            }

            /* define success as capturing the correct text */
            // var success = replay.events.length == replay.index;
            var success = true;
            for (var i = 0, ii = correctCaptures.length; i < ii; ++i) {
              if (!correctCaptures[i].match)
                success = false;
            }

            var time = replay.time;
            var error = replay.errorMsg;

            saveText("", JSON.stringify(success));

            log.debug('Finished benchmark');
            scriptServer.saveBenchmarkRun(benchmark.id, success, replay.index,
                replay.events.length, time, notes, correctCaptures, error);

            replayOnce(pastRuns + 1);
          });

          controller.replay = r;

          // kill script after timeout period
          timeoutId = setTimeout(function() {
            r.finish();
          }, params.benchmark.timeout * 1000);
        }
        replayOnce(0);
      });
    }
  };

  return Benchmarker;
})();

/* singleton object */
var b = new Benchmarker(ports, record, scriptServer, controller);

/* set of benchmarks for the paper */
var paperBenchmarks = ['allrecipes','gmail','drugs','goodreads','google translate','myfitnesspal','thesaurus','xe','yahoo finance','yelp','zillow','mapquest','google','opentable','target','walmart','facebook','booking','expedia','hotels','southwest','trip advisor'];

function runAllBenchmarks(numRuns) {
  b.getBenchmarks(function(err, matches) {
    var benchmarks = [];
    for (var i = 0, ii = matches.length; i < ii; ++i) {
      benchmarks.push({benchmark: matches[i]});
    }
    b.runBenchmarks(benchmarks, numRuns)
  });
}

function runBenchmark(name, numRuns) {
  b.getBenchmarkByName(name, function(err, matches) {
    if (matches.length > 0) {
      var benchmark = matches[0];
      var benchmarks = [];
      benchmarks.push({benchmark: benchmark});
      b.runBenchmarks(benchmarks, numRuns);
    }
  });
}

function makeSynthesizedBenchmarks(name, callback) {
  scriptServer.getScripts(name, function(err, scripts) {
    var whitelist = ['original', 'original-nowait', 'original-triggers',
                     'initial-triggers', 'final', 'final-triggers'];

    var numBenchmarks = 0;
    for (var i = 0, ii = scripts.length; i < ii; ++i) {
      /* create local scope */
      (function() {
        var s = scripts[i];
        var notes = JSON.parse(s.notes);
        /* find scripts that contain whitelisted type, and are not replays */
        if (whitelist.indexOf(notes.state) >= 0 && !notes.replay) {
          numBenchmarks += 1;
          scriptServer.getScript(s.id, function(err, script) {
            var captures = script.events.filter(function(e) {
              return e.type == "capture";
            });

            var success = captures.map(function(c) {
              return c.target.snapshot.prop.innerText;
            });

            scriptServer.saveBenchmark(s.name + '-' + notes.state, s.id,
                success, true, callbackReady);
          });
        }
      })();
    }

    /* if no benchmarks matched, then immediately return to callback */
    if (numBenchmarks == 0)
      return callback(null, []);

    var ids = [];
    function callbackReady(id) {
      ids.push(id);
      if (callback && ids.length == numBenchmarks)
        return callback(null, ids);
    }
  });
}

function runSynthesizeBenchmarkLoop(names, numRuns) {
  function helper(index) {
    if (index >= names.length)
      return;

    runSynthesizeBenchmark(names[index], numRuns, function(err) {
      if (err)
        log.error('Error in runSynthesizeBenchmarkLoop:', err);
      helper(index + 1);
    });
  }
  helper(0);
}

function runSynthesizeBenchmark(name, numRuns, cont) {
  synthesizeTriggers(name, function(err, timestampName) {
    scriptServer.finishedProcessing(function() {
      makeSynthesizedBenchmarks(timestampName, function(err, benchmarkIds) {
        log.log(benchmarkIds);
        scriptServer.finishedProcessing(function() {
          b.getBenchmarks(function(err, benchmarks) {
            benchmarks = benchmarks.filter(function(b) {
              return benchmarkIds.indexOf(b.id) >= 0;
            });
            benchmarks =  benchmarks.map(function(b) {
              return {benchmark: b};
            });
            log.log(benchmarks);
            b.runBenchmarks(benchmarks, numRuns, cont)
          });
        });
      });
    });
  });
}

<|endoftext|>


<commit_before>window.PhyloTree = {

    PhyloTree: function(treeString) {
        //console.log("new PhyloTree for: " + treeString);
        var leafCount = 0;
        var jsonTree;
        if(treeString[0] == "(" ){
            console.log("tree looks like newick");
            jsonTree = newickToJSON(treeString);
        } else {
            jsonTree = eval("("+treeString+")");
            finalizeTree(jsonTree);
        }

        this.getJSONTree = function() {
            return jsonTree;
        }

        this.getLeafCount = function() {
            return leafCount;
        }

        this.getTipCount = function() {

        }

        this.getTipLabels = function() {
            var tipLabels = new Array();
            visit(this.getJSONTree(), function(node) {
                if(!node.c || node.c.length == 0) {
                    tipLabels.push(node.n);
                }
            });
            return tipLabels;
        }

        function visit(parent, visitFn, childrenFn) {
            if (!parent) return;

            visitFn(parent);

            var children = childrenFn ? childrenFn(parent) : parent.c;
            if (children) {
                var count = children.length;
                for (var i = 0; i < count; i++) {
                    visit(children[i], visitFn, childrenFn);
                }
            }
        }

        function newickToJSON_biojs (s) {
            var ancestors = [];
            var tree = {};
            var tokens = s.split(/\s*(;|\(|\)|,|:)\s*/);
            for (var i=0; i<tokens.length; i++) {
                var token = tokens[i];
                switch (token) {
                    case '(': // new children
                        var subtree = {};
                        tree.c = [subtree];
                        ancestors.push(tree);
                        tree = subtree;
                        break;
                    case ',': // another branch
                        var subtree = {};
                        ancestors[ancestors.length-1].c.push(subtree);
                        tree = subtree;
                        break;
                    case ')': // optional name next
                        tree = ancestors.pop();
                        break;
                    case ':': // optional length next
                        break;
                    default:
                        var x = tokens[i-1];
                        if (x == ')' || x == '(' || x == ',') {
                            tree.s = parseInt(token);
                        } else if (x == ':') {
                            tree.l = parseFloat(token);
                        }
                }
            }
            finalizeTree(tree);
            return tree;
        }

        function newickToJSON(nwk) {
            var commaProtect = "&&";
            nwk=nwk.trim();
            if(nwk.substr(-1) != ";"){
                nwk=nwk+";";
            }
            nwk = nwk.replace(/;/, "}")
                .replace(/\=/g,"")
                .replace(/\'/g,"")
                .replace(/\#/g,"")
                .replace(/\)$/g, "}]}")
                .replace(/,([\w+\|\.\/-]+)/g, ",\"n\":\"$1\"")
                .replace(/\(([\w+\|\.\/-]+)/g, "\(\"n\":\"$1\"")
                .replace(/^\(/, "{\"c\":[{")
                .replace(/:([-+]?[0-9]*\.?[0-9]+)/g, commaProtect + "\"l\":$1")
                .replace(/\)(\d*)/g, ")" + commaProtect + "\"s\":$1")
                .replace(/&&\"s\":&&/g, "&&\"s\":0&&")
                .replace(/\(/g, "\"c\":[{")
                .replace(/\)/g, "}]")
                .replace(/,/g, "},{")
                .replace(/\"s\":\}/,"\"s\":0}")
                .replace(/&&/g, ",");
    //            .replace(/^\{\"c\"\:\[\{([\w+\.\/-]+)/,"{\"c\":[{\"n\":\"$1\"");
            console.log("tree json string: " + nwk);
            var r = JSON.parse(nwk);
            r.labels=[{}]; //list of objects that map node id to label
            finalizeTree(r);
            return r;
        }

        function setInternalNodeYs(node) {
            var r = 0;
            if(node.c) {
                var childYSum = 0;
                node.c.forEach(function(child){
                    childYSum += setInternalNodeYs(child)
                });
                r = childYSum / node.c.length;
                node.py = r;
            } else {
                r = node.py;
            }

            return r;
        }

        function setNodeMaxStepsToTip(node) {
            var r = 0;
            if(node.c) {
                var maxChildSteps = 0;
                node.c.forEach(function(child){
                    maxChildSteps = Math.max(maxChildSteps, setNodeMaxStepsToTip(child));
                });
                r = maxChildSteps +1;
                node.cx = r;
            } else {
                r = 0;
                node.cx = 0;
            }

            return r;
        }

        function countNodeDescendants(node) {
            var r = 0;
            if(node.c) {
                node.c.forEach(function(child){
                    r += countNodeDescendants(child)
                });
                node.d = r;
            } else {
                r = 1;
                node.d = 0;
            }

            return r;
        }

        function finalizeTree(tree){
            var tipIndex = 0;
            countNodeDescendants(tree);
            var nodeId = 0;
            tree.px = 0;
            visit(tree,
                function(node){
                    var tmp_label=[];
                    if(!node.c && node.n) {
                        //try to parse out the genus and species name
                        node.id = node.n;
                        node.n = node.n.replace(/_/g, " ");
                        var fields = node.n.split(" ");
                        var genusIndex = 0;
                        if(fields[0] == "Candidatus") {
                            genusIndex++;
                            node.prefix = fields[0];
                        }
                        node.genus = fields[genusIndex];
                        var species = fields[genusIndex+1];
                        node.species = species ? species : "";
                        for(var i = 2; genusIndex+i < fields.length; i++) {
                            species = species + " " + fields[genusIndex+i]
                        }
                        node.species_strain = species ? species: "";
                        tmp_label.push(node.genus);
                        tmp_label.push(node.species_strain);
                    } else {
                        node.id="inode"+nodeId;
                        node.n = ""+nodeId;
                    }
                    if(node.c) {
                        node.c.forEach(function(child){
                            child.parent = node;
                            if(child.l || child.l == 0) {
                                child.px = node.px + child.l + .01;
                            }
                        });

                        node.c.sort(function(a,b){
                            return b.d - a.d;
                        });
                    } else {
                        node.label = tmp_label.join(" ");
                        tree.labels[0][node.id]=node.label;
                        leafCount++;
                        node.ti = tipIndex++;
                        node.py = node.ti;
                    }
                    nodeId++;
                },

                function(node){
                    var r = node.c ? node.c : null;
                    return r;
                 });
            setInternalNodeYs(tree);
            setNodeMaxStepsToTip(tree);
        }

    }

}

<commit_msg>bump spacing<commit_after>window.PhyloTree = {

    PhyloTree: function(treeString) {
        //console.log("new PhyloTree for: " + treeString);
        var leafCount = 0;
        var jsonTree;
        if(treeString[0] == "(" ){
            console.log("tree looks like newick");
            jsonTree = newickToJSON(treeString);
        } else {
            jsonTree = eval("("+treeString+")");
            finalizeTree(jsonTree);
        }

        this.getJSONTree = function() {
            return jsonTree;
        }

        this.getLeafCount = function() {
            return leafCount;
        }

        this.getTipCount = function() {

        }

        this.getTipLabels = function() {
            var tipLabels = new Array();
            visit(this.getJSONTree(), function(node) {
                if(!node.c || node.c.length == 0) {
                    tipLabels.push(node.n);
                }
            });
            return tipLabels;
        }

        function visit(parent, visitFn, childrenFn) {
            if (!parent) return;

            visitFn(parent);

            var children = childrenFn ? childrenFn(parent) : parent.c;
            if (children) {
                var count = children.length;
                for (var i = 0; i < count; i++) {
                    visit(children[i], visitFn, childrenFn);
                }
            }
        }

        function newickToJSON_biojs (s) {
            var ancestors = [];
            var tree = {};
            var tokens = s.split(/\s*(;|\(|\)|,|:)\s*/);
            for (var i=0; i<tokens.length; i++) {
                var token = tokens[i];
                switch (token) {
                    case '(': // new children
                        var subtree = {};
                        tree.c = [subtree];
                        ancestors.push(tree);
                        tree = subtree;
                        break;
                    case ',': // another branch
                        var subtree = {};
                        ancestors[ancestors.length-1].c.push(subtree);
                        tree = subtree;
                        break;
                    case ')': // optional name next
                        tree = ancestors.pop();
                        break;
                    case ':': // optional length next
                        break;
                    default:
                        var x = tokens[i-1];
                        if (x == ')' || x == '(' || x == ',') {
                            tree.s = parseInt(token);
                        } else if (x == ':') {
                            tree.l = parseFloat(token);
                        }
                }
            }
            finalizeTree(tree);
            return tree;
        }

        function newickToJSON(nwk) {
            var commaProtect = "&&";
            nwk=nwk.trim();
            if(nwk.substr(-1) != ";"){
                nwk=nwk+";";
            }
            nwk = nwk.replace(/;/, "}")
                .replace(/\=/g,"")
                .replace(/\'/g,"")
                .replace(/\#/g,"")
                .replace(/\)$/g, "}]}")
                .replace(/,([\w+\|\.\/-]+)/g, ",\"n\":\"$1\"")
                .replace(/\(([\w+\|\.\/-]+)/g, "\(\"n\":\"$1\"")
                .replace(/^\(/, "{\"c\":[{")
                .replace(/:([-+]?[0-9]*\.?[0-9]+)/g, commaProtect + "\"l\":$1")
                .replace(/\)(\d*)/g, ")" + commaProtect + "\"s\":$1")
                .replace(/&&\"s\":&&/g, "&&\"s\":0&&")
                .replace(/\(/g, "\"c\":[{")
                .replace(/\)/g, "}]")
                .replace(/,/g, "},{")
                .replace(/\"s\":\}/,"\"s\":0}")
                .replace(/&&/g, ",");
    //            .replace(/^\{\"c\"\:\[\{([\w+\.\/-]+)/,"{\"c\":[{\"n\":\"$1\"");
            console.log("tree json string: " + nwk);
            var r = JSON.parse(nwk);
            r.labels=[{}]; //list of objects that map node id to label
            finalizeTree(r);
            return r;
        }

        function setInternalNodeYs(node) {
            var r = 0;
            if(node.c) {
                var childYSum = 0;
                node.c.forEach(function(child){
                    childYSum += setInternalNodeYs(child)
                });
                r = childYSum / node.c.length;
                node.py = r;
            } else {
                r = node.py;
            }

            return r;
        }

        function setNodeMaxStepsToTip(node) {
            var r = 0;
            if(node.c) {
                var maxChildSteps = 0;
                node.c.forEach(function(child){
                    maxChildSteps = Math.max(maxChildSteps, setNodeMaxStepsToTip(child));
                });
                r = maxChildSteps +1;
                node.cx = r;
            } else {
                r = 0;
                node.cx = 0;
            }

            return r;
        }

        function countNodeDescendants(node) {
            var r = 0;
            if(node.c) {
                node.c.forEach(function(child){
                    r += countNodeDescendants(child)
                });
                node.d = r;
            } else {
                r = 1;
                node.d = 0;
            }

            return r;
        }

        function finalizeTree(tree){
            var tipIndex = 0;
            countNodeDescendants(tree);
            var nodeId = 0;
            tree.px = 0;
            visit(tree,
                function(node){
                    var tmp_label=[];
                    if(!node.c && node.n) {
                        //try to parse out the genus and species name
                        node.id = node.n;
                        node.n = node.n.replace(/_/g, " ");
                        var fields = node.n.split(" ");
                        var genusIndex = 0;
                        if(fields[0] == "Candidatus") {
                            genusIndex++;
                            node.prefix = fields[0];
                        }
                        node.genus = fields[genusIndex];
                        var species = fields[genusIndex+1];
                        node.species = species ? species : "";
                        for(var i = 2; genusIndex+i < fields.length; i++) {
                            species = species + " " + fields[genusIndex+i]
                        }
                        node.species_strain = species ? species: "";
                        tmp_label.push(node.genus);
                        tmp_label.push(node.species_strain);
                    } else {
                        node.id="inode"+nodeId;
                        node.n = ""+nodeId;
                    }
                    if(node.c) {
                        node.c.forEach(function(child){
                            child.parent = node;
                            if(child.l || child.l == 0) {
                                child.px = node.px + child.l + .012;
                            }
                        });

                        node.c.sort(function(a,b){
                            return b.d - a.d;
                        });
                    } else {
                        node.label = tmp_label.join(" ");
                        tree.labels[0][node.id]=node.label;
                        leafCount++;
                        node.ti = tipIndex++;
                        node.py = node.ti;
                    }
                    nodeId++;
                },

                function(node){
                    var r = node.c ? node.c : null;
                    return r;
                 });
            setInternalNodeYs(tree);
            setNodeMaxStepsToTip(tree);
        }

    }

}

<|endoftext|>


<commit_before>/**
 * Copyright IBM Corp. 2016, 2018
 *
 * This source code is licensed under the Apache-2.0 license found in the
 * LICENSE file in the root directory of this source tree.
 */

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { isForwardRef } from 'react-is';
import debounce from 'lodash.debounce';
import classNames from 'classnames';
import Information from '@carbon/icons-react/lib/information/16';
import { settings } from 'carbon-components';
import FloatingMenu, {
  DIRECTION_LEFT,
  DIRECTION_TOP,
  DIRECTION_RIGHT,
  DIRECTION_BOTTOM,
} from '../../internal/FloatingMenu';
import ClickListener from '../../internal/ClickListener';
import mergeRefs from '../../tools/mergeRefs';
import { keys, keyCodes, matches as keyDownMatch } from '../../tools/key';
import isRequiredOneOf from '../../prop-types/isRequiredOneOf';

const { prefix } = settings;

/**
 * @param {Element} menuBody The menu body with the menu arrow.
 * @param {string} menuDirection Where the floating menu menu should be placed relative to the trigger button.
 * @returns {FloatingMenu~offset} The adjustment of the floating menu position, upon the position of the menu arrow.
 * @private
 */
const getMenuOffset = (menuBody, menuDirection) => {
  const arrowStyle = menuBody.ownerDocument.defaultView.getComputedStyle(
    menuBody,
    ':before'
  );
  const arrowPositionProp = {
    [DIRECTION_LEFT]: 'right',
    [DIRECTION_TOP]: 'bottom',
    [DIRECTION_RIGHT]: 'left',
    [DIRECTION_BOTTOM]: 'top',
  }[menuDirection];
  const menuPositionAdjustmentProp = {
    [DIRECTION_LEFT]: 'left',
    [DIRECTION_TOP]: 'top',
    [DIRECTION_RIGHT]: 'left',
    [DIRECTION_BOTTOM]: 'top',
  }[menuDirection];
  const values = [arrowPositionProp, 'border-bottom-width'].reduce(
    (o, name) => ({
      ...o,
      [name]: Number(
        (/^([\d-]+)px$/.exec(arrowStyle.getPropertyValue(name)) || [])[1]
      ),
    }),
    {}
  );
  values[arrowPositionProp] = values[arrowPositionProp] || -6; // IE, etc.
  if (Object.keys(values).every(name => !isNaN(values[name]))) {
    const {
      [arrowPositionProp]: arrowPosition,
      'border-bottom-width': borderBottomWidth,
    } = values;
    return {
      left: 0,
      top: 0,
      [menuPositionAdjustmentProp]:
        Math.sqrt(Math.pow(borderBottomWidth, 2) * 2) - arrowPosition,
    };
  }
};

class Tooltip extends Component {
  state = {};

  static propTypes = {
    /**
     * The ID of the trigger button.
     */
    triggerId: PropTypes.string,

    /**
     * The ID of the tooltip content.
     */
    tooltipId: PropTypes.string,

    /**
     * Open/closed state.
     */
    open: PropTypes.bool,

    /**
     * Contents to put into the tooltip.
     */
    children: PropTypes.node,

    /**
     * The CSS class names of the tooltip.
     */
    className: PropTypes.string,

    /**
     * The CSS class names of the trigger UI.
     */
    triggerClassName: PropTypes.string,

    /**
     * Where to put the tooltip, relative to the trigger UI.
     */
    direction: PropTypes.oneOf(['bottom', 'top', 'left', 'right']),

    /**
     * The adjustment of the tooltip position.
     */
    menuOffset: PropTypes.oneOfType([
      PropTypes.shape({
        top: PropTypes.number,
        left: PropTypes.number,
      }),
      PropTypes.func,
    ]),

    /**
     * The callback function to optionally render the icon element.
     * It should be a component with React.forwardRef().
     */
    renderIcon: function(props, propName, componentName) {
      if (props[propName] == undefined) {
        return;
      }
      const RefForwardingComponent = props[propName];
      if (!isForwardRef(<RefForwardingComponent />))
        return new Error(`Invalid value of prop '${propName}' supplied to '${componentName}',
                          it should be created/wrapped with React.forwardRef() to have a ref and access the proper
                          DOM node of the element to calculate its position in the viewport.`);
    },

    /**
     * `true` to show the default tooltip icon.
     */
    showIcon: PropTypes.bool,

    /**
     * The name of the default tooltip icon.
     */
    iconName: PropTypes.string,

    ...isRequiredOneOf({
      /**
       * The content to put into the trigger UI, except the (default) tooltip icon.
       */
      triggerText: PropTypes.node,
      /**
       * The description of the default tooltip icon, to be put in its SVG 'aria-label' and 'alt' .
       */
      iconDescription: PropTypes.string,
    }),

    /**
     * Optional prop to specify the tabIndex of the Tooltip
     */
    tabIndex: PropTypes.number,
  };

  static defaultProps = {
    open: false,
    direction: DIRECTION_BOTTOM,
    renderIcon: Information,
    showIcon: true,
    triggerText: null,
    menuOffset: getMenuOffset,
  };

  /**
   * The element of the tooltip body.
   * @type {Element}
   * @private
   */
  _tooltipEl = null;

  componentDidMount() {
    if (!this._debouncedHandleHover) {
      this._debouncedHandleHover = debounce(this._handleHover, 200);
    }
    requestAnimationFrame(() => {
      this.getTriggerPosition();
    });

    document.addEventListener('keydown', this.handleEscKeyPress, false);
  }

  componentWillUnmount() {
    if (this._debouncedHandleHover) {
      this._debouncedHandleHover.cancel();
      this._debouncedHandleHover = null;
    }

    document.removeEventListener('keydown', this.handleEscKeyPress, false);
  }

  static getDerivedStateFromProps({ open }, state) {
    /**
     * so that tooltip can be controlled programmatically through this `open` prop
     */
    const { prevOpen } = state;
    return prevOpen === open
      ? null
      : {
          open,
          prevOpen: open,
        };
  }

  getTriggerPosition = () => {
    if (this.triggerEl) {
      const triggerPosition = this.triggerEl.getBoundingClientRect();
      this.setState({ triggerPosition });
    }
  };

  /**
   * Handles `mouseover`/`mouseout`/`focus`/`blur` event.
   * @param {string} state `over` to show the tooltip, `out` to hide the tooltip.
   * @param {Element} [relatedTarget] For handing `mouseout` event, indicates where the mouse pointer is gone.
   */
  _handleHover = (state, relatedTarget) => {
    if (state === 'over') {
      this.getTriggerPosition();
      this.setState({ open: true });
    } else {
      // Note: SVGElement in IE11 does not have `.contains()`
      const shouldPreventClose =
        relatedTarget &&
        ((this.triggerEl &&
          this.triggerEl.contains &&
          this.triggerEl.contains(relatedTarget)) ||
          (this._tooltipEl && this._tooltipEl.contains(relatedTarget)));
      if (!shouldPreventClose) {
        this.setState({ open: false });
      }
    }
  };

  /**
   * The debounced version of the `mouseover`/`mouseout`/`focus`/`blur` event handler.
   * @type {Function}
   * @private
   */
  _debouncedHandleHover = null;

  /**
   * @returns {Element} The DOM element where the floating menu is placed in.
   */
  _getTarget = () =>
    (this.triggerEl &&
      this.triggerEl.closest('[data-floating-menu-container]')) ||
    document.body;

  handleMouse = evt => {
    if (evt.type === 'click') {
      evt.stopPropagation();
      const shouldOpen = !this.state.open;
      if (shouldOpen) {
        this.getTriggerPosition();
      }
      this.setState({ open: shouldOpen });
    }
  };

  handleClickOutside = evt => {
    const shouldPreventClose =
      evt &&
      evt.target &&
      this._tooltipEl &&
      this._tooltipEl.contains(evt.target);
    if (!shouldPreventClose) {
      this.setState({ open: false });
    }
  };

  handleKeyPress = event => {
    if (keyDownMatch(event, [keys.ESC, keyCodes.ESC, keyCodes.IEESC])) {
      event.stopPropagation();
      this.setState({ open: false });
    }

    if (
      keyDownMatch(event, [
        keys.ENTER,
        keyCodes.ENTER,
        keys.SPACE,
        keyCodes.SPACE,
      ])
    ) {
      event.stopPropagation();
      this.setState({ open: !this.state.open });
    }
  };

  handleEscKeyPress = event => {
    const { open } = this.state;
    if (open && keyDownMatch(event, [keys.ESC, keyCodes.ESC, keyCodes.IEESC])) {
      return this.setState({ open: false });
    }
  };

  render() {
    const {
      triggerId = (this.triggerId =
        this.triggerId ||
        `__carbon-tooltip-trigger_${Math.random()
          .toString(36)
          .substr(2)}`),
      tooltipId = (this.tooltipId =
        this.tooltipId ||
        `__carbon-tooltip_${Math.random()
          .toString(36)
          .substr(2)}`),
      children,
      className,
      triggerClassName,
      direction,
      triggerText,
      showIcon,
      iconName,
      iconDescription,
      renderIcon: IconCustomElement,
      menuOffset,
      tabIndex = 0,
      innerRef: ref,
      ...other
    } = this.props;

    const { open } = this.state;

    const tooltipClasses = classNames(
      `${prefix}--tooltip`,
      { [`${prefix}--tooltip--shown`]: open },
      className
    );

    const triggerClasses = classNames(
      `${prefix}--tooltip__label`,
      triggerClassName
    );

    const refProp = mergeRefs(ref, node => {
      this.triggerEl = node;
    });

    const iconProperties = { name: iconName, role: null, description: null };

    const properties = {
      role: 'button',
      tabIndex: tabIndex,
      onClick: this.handleMouse,
      onKeyDown: this.handleKeyPress,
      onMouseOver: this.handleMouse,
      onMouseOut: this.handleMouse,
      onFocus: this.handleMouse,
      onBlur: this.handleMouse,
      'aria-haspopup': 'true',
      'aria-expanded': open,
      // if the user provides property `triggerText`,
      // then the button should use aria-describedby to point to its id,
      // if the user doesn't provide property `triggerText`,
      // then an aria-label will be provided via the `iconDescription` property.
      ...(triggerText
        ? {
            'aria-describedby': triggerId,
          }
        : {
            'aria-label': iconDescription,
          }),
    };

    return (
      <>
        <ClickListener onClickOutside={this.handleClickOutside}>
          {showIcon ? (

              {triggerText}
              <div className={`${prefix}--tooltip__trigger`} {...properties}>
                <IconCustomElement ref={refProp} {...iconProperties} />

          ) : (

              {triggerText}

          )}
        </ClickListener>
        {open && (
          <FloatingMenu
            target={this._getTarget}
            menuPosition={this.state.triggerPosition}
            menuDirection={direction}
            menuOffset={menuOffset}
            menuRef={node => {
              this._tooltipEl = node;
            }}>

              <span className={`${prefix}--tooltip__caret`} />
              {children}

          </FloatingMenu>
        )}
      </>
    );
  }
}

export default (() => {
  const forwardRef = (props, ref) => <Tooltip {...props} innerRef={ref} />;
  forwardRef.displayName = 'Tooltip';
  return React.forwardRef(forwardRef);
})();
<commit_msg>fix(Tooltip): remove ARIA attribute (#2656)<commit_after>/**
 * Copyright IBM Corp. 2016, 2018
 *
 * This source code is licensed under the Apache-2.0 license found in the
 * LICENSE file in the root directory of this source tree.
 */

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { isForwardRef } from 'react-is';
import debounce from 'lodash.debounce';
import classNames from 'classnames';
import Information from '@carbon/icons-react/lib/information/16';
import { settings } from 'carbon-components';
import FloatingMenu, {
  DIRECTION_LEFT,
  DIRECTION_TOP,
  DIRECTION_RIGHT,
  DIRECTION_BOTTOM,
} from '../../internal/FloatingMenu';
import ClickListener from '../../internal/ClickListener';
import mergeRefs from '../../tools/mergeRefs';
import { keys, keyCodes, matches as keyDownMatch } from '../../tools/key';
import isRequiredOneOf from '../../prop-types/isRequiredOneOf';

const { prefix } = settings;

/**
 * @param {Element} menuBody The menu body with the menu arrow.
 * @param {string} menuDirection Where the floating menu menu should be placed relative to the trigger button.
 * @returns {FloatingMenu~offset} The adjustment of the floating menu position, upon the position of the menu arrow.
 * @private
 */
const getMenuOffset = (menuBody, menuDirection) => {
  const arrowStyle = menuBody.ownerDocument.defaultView.getComputedStyle(
    menuBody,
    ':before'
  );
  const arrowPositionProp = {
    [DIRECTION_LEFT]: 'right',
    [DIRECTION_TOP]: 'bottom',
    [DIRECTION_RIGHT]: 'left',
    [DIRECTION_BOTTOM]: 'top',
  }[menuDirection];
  const menuPositionAdjustmentProp = {
    [DIRECTION_LEFT]: 'left',
    [DIRECTION_TOP]: 'top',
    [DIRECTION_RIGHT]: 'left',
    [DIRECTION_BOTTOM]: 'top',
  }[menuDirection];
  const values = [arrowPositionProp, 'border-bottom-width'].reduce(
    (o, name) => ({
      ...o,
      [name]: Number(
        (/^([\d-]+)px$/.exec(arrowStyle.getPropertyValue(name)) || [])[1]
      ),
    }),
    {}
  );
  values[arrowPositionProp] = values[arrowPositionProp] || -6; // IE, etc.
  if (Object.keys(values).every(name => !isNaN(values[name]))) {
    const {
      [arrowPositionProp]: arrowPosition,
      'border-bottom-width': borderBottomWidth,
    } = values;
    return {
      left: 0,
      top: 0,
      [menuPositionAdjustmentProp]:
        Math.sqrt(Math.pow(borderBottomWidth, 2) * 2) - arrowPosition,
    };
  }
};

class Tooltip extends Component {
  state = {};

  static propTypes = {
    /**
     * The ID of the trigger button.
     */
    triggerId: PropTypes.string,

    /**
     * The ID of the tooltip content.
     */
    tooltipId: PropTypes.string,

    /**
     * Open/closed state.
     */
    open: PropTypes.bool,

    /**
     * Contents to put into the tooltip.
     */
    children: PropTypes.node,

    /**
     * The CSS class names of the tooltip.
     */
    className: PropTypes.string,

    /**
     * The CSS class names of the trigger UI.
     */
    triggerClassName: PropTypes.string,

    /**
     * Where to put the tooltip, relative to the trigger UI.
     */
    direction: PropTypes.oneOf(['bottom', 'top', 'left', 'right']),

    /**
     * The adjustment of the tooltip position.
     */
    menuOffset: PropTypes.oneOfType([
      PropTypes.shape({
        top: PropTypes.number,
        left: PropTypes.number,
      }),
      PropTypes.func,
    ]),

    /**
     * The callback function to optionally render the icon element.
     * It should be a component with React.forwardRef().
     */
    renderIcon: function(props, propName, componentName) {
      if (props[propName] == undefined) {
        return;
      }
      const RefForwardingComponent = props[propName];
      if (!isForwardRef(<RefForwardingComponent />))
        return new Error(`Invalid value of prop '${propName}' supplied to '${componentName}',
                          it should be created/wrapped with React.forwardRef() to have a ref and access the proper
                          DOM node of the element to calculate its position in the viewport.`);
    },

    /**
     * `true` to show the default tooltip icon.
     */
    showIcon: PropTypes.bool,

    /**
     * The name of the default tooltip icon.
     */
    iconName: PropTypes.string,

    ...isRequiredOneOf({
      /**
       * The content to put into the trigger UI, except the (default) tooltip icon.
       */
      triggerText: PropTypes.node,
      /**
       * The description of the default tooltip icon, to be put in its SVG 'aria-label' and 'alt' .
       */
      iconDescription: PropTypes.string,
    }),

    /**
     * Optional prop to specify the tabIndex of the Tooltip
     */
    tabIndex: PropTypes.number,
  };

  static defaultProps = {
    open: false,
    direction: DIRECTION_BOTTOM,
    renderIcon: Information,
    showIcon: true,
    triggerText: null,
    menuOffset: getMenuOffset,
  };

  /**
   * The element of the tooltip body.
   * @type {Element}
   * @private
   */
  _tooltipEl = null;

  componentDidMount() {
    if (!this._debouncedHandleHover) {
      this._debouncedHandleHover = debounce(this._handleHover, 200);
    }
    requestAnimationFrame(() => {
      this.getTriggerPosition();
    });

    document.addEventListener('keydown', this.handleEscKeyPress, false);
  }

  componentWillUnmount() {
    if (this._debouncedHandleHover) {
      this._debouncedHandleHover.cancel();
      this._debouncedHandleHover = null;
    }

    document.removeEventListener('keydown', this.handleEscKeyPress, false);
  }

  static getDerivedStateFromProps({ open }, state) {
    /**
     * so that tooltip can be controlled programmatically through this `open` prop
     */
    const { prevOpen } = state;
    return prevOpen === open
      ? null
      : {
          open,
          prevOpen: open,
        };
  }

  getTriggerPosition = () => {
    if (this.triggerEl) {
      const triggerPosition = this.triggerEl.getBoundingClientRect();
      this.setState({ triggerPosition });
    }
  };

  /**
   * Handles `mouseover`/`mouseout`/`focus`/`blur` event.
   * @param {string} state `over` to show the tooltip, `out` to hide the tooltip.
   * @param {Element} [relatedTarget] For handing `mouseout` event, indicates where the mouse pointer is gone.
   */
  _handleHover = (state, relatedTarget) => {
    if (state === 'over') {
      this.getTriggerPosition();
      this.setState({ open: true });
    } else {
      // Note: SVGElement in IE11 does not have `.contains()`
      const shouldPreventClose =
        relatedTarget &&
        ((this.triggerEl &&
          this.triggerEl.contains &&
          this.triggerEl.contains(relatedTarget)) ||
          (this._tooltipEl && this._tooltipEl.contains(relatedTarget)));
      if (!shouldPreventClose) {
        this.setState({ open: false });
      }
    }
  };

  /**
   * The debounced version of the `mouseover`/`mouseout`/`focus`/`blur` event handler.
   * @type {Function}
   * @private
   */
  _debouncedHandleHover = null;

  /**
   * @returns {Element} The DOM element where the floating menu is placed in.
   */
  _getTarget = () =>
    (this.triggerEl &&
      this.triggerEl.closest('[data-floating-menu-container]')) ||
    document.body;

  handleMouse = evt => {
    if (evt.type === 'click') {
      evt.stopPropagation();
      const shouldOpen = !this.state.open;
      if (shouldOpen) {
        this.getTriggerPosition();
      }
      this.setState({ open: shouldOpen });
    }
  };

  handleClickOutside = evt => {
    const shouldPreventClose =
      evt &&
      evt.target &&
      this._tooltipEl &&
      this._tooltipEl.contains(evt.target);
    if (!shouldPreventClose) {
      this.setState({ open: false });
    }
  };

  handleKeyPress = event => {
    if (keyDownMatch(event, [keys.ESC, keyCodes.ESC, keyCodes.IEESC])) {
      event.stopPropagation();
      this.setState({ open: false });
    }

    if (
      keyDownMatch(event, [
        keys.ENTER,
        keyCodes.ENTER,
        keys.SPACE,
        keyCodes.SPACE,
      ])
    ) {
      event.stopPropagation();
      this.setState({ open: !this.state.open });
    }
  };

  handleEscKeyPress = event => {
    const { open } = this.state;
    if (open && keyDownMatch(event, [keys.ESC, keyCodes.ESC, keyCodes.IEESC])) {
      return this.setState({ open: false });
    }
  };

  render() {
    const {
      triggerId = (this.triggerId =
        this.triggerId ||
        `__carbon-tooltip-trigger_${Math.random()
          .toString(36)
          .substr(2)}`),
      tooltipId = (this.tooltipId =
        this.tooltipId ||
        `__carbon-tooltip_${Math.random()
          .toString(36)
          .substr(2)}`),
      children,
      className,
      triggerClassName,
      direction,
      triggerText,
      showIcon,
      iconName,
      iconDescription,
      renderIcon: IconCustomElement,
      menuOffset,
      tabIndex = 0,
      innerRef: ref,
      ...other
    } = this.props;

    const { open } = this.state;

    const tooltipClasses = classNames(
      `${prefix}--tooltip`,
      { [`${prefix}--tooltip--shown`]: open },
      className
    );

    const triggerClasses = classNames(
      `${prefix}--tooltip__label`,
      triggerClassName
    );

    const refProp = mergeRefs(ref, node => {
      this.triggerEl = node;
    });

    const iconProperties = { name: iconName, role: null, description: null };

    const properties = {
      role: 'button',
      tabIndex: tabIndex,
      onClick: this.handleMouse,
      onKeyDown: this.handleKeyPress,
      onMouseOver: this.handleMouse,
      onMouseOut: this.handleMouse,
      onFocus: this.handleMouse,
      onBlur: this.handleMouse,
      'aria-haspopup': 'true',
      'aria-expanded': open,
      // if the user provides property `triggerText`,
      // then the button should use aria-describedby to point to its id,
      // if the user doesn't provide property `triggerText`,
      // then an aria-label will be provided via the `iconDescription` property.
      ...(triggerText
        ? {
            'aria-describedby': triggerId,
          }
        : {
            'aria-label': iconDescription,
          }),
    };

    return (
      <>
        <ClickListener onClickOutside={this.handleClickOutside}>
          {showIcon ? (

              {triggerText}
              <div className={`${prefix}--tooltip__trigger`} {...properties}>
                <IconCustomElement ref={refProp} {...iconProperties} />

          ) : (

              {triggerText}

          )}
        </ClickListener>
        {open && (
          <FloatingMenu
            target={this._getTarget}
            menuPosition={this.state.triggerPosition}
            menuDirection={direction}
            menuOffset={menuOffset}
            menuRef={node => {
              this._tooltipEl = node;
            }}>

              <span className={`${prefix}--tooltip__caret`} />
              {children}

          </FloatingMenu>
        )}
      </>
    );
  }
}

export default (() => {
  const forwardRef = (props, ref) => <Tooltip {...props} innerRef={ref} />;
  forwardRef.displayName = 'Tooltip';
  return React.forwardRef(forwardRef);
})();
<|endoftext|>