Protractor: Looping a simple test many times - no parameters - protractor

I have a simple test that my Dev colleagues would like to run repeatedly - they have experienced issues where a page loads, then refuses to render correctly.
Here is the code of the test:
describe('DBM Tags', function() {
it('clears prefill basket', function() {
var startTime;
browser.get('https://gxptag.guestline.net/qa/');
// browser.driver.manage().window().maximize();
browser.ignoreSynchronization = true,
browser.sleep(3000);
expect(browser.getTitle()).toEqual('DBM QA Tag Tester');
browser.sleep(500);
//timer start
browser.controlFlow().execute(function() {
startTime = new Date().getTime();
});
//Clicks on basket prefill to load Hotel1
element(by.xpath("/html/body/div[1]/div[1]/button[6]")).click();
browser.switchTo().frame(element(by.tagName('iframe')).getWebElement());
browser.sleep(500);
var EC = protractor.ExpectedConditions;
var e = element(by.xpath ('/html/body/div[1]/div[2]/div/div[2]/div/div[2]/div[2]/div/div[1]/div/span'));
browser.wait(EC.presenceOf(e),5000);
//timer stop
browser.controlFlow().execute(function() {
var endTime = new Date().getTime();
var elapsedTime = endTime - startTime;
console.log('Elapsed Time Basket Prefill modal = ' + elapsedTime + 'ms');
});
browser.switchTo().defaultContent();
//verifies there is a value
browser.switchTo().frame(element(by.tagName('iframe')).getWebElement());
var value1 = element(by.xpath('/html/body/div[1]/div[2]/div/div[2]/div/div[2]/div[2]/div/div[2]/div/div/div/div[2]/div/div[1]/span/span'));
expect(value1.getText()).toEqual('£440.00');
browser.sleep(1000);
//closes modal
browser.switchTo().defaultContent();
element(by.xpath('//*[#id="dbm-close-btn"]')).click();
browser.sleep(500);
//clicks on Hotel1
element(by.xpath('/html/body/div[1]/div[1]/button[3]')).click();
browser.sleep(3000);
//clears room
browser.switchTo().frame(element(by.tagName('iframe')).getWebElement());
browser.sleep(3000);
element(by.deepCss('.removeBooking > svg:nth-child(1)')).click();
browser.sleep(1000);
browser.switchTo().defaultContent();
element (by.xpath('//*[#id="dbm-close-btn"]')).click();
browser.sleep(1000);
});
});
What I want to do is loop this code x times...in the old VB parlance
for x = 1 to 100,
//code here
next x
I appreciate we need to consider promises but any other advice would be greatly appreciated.
Thanks

I didn't have time to test it, so there might be errors here and there but use it as an approach
make your spec like so
let j = Number(process.env.RERUN) || 1;
for (let i = 0; i < j; i++) {
describe("Suite", () => {
it('1', async () => {
// your test case
});
});
}
and start the protractor with this command
RERUN=100 protractor protractor.conf.js
P.S.
this approach can be used as well https://moduscreate.com/blog/protractor_parameters_adding_flexibility_automation_tests/
this way, you'd need to change one line in the spec
let j = Number(browser.params.rerun) || 1;
and start your protractor so
protractor conf.js --parameters.rerun=100

So to sum up!
Add this to the spec:
let j = Number(browser.params.rerun) || 1;
for (let i = 0; i < j; i++) {
describe("Suite", () => {
it('1', async () => {
});
});
}
THEN to the config.js file in the 'exports' section add:
params: {
rerun: 5
},
..then start the test with
Protractor config.js
the test will run 5 times.
Thanks to #Sergey Pleshakov

Related

How to get nodes in OpenStreetMap using Leaflet strictly contained in my current view?

