Skip to content

Commit c8a527c

Browse files
committed
Selenium IDE Scheduler in one massive commit
1 parent ccc44e2 commit c8a527c

15 files changed

+1724
-6
lines changed

Diff for: ide/main/src/content/editor.js

+48-3
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ function Editor(window) {
153153
this.document = document;
154154
this.recordButton = document.getElementById("record-button");
155155
this.recordMenuItem = document.getElementById("menu_record");
156+
this.scheduleButton = document.getElementById("schedule-button");
157+
this.scheduleMenuItem = document.getElementById("menu_schedule");
156158
this.speedMaxInterval = parseInt(document.getElementById("speedSlider").getAttribute("maxpos"));
157159
this.initMenus();
158160
this.app.initOptions();
@@ -222,6 +224,9 @@ function Editor(window) {
222224
openTabOrWindow('http://code.google.com/p/selenium/wiki/SeIDEReleaseNotes');
223225
Preferences.setAndSave(this.app.options, 'currentVersion', versionString);
224226
}
227+
228+
this.seleniumScheduler = new SeleniumScheduler(this);
229+
this.scheduler = this.seleniumScheduler.scheduler;
225230
this.log.info("Ready");
226231
this.app.notify('initComplete');
227232
this.health.addEvent('editor', 'initialized');
@@ -278,6 +283,7 @@ Editor.controller = {
278283
case "cmd_selenium_rollup":
279284
case "cmd_selenium_reload":
280285
case "cmd_selenium_record":
286+
case "cmd_selenium_schedule":
281287
case "cmd_selenium_speed_fastest":
282288
case "cmd_selenium_speed_faster":
283289
case "cmd_selenium_speed_slower":
@@ -323,7 +329,9 @@ Editor.controller = {
323329
return editor.app.isPlayable() && (editor.selDebugger.state == Debugger.PLAYING || editor.selDebugger.state == Debugger.PAUSED);
324330
case "cmd_selenium_step":
325331
return editor.app.isPlayable() && editor.selDebugger.state == Debugger.PAUSED;
326-
case "cmd_selenium_record":
332+
case "cmd_selenium_record": //TODO base it on scheduler?
333+
return true;
334+
case "cmd_selenium_schedule":
327335
return true;
328336
case "cmd_selenium_speed_fastest":
329337
return editor.getInterval() > 0;
@@ -412,6 +420,35 @@ Editor.controller = {
412420
case "cmd_selenium_record":
413421
editor.toggleRecordingEnabled();
414422
break;
423+
case "cmd_selenium_schedule":
424+
editor.scheduleButton.checked = !editor.scheduleButton.checked;
425+
if (editor.scheduleButton.checked) {
426+
//TODO hasJobs() is not enough as there may be jobs that are not valid, need hasValidJobs()
427+
if (editor.scheduler.hasJobs()) {
428+
editor.toggleRecordingEnabled(false);
429+
if (editor.scheduler.pendingJobCount() > 0) {
430+
var answer = PromptService.yesNoCancel(Editor.getString('scheduler.runNow.message'), Editor.getString('scheduler.runNow.title'));
431+
if (answer.yes) {
432+
editor.scheduler.start();
433+
} else if (answer.no) {
434+
editor.scheduler.resetNextRun();
435+
editor.scheduler.start();
436+
} else {
437+
//Canceled
438+
editor.scheduleButton.checked = !editor.scheduleButton.checked;
439+
}
440+
} else {
441+
editor.scheduler.start();
442+
}
443+
} else {
444+
if (PromptService.yesNo(Editor.getString('scheduler.setupJobs.message'), Editor.getString('scheduler.setupJobs.title')).yes) {
445+
editor.openSeleniumIDEScheduler();
446+
}
447+
}
448+
} else {
449+
editor.scheduler.stop();
450+
}
451+
break;
415452
case "cmd_selenium_speed_fastest":
416453
editor.updateInterval(-1000);
417454
break;
@@ -689,7 +726,7 @@ Editor.prototype.resetWindow = function () {
689726
Editor.prototype.submitDiagInfo = function(){
690727
this.health.runDiagnostics();
691728
var data = {
692-
data: this.health.getJSON()
729+
data: this.health.getJSON(true)
693730
};
694731
window.openDialog("chrome://selenium-ide/content/health/diag-info.xul", "diagInfo", "chrome,modal,resizable", data);
695732
if (data.data.length > 0) {
@@ -739,7 +776,7 @@ Editor.prototype.updateDeveloperTools = function (show) {
739776

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

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

899+
Editor.prototype.openSeleniumIDEScheduler = function (event) {
900+
if (event) {
901+
event.stopPropagation();
902+
}
903+
window.openDialog("chrome://selenium-ide/content/scheduler/schedulerui.xul", "scheduler", "chrome,modal,resizable", this);
904+
this.scheduleButton.checked = this.scheduler.isActive();
905+
};
906+
862907
Editor.prototype.showInBrowser = function (url, newWindow) {
863908
if (newWindow) {
864909
return this.window.open(url);

Diff for: ide/main/src/content/preferences.js

+3
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ SeleniumIDE.Preferences.DEFAULT_OPTIONS = {
156156
executeUsingWebDriver: "false",
157157
webDriverBrowserString: "firefox",
158158

159+
//Scheduler related options
160+
jobResultsServer: 'http://localhost:3000/api/result',
161+
159162
//Other options
160163
// This should be called 'userExtensionsPaths', but it is left for backward compatibility.
161164
userExtensionsURL: "",
+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/*
2+
* NaturalLanguageProcessor - a Javascript based library to convert English like expressions into cron like expressions
3+
*
4+
* Copyright 2014,2015 Samit Badle
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
/*
20+
*Every 15 minutes
21+
*Every hour
22+
*Every 2 hours at 5
23+
*Every day at 8
24+
*Every weekday at 8
25+
On weekday at 8
26+
*Daily at 8
27+
*At midnight
28+
*Sunday at midnight
29+
*Sunday at noon
30+
*Sunday at 8am
31+
*Sunday at 8:15am
32+
*Sunday at 8:15
33+
Every hour on Monday
34+
Every Monday Every hour
35+
Sunday at 0815
36+
Monday at 1000, 11:15
37+
*/
38+
39+
function NaturalLanguageProcessor() {
40+
}
41+
42+
NaturalLanguageProcessor.prototype.fromString = function(string) {
43+
return NaturalLanguageProcessor.fromString(string);
44+
};
45+
46+
NaturalLanguageProcessor.fromString = function(string) {
47+
var m;
48+
m = string.match(/^\s*(?:every\s*)?(\d+)(?:\s*(?:min(?:ute)?(?:s)?))\s*$/i);
49+
if (m) {
50+
return this._fromMinutes(parseInt(m[1], 10));
51+
}
52+
m = string.match(/^\s*(?:every\s*)?(\d*)(?:\s*(?:hour(?:s)?))(?:\s+at\s+(\d+)(?:\s*(?:min(?:ute)?(?:s)?))?)?\s*$/i);
53+
if (m) {
54+
return this._fromHours(m[1] && m[1].length > 0 ? parseInt(m[1], 10) : 1, m.length > 2 ? parseInt(m[2], 10) : 0);
55+
}
56+
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);
57+
if (m) {
58+
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]) : '*');
59+
}
60+
};
61+
62+
NaturalLanguageProcessor._fromMinutes = function(minutes, days) {
63+
//TODO extract day processing into a separate fn
64+
if (!days || days == '') {
65+
days = '*';
66+
} else {
67+
if (days == 'weekday') {
68+
days = '1-5';
69+
} else if (days == 'weekend') {
70+
days = '0,6';
71+
} else {
72+
//TODO
73+
}
74+
//TODO
75+
}
76+
if (minutes == 0) {
77+
//TODO cannot be every 0 minutes
78+
} else if (minutes < 60) {
79+
if (minutes % 5 == 0) {
80+
switch (minutes) {
81+
case 5: return days + " * *";
82+
case 10: return days + " * */2";
83+
case 15: return days + " * */3";
84+
case 20: return days + " * */4";
85+
case 30: return days + " * */6";
86+
}
87+
//TODO error not valid minute interval
88+
} else {
89+
//TODO error. can only be a multiple of 5
90+
}
91+
} else if (minutes % 60 == 0) {
92+
return this._fromHours(minutes / 60);
93+
}
94+
//TODO error. not a valid hour interval
95+
};
96+
97+
NaturalLanguageProcessor._fromHours = function(hours, minute) {
98+
if (minute) {
99+
if (minute >= 0 && minute < 60 && minute % 5 == 0) {
100+
minute /= 5;
101+
} else {
102+
//TODO invalid minute
103+
}
104+
} else {
105+
minute = 0;
106+
}
107+
if (hours == 0) {
108+
//TODO error cannot be every 0 hour
109+
} else if (hours < 24) {
110+
switch (hours) {
111+
case 1: return "* * " + minute;
112+
case 2: return "* */2 " + minute;
113+
case 3: return "* */3 " + minute;
114+
case 4: return "* */4 " + minute;
115+
case 6: return "* */6 " + minute;
116+
case 8: return "* */8 " + minute;
117+
case 12: return "* */12 " + minute;
118+
}
119+
//TODO error not valid minute interval
120+
} else if (hours % 24 == 0) {
121+
return this._fromDays(hours / 24);
122+
}
123+
//TODO error. not a valid day interval
124+
};
125+
126+
NaturalLanguageProcessor._fromTime = function(hour, minute, ampm, day) {
127+
if (ampm) {
128+
if (ampm.toLowerCase() === 'pm') {
129+
if (hour >= 1 && hour <= 12) {
130+
if (hour != 12) {
131+
hour += 12;
132+
}
133+
} else {
134+
//TODO error
135+
}
136+
} else {
137+
if (hour >= 1 && hour <= 12) {
138+
if (hour == 12) {
139+
hour = 0;
140+
}
141+
} else {
142+
//TODO error
143+
}
144+
}
145+
} else {
146+
if (hour < 0 || hour > 23) {
147+
//TODO error
148+
}
149+
}
150+
if (!minute) {
151+
minute = 0;
152+
}
153+
if (minute < 0 || minute >= 60) {
154+
//TODO invalid time portion
155+
} else if (minute % 5 == 0) {
156+
minute /= 5;
157+
return day + " " + hour + " " + minute;
158+
} else {
159+
//TODO error. can only be a multiple of 5
160+
}
161+
//TODO error. not a valid hour interval
162+
};
163+
164+
NaturalLanguageProcessor._fromDays = function(daysList) {
165+
var ra = [0, 0, 0, 0, 0, 0, 0];
166+
var rx = [/^sun(?:day)?$/i, /^mon(?:day)?$/i, /^tue(?:sday)?$/i, /^wed(?:nesday)?$/i, /^thu(?:rsday)?$/i, /^fri(?:day)?$/i, /^sat(?:urday)?$/i];
167+
var days = daysList.split(',');
168+
for (var i = 0; i < days.length; i++) {
169+
var d = days[i].replace(/\s+/g, '');
170+
for (var x = 0; x < 7; x++) {
171+
if (rx[x].test(d)) {
172+
ra[x] = 1;
173+
break;
174+
}
175+
}
176+
if (d.match(/^daily$/i)) {
177+
return '*';
178+
}
179+
if (d.match(/^day$/i)) {
180+
return '*';
181+
}
182+
if (d.match(/^weekday$/i)) {
183+
ra[1] = 1;
184+
ra[2] = 1;
185+
ra[3] = 1;
186+
ra[4] = 1;
187+
ra[5] = 1;
188+
}
189+
if (d.match(/^weekend$/i)) {
190+
ra[0] = 1;
191+
ra[6] = 1;
192+
}
193+
}
194+
var day = '';
195+
for (x = 0; x < 7; x++) {
196+
if (ra[x] == 1) {
197+
day += ',' + x;
198+
}
199+
}
200+
return day.length > 0 ? day.substr(1) : '';
201+
};

0 commit comments

Comments
 (0)