java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/PageObject.java
... ...
@@ -517,6 +517,11 @@ public class PageObject {
517 517
waitUntil((driver) -> supplier.getAsBoolean());
518 518
}
519 519
520
+ protected void waitUntilAlertIsPresent() {
521
+ WebDriverWait webDriverWait = new WebDriverWait(driver, DEFAULT_LOOKUP_TIMEOUT);
522
+ webDriverWait.until(ExpectedConditions.alertIsPresent());
523
+ }
524
+
520 525
/**
521 526
* Returns a {@link PageArea} instance representing the element with the specified selenium id using the
522 527
* {@link WebDriver} as search context.
java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/usermanagement/UserManagementPanelPO.java
... ...
@@ -1,5 +1,9 @@
1 1
package com.sap.sailing.selenium.pages.adminconsole.usermanagement;
2 2
3
+import java.util.ArrayList;
4
+import java.util.List;
5
+
6
+import org.openqa.selenium.ElementNotSelectableException;
3 7
import org.openqa.selenium.StaleElementReferenceException;
4 8
import org.openqa.selenium.WebDriver;
5 9
import org.openqa.selenium.WebElement;
... ...
@@ -39,16 +43,24 @@ public class UserManagementPanelPO extends PageArea {
39 43
40 44
public DataEntryPO findUser(final String username) {
41 45
final CellTablePO<DataEntryPO> table = getUserTable();
46
+ List<DataEntryPO> dataEntries = new ArrayList<DataEntryPO>();
47
+ waitUntil(() -> {
48
+ List<DataEntryPO> entries;
49
+ try {
50
+ entries = table.getEntries();
51
+ dataEntries.addAll(entries);
52
+ } catch (StaleElementReferenceException e) {
53
+ entries = null;
54
+ }
55
+ return entries != null;
56
+ });
42 57
for (DataEntryPO entry : table.getEntries()) {
43
- String name;
44 58
try {
45
- name = entry.getColumnContent("User name");
59
+ if (username.equals(entry.getColumnContent("User name"))) {
60
+ return entry;
61
+ }
46 62
} catch (StaleElementReferenceException e) {
47 63
// entry is not existing any more but must not break iteration
48
- name = null;
49
- }
50
- if (username.equals(name)) {
51
- return entry;
52 64
}
53 65
}
54 66
return null;
... ...
@@ -56,11 +68,15 @@ public class UserManagementPanelPO extends PageArea {
56 68
57 69
public EditUserDialogPO getEditUserDialog(final String username) {
58 70
DataEntryPO entry = findUser(username);
59
- if (entry != null) {
60
- final WebElement action = ActionsHelper.findUpdateAction(entry.getWebElement());
61
- action.click();
62
- final WebElement dialog = findElementBySeleniumId(this.driver, "UserEditDialog");
63
- return new EditUserDialogPO(this.driver, dialog);
71
+ try {
72
+ if (entry != null) {
73
+ final WebElement action = ActionsHelper.findUpdateAction(entry.getWebElement());
74
+ action.click();
75
+ final WebElement dialog = findElementBySeleniumId(this.driver, "UserEditDialog");
76
+ return new EditUserDialogPO(this.driver, dialog);
77
+ }
78
+ } catch (StaleElementReferenceException e) {
79
+ // entry is not existing any more
64 80
}
65 81
return null;
66 82
}
... ...
@@ -87,16 +103,20 @@ public class UserManagementPanelPO extends PageArea {
87 103
}
88 104
89 105
public void selectUser(String name) {
90
- final CellTablePO<DataEntryPO> table = getUserTable();
91
- final DataEntryPO findUser = findUser(name);
92
- if(findUser != null) {
93
- table.selectEntry(findUser);
106
+ try {
107
+ final DataEntryPO userTableEntry = findUser(name);
108
+ if (userTableEntry != null) {
109
+ userTableEntry.select();
110
+ }
111
+ } catch (StaleElementReferenceException e) {
112
+ throw new ElementNotSelectableException("Cannot select user any more. Entry has already been removed from DOM.", e);
94 113
}
95 114
}
96 115
97 116
public void deleteUser(String name) {
98 117
selectUser(name);
99 118
deleteSelectedUser();
119
+ waitUntilAlertIsPresent();
100 120
driver.switchTo().alert().accept();
101 121
// wait until cell is removed from page
102 122
waitUntil(() -> findUser(name) == null);
wiki/info/landscape/olympic-setup.md
103 123
index 374f7a7..b5d775a
104
--- a/wiki/info/landscape/olympic-setup.md
124
+++ b/wiki/info/landscape/olympic-setup.md
... ...
@@ -65,6 +65,6 @@ Three MongoDB nodes are intended to run during regular operations: sap-p1-1:1020
65 65
66 66
sap-p1-1 normally is the master for the ``tokyo2020`` replica set. It shall replicate the shared services, in particular ``SecurityServiceImpl``, from ``security-service.sapsailing.com``, like any normal server in our landscape, only that here we have to make sure we can target the default RabbitMQ in eu-west-1 and can see the ``security-service.sapsailing.com`` master directly or even better the load balancer.
67 67
68
-*TODO* find out whether an SSH port forward using a DNS hostname will resolve this host name again each time a connection is made. Probably, forwarding to ``security-service.sapsailing.com:443`` could just work...
68
+SSH local port forwards (configured with the ``-L`` option) that use hostnames instead of IP addresses for the remote host specification are resolved each time a new connection is established through this forward. If the DNS entry resolves to multiple IPs or if the DNS entry changes over time, later connection requests through the port forward will honor the new host name's DNS resolution.
69 69
70 70
sap-p1-2 normally is a replica for the ``tokyo2020`` replica set, using the local RabbitMQ running on sap-p1-1. Its outbound ``REPLICATION_CHANNEL`` will be ``tokyo2020-replica`` and uses the RabbitMQ running in ap-northeast-1, using an SSH port forward. A reverse port forward from ap-northeast-1 to the application port 8888 on sap-p1-2 has to be established which replicas running in ap-northeast-1 will use to reach their master through HTTP. This way, adding more replicas on the AWS side in the cloud will not require any additional bandwidth between cloud and on-site network, except that the reverse HTTP channel, which uses only little traffic, will see additional traffic per replica whereas all outbound replication goes to the single exchange in the RabbitMQ node running in ap-northeast-1.
... ...
\ No newline at end of file