I'm able to correctly query data from the OSM api.
I can also show highways and trunks correctly on the map.
However, the query gives me back always results for a fixed zoom even if my current zoom is higher.
this is how i do my call:
var opl = new L.OverPassLayer({
minZoom: 14,
query: '(way({{bbox}})["highway"~"^(' + query + ')$"];);(._;>;);out geom;',
onSuccess: function (data) {
console.log(data);
urlxml = data.urlxml;
data = data.result;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
// Typical action to be performed when the document is ready:
//document.getElementById("demo").innerHTML = xhttp.responseText;
$("#fileData").text(xhttp.responseText);
console.log(xhttp.responseText);
}
};
xhttp.open("GET", urlxml, true);
console.log(urlxml);
xhttp.send();
console.log(urlxml);
for (let i = 0; i < data.elements.length; i++) {
let pos;
let marker;
const e = data.elements[i];
if (e.id in this._ids) {
continue;
}
this._ids[e.id] = true;
if (e.type === "way") {
let posWay = [];
for (let j = 0; j < e.geometry.length; j++) {
pos = L.latLng(e.geometry[j].lat, e.geometry[j].lon);
posWay.push(pos);
}
var polyline = L.polyline(posWay, { color: "blue" }).addTo(map);
}
console.log("DATA: " + JSON.stringify(data.elements));
}
},
});
How can i get results from the current view only?
Thank you.

Cascading Dropdowns with storage to Local Storage

Am trying to save Cascading dropdown options to local storage, and am coming up with a few issues:
-The dropdowns are registered in Localstorage when changed, but they are not saving on refresh
-They are not being retrieved (probably because of the former issue).
Here's a link to the testing site:
https://www.flighteducation.co.uk/Panelcraft/Bespoke.php
Here is the script for the cascading dropdowns:
var subjectObject = {
"WALL": {
"NON FIRE RATED": ["BEADED", "NON-BEADED"],
"FIRE RATED 1 HOUR": ["BEADED", "NON-BEADED"],
"FIRE RATED 2 HOUR": ["BEADED", "NON-BEADED"],
},
"CEILING": {
"NON FIRE RATED": ["BEADED", "NON-BEADED"],
"FIRE RATED 1 HOUR": ["BEADED", "NON-BEADED"]
}
}
window.onload = function() {
var subjectSel = document.getElementById("subject");
var topicSel = document.getElementById("topic");
var chapterSel = document.getElementById("chapter");
for (var x in subjectObject) {
subjectSel.options[subjectSel.options.length] = new Option(x, x);
}
subjectSel.onchange = function() {
chapterSel.length = 1;
topicSel.length = 1;
for (var y in subjectObject[this.value]) {
topicSel.options[topicSel.options.length] = new Option(y, y);
}
}
topicSel.onchange = function() {
chapterSel.length = 1;
var z = subjectObject[subjectSel.value][this.value];
for (var i = 0; i < z.length; i++) {
chapterSel.options[chapterSel.options.length] = new Option(z[i], z[I]);
}
}
}
   
The code for local storage looks like this:
let options = [position, fire, frame];
for (let i = 0; i < options.length; i++) {
if (window.localStorage.getItem('dropdownValue') === options[i].value) {
options[i].setAttribute('selected', 'selected');
}
}
$(function () {
$('#number').change(function () {
localStorage.setItem('BespokeOrderInput', this.value);
});
if (localStorage.getItem('BespokeOrderInput')) {
$('#number').val(localStorage.getItem('BespokeOrderInput')).trigger('change');
}
});
$(function () {
$('#subject').change(function () {
localStorage.setItem('BespokeOrderForm1', this.value);
});
if (localStorage.getItem('BespokeOrderForm1')) {
$('#subject').val(localStorage.getItem('BespokeOrderForm1')).trigger('change');
}
});
with the $(function) being repeated for each item
the code looks like this for each dropdown (id being different for each)
<select class="list-dropdown" name="chapter" id="chapter">
<option id="frame" value="" selected="selected">PLEASE SELECT FIRE RATING FIRST</option>
</select>
The inputs for the numbers are saving and retrieving with no problem, but as mentioned above dropdowns are not working.
Very new to Localstorage stuff, and I appreciate anyone's time!
thanks

Limit size of entered data in tinyMCE 5

