Skip to content

Commit

Permalink
Selenium IDE Scheduler in one massive commit
Browse files Browse the repository at this point in the history
  • Loading branch information
samitbadle committed Mar 9, 2015
1 parent ccc44e2 commit c8a527c
Show file tree
Hide file tree
Showing 15 changed files with 1,724 additions and 6 deletions.
51 changes: 48 additions & 3 deletions ide/main/src/content/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ function Editor(window) {
this.document = document;
this.recordButton = document.getElementById("record-button");
this.recordMenuItem = document.getElementById("menu_record");
this.scheduleButton = document.getElementById("schedule-button");
this.scheduleMenuItem = document.getElementById("menu_schedule");
this.speedMaxInterval = parseInt(document.getElementById("speedSlider").getAttribute("maxpos"));
this.initMenus();
this.app.initOptions();
Expand Down Expand Up @@ -222,6 +224,9 @@ function Editor(window) {
openTabOrWindow('http://code.google.com/p/selenium/wiki/SeIDEReleaseNotes');
Preferences.setAndSave(this.app.options, 'currentVersion', versionString);
}

this.seleniumScheduler = new SeleniumScheduler(this);
this.scheduler = this.seleniumScheduler.scheduler;
this.log.info("Ready");
this.app.notify('initComplete');
this.health.addEvent('editor', 'initialized');
Expand Down Expand Up @@ -278,6 +283,7 @@ Editor.controller = {
case "cmd_selenium_rollup":
case "cmd_selenium_reload":
case "cmd_selenium_record":
case "cmd_selenium_schedule":
case "cmd_selenium_speed_fastest":
case "cmd_selenium_speed_faster":
case "cmd_selenium_speed_slower":
Expand Down Expand Up @@ -323,7 +329,9 @@ Editor.controller = {
return editor.app.isPlayable() && (editor.selDebugger.state == Debugger.PLAYING || editor.selDebugger.state == Debugger.PAUSED);
case "cmd_selenium_step":
return editor.app.isPlayable() && editor.selDebugger.state == Debugger.PAUSED;
case "cmd_selenium_record":
case "cmd_selenium_record": //TODO base it on scheduler?
return true;
case "cmd_selenium_schedule":
return true;
case "cmd_selenium_speed_fastest":
return editor.getInterval() > 0;
Expand Down Expand Up @@ -412,6 +420,35 @@ Editor.controller = {
case "cmd_selenium_record":
editor.toggleRecordingEnabled();
break;
case "cmd_selenium_schedule":
editor.scheduleButton.checked = !editor.scheduleButton.checked;
if (editor.scheduleButton.checked) {
//TODO hasJobs() is not enough as there may be jobs that are not valid, need hasValidJobs()
if (editor.scheduler.hasJobs()) {
editor.toggleRecordingEnabled(false);
if (editor.scheduler.pendingJobCount() > 0) {
var answer = PromptService.yesNoCancel(Editor.getString('scheduler.runNow.message'), Editor.getString('scheduler.runNow.title'));
if (answer.yes) {
editor.scheduler.start();
} else if (answer.no) {
editor.scheduler.resetNextRun();
editor.scheduler.start();
} else {
//Canceled
editor.scheduleButton.checked = !editor.scheduleButton.checked;
}
} else {
editor.scheduler.start();
}
} else {
if (PromptService.yesNo(Editor.getString('scheduler.setupJobs.message'), Editor.getString('scheduler.setupJobs.title')).yes) {
editor.openSeleniumIDEScheduler();
}
}
} else {
editor.scheduler.stop();
}
break;
case "cmd_selenium_speed_fastest":
editor.updateInterval(-1000);
break;
Expand Down Expand Up @@ -689,7 +726,7 @@ Editor.prototype.resetWindow = function () {
Editor.prototype.submitDiagInfo = function(){
this.health.runDiagnostics();
var data = {
data: this.health.getJSON()
data: this.health.getJSON(true)
};
window.openDialog("chrome://selenium-ide/content/health/diag-info.xul", "diagInfo", "chrome,modal,resizable", data);
if (data.data.length > 0) {
Expand Down Expand Up @@ -739,7 +776,7 @@ Editor.prototype.updateDeveloperTools = function (show) {

//Samit: Enh: Provide a bit of visual assistance
Editor.prototype.updateVisualEye = function (show) {
var container = document.getElementById("selenium-ide") || document.getElementById("selenium-ide-sidebar") ;
var container = document.getElementById("selenium-ide") || document.getElementById("selenium-ide-sidebar");
show ? container.classList.add("visualeye") : container.classList.remove("visualeye");
};

Expand Down Expand Up @@ -859,6 +896,14 @@ Editor.prototype.openSeleniumIDEPreferences = function () {
window.openDialog("chrome://selenium-ide/content/optionsDialog.xul", "options", "chrome,modal,resizable", null);
};

Editor.prototype.openSeleniumIDEScheduler = function (event) {
if (event) {
event.stopPropagation();
}
window.openDialog("chrome://selenium-ide/content/scheduler/schedulerui.xul", "scheduler", "chrome,modal,resizable", this);
this.scheduleButton.checked = this.scheduler.isActive();
};

Editor.prototype.showInBrowser = function (url, newWindow) {
if (newWindow) {
return this.window.open(url);
Expand Down
3 changes: 3 additions & 0 deletions ide/main/src/content/preferences.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ SeleniumIDE.Preferences.DEFAULT_OPTIONS = {
executeUsingWebDriver: "false",
webDriverBrowserString: "firefox",

//Scheduler related options
jobResultsServer: 'http://localhost:3000/api/result',

//Other options
// This should be called 'userExtensionsPaths', but it is left for backward compatibility.
userExtensionsURL: "",
Expand Down
201 changes: 201 additions & 0 deletions ide/main/src/content/scheduler/natural-language-english.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/*
* NaturalLanguageProcessor - a Javascript based library to convert English like expressions into cron like expressions
*
* Copyright 2014,2015 Samit Badle
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/*
*Every 15 minutes
*Every hour
*Every 2 hours at 5
*Every day at 8
*Every weekday at 8
On weekday at 8
*Daily at 8
*At midnight
*Sunday at midnight
*Sunday at noon
*Sunday at 8am
*Sunday at 8:15am
*Sunday at 8:15
Every hour on Monday
Every Monday Every hour
Sunday at 0815
Monday at 1000, 11:15
*/

function NaturalLanguageProcessor() {
}

NaturalLanguageProcessor.prototype.fromString = function(string) {
return NaturalLanguageProcessor.fromString(string);
};

NaturalLanguageProcessor.fromString = function(string) {
var m;
m = string.match(/^\s*(?:every\s*)?(\d+)(?:\s*(?:min(?:ute)?(?:s)?))\s*$/i);
if (m) {
return this._fromMinutes(parseInt(m[1], 10));
}
m = string.match(/^\s*(?:every\s*)?(\d*)(?:\s*(?:hour(?:s)?))(?:\s+at\s+(\d+)(?:\s*(?:min(?:ute)?(?:s)?))?)?\s*$/i);
if (m) {
return this._fromHours(m[1] && m[1].length > 0 ? parseInt(m[1], 10) : 1, m.length > 2 ? parseInt(m[2], 10) : 0);
}
m = string.replace(/at midnight\s*$/i, 'at 0:0').replace(/at noon\s*$/i, 'at 12:00').match(/^\s*(?:every\s+)?(?:([A-Za-z ,]+)\s+)?at\s+(\d+)(?::(\d+)\s*(am|pm)?)?\s*$/i);
if (m) {
return this._fromTime(parseInt(m[2], 10), m[3] && m[3].length > 0 ? parseInt(m[3], 10) : 0, m[4], m[1].length > 0 ? this._fromDays(m[1]) : '*');
}
};

NaturalLanguageProcessor._fromMinutes = function(minutes, days) {
//TODO extract day processing into a separate fn
if (!days || days == '') {
days = '*';
} else {
if (days == 'weekday') {
days = '1-5';
} else if (days == 'weekend') {
days = '0,6';
} else {
//TODO
}
//TODO
}
if (minutes == 0) {
//TODO cannot be every 0 minutes
} else if (minutes < 60) {
if (minutes % 5 == 0) {
switch (minutes) {
case 5: return days + " * *";
case 10: return days + " * */2";
case 15: return days + " * */3";
case 20: return days + " * */4";
case 30: return days + " * */6";
}
//TODO error not valid minute interval
} else {
//TODO error. can only be a multiple of 5
}
} else if (minutes % 60 == 0) {
return this._fromHours(minutes / 60);
}
//TODO error. not a valid hour interval
};

NaturalLanguageProcessor._fromHours = function(hours, minute) {
if (minute) {
if (minute >= 0 && minute < 60 && minute % 5 == 0) {
minute /= 5;
} else {
//TODO invalid minute
}
} else {
minute = 0;
}
if (hours == 0) {
//TODO error cannot be every 0 hour
} else if (hours < 24) {
switch (hours) {
case 1: return "* * " + minute;
case 2: return "* */2 " + minute;
case 3: return "* */3 " + minute;
case 4: return "* */4 " + minute;
case 6: return "* */6 " + minute;
case 8: return "* */8 " + minute;
case 12: return "* */12 " + minute;
}
//TODO error not valid minute interval
} else if (hours % 24 == 0) {
return this._fromDays(hours / 24);
}
//TODO error. not a valid day interval
};

NaturalLanguageProcessor._fromTime = function(hour, minute, ampm, day) {
if (ampm) {
if (ampm.toLowerCase() === 'pm') {
if (hour >= 1 && hour <= 12) {
if (hour != 12) {
hour += 12;
}
} else {
//TODO error
}
} else {
if (hour >= 1 && hour <= 12) {
if (hour == 12) {
hour = 0;
}
} else {
//TODO error
}
}
} else {
if (hour < 0 || hour > 23) {
//TODO error
}
}
if (!minute) {
minute = 0;
}
if (minute < 0 || minute >= 60) {
//TODO invalid time portion
} else if (minute % 5 == 0) {
minute /= 5;
return day + " " + hour + " " + minute;
} else {
//TODO error. can only be a multiple of 5
}
//TODO error. not a valid hour interval
};

NaturalLanguageProcessor._fromDays = function(daysList) {
var ra = [0, 0, 0, 0, 0, 0, 0];
var rx = [/^sun(?:day)?$/i, /^mon(?:day)?$/i, /^tue(?:sday)?$/i, /^wed(?:nesday)?$/i, /^thu(?:rsday)?$/i, /^fri(?:day)?$/i, /^sat(?:urday)?$/i];
var days = daysList.split(',');
for (var i = 0; i < days.length; i++) {
var d = days[i].replace(/\s+/g, '');
for (var x = 0; x < 7; x++) {
if (rx[x].test(d)) {
ra[x] = 1;
break;
}
}
if (d.match(/^daily$/i)) {
return '*';
}
if (d.match(/^day$/i)) {
return '*';
}
if (d.match(/^weekday$/i)) {
ra[1] = 1;
ra[2] = 1;
ra[3] = 1;
ra[4] = 1;
ra[5] = 1;
}
if (d.match(/^weekend$/i)) {
ra[0] = 1;
ra[6] = 1;
}
}
var day = '';
for (x = 0; x < 7; x++) {
if (ra[x] == 1) {
day += ',' + x;
}
}
return day.length > 0 ? day.substr(1) : '';
};
Loading

0 comments on commit c8a527c

Please sign in to comment.