· 5 years ago · Jul 14, 2020, 10:38 AM
1package com.dsbu.framework.adapters;
2
3import com.dsbu.common.SharedClass;
4import com.dsbu.framework.Utils;
5import com.google.gson.Gson;
6import com.google.gson.JsonArray;
7import com.google.gson.JsonElement;
8import com.google.gson.JsonObject;
9import com.selenium.driver.Drivers;
10import com.selenium.elements.ThermoWebElement;
11import org.junit.Assert;
12import org.openqa.selenium.By;
13import org.openqa.selenium.Keys;
14import org.openqa.selenium.NotFoundException;
15import org.openqa.selenium.WebElement;
16import org.openqa.selenium.interactions.Actions;
17import org.openqa.selenium.remote.RemoteWebDriver;
18import org.openqa.selenium.support.ui.ExpectedConditions;
19import org.openqa.selenium.support.ui.WebDriverWait;
20
21import java.io.IOException;
22import java.text.ParseException;
23import java.text.SimpleDateFormat;
24import java.util.*;
25
26public class DesignerFrameworkAdapter extends SPAFrameworkAdapter {
27
28 private final String RightPanelId = "tfs-componentdef-right-panel";
29 private final String RightPanelControl = ".//div[@class='k-content']/div/div/div[contains(@class, 'tfs-control')][contains(@id, '%s')]";
30
31 private final String CALENDAR_INFO_PATH = "//div[@class='k-widget k-calendar k-calendar-infinite']/div[2]/div/span[@class='k-button k-bare k-title']";
32 private final String CALENDAR_DAY_MONTH_PATH = "//div[@class='k-widget k-calendar k-calendar-infinite']/div[2]/div[2]/table//td[@title='%s']/span";
33
34 private final String CenterPanelId = "tfs-componentdef-center-panel";
35 private final String EXPRESSION_EDITOR_CLASS = "(//div[@class='tfs-expressioneditor'])[%s]";
36
37 private final String EXPRESSION_EDITOR_PATH = ".//div[@class='tfs-expressioneditor']";
38
39 private final String EXPRESSION_EDITOR_TEXTAREA_PATH = "./div[2]/div[contains(@class,'tfs-expression-text')]/div[contains(@class,'tfs-expression-textarea')]";
40
41 private final String EXPRESSION_EDITOR_DELETE_BUTTON_PATH = "./div[2]/div[contains(@class,'tfs-expression-delete')]/button";
42
43 private final String EXPRESSION_EDITOR_OPTIONS_PATH = "//div[contains(@class,'tfs-expression-options')]/div/div[@class='k-item k-state-default']";
44
45 private final String EXPRESSION_EDIOTR_OPTIONS_EXPANDED_PATH = "//div[contains(@class,'tfs-expression-options')]/div/div[@class='k-item k-state-default k-state-expanded']";
46
47 private final String EXPRESSION_EDITOR_SUBMIT_BUTTON_PATH = "//div[@role='dialog']//button[text()='Submit']";
48
49 private final String EXPRESSION_EDITOR_WINDOWS_ACTION_PATH = ".//div[@class='k-window-actions k-dialog-actions']";
50
51 //Components Layout Editor
52
53 private final String LEFT_PANEL_ID = "tfs-componentdef-left-panel";
54
55 private final String LEFT_PANEL_CONTROL = ".//div[contains(@class, 'tfs-label tfs-control')]/div/div";
56
57 private final String GRID_PATH = ".//div[@class='tfs-editablegrid tfs-control ']";
58
59 private final String CENTER_PANEL_ID = "tfs-componentdef-center-panel";
60
61 private final String RIGHT_PANEL_ID = "tfs-componentdef-right-panel";
62
63 private final String RIGHT_PANEL_CONTROL = ".//div[@class='k-content']/div/div/div[contains(@class, 'tfs-control')][contains(@id, '%s')]";
64
65 private final String EDIT_DIALOG_PATH = "./div/div[2]";
66
67 private final String SUBMIT_BUTTON_PATH = "./div[3]/button";
68
69 Map<String, String> operators = new HashMap<>();
70 Map<String, String> traceTypes = new HashMap<>();
71
72 List<String> controlsEdited = new ArrayList<>();
73
74
75 Utils designerUtils = new Utils();
76
77 private int totalFormCols;
78
79
80 public DesignerFrameworkAdapter(RemoteWebDriver driver) {
81 super(driver);
82 }
83
84 /// <summary>
85 /// Navigate to the Angular URL provided
86 /// </summary>
87 /// <param name="Url">The URL</param>
88 public void navigateToAngularSite(String Url) throws IOException {
89 launchUrl(Url);
90 //this._driver.getRwDriver().navigate().to(Url);
91 }
92
93 /// <summary>
94 /// Clicks the toolbar button.
95 /// </summary>
96 /// <param name="buttonName">Name of the button.</param>
97 public void clickToolbarButton(String buttonName) throws Exception {
98 ThermoWebElement toolbarButton = ThermoWebElement.xpath("//div[@class='tfs-toolbar tfs-control ']//button[text()='" + buttonName + "']");
99 click(toolbarButton);
100 }
101 public String clickActionButtonForm(String button, String newName)
102 {
103 SharedClass.formName = super.clickActionButtonForm(button, setFormName(newName));
104 return SharedClass.formName;
105 }
106
107
108
109 public String checkFormControls(JsonObject formControls, WebElement container) throws Exception {
110 String ret = "";
111
112
113
114 if (container == null){
115 WebElement standardouput = null;
116 if (checkArea("StandardOutput", standardouput))
117 container = findWebElementBy(By.xpath(".//div[@class='tfs-form tfs-control ']"), standardouput);
118 }
119
120
121
122
123 // Go through the control definition stored within the Form object
124 if (formControls.get("Controls") != null)
125 {
126 for (JsonElement control : formControls.get("Controls").getAsJsonArray())
127 {
128 try
129 {
130 // Find the Control
131 WebElement controlContainer = findWebElementBy(By.xpath(".//div[contains(@id, '" + control.getAsJsonObject().get("ControlName").getAsString() + "')]"), container);
132
133
134
135 // Find the inner controls if we have a container
136 JsonArray containerPanels = getContainerCollection(control.getAsJsonObject(), true, null);
137
138
139
140 if (containerPanels != null)
141 for (JsonElement item : containerPanels)
142 {
143 ret = checkFormControls(item.getAsJsonObject(), controlContainer);
144 if (!"".equals(ret))
145 break;
146 }
147 }
148 catch (NotFoundException e)
149 {
150 ret = e.getMessage();
151 break;
152 }
153
154
155
156 }
157 }
158
159
160
161 return ret;
162 }
163
164 public int getTotalFormCols() {
165 return totalFormCols;
166 }
167
168
169
170 public void setTotalFormCols(int totalFormCols) {
171 this.totalFormCols = totalFormCols;
172 }
173
174
175 /// <summary>
176 /// Edit the control properties using the input control definition
177 /// </summary>
178 /// <param name="controlDef">Control definition</param>
179 public void editControlProperties(JsonObject controlDef) throws Exception {
180 //ThermoWebElement rightPanel = ThermoWebElement.id(RightPanelId);
181 WebElement rightPanel = findWebElementBy(By.id(RIGHT_PANEL_ID));
182 //ThermoWebElement panelsBarRight = ThermoWebElement.xpath("//div[contains(@id, '_ComponentDefPanelBarRight')]/div/div");
183 List<WebElement> panelsBarRight = findWebElementsBy(By.xpath(".//div[contains(@id, '_ComponentDefPanelBarRight')]/div/div"), rightPanel);
184
185 //HashMap<Object> controlDefProperties = SharedClass.formDefinition.keySet();
186
187 // Iterator<String> keys = SharedClass.formDefinition.keys();
188
189 //CheckControlVisibleExceptions(controlDef, panelsBarRight);
190
191 // Go through the right panel properties
192 for (WebElement category:panelsBarRight)
193 {
194 if (category.getAttribute("aria-expanded").equals("false"))
195 category.click();
196
197 HashMap<String, WebElement> rightCtrlPropsLabelElem = new HashMap<>();
198 HashMap<String, String> rightCtrlPropsLabelValue = new HashMap<String, String>();
199 List<WebElement> props = findWebElementsBy(By.xpath(String.format(RIGHT_PANEL_CONTROL, "") + "[not(contains(@style, 'display: none;'))]"), category);
200 // Create the Dictionary to Join the Properties
201 for (WebElement propName:props)
202 {
203 WebElement inputElement = findWebElementBy(By.xpath("./table[@class='tfs-edit-table']//table[@class='tfs-edit-tctrl']/tbody/tr[1]/td/*"), propName);
204 String elementClass = inputElement.getAttribute("class");
205 String value = "";
206 if (elementClass.contains("k-checkbox"))
207 value = "false";
208 //input type
209 if (elementClass.contains("k-textbox"))
210 {
211 value = findWebElementBy(By.xpath(".//input"), propName).getAttribute("value");
212 }
213 else if (elementClass.contains("k-textarea"))
214 {
215 value = findWebElementBy(By.xpath(".//textarea"), propName).getAttribute("value");
216 }
217 else if (elementClass.contains("k-dropdown"))
218 {
219 value = findWebElementBy(By.xpath(".//span[@class='k-input']"), propName).getText();
220 }
221 else if (elementClass.contains("k-multiselect"))
222 {
223 value = findWebElementsBy(By.xpath(".//li/span[1]"), propName).toString();
224 }
225 rightCtrlPropsLabelElem.put(getLabelFromElement(propName), propName);
226 rightCtrlPropsLabelValue.put(getLabelFromElement(propName), value);
227 }
228
229 Set<Map.Entry<String, JsonElement>> entries = controlDef.entrySet();
230 Map<String, WebElement> elementsToModify = new HashMap<>();
231 for(String label : rightCtrlPropsLabelValue.keySet()){
232 boolean found = entries
233 .stream()
234 .anyMatch(e -> e.getKey().equals(label) && !e.getValue().toString().replace("\"", "").equals(rightCtrlPropsLabelValue.get(label)));
235 if(found){
236 elementsToModify.put(label, rightCtrlPropsLabelElem.get(label));
237 }
238
239 }
240
241 for(String label : elementsToModify.keySet()){
242 setPropertyValue(controlDef.get(label).toString().replace("\"", ""), elementsToModify.get(label), controlDef);
243 }
244 }
245 }
246
247 /// <summary>
248 /// Add the controls by drag and drop.
249 /// </summary>
250 /// <param name="controls">Collection of controls.</param>
251 public void addFormControls(JsonObject form) throws Exception {
252 editControlProperties(form);
253 //TotalFormCols = form.Value<int>("TotalCols");
254 dragAndDropControls(orderControls(form.get("Controls").getAsJsonArray()), null);
255 }
256
257 /// <summary>
258 /// Drags the and drop controls.
259 /// </summary>
260 /// <param name="controls">The controls.</param>
261 /// <param name="destination">The destination.</param>
262 /// <exception cref="Exception"></exception>
263 private void dragAndDropControls(JsonArray controls, WebElement destination) throws Exception {
264 WebElement foundControl = null;
265 WebElement leftPanel = findWebElementBy(By.id(LEFT_PANEL_ID));
266 List<WebElement> panelsBarLeft = findWebElementsBy(By.xpath(".//div[contains(@id, '_ComponentDefPanelBarLeft')]"), leftPanel);
267
268
269
270 // TODO WriteLine(" ** Added Controls ** ");
271
272
273
274 // Go through the control definition stored within the Form object
275 for(JsonElement controlDef : controls){
276 boolean found = false;
277 for(WebElement panel : panelsBarLeft){
278 List<WebElement> controlsDesigner = findWebElementsBy(By.xpath(LEFT_PANEL_CONTROL), panel);
279 for(WebElement controlName : controlsDesigner){
280 if(controlName.getText().trim().equals(controlDef.getAsJsonObject().get("ControlType").getAsString())){
281 foundControl = controlName;
282 found = true;
283 break;
284 }
285 }
286 if(found) break;
287 }
288 if (!found)
289 throw new Exception(String.format("Form Definition control '%s' not found", controlDef.getAsJsonObject().get("ControlType").getAsString()));
290
291
292
293 if (destination == null){
294 dragAndDrop(foundControl, findLayoutControlDestination(controlDef.getAsJsonObject()));
295 } else {
296 dragAndDrop(foundControl, findWebElementBy(By.xpath("./div[last()]"), destination));
297 }
298
299
300
301 // Added the control
302 //TODO WriteLine(string.Format(" - '{0}'", foundControl.Text.TrimStart()));
303
304
305
306 setupControlDetails(controlDef.getAsJsonObject());
307
308
309
310 JsonArray containerPanels = getContainerCollection(controlDef.getAsJsonObject(), false, null);
311
312
313
314 // If this is a container, call the children controls recursively
315 if (containerPanels != null)
316 {
317
318
319
320 // Get the destination position for the controls within the panes
321 WebElement container = findWebElementBy(By.xpath("//div[@draggable='true']/div[contains(@id, '" + controlDef.getAsJsonObject().get("ControlName").getAsString() + "')]"));
322
323
324
325 editContainerControl(controlDef.getAsJsonObject(), container);
326 }
327 }
328 }
329
330 /// <summary>
331 /// Setup the control details for controls with JSON list edition.
332 /// </summary>
333 /// <param name="controlDef">The control definition.</param>
334 private void setupControlDetails(JsonObject controlDef) throws Exception {
335 switch (controlDef.get("ControlType").getAsString())
336 {
337 case "PanelBar":
338 editControlSingleProperty(controlDef, "Control", "Items");
339 addEditedControl(controlDef);
340 editControlSingleProperty(controlDef, "Control", "ExpandMode");
341 editControlSingleProperty(controlDef, "Binding", "ControlName");
342 break;
343 case "PanelBarItem":
344 editControlSingleProperty(controlDef, "Control", "Items");
345 editControlSingleProperty(controlDef, "Binding", "ControlName");
346 break;
347 case "Splitter":
348 editControlSingleProperty(controlDef, "Control", "Panes");
349 addEditedControl(controlDef);
350 editControlSingleProperty(controlDef, "Binding", "ControlName");
351 break;
352 default:
353 editControlSingleProperty(controlDef, "Binding", "ControlName");
354 break;
355 }
356 }
357
358 /// <summary>
359 /// Edit the control properties using the input control definition
360 /// </summary>
361 /// <param name="controlDef">Control definition</param>
362 /// <param name="label">The label.</param>
363 /// <param name="property">The property.</param>
364 private void editControlSingleProperty(JsonObject controlDef, String label, String property) throws Exception {
365 WebElement panelBarRight = findWebElementBy(By.xpath("//div[@id='" + RightPanelId + "']//div[contains(@id, '_ComponentDefPanelBarRight')]//span[text()='" + label + "']/ancestor::div[@role='treeitem']"));
366
367
368
369 // Go through the right panel properties
370
371
372
373 if (panelBarRight.getAttribute("aria-expanded").equals("false"))
374 panelBarRight.click();
375
376
377
378 WebElement propertyElement = findWebElementBy(By.xpath(String.format(RightPanelControl, property)), panelBarRight);
379
380
381
382 // Get the value of the property
383 String value = getPropertyValue(propertyElement);
384 String jsonValue = controlDef.get(property).getAsString();
385 if (value != null)
386 if (!value.equals(jsonValue))
387 setPropertyValue(jsonValue, propertyElement,controlDef);
388
389
390
391 return;
392 }
393
394 /// <summary>
395 /// Adds the edited control.
396 /// </summary>
397 /// <param name="controlDef">The control definition.</param>
398 private void addEditedControl(JsonObject controlDef)
399 {
400 controlsEdited.add(controlDef.get("ControlName").getAsString());
401 }
402
403
404 /// <summary>
405 /// Setup the container details.
406 /// </summary>
407 /// <param name="controlDef">The control definition.</param>
408 /// <param name="container">The container.</param>
409 private void editContainerControl(JsonObject controlDef, WebElement container) throws Exception {
410 JsonArray containerPanels = getContainerCollection(controlDef, false, null);
411
412
413 if ((controlDef.get("ControlType").getAsString().equals("PanelBar")) || (controlDef.get("ControlType").getAsString().equals("PanelBarItem")))
414 {
415 //Expand the collapsed panels in order to allow the drag and drop
416 List<WebElement> panelBarItems = findWebElementsBy(By.xpath(".//span[@class='k-icon k-i-arrow-s k-panelbar-expand']"), container);
417 int i = 0;
418 for (WebElement panel : panelBarItems)
419 {
420 if (containerPanels.get(i).getAsJsonObject().get("Disabled").getAsBoolean())
421 i++;
422
423
424 panel.click();
425
426
427 WebElement panelItem = null;
428
429
430 if (containerPanels.get(i).getAsJsonObject().get("Items").getAsJsonArray().size() != 0)
431 {
432 editControlSingleProperty(containerPanels.get(i).getAsJsonObject(), "Control", "Items");
433
434
435 JsonArray subcontrolDef = orderControls(controlDef.get("Items").getAsJsonArray());
436 panelItem = findWebElementBy(By.xpath("./../.."), panel);
437 editContainerControl(subcontrolDef.get(i).getAsJsonObject(), panelItem);
438 }
439 if (containerPanels.get(i).getAsJsonObject().get("Controls").getAsJsonArray().size() != 0)
440 {
441 panelItem = findWebElementBy(By.xpath("./../.."), panel);
442 WebElement containerPaneElement = findWebElementBy(By.xpath(".//div[contains(@class, 'k-panel k-group')]/div/div"), panelItem);
443 dragAndDropControls(orderControls(containerPanels.get(i).getAsJsonObject().get("Controls").getAsJsonArray()), containerPaneElement);
444 }
445
446
447 panel.click();
448 i++;
449 }
450 }
451
452 if (controlDef.get("ControlType").getAsString().equals("Splitter"))
453 {
454 int index = 0;
455 // Go through the children controls of the container
456 for (JsonElement item : containerPanels)
457 {
458 WebElement splitterItem = findWebElementBy(By.xpath(".//div[contains(@id, '" + item.getAsJsonObject().get("ControlName").getAsString() + "')]//div[@class='Cell__Cell-jsYrZv horsTV tfs-css-grid-cell tfs-css-grid-empty-cell']"), container);
459 splitterItem.click();
460
461
462 editControlSingleProperty(item.getAsJsonObject(), "Binding", "ControlName");
463 dragAndDropControls(orderControls(item.getAsJsonObject().get("Controls").getAsJsonArray()), findWebElementBy(By.xpath("./.."), splitterItem));
464 index++;
465 }
466 }
467 }
468
469
470 /// <summary>
471 /// Order the JSON controls by RowNumber and ColNumber
472 /// </summary>
473 /// <param name="form">The form definition.</param>
474 /// <returns>The control collection ordered</returns>
475 public JsonArray orderControls(JsonArray controls)
476 {
477 //return controls.OrderBy(r => r.Value<int>("RowNumber")).ThenBy(c => c.Value<int>("ColNumber"));
478 ArrayList<JsonObject> controlsList = new ArrayList<>();
479 for(JsonElement control : controls){
480 controlsList.add(control.getAsJsonObject());
481 }
482
483
484
485 controlsList.sort((o1, o2) -> {
486 int o1RowNumber = o1.get("RowNumber").getAsInt();
487 int o2RowNumber = o2.get("RowNumber").getAsInt();
488 int o1ColNumber = o1.get("ColNumber").getAsInt();
489 int o2ColNumber = o2.get("ColNumber").getAsInt();
490 if (o1RowNumber > o2RowNumber) {
491 return 1;
492 } else if (o1RowNumber < o2RowNumber) {
493 return -1;
494 }else {
495 if(o1ColNumber > o2ColNumber){
496 return 1;
497 }else if (o1ColNumber < o2ColNumber){
498 return -1;
499 }else {
500 return 0;
501 }
502 }
503 });
504
505
506
507 JsonArray array = new JsonArray();
508
509
510
511 for(JsonObject object : controlsList) {
512 array.add(object);
513 }
514
515
516
517 return array;
518 }
519
520
521
522
523 private WebElement findLayoutControlDestination(JsonObject controlDef){
524 // Find the destination WebElement to drop the control
525 WebElement centerPanel = findWebElementBy(By.id(CenterPanelId));
526
527
528
529 // Find the CSS Grid destination
530 List<WebElement> gridCSS = findWebElementsBy(By.xpath("./div/div[2]/div"), centerPanel);
531
532
533
534 int gridCSSPos = controlDef.get("RowNumber").getAsInt() * totalFormCols + controlDef.get("ColNumber").getAsInt();
535
536
537
538 // Check if the grid CSS exists, otherwise, need to positionate in the previous row.
539 if (gridCSSPos >= gridCSS.size())
540 gridCSSPos -= totalFormCols;
541
542
543
544 return gridCSS.get(gridCSSPos);
545 }
546
547 private void setPropertyValue(String value, WebElement element, JsonObject controlDef) throws Exception {
548 String controlClass = element.getAttribute("class");
549
550 if(controlClass != null && !controlClass.isEmpty()){
551 int indexOf = controlClass.indexOf(' ');
552 if(indexOf > -1) controlClass = controlClass.substring(0, indexOf);
553 }
554
555 Actions actions = new Actions(rwDriver);
556
557 switch(controlClass){
558 case "tfs-textedit":
559 case "tfs-numericedit":
560 setValue(findWebElementBy(By.xpath(".//input"),element), value);
561 if(rwDriver.getCapabilities().getBrowserName().equals("Safari")){
562 element.sendKeys(Keys.TAB);
563 }else{
564 actions.sendKeys(Keys.TAB).perform();
565 }
566 break;
567 case "tfs-bindingexpressionedit":
568 selectExpression(element);
569
570 // Delete the current expression
571 deleteCurrentExpression(element);
572
573 // Go through the inputExpression to generate the new expression
574 editExpression(value, element);
575
576 closeAndSubmitExpressionEditor();
577
578 break;
579 case "tfs-dropdown":
580 WebElement span = findWebElementBy(By.xpath(".//span[contains(@class, 'k-widget')]"), element);
581 WebDriverWait wait = new WebDriverWait(rwDriver, LongSearchTimeout.toMillis());
582
583 String spanClass = span.getAttribute("class");
584 if(spanClass.contains("k-multiselect") || spanClass.contains("k-autocomplete") || spanClass.contains("k-combobox")){
585 WebElement dropdown = findWebElementBy(By.xpath(".//input"),element);
586 dropdown.clear();
587 if(value.contains("[")){
588 String[] values = value.split("\\W");
589 for (String option : values){
590 dropdown.click();
591 dropdown.sendKeys(option);
592 wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//li[text()='" + option + "']")));
593 findWebElementBy(By.xpath("//li[text()='" + option + "']")).click();
594 wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//li[text()='" + option + "']")));
595 }
596 }
597 else
598 {
599 dropdown.click();
600 dropdown.sendKeys(value);
601 findWebElementBy(By.xpath("//li[text()='" + value + "']")).click();
602 }
603 }
604 else // is k-dropdown
605 {
606 WebElement dropdown = findWebElementBy(By.xpath(".//span[@class='k-input']"), element);
607 dropdown.click();
608 if (value == "")
609 value = "(None)";
610 try
611 {
612 findWebElementBy(By.xpath("//li[text()='" + value + "']")).click();
613 }
614 catch (NullPointerException n)
615 {
616 findWebElementBy(By.xpath("//li[contains(text(),'" + value + "')]")).click();
617 }
618
619 wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//li[text()='" + value + "']")));
620 //REVIEW, It's needed?
621 // wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(element.getAttribute("xpath") + "//span[@aria-expanded='false']")));
622
623 }
624 break;
625 case "tfs-unitclassdropdown":
626 WebElement dropdown = findWebElementBy(By.xpath(".//span[@class='k-input']"), element);
627 dropdown.click();
628 findWebElementBy(By.xpath("//li[text()='" + value + "']")).click();
629 break;
630 case "tfs-checkbox":
631 WebElement checkbox = findWebElementBy(By.xpath(".//input"), element);
632
633 if(Boolean.parseBoolean(value) != checkbox.isSelected()){
634 clickWithJavaScript(checkbox);
635 }
636 break;
637 case "tfs-jsonlistedit":
638 //This avoid a second visit of the same items
639 if (controlsEdited.contains(controlDef.get("ControlName").getAsString())){
640 break;
641 }
642
643 WebElement editJson = findWebElementBy(By.tagName("button"), element);
644 editJson.click();
645
646 WebElement dialog = findWebElementBy(By.xpath("." + EDIT_DIALOG_PATH), editJson);
647
648 String container = element.getAttribute("id");
649 container = container.substring(container.lastIndexOf('_') + 1);
650 JsonArray containerPanel;
651 int rowsToAdd;
652
653 if(container.equals("Columns") ||container.equals("Buttons")){
654 containerPanel = getContainerCollection(controlDef, true, container);
655 rowsToAdd = getGridNewRecords(controlDef, container);
656 }else{
657 containerPanel = getContainerCollection(controlDef, true, null);
658 rowsToAdd = getGridNewRecords(controlDef, null);
659 }
660 int existingRecords = getGridExistingRecordsNumber(dialog);
661 if(existingRecords < rowsToAdd){
662 addPanelProperties(dialog, rowsToAdd - existingRecords);
663 }
664 int panelIndex = 1;
665 for(JsonElement item : containerPanel){
666 editPanelProperties(item.getAsJsonObject(), dialog, panelIndex);
667 panelIndex++;
668 }
669 findWebElementBy(By.xpath(SUBMIT_BUTTON_PATH), dialog).click();
670 break;
671 case "tfs-datepicker":
672 if(value != null && !value.isEmpty()){
673 element.click();
674 WebElement input = findWebElementBy(By.xpath(".//span[@role='button' and @title='Toggle calendar']"), element);
675 setDateValue(input,value);
676 }
677 break;
678 case "tfs-textarea":
679 WebElement textarea = findWebElementBy(By.xpath(".//textarea"),element);
680 textarea.click();
681 textarea.sendKeys(value);
682 break;
683 case "tfs-editable-grid-cell-editor":
684 case "tfs-editable-grid-center-cell":
685 WebElement inputDiv = findWebElementBy(By.xpath("./*"),element);
686 String editCellClass = inputDiv.getAttribute("class");
687
688 if(editCellClass.contains("k-textbox")){
689 if(inputDiv.getAttribute("readonly").equals("true")){
690 WebElement editJsonB = findWebElementBy(By.tagName("button"), element);
691 editJsonB.click();
692
693 WebElement dialog2 = findWebElementBy(By.xpath("." + EDIT_DIALOG_PATH), editJsonB);
694 JsonArray containerPanels = getContainerCollection(controlDef,true, null);
695 int rowsToAdd2 = containerPanels.size();
696 int existingRecord2 = getGridExistingRecordsNumber(dialog2);
697 if(existingRecord2 < rowsToAdd2){
698 addPanelProperties(dialog2,rowsToAdd2-existingRecord2);
699 }
700 // Edit container "Panes" or "Items"
701 int panelIndex2 = 1;
702 for (JsonElement item : containerPanels)
703 {
704 editPanelProperties(item.getAsJsonObject(), dialog2, panelIndex2);
705 panelIndex2++;
706 }
707
708 // Submit the edition of Items and buttons
709 findWebElementBy(By.xpath(SUBMIT_BUTTON_PATH), dialog2).click();
710 }
711 else {
712 setValue(inputDiv, value);
713 }
714 }
715 else if (editCellClass.contains("k-checkbox"))
716 actions.sendKeys(Keys.SPACE).perform();
717
718 else if (editCellClass.contains("k-dropdown"))
719 {
720 WebElement span2 = findWebElementBy(By.xpath(".//span[@class='k-input']"), inputDiv);
721 WebDriverWait wait2 = new WebDriverWait(rwDriver, LongSearchTimeout.toMillis());
722 span2.click();
723 if (value.equals(""))
724 value = "(None)";
725 try
726 {
727 findWebElementBy(By.xpath("//li[text()='" + value + "']")).click();
728 }
729 catch (NullPointerException n)
730 {
731 findWebElementBy(By.xpath("//li[contains(text(),'" + value + "')]")).click();
732 }
733
734 wait2.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(element.getAttribute("xpath") + "//span[@aria-expanded='false']")));
735 }
736 else if (editCellClass.contains("k-combobox"))
737 {
738 WebElement input = findWebElementBy(By.xpath(".//input[@class='k-input']"), inputDiv);
739 WebDriverWait wait2 = new WebDriverWait(rwDriver, LongSearchTimeout.toMillis());
740
741 input.click();
742 input.sendKeys(value);
743 findWebElementBy(By.xpath("//li[text()='" + value + "']")).click();
744 }
745 break;
746 case "tfs-serviceparamsedit":
747 WebElement editJson_service = findWebElementBy(By.tagName("button"), element);
748 editJson_service.click();
749
750 WebElement dialog_service = findWebElementBy(By.xpath("." + EDIT_DIALOG_PATH), editJson_service);
751
752 String container_service = element.getAttribute("id");
753 container_service = container_service.substring(container_service.lastIndexOf('_') + 1);
754
755 // Edit container
756 int panelIndex_service = 1;
757 editPanelProperties(controlDef.get("DropDownServiceParams").getAsJsonObject(), dialog_service, panelIndex_service);
758
759
760 // Submit the edition
761 findWebElementBy(By.xpath(SUBMIT_BUTTON_PATH), dialog_service).click();
762
763 break;
764 case "tfs-jsedit":
765 findWebElementBy(By.xpath(".//button"), element).click();
766
767 WebElement dialog_jsedit = findWebElementBy(By.xpath(".//div[@class='k-widget k-window k-dialog']"), element);
768
769 // Add the Javascript code
770 rwDriver.executeScript(String.format("document.querySelector(\".CodeMirror\").CodeMirror.setValue(\"%s\")", value));
771
772 findWebElementBy(By.xpath(SUBMIT_BUTTON_PATH), dialog_jsedit).click();
773
774 break;
775 case "tfs-graphsettingsedit":
776 findWebElementBy(By.xpath(".//button"), element).click();
777
778 WebElement dialog_graph = findWebElementBy(By.xpath(".//div[@class='k-widget k-window k-dialog']"), element);
779 setGraphAssociations();
780 graphEditor(value, dialog_graph);
781
782 findWebElementBy(By.xpath(SUBMIT_BUTTON_PATH), dialog_graph).click();
783 break;
784 }
785 }
786
787 private void setGraphAssociations(){
788 traceTypes = new HashMap<>();
789 traceTypes.put("bar", "Bar");
790 traceTypes.put("heatmap", "Heatmap");
791 traceTypes.put("table", "Table");
792 traceTypes.put("countour", "Contour");
793 traceTypes.put("pie", "Pie");
794 traceTypes.put("box", "Box");
795 traceTypes.put("violin", "Violin");
796 traceTypes.put("histogram", "Histogram");
797 traceTypes.put("histogram2d", "2D Histogram");
798 traceTypes.put("histogram2dcontour", "2D Contour Histogram");
799 traceTypes.put("scatter3d", "3D Scatter"); // mode markers
800 traceTypes.put("scatter3d2", "3D Line"); //mode lines
801 traceTypes.put("surface", "3D Surface");
802 traceTypes.put("mesh3d", "3D Mesh");
803 traceTypes.put("cone", "Cone");
804 traceTypes.put("streamtube", "Streamtube");
805 traceTypes.put("scattermapbox", "Tile Map");
806 traceTypes.put("scattergeo", "Atlas Map");
807 traceTypes.put("chroplethmapbox", "Choropleth Tile Map");
808 traceTypes.put("chropleth", "Choropleth Atlas Map");
809 traceTypes.put("densitymapbox", "Density Tile Map");
810 traceTypes.put("candlestick", "Candlestick");
811 traceTypes.put("ohcl", "OHCL");
812 traceTypes.put("waterfall", "Waterfall");
813 traceTypes.put("funnel", "Funnel");
814 traceTypes.put("funnelarea", "Funnel Area");
815 traceTypes.put("scatterpolar", "Polar Scatter");
816 traceTypes.put("barpolar", "Polar Bar");
817 traceTypes.put("scatterternary", "Ternary Scatter");
818 traceTypes.put("sunburst", "Sunburst");
819 traceTypes.put("treemap", "Treemap");
820 traceTypes.put("sankey", "Sankey");
821
822 operators = new HashMap<>();
823 operators.put("Equal", "=");
824 operators.put("LessOrEqual", "<=");
825 operators.put("NotEqual", "<>");
826 operators.put("Greater", ">");
827 operators.put("GreaterOrEqual", ">=");
828 operators.put("Not", "!");
829 operators.put("Less", "<");
830 operators.put("And", "And");
831 operators.put("Or", "Or");
832 }
833
834 private void graphEditor(String data, WebElement dialog) throws Exception {
835 Gson gson = new Gson();
836 JsonObject jsonData = gson.fromJson(data, JsonObject.class);
837 if(jsonData.has("data")){
838 findWebElementBy(By.xpath(".//button[contains(@class, 'js-add-button')]"), dialog).click();
839 }
840 findWebElementBy(By.xpath(".//div[text()='Data Sources']"), dialog).click();
841
842 JsonObject tokens = jsonData.get("dataSources").getAsJsonObject();
843 if(tokens.size() == 30){
844 findWebElementBy(By.xpath(".//div[contains(@id, 'DataSourcesPanel_DataSourcesGridButtonGroup')]//div[contains(@id, 'DataSourcesPanel_DataSourcesGridButtonGroupButton1')]/div/button"), dialog).click();
845 }else{
846 Set<Map.Entry<String, JsonElement>> dataSources = tokens.entrySet();
847 for(Map.Entry<String, JsonElement> item : dataSources){
848 findWebElementBy(By.xpath(".//div[contains(@id, 'DataSourcesPanel_DataSourcesGridButtonGroup')]//div[contains(@id, 'DataSourcesPanel_DataSourcesGridButtonGroupButton0')]/div/button"), dialog).click();
849 setDataSourceValue(dialog, item.getValue(), 2);
850 setDataSourceValue(dialog, item.getKey(), 1);
851 }
852 }
853 setTraceValues (dialog, jsonData);
854 }
855
856 public void setDataSourceValue(WebElement dialog, Object item, int cellPos) throws Exception {
857 JsonElement valueCasted = null;
858 String keyCasted = "";
859
860
861
862
863
864
865 if(item instanceof String){
866 keyCasted = (String)item;
867 }else if (item instanceof JsonElement){
868 valueCasted = (JsonElement)item;
869 }
870 String rowPath = ".//div[contains(@id, 'DataSourcesPanel_DataSourcesGrid')]//div[@class='k-grid-container']//table/tbody/tr";
871 WebElement cellElement;
872 boolean boundedData = false;
873 Actions act = new Actions(rwDriver);
874
875 switch (cellPos)
876
877 {
878 case 1:
879 findWebElementBy(By.xpath(rowPath + "/td[text()='New DataSource']"), dialog).click();
880 cellElement = findWebElementBy(By.xpath(rowPath + "/td/input[@value='New DataSource']"), dialog);
881 cellElement.clear();
882 cellElement.click();
883 act.sendKeys(keyCasted.replace("\r\n", "")).perform();
884 WebElement editButton = findWebElementBy(By.xpath(".//div[contains(@id, 'DataSourcesPanel_DataSourcesGridButtonGroup')]//div[contains(@id, 'DataSourcesPanel_DataSourcesGridButtonGroupButton2')]/div/button"), dialog);
885 if (!(editButton.getAttribute("class").contains("k-state-disabled")))
886 editButton.click();
887 break;
888 case 2:
889
890 findWebElementBy(By.xpath(rowPath + "/td[text()='[]']"), dialog).click();
891 cellElement = findWebElementBy(By.xpath(rowPath + "/td[@class='tfs-editable-grid-cell-editor']/button/span[@class='k-icon k-i-edit']/parent::button"), dialog);
892 cellElement.click();
893
894 //Check the data is empty
895 checkPopupRowIsEmpty("Service Name", dialog);
896 checkPopupRowIsEmpty("Entity Type Name", dialog);
897 checkPopupRowIsEmpty("Filter Expression", dialog);
898 checkPopupRowIsEmpty("Select Attribute", dialog);
899
900 //Fill Popup data
901 cellElement = findWebElementBy(By.xpath(rowPath + "//div[contains(@aria-labelledby, 'Popup')]//textarea[text()='[]']"), dialog);
902 cellElement.clear();
903 cellElement.click();
904
905
906
907
908
909
910
911
912 if (valueCasted.getAsJsonObject().get("value") != null)
913 {
914 act.sendKeys(valueCasted.getAsJsonObject().get("value").getAsString().replace("\r\n", "")).perform();
915 }
916 else
917 act.sendKeys(valueCasted.getAsString().replace("\r\n", "")).perform();
918
919 if (valueCasted.getAsJsonObject().get("serviceName") != null)
920 {
921 findWebElementBy(By.xpath("(.//div[contains(@aria-labelledby, 'Popup')]//div[text()='Service Name']/following-sibling::div//input)[1]"), dialog).click();
922 act = new Actions(rwDriver);
923 act.sendKeys(valueCasted.getAsJsonObject().get("serviceName").getAsString()).perform();
924 findWebElementBy(By.xpath("//div[contains(@class, 'k-animation-container')]/div[@class='k-popup k-child-animation-container undefined']//li[text()='" + valueCasted.getAsJsonObject().get("serviceName").getAsString() + "']")).click();
925 boundedData = true;
926 }
927 if (valueCasted.getAsJsonObject().get("entityTypeName") != null)
928 {
929 findWebElementBy(By.xpath("(.//div[contains(@aria-labelledby, 'Popup')]//div[text()='Entity Type Name']/following-sibling::div//input)[1]"), dialog).click();
930 act = new Actions(rwDriver);
931 act.sendKeys(valueCasted.getAsJsonObject().get("entityTypeName").getAsString()).perform();
932 findWebElementBy(By.xpath("//div[contains(@class, 'k-animation-container')]/div[@class='k-popup k-child-animation-container undefined']//li[text()='" + valueCasted.getAsJsonObject().get("entityTypeName").getAsString() + "']")).click();
933 boundedData = true;
934 }
935
936 //Has any filter?
937 if (valueCasted.getAsJsonObject().get("filterExpression") != null &&
938 valueCasted.getAsJsonObject().get("filterExpression").getAsJsonObject().get("Tree").getAsString() != null)
939 {
940 cellElement = findWebElementBy(By.xpath(".//div[contains(@aria-labelledby, 'Popup')]"), dialog);
941 selectExpression(cellElement);
942 editExpression(valueCasted.getAsJsonObject().get("filterExpression").getAsString(), cellElement);
943 closeAndSubmitExpressionEditor();
944 boundedData = true;
945
946
947
948
949
950
951 }
952
953 if (valueCasted.getAsJsonObject().get("attribute") != null)
954 {
955 findWebElementBy(By.xpath("(.//div[contains(@aria-labelledby, 'Popup')]//div[text()='Select Attribute']/following-sibling::div//input)[1]"), dialog).click();
956 act = new Actions(rwDriver);
957 act.sendKeys(valueCasted.getAsJsonObject().get("attribute").getAsString()).perform();
958 }
959
960 findWebElementBy(By.xpath(rowPath + "//div[@class='k-dialog-buttongroup k-dialog-button-layout-stretched']/button[text()='Submit']"), dialog).click();
961
962 if (boundedData)
963 {
964 try// Ensures the data bounded icon is displayed
965 {
966 findWebElementBy(By.xpath(rowPath + "/td[text()='New DataSource']/parent::tr/td[2]/span[@class='k-icon k-i-arrow-drill']"), dialog);
967
968 }
969 catch (NullPointerException n)
970 {
971 throw new Exception("Data Bounded icon not found");
972 }
973 }
974
975 break;
976 default:
977 break;
978 }
979
980 }
981
982 public void checkPopupRowIsEmpty(String item, WebElement dialog){
983 Assert.assertEquals("", findWebElementBy(By.xpath("(.//div[contains(@aria-labelledby, 'Popup')]//div[text()='" + item + "']/following-sibling::div//input)[1]"), dialog).getAttribute("value"));
984 }
985
986 public void setTraceValues(WebElement dialog, JsonObject jsonData){
987 findWebElementBy(By.xpath(".//div[text()='Traces']"), dialog).click();
988
989 findWebElementBy(By.xpath(".//div[@class='panel']//div[@class='trace-type-select-button']"), dialog).click();
990
991 String graph = jsonData.get("type").getAsString();
992 if(graph.equals("scatter")){
993 if(jsonData.get("mode").getAsString().equals("lines")){
994 if(jsonData.get("mode").getAsString().equals("1")){
995 graph = "Area";
996 }else{
997 graph = "Line";
998 }
999 }else{
1000 graph = "Scatter";
1001 }
1002 }else{
1003 graph = traceTypes.get(graph);
1004 }
1005 findWebElementBy(By.xpath(".//div[@class='trace-item__label' and text()='" + graph + "']"), dialog).click();
1006 JsonObject columnNames = jsonData.get("meta").getAsJsonObject().get("columnNames").getAsJsonObject();
1007
1008 List<WebElement> columns = findWebElementsBy(By.xpath(".//div[@class='panel__content']//div[@class='field__title-text']"), dialog);
1009 List<WebElement> columnsControls = findWebElementsBy(By.xpath(".//div[@class='panel__content']//div[contains(@class,'Select__control')]"), dialog);
1010
1011 for(int i = 1; i < columns.size(); i++){
1012 String value = columnNames.get(columns.get(i).getText()).getAsString();
1013 columnsControls.get(i-1).click();
1014 findWebElementBy(By.xpath("//div[contains(@class,'Select__menu-list')]/div[text()='" + value + "']"), dialog).click();
1015 }
1016 }
1017
1018 private void addPanelProperties(WebElement dialog, int columns){
1019 WebElement editableGrid = findWebElementBy(By.xpath(GRID_PATH),dialog);
1020 int existingRecords = getGridExistingRecordsNumber(editableGrid);
1021 do
1022 {
1023 findWebElementBy(By.xpath(".//button[@class='k-button k-button-icon']"), editableGrid).click();
1024 existingRecords++;
1025 } while (existingRecords < columns);
1026 }
1027
1028 private void editPanelProperties(JsonObject controlDef, WebElement dialog, int row) throws Exception {
1029 Set<Map.Entry<String, JsonElement>> controlDefProperties = controlDef.entrySet();
1030 WebElement editableGrid = findWebElementBy(By.xpath(GRID_PATH), dialog);
1031 Map<String, Integer> headNameId = new HashMap<>();
1032
1033 int column = 0;
1034 int i;
1035 if (editableGrid.getAttribute("id").contains("DropDownServiceParams"))
1036 i = 1;
1037 else
1038 i = 2;
1039 List<WebElement> listHeaders = findWebElementsBy(By.xpath(".//th//span/parent::th/a"), editableGrid);
1040
1041 for (WebElement header : listHeaders)
1042 {
1043 headNameId.put(header.getAttribute("innerHTML").replace(" ", ""), i);
1044 i++;
1045 }
1046 for (Map.Entry<String, JsonElement> prop : controlDefProperties)
1047 {
1048
1049 if(headNameId.get(prop.getKey()) != null){
1050 column = headNameId.get(prop.getKey());
1051 }else{
1052 //The header was Text instead of Caption?
1053 if(prop.getKey().equals("Text") && headNameId.containsKey("Caption")){
1054 column = headNameId.get("Caption");
1055 }else{
1056 // The header found doesn't exist in the displayed header
1057 continue;
1058 }
1059 }
1060 if(!prop.getValue().getAsString().equals("")){
1061 WebElement cell = findWebElementBy(By.xpath(String.format(".//tr[%s]/td[%s]", row, column)), editableGrid);
1062 cell.click();
1063 editableGrid = findWebElementBy(By.xpath(GRID_PATH), dialog);
1064 WebElement cellValue = findWebElementBy(By.xpath(String.format(".//tr[%s]/td[%s]", row, column)), editableGrid);
1065
1066 // Get the value of the property
1067 String value = getPropertyValue(cellValue);
1068
1069 String jsonValue = prop.getValue().getAsString();
1070 if(!value.equals(jsonValue)){
1071 setPropertyValue(jsonValue, cellValue, controlDef);
1072 if(isWebElementPresentBy(By.xpath(".//button[@class='k-button k-primary k-button-icon']//span[@class='k-icon k-i-edit']"), dialog)){
1073 findWebElementBy(By.xpath(".//button[@class='k-button k-primary k-button-icon']//span[@class='k-icon k-i-edit']"), dialog).click();
1074 }
1075 }
1076 //If the control is a separator, there is no need to iterate more
1077 if (jsonValue.equals("Separator"))
1078 break;
1079 }
1080 }
1081 }
1082
1083 /// <summary>
1084 /// Gets the value.
1085 /// </summary>
1086 /// <param name="element">The element.</param>
1087 /// <returns></returns>
1088 private String getPropertyValue(WebElement element){
1089 String value = "";
1090 String controlClass = element.getAttribute("class");
1091 if(controlClass != null && !controlClass.isEmpty()){
1092 int indexOf = controlClass.indexOf(" ");
1093 if(indexOf > -1){
1094 controlClass = controlClass.substring(0, indexOf);
1095 }
1096 }
1097 //Identify the type of cel by the class
1098 switch (controlClass)
1099 {
1100 case "tfs-textedit":
1101 case "tfs-bindingexpressionedit":
1102 {
1103 value = findWebElementBy(By.xpath(".//input"), element).getAttribute("value");
1104 break;
1105 }
1106
1107 case "tfs-dropdown":
1108 {
1109 WebElement span = findWebElementBy(By.xpath(".//span[contains(@class, 'k-widget')]"), element);
1110 String spanClass = span.getAttribute("class");
1111 if (spanClass.contains("k-multiselect") ||
1112 spanClass.contains("k-autocomplete") ||
1113 spanClass.contains("k-combobox"))
1114
1115 value = findWebElementBy(By.xpath(".//input"), span).getAttribute("value");
1116 else // is k-dropdown
1117 value = findWebElementBy(By.xpath(".//span[@class='k-input']"), span).getText();
1118 break;
1119 }
1120 case "tfs-unitclassdropdown":
1121 {
1122 value = findWebElementBy(By.xpath(".//span[@class='k-input']"), element).getText();
1123 break;
1124 }
1125 case "tfs-checkbox":
1126 {
1127 WebElement input = findWebElementBy(By.xpath(".//input"), element);
1128 value = String.valueOf(input.isSelected());
1129 break;
1130 }
1131 case "tfs-numericedit":
1132 case "tfs-jsonlistedit":
1133 case "tfs-datepicker":
1134 case "tfs-serviceparamsedit":
1135 {
1136 value = findWebElementBy(By.xpath(".//input"), element).getAttribute("value");
1137 break;
1138 }
1139 case "tfs-textarea":
1140 {
1141 value = findWebElementBy(By.xpath(".//textarea"), element).getAttribute("value");
1142 break;
1143 }
1144 case "tfs-editable-grid-cell-editor":
1145 case "tfs-editable-grid-center-cell":
1146 {
1147
1148 WebElement inputDiv = findWebElementBy(By.xpath("./*"), element);
1149 String editCellClass = inputDiv.getAttribute("class");
1150
1151 if (editCellClass.contains("k-textbox"))
1152
1153 value = inputDiv.getAttribute("value");
1154 else if (editCellClass.contains("k-checkbox"))
1155 value = String.valueOf(inputDiv.isSelected());
1156
1157 else if (editCellClass.contains("k-dropdown"))
1158 value = findWebElementBy(By.xpath(".//span[@class='k-input']"), inputDiv).getText();
1159 else if (editCellClass.contains("k-combobox"))
1160 value = findWebElementBy(By.xpath(".//input[@class='k-input']"), inputDiv).getAttribute("value");
1161 break;
1162 }
1163
1164 }
1165 return value;
1166 }
1167
1168
1169 private JsonArray getContainerCollection(JsonObject controlDef, boolean getValue, String container){
1170 JsonArray collection = null;
1171 switch (controlDef.get("ControlType").getAsString()){
1172 case "Splitter":
1173 collection = controlDef.get("Panes").getAsJsonArray();
1174 break;
1175 case "PanelBar":
1176 collection = controlDef.get("Items").getAsJsonArray();
1177 break;
1178 case "DropdownButton":
1179 case "SplitButton":
1180 case "Toolbar":
1181 if(getValue) collection = controlDef.get("Items").getAsJsonArray();
1182 break;
1183 case "ButtonGroup":
1184 if(getValue && container != null) collection = controlDef.get(container).getAsJsonArray();
1185 break;
1186 default:
1187 if (controlDef.get("Items") != null)
1188 collection = controlDef.get("Items").getAsJsonArray();
1189 break;
1190 }
1191 return collection;
1192 }
1193
1194
1195 private int getGridExistingRecordsNumber(WebElement dialog){
1196 List<WebElement> rows = findWebElementsBy(By.xpath(".//tr"), dialog);
1197 for(WebElement elem : rows) {
1198 if (elem.getAttribute("class") == "k-grid-norecords")
1199 return 0;
1200 }
1201 return findWebElementsBy(By.xpath(GRID_PATH + "//tr"), dialog).size() - 1;
1202 }
1203
1204 private int getGridNewRecords(JsonObject controlDef, String container){
1205 Set<Map.Entry<String,JsonElement>> controlDefProperties = controlDef.entrySet();
1206 int gridRecordsNumber = 0;
1207
1208 for(Map.Entry<String,JsonElement> prop : controlDefProperties){
1209 if(prop.getValue().isJsonArray() && prop.getKey().equals("Controls")){
1210 if(container != null && !container.equals(prop.getKey())){
1211 continue;
1212 }
1213 gridRecordsNumber = prop.getValue().getAsJsonArray().size();
1214 break;
1215 }
1216 }
1217 return gridRecordsNumber;
1218 }
1219
1220 /// <summary>
1221 /// Gets the label from Element.
1222 /// </summary>
1223 /// <param name="element">The element.</param>
1224 /// <returns></returns>
1225 private String getLabelFromElement(WebElement element)
1226 {
1227 String label = element.getAttribute("id");
1228 label = label.substring(label.lastIndexOf('_') + 1);
1229 //Identify if is control that depends on other control value and set the name without numbers
1230 //if (label.(char.IsDigit))
1231 // label = label.Remove(label.IndexOfAny("0123456789".ToCharArray()));
1232 return label;
1233 }
1234
1235 /// <summary>
1236 /// Edit the controls from the Form
1237 /// </summary>
1238 /// <param name="controls">Collection of controls.</param>
1239 public void editFormControls(JsonArray controls) throws Exception {
1240 editFormControls(controls, null);
1241 }
1242
1243 /// <summary>
1244 /// Edit the control properties within the Form added
1245 /// </summary>
1246 /// <param name="controls">Collection of controls.</param>
1247 /// <param name="containerControl">Control container WebElement.</param>
1248 public void editFormControls(JsonArray controls, WebElement containerControl) throws Exception {
1249
1250 // Find the Center Panel if container is default
1251 if (containerControl == null)
1252 containerControl = findWebElementBy(By.id(CenterPanelId));
1253
1254 //WriteLine(" ** Edited Controls ** ");
1255
1256 for (int i=0; i< controls.size(); i++)
1257 {
1258 Boolean found = isWebElementPresentBy(By.xpath(".//div[contains(@id, '_" + ((JsonObject)controls.get(i)).get("ControlName").getAsString() + "')]"), containerControl);
1259 if (!found)
1260 throw new Exception(String.format("Form Definition control '%s' not found", ((JsonObject)controls.get(i)).get("ControlType").getAsString()));
1261 WebElement element = findWebElementBy(By.xpath(".//div[contains(@id, '_" + ((JsonObject)controls.get(i)).get("ControlName").getAsString() + "')]"), containerControl);
1262 ThermoWebElement elem = ThermoWebElement.xpath("//div[contains(@id, '_" + ((JsonObject)controls.get(i)).get("ControlName").getAsString() + "')]");
1263 click(elem);
1264 editControlProperties(((JsonObject)controls.get(i)));
1265
1266 JsonArray containerPanels = getContainerCollection((JsonObject)controls.get(i), true, null);
1267 if (containerPanels != null)
1268 {
1269 // Get the destination position for the controls within the panes
1270 WebElement container = findWebElementBy(By.xpath(".//div[contains(@id, '" + ((JsonObject)controls.get(i)).get("ControlName").getAsString() + "')]"), containerControl);
1271
1272 List<WebElement> containerPaneElements = null;
1273 List<WebElement> panelBarItems = null;
1274
1275 switch (((JsonObject)controls.get(i)).get("ControlType").getAsString())
1276 {
1277 case "PanelBar":
1278 panelBarItems = findWebElementsBy(By.xpath(".//span[@class='k-icon k-i-arrow-s k-panelbar-expand']"), container);
1279 int j = 0;
1280 for (WebElement panel:panelBarItems)
1281 {
1282 if (((JsonObject)containerPanels.get(j)).get("Disabled").getAsBoolean() == true)
1283 j++;
1284 panel.click();
1285
1286 WebElement panelBarElements = findWebElementBy(By.xpath(".//div[contains(@class, 'k-panel k-group')]"), container);
1287 editFormControls(((JsonObject)containerPanels.get(i)).get("Controls").getAsJsonArray(), panelBarElements);
1288 panel.click();
1289 i++;
1290 }
1291 break;
1292 case "Splitter":
1293 containerPaneElements = findWebElementsBy(By.xpath("./div/div[contains(@class, 'k-pane')]/div/div"), container);
1294 break;
1295 default:
1296 continue;
1297 }
1298
1299 if (((JsonObject)controls.get(i)).get("ControlType").getAsString() != "PanelBar")
1300 {
1301 // Select back the container control to complete the edition of the properties
1302 // Find the Div with the "tfs-componentdef-header"
1303 findWebElementBy(By.xpath("./div[1]"), container).click();
1304
1305 int index = 0;
1306 // Go through the children controls
1307 for (JsonElement item:containerPanels)
1308 {
1309 editFormControls(((JsonObject)item).get("Controls").getAsJsonArray(), containerPaneElements.get(index));
1310 index++;
1311 }
1312 }
1313 }
1314 }
1315
1316 }
1317
1318
1319 /// <summary>
1320 /// Get the collection of the container. It can be "Panes" or "Items"
1321 /// </summary>
1322 /// <param name="controlDef">Definion of the control</param>
1323 /// <param name="getValue">if set to <c>true</c> [get value].</param>
1324 /// <param name="container">The container.</param>
1325 /// <returns></returns>
1326 private JsonArray getContainerCollection(JsonObject controlDef, Boolean getValue, String container)
1327 {
1328 JsonArray collection = null;
1329 switch (controlDef.get("ControlType").getAsString())
1330 {
1331 case "Splitter":
1332 collection = controlDef.get("Panes").getAsJsonArray();
1333 break;
1334 case "PanelBar":
1335 collection = controlDef.get("Items").getAsJsonArray();
1336 break;
1337 case "DropDownButton":
1338 case "SplitButton":
1339 case "Toolbar":
1340 if (getValue)
1341 collection = controlDef.get("Items").getAsJsonArray();
1342 break;
1343 case "ButtonGroup":
1344 if (getValue)
1345 collection = controlDef.get("Buttons").getAsJsonArray();
1346 break;
1347 case "EditableGrid":
1348 if (getValue)
1349 {
1350 if (container != null)
1351 collection = controlDef.get(container).getAsJsonArray();
1352 }
1353 break;
1354 default:
1355 collection = controlDef.get("Items").getAsJsonArray();
1356 break;
1357 }
1358
1359 return collection;
1360 }
1361
1362 /// <summary>
1363 /// Check if the Angular Site is opened
1364 /// </summary>
1365 /// <returns>True or False</returns>
1366 public Boolean checkAngularSite() throws Exception {
1367 /*WebDriverWait wait = new WebDriverWait(rwDriver, Long.parseLong(SharedClass.getProps().getProperty("SearchTimeout")));
1368 wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[@class='tfs-spa-loading-container']")));
1369 return IsWebElementPresentBy(By.tagName("app-root"));*/
1370 waitForPageToLoad();
1371 ThermoWebElement spaLoading = ThermoWebElement.xpath("//div[@class='tfs-spa-loading-container']");
1372 // waitForElementToBecomeInvisible(spaLoading); // This throw an exception due to no .isDisplayed property in the element found
1373 ThermoWebElement rootSPA = ThermoWebElement.tagName("app-root");
1374 return isElementPresent(rootSPA);
1375 }
1376
1377 /// <summary>
1378 /// Check if the Angular Site is opened
1379 /// </summary>
1380 /// <returns>True or False</returns>
1381 public Boolean checkAngularSite(String path, String tagName) throws Exception {
1382 /*WebDriverWait wait = new WebDriverWait(rwDriver, Long.parseLong(SharedClass.getProps().getProperty("SearchTimeout")));
1383 wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath(path)));
1384 return IsWebElementPresentBy(By.tagName(tagName));*/
1385 waitForPageToLoad();
1386 ThermoWebElement spaLoading = ThermoWebElement.xpath(path);
1387 // waitForElementToBecomeInvisible(spaLoading); // This throw an exception due to no .isDisplayed property in the element found
1388 ThermoWebElement rootSPA = ThermoWebElement.tagName(tagName);
1389 return isElementPresent(rootSPA);
1390 }
1391
1392 /// <summary>
1393 /// Check the Home Page of the Angular site is properly rendered
1394 /// </summary>
1395 /// <returns>True or False</returns>
1396 public Boolean checkHomePageRendered() throws Exception {
1397 return isWebElementPresentBy(By.xpath("//app-home[@class='tfs-spa-home-container']"));
1398 //ThermoWebElement HomePage = ThermoWebElement.xpath("//app-home[@class='tfs-spa-home-container']");
1399 //return isElementPresent(HomePage);
1400 }
1401
1402 public Boolean checkHomePageRendered(String path) throws Exception {
1403 return isWebElementPresentBy(By.xpath(path));
1404 //ThermoWebElement HomePage = ThermoWebElement.xpath(path);
1405 //return isElementPresent(HomePage);
1406 }
1407
1408 /*public Boolean IsWebElementPresentBy(By xpath){
1409 try{
1410 ThermoWebElement webElement;
1411 webElement= (ThermoWebElement) _driver.getRwDriver().findElement(xpath);
1412 return true;
1413 }
1414 catch (Exception e) {
1415 return false;
1416 }
1417 }*/
1418
1419 public JsonObject loadInputFormDefinition(String filename){
1420 //TODO report implementation?
1421 return this.designerUtils.loadInputFormDefinition(filename);
1422 }
1423
1424 public boolean checkFormIsEmpty() {
1425 WebElement container = findWebElementBy(By.xpath(".//div[@class='tfs-componentdef-center-panel']/div[@class='tfs-form tfs-control ']"));
1426 return isWebElementPresentBy(By.xpath(".//div[contains(@class, 'grid-empty-cell')]"), container);
1427 }
1428 //TODO revisar
1429 public void setDateValue(WebElement element, String inputValue){
1430 element.click();
1431 setDateValue(inputValue);
1432 }
1433 //TODO revisar
1434 public void setDateValue(String inputValue) {
1435
1436 boolean found = false;
1437 Actions builder = new Actions(rwDriver);
1438 try{
1439 Date dt = new SimpleDateFormat("yyyy-MM-dd").parse(inputValue);
1440 String[] date = new SimpleDateFormat("yyyy-MMM-d").format(dt).split("-");
1441 WebDriverWait wait = new WebDriverWait(rwDriver, LongSearchTimeout.getSeconds());
1442 wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(CALENDAR_INFO_PATH)));
1443 WebElement calendar = findWebElementBy(By.xpath(CALENDAR_INFO_PATH));
1444 calendar.click();
1445 String currentYear = calendar.getAttribute("value");
1446 List<WebElement> yearList = findWebElementsBy(By.xpath("//div[contains(@class, 'k-popup')]//ul[@class='k-reset']//li/span"));
1447 String scrolling;
1448
1449 if(Integer.parseInt(date[0]) < Integer.parseInt(currentYear)){
1450 scrolling = "up";
1451 }else{
1452 scrolling = "down";
1453 }
1454 while(!found){
1455 for(WebElement year : yearList) {
1456 if(year.getText().equals(date[0])){
1457 year.click();
1458 found = true;
1459 break;
1460 }
1461 }
1462 if(found)
1463 break;
1464 if(scrolling.equals("up")){
1465 for(int i = 0; i < 6; i++){
1466 builder.sendKeys(Keys.ARROW_UP).perform();
1467 }
1468 }else{
1469 for(int i = 0; i < 6; i++){
1470 builder.sendKeys(Keys.ARROW_DOWN).perform();
1471 }
1472 }
1473 yearList = findWebElementsBy(By.xpath("//div[contains(@class, 'k-popup')]//ul[@class='k-reset']//li/span"));
1474 }
1475 findWebElementBy(By.xpath(String.format(CALENDAR_DAY_MONTH_PATH, date[0] + " " + date[1]))).click();
1476 findWebElementBy(By.xpath(String.format(CALENDAR_DAY_MONTH_PATH, dt.toString())));
1477 wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[@class='k-widget k-calendar k-calendar-infinite']")));
1478
1479 }catch (ParseException pe){
1480 pe.printStackTrace();
1481 }
1482
1483 }
1484
1485 private void selectExpression(WebElement containerElement){
1486 WebElement element = findWebElementBy(By.className("tfs-expressioneditor"), containerElement);
1487 findWebElementBy(By.tagName("button"),element).click();
1488 }
1489
1490 private void deleteCurrentExpression(WebElement containerElement) {
1491 WebElement dialog = openExpressionEditorDialog(EXPRESSION_EDITOR_PATH, containerElement);
1492 deleteExpression(dialog);
1493 }
1494
1495 private void deleteExpression(WebElement dialog){
1496 int i = 0;
1497
1498 WebElement textArea = findWebElementBy(By.xpath(EXPRESSION_EDITOR_TEXTAREA_PATH), dialog);
1499 do {
1500 i++;
1501 WebElement parent = findWebElementBy(By.xpath("./div/div[" + i + "]"), textArea);
1502 parent.click();
1503
1504 WebElement button = findWebElementBy(By.xpath(EXPRESSION_EDITOR_DELETE_BUTTON_PATH), dialog);
1505 if(button.isEnabled()){
1506 button.click();
1507 }
1508 }while (findWebElementsBy(By.xpath("./div//div"), textArea).size() > 2);
1509 }
1510
1511 private WebElement openExpressionEditorDialog(String expressionEditorClass, WebElement containerElement){
1512 WebElement expressionEditor = findWebElementBy(By.xpath(expressionEditorClass), containerElement);
1513 return findWebElementBy(By.xpath(EDIT_DIALOG_PATH), expressionEditor);
1514 }
1515
1516 private void editExpression (String expression, WebElement containerElement) throws Exception {
1517 //TODO revisar bien la estructura del JSON
1518 WebElement dialog = openExpressionEditorDialog(EXPRESSION_EDITOR_PATH, containerElement);
1519 Gson gson = new Gson();
1520 JsonObject exp = gson.fromJson(expression, JsonObject.class);
1521 identifyExpressionEditorOption(exp.get("Tree").getAsJsonObject().get("operator").getAsString(),
1522 exp.get("Tree").getAsJsonObject().get("args").getAsString(),
1523 exp.get("Text").getAsString(),
1524 dialog);
1525
1526 JsonArray argsList = exp.get("Tree").getAsJsonObject().get("args").getAsJsonArray();
1527 if(argsList.size() > 1){
1528 for(JsonElement item : argsList){
1529 identifyExpressionEditorOption(item.getAsJsonObject().get("operator").getAsString(),
1530 item.getAsJsonObject().get("args").getAsJsonArray().get(0).getAsString(),
1531 item.getAsJsonObject().get("args").getAsJsonArray().get(0).getAsString(),
1532 dialog);
1533 }
1534 }
1535
1536 }
1537
1538 private void identifyExpressionEditorOption(String op, String arg, String item, WebElement dialog) throws Exception {
1539 if(op.equals("PublishProperty")){
1540 if(arg.contains("FormArguments")){
1541 selectExpressionEditorOption("Form Arguments", item, ".//span", dialog);
1542 }else{
1543 selectExpressionEditorOption("Publish Properties", item, ".//span", dialog);
1544 }
1545 }else if (op.equals("DataAttribute")){
1546 selectExpressionEditorOption("DataAttribute", item, ".//span", dialog);
1547 }else if(op.equals("Literal")){
1548 String type;
1549 String iniValue;
1550 if(tryParseInt(item)){
1551 type = "Number";
1552 iniValue = "0";
1553 } else if (tryParseBoolean(item)){
1554 type = "Boolean";
1555 iniValue = "False";
1556 } else if (tryParseDate(item)){
1557 type = "Date";
1558 iniValue = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
1559 }else {
1560 type = "Text";
1561 iniValue = "Text";
1562 }
1563 selectExpressionEditorOption("Literales", type, ".//span", dialog);
1564 addCustomValueForExpression(item, dialog, iniValue);
1565 }else if(operators.containsKey(op)){
1566 selectExpressionEditorOption("Operators", operators.get(op), ".//button", dialog);
1567 }
1568 }
1569
1570 private void addCustomValueForExpression(String value, WebElement dialog, String initialCustomValue){
1571 doubleClick(findWebElementBy(By.xpath("./div"), selectToken(By.xpath("./div/div"), dialog, initialCustomValue)));
1572 findAndSetValue(value, dialog);
1573 }
1574
1575 private void findAndSetValue(String value, WebElement dialog) {
1576 // Find the Edit value dialog
1577 WebElement editValueDialog = findWebElementBy(By.xpath(EXPRESSION_EDITOR_TEXTAREA_PATH + "/div[2]/div[@class='k-widget k-window k-dialog']"), dialog);
1578 WebElement input;
1579 // Set the token number value from the expression
1580 try {
1581 input = findWebElementBy(By.xpath(".//input[contains(@class, 'tfs-edit-input')]"), editValueDialog);
1582 setValue(input, value);
1583 }catch (Exception e){
1584 input = findWebElementBy(By.xpath("./div[2]/span/span/span[@title='Toggle calendar']"), editValueDialog);
1585 setDateValue(input, value);
1586 }
1587 findWebElementBy(By.xpath(".//button[@class='k-button k-primary']"), editValueDialog).click();
1588 }
1589
1590 private boolean tryParseInt(String value){
1591 try {
1592 Integer.parseInt(value);
1593 return true;
1594 } catch (NumberFormatException e) {
1595 return false;
1596 }
1597 }
1598
1599 private boolean tryParseBoolean(String value){
1600 return (value.equalsIgnoreCase(Boolean.valueOf(true).toString()) || value.equalsIgnoreCase(Boolean.valueOf(false).toString()));
1601 }
1602
1603 private boolean tryParseDate(String value) {
1604 try {
1605 new SimpleDateFormat("yyyy-MMM-d").parse(value);
1606 return true;
1607 }catch(ParseException pe){
1608 try {
1609 new SimpleDateFormat("yyyyy-MM-dd").parse(value);
1610 }catch (ParseException p) {
1611 return false;
1612 }
1613 }
1614 return false;
1615 }
1616
1617 private void selectExpressionEditorOption(String panelBarItem, String token, String itemsXPath, WebElement dialog) throws Exception {
1618 // Select the next "?" tfs-expression-token
1619 //It's expression editor or Traversal?
1620 if(dialog.getAttribute("aria-labelledby").contains("CalcExpression") || dialog.getAttribute("aria-labelledby").contains("undefinedPopup"))
1621 selectToken(By.xpath("./div/div"), dialog, "?");
1622
1623 // Wait to select the token to then select the option tab
1624 wait(ShortWait);
1625
1626 List<WebElement> options = findWebElementsBy(By.xpath(EXPRESSION_EDITOR_OPTIONS_PATH), dialog);
1627 int count = 0;
1628 for (WebElement item : options) {
1629 if(item.getText().contains(panelBarItem)){
1630 item.click();
1631 break;
1632 }
1633 count++;
1634 }
1635
1636 // Wait to expand the options to be clicked
1637 wait(ExtraShortWait);
1638
1639 // Check if the input expression option was found
1640 if(count == options.size()){
1641 options = findWebElementsBy(By.xpath(EXPRESSION_EDIOTR_OPTIONS_EXPANDED_PATH), dialog);
1642 count = 0;
1643 }
1644
1645 List<WebElement> items = findWebElementsBy(By.xpath(itemsXPath), options.get(count));
1646
1647 String[] tokens = token.split("\\.");
1648 if(tokens.length > 1 && panelBarItem != "Publish Properties") {
1649 for(String tok : tokens){
1650 selectExpressionEditorOption(panelBarItem, tok, itemsXPath, dialog);
1651 }
1652 }else {
1653 count = 0;
1654 for(WebElement item : items){
1655 if(item.getText().equals(token) || item.getText().equals("$CONTROL$." + token)){
1656 item.click();
1657 break;
1658 }
1659 count++;
1660 }
1661
1662 if(count == items.size()){
1663 throw new Exception(String.format("%s %s not found", panelBarItem, token));
1664 }
1665 }
1666 }
1667
1668 private WebElement selectToken(By by, WebElement dialog, String token){
1669 WebElement textarea = findWebElementBy(By.xpath(EXPRESSION_EDITOR_TEXTAREA_PATH), dialog);
1670 return selectNextToken(findWebElementsBy(by, textarea), token, false);
1671 }
1672
1673 private WebElement selectNextToken(List<WebElement> tokenContainer, String token, boolean clickedToken) {
1674 clickedToken = false;
1675 WebElement foundItem = null;
1676 for(WebElement item: tokenContainer){
1677 if(item.getText().equals(token) && (!clickedToken)){
1678 foundItem = item;
1679 foundItem.click();
1680 clickedToken = true;
1681 return foundItem;
1682 }
1683 if(item.getText().contains(token)){
1684 if((item.getText().length()>1) && !clickedToken){
1685 List<WebElement> divElements = findWebElementsBy(By.xpath("./div"), item);
1686 if(divElements.size() == 0){
1687 foundItem = item;
1688 break;
1689 }
1690 foundItem = selectNextToken(divElements, token, clickedToken);
1691 }
1692 }
1693 }
1694 return foundItem;
1695 }
1696
1697
1698 private void closeAndSubmitExpressionEditor(){
1699 findWebElementBy(By.xpath(EXPRESSION_EDITOR_SUBMIT_BUTTON_PATH)).click();
1700 }
1701}