I use tinyMCE 5 in my web site to enter data stored in a database. Therefore I need to limit the entered size, including format information, to the size of the data field. How can I prohibit the user to enter more then the allowed number of bytes, say 2000?
Best of all if I could add some information like "42/2000" on the status bar.
We had a similar requirement in our project (difference: the output should be <entered_chars>/<chars_left> instead of <entered_chars>/<max_chars>), and it ended up being a custom plugin, based on the wordcount plugin. There is some hacks in there, which could make it fail whenever tinyMCE changes, since there is no API for the statusbar in version 5 at this point of time.
But maybe you will still find it useful:
(function () {
'use strict';
var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
var maxChars = function (editor) {
return editor.getParam('number_max_chars', 3600);
};
var applyMaxChars = function (editor) {
return editor.getParam('restrict_to_max_chars', true);
};
var Settings = {
maxChars: maxChars,
applyMaxChars: applyMaxChars
};
var global$1 = tinymce.util.Tools.resolve('tinymce.dom.TreeWalker');
var getText = function (node, schema) {
var blockElements = schema.getBlockElements();
var shortEndedElements = schema.getShortEndedElements();
var isNewline = function (node) {
return blockElements[node.nodeName] || shortEndedElements[node.nodeName];
};
var textBlocks = [];
var txt = '';
var treeWalker = new global$1(node, node);
while (node = treeWalker.next()) {
if (node.nodeType === 3) {
txt += node.data;
} else if (isNewline(node) && txt.length) {
textBlocks.push(txt);
txt = '';
}
}
if (txt.length) {
textBlocks.push(txt);
}
return textBlocks;
};
var strLen = function (str) {
return str.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '_').length;
};
var countCharacters = function (node, schema) {
var text = getText(node, schema).join('');
return strLen(text);
};
var createBodyCounter = function (editor, count) {
return function () {
return count(editor.getBody(), editor.schema);
};
};
var createMaxCount = function (editor) {
return function () {
return Settings.maxChars(editor);
}
}
var createRestrictToMaxCount = function (editor) {
return function () {
return Settings.applyMaxChars(editor);
}
}
var get = function (editor) {
return {
getCount: createBodyCounter(editor, countCharacters),
getMaxCount: createMaxCount(editor),
getRestrictToMaxCount: createRestrictToMaxCount(editor)
};
};
var global$2 = tinymce.util.Tools.resolve('tinymce.util.Delay');
function isAllowedKeycode(event) {
// allow arrow keys, backspace and delete
const key = event.keyCode;
return key === 37 || key === 38 || key === 39 || key === 40 || key === 8
|| key === 46;
}
var updateCount = function (editor, api) {
editor.getContainer().getElementsByClassName(
'tox-statusbar__text-container')[0].textContent = String(
api.getCount()) + " / " + String(
Settings.maxChars(editor) - api.getCount());
};
var setup = function (editor, api, delay) {
var debouncedUpdate = global$2.debounce(function () {
return updateCount(editor, api);
}, delay);
editor.on('init', function () {
updateCount(editor, api);
global$2.setEditorTimeout(editor, function () {
editor.on('SetContent BeforeAddUndo Undo Redo keyup', debouncedUpdate);
editor.on('SetContent BeforeAddUndo Undo Redo keydown', function (e) {
if (!isAllowedKeycode(e) && Settings.applyMaxChars(editor) &&
api.getCount() >= Settings.maxChars(editor)) {
e.preventDefault();
e.stopPropagation();
}
});
}, 0);
});
};
function Plugin(delay) {
if (delay === void 0) {
delay = 300;
}
global.add('charactercount', function (editor) {
var api = get(editor);
setup(editor, api, delay);
return api;
});
}
Plugin();
}());
Currently I'm working on a preprocessor for the paste plugin, so that the max_length effects also pasted text. That's why you see the charactercount API in the code.

css/javascript multiple card flip: reset other cards

So I'm currently using this one: http://jsfiddle.net/nawdpj5j/10/
Now what I need is that when I flip one card (doesn't matter which one) and then flip another one the first one resets/turnes back.
I think I need to add something in here:
var init = function() {
var flippers = document.getElementsByClassName("flip");
for(i = 0; i < flippers.length; i++){
flippers[i].addEventListener( 'click', function(){
var cardID = this.dataset.targetid;
var card = document.getElementById(cardID);
card.toggleClassName('flipped');
}, false);
}
};
Thank you in advance!
You can get an array of all flipped cards and flip them back whenever a card is flipped like so:
var init = function() {
var flippers = document.getElementsByClassName("flip");
for (i = 0; i < flippers.length; i++) {
flippers[i].addEventListener('click', function() {
var cardID = this.dataset.targetid;
var card = document.getElementById(cardID);
var flipped = document.getElementsByClassName('flipped');
for (i = 0; i < flipped.length; i++) {
if (card !== flipped[i]) {
flipped[i].toggleClassName('flipped');
}
}
card.toggleClassName('flipped');
}, false);
}
};
window.addEventListener('DOMContentLoaded', init, false);
Here is a link to a working demo JS FIDDLE

Restart progress indicator button selection press in SAPUI5?

I am new to SAPUI5. I have two controllers participantList.controller.js and Topic.controller.js. I have defined function called refreshData in participantList.js and I am trying to call that function Topic.Controller.js. Overall, I have progress indicator set up at top in participantList view. So, every time when I navigate from Topic view to participant view by selecting topic on topic view, I want to restart progress indicator that's on participant view. Please help!
Here is code for ParticipantList.controller.js:
var reset;
var list;
sap.ui.define([
"fiveminuteapp/controller/BaseController",
"fiveminuteapp/controller/Topic.controller"
],
function(BaseController, participant) {
"use strict";
return BaseController.extend("fiveminuteapp.controller.participant.ParticipantList", {
onInit: function() {
var topicheader = this.byId("employeeListPage");
topicheader.setTitle(topic);
this.listfunction();
this.testFunction();
},
refreshData: function() {
clearInterval(reset);
lTime.setText("5:00");
setInterval(reset);
},
testFunction: function() {
var setMinutes = 5;
var originalTime = setMinutes * 60;
var time = originalTime;
var lTime = this.byId("labelTimeLeft");
var progress = this.byId("progressIndicator");
reset = setInterval(function() {
var minutes;
var seconds;
if (time > -1) {
minutes = Math.floor(time / 60);
seconds = time % 60;
time = time - 1;
if (minutes < 10 && seconds < 10) {
lTime.setText("0" + minutes + ":" + "0" + seconds);
} else if (minutes < 10) {
lTime.setText("0" + minutes + ":" + seconds);
} else if (seconds < 10) {
lTime.setText(minutes + ":" + "0" + seconds);
}
progress.setPercentValue((time / originalTime) * 100);
} else {
clearInterval(reset);
lTime.setText("5:00");
setInterval(reset);
if(lTime.getText() === "00:00"){
$.ajax({
type: "post",
data:{username: username},
url:"/fiveminuteapp/AddPoints"
})
}
}
}, 1000);
},
listfunction: function(){
var test = this.getView().byId("participantList");
setInterval(function(){
var aData = $.ajax({
type: "get",
data:{topic : topic},
contentType : "application/json",
url:"/fiveminuteapp/RetrieveName",
dataType: "json",
async:false,
}).responseJSON;
var oModel = new sap.ui.model.json.JSONModel(aData);
test.setModel(oModel, 'listmodel')
},5000)
}
});
});
and here is code for Topic.Controller.js:
sap.ui.define([
"fiveminuteapp/controller/BaseController",
"fiveminuteapp/controller/participant/ParticipantList.controller"
], function(BaseController, participant) {
"use strict";
return BaseController.extend("fiveminuteapp.controller.Topic", {
onNavToParticipant: function(oEvent) {
var otime = window.originalTime;
var oItem = oEvent.getSource();
var oContext = oItem.getBindingContext("topics");
var topicSelected = oContext.getProperty("TopicChoices");
topic = topicSelected;
$.ajax({
type: "post",
data:{username: username, topic : topic},
url:"/fiveminuteapp/InsertTopic"
})
this.getRouter().navTo("participantList");
var time = participant.refreshData();
//sap.ui.controller("ParticipantList.controller.js").refreshData();
}
});
});
Topic view
Participant view
I assume you are using Routing in your application. If yes, you can attach route pattern match handlers to specific routes, which handlers will be invoked by the framework every time when the specific route has been matched.
Register a handler in your ParticipantList.controller.js onInit() method:
oRouter.getRoute("participantList").attachPatternMatched(this._onRouteMatched, this);
Then implement the handler function itself in ParticipantList.controller.js with name _onRouteMatched():
_onRouteMatched: function (oEvent) {
this.refreshData();
}
More details can be found in the official UI5 documentation.