diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling.launch b/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling.launch index 0c012601c94..e19f996d629 100755 --- a/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT Remote Profiling.launch @@ -27,7 +27,6 @@ - @@ -46,7 +45,6 @@ - diff --git a/java/com.sap.sailing.gwt.ui/SailingGWT.launch b/java/com.sap.sailing.gwt.ui/SailingGWT.launch index 972faa69fac..6cf37e1ef58 100755 --- a/java/com.sap.sailing.gwt.ui/SailingGWT.launch +++ b/java/com.sap.sailing.gwt.ui/SailingGWT.launch @@ -1,55 +1,59 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java index f9b82ec355e..0c8e10c65f8 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AdminConsoleEntryPoint.java @@ -36,6 +36,7 @@ import com.sap.sailing.gwt.ui.masterdataimport.MasterDataImportPanel; import com.sap.sailing.gwt.ui.shared.BetterDateTimeBox; import com.sap.sailing.gwt.ui.shared.RegattaDTO; import com.sap.sse.gwt.client.async.AsyncActionsExecutor; +import com.sap.sse.gwt.client.async.MarkedAsyncCallback; public class AdminConsoleEntryPoint extends AbstractEntryPoint implements RegattaRefresher { private Set regattaDisplayers; @@ -207,18 +208,19 @@ public class AdminConsoleEntryPoint extends AbstractEntryPoint implements Regatt @Override public void fillRegattas() { - sailingService.getRegattas(new AsyncCallback>() { - @Override - public void onSuccess(List result) { - for (RegattaDisplayer regattaDisplayer : regattaDisplayers) { - regattaDisplayer.fillRegattas(result); - } - } - - @Override - public void onFailure(Throwable caught) { - reportError("Remote Procedure Call getRegattas() - Failure"); - } - }); + sailingService.getRegattas(new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onSuccess(List result) { + for (RegattaDisplayer regattaDisplayer : regattaDisplayers) { + regattaDisplayer.fillRegattas(result); + } + } + + @Override + public void onFailure(Throwable caught) { + reportError("Remote Procedure Call getRegattas() - Failure"); + } + })); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DebugIdHelper.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DebugIdHelper.java new file mode 100644 index 00000000000..8bc293b508e --- /dev/null +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/DebugIdHelper.java @@ -0,0 +1,45 @@ +package com.sap.sailing.gwt.ui.client; + +/** + *

Helper class for generating debug identifiers.

+ * + * @author + * Riccardo Nimser + */ +public class DebugIdHelper { + /** + *

Creates a debug identifier for the given enum value. The identifier is the camel cased name of the enum value + * as declared in its enum declaration. The name is split into single words using the underscore.

+ * + * @param value + * The enum value for which the identfier should be created. + * @return + * A debug identifier for the given enum value. + */ + public static > String createDebugId(T value) { + return createDebugId(value.name(), "_"); + } + + /** + *

Creates a debug identifier for the given name. The name is splited into single words using all whitespace + * characters.

+ * + * @param value + * The name for which the identifier should be created. + * @return + * A debug identifier for the given enum value. + */ + public static String createDebugId(String name) { + return createDebugId(name, "\\s"); + } + + private static String createDebugId(String name, String splitRegex) { + StringBuilder builder = new StringBuilder(); + + for (String token : name.split(splitRegex)) { + builder.append(token.substring(0, 1).toUpperCase()); + builder.append(token.substring(1, token.length()).toLowerCase()); + } + return builder.toString(); + } +} diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java index 0123c90f005..da1b2b0303f 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/AbstractCompetitorLeaderboardChart.java @@ -159,6 +159,7 @@ public abstract class AbstractCompetitorLeaderboardChart extends A break; } chart.setTitle(new ChartTitle().setText(DetailTypeFormatter.format(selectedDetailType)), null); + chart.ensureDebugId("CompetitorChart"); final String unit = DetailTypeFormatter.getUnit(getSelectedDetailType()); final String label = unit.isEmpty() ? "" : "[" + unit + "]"; chart.getYAxis().setAxisTitleText(label); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/MultiCompetitorLeaderboardChartSettingsDialogComponent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/MultiCompetitorLeaderboardChartSettingsDialogComponent.java index 327fbbb90bf..8b81686a151 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/MultiCompetitorLeaderboardChartSettingsDialogComponent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/charts/MultiCompetitorLeaderboardChartSettingsDialogComponent.java @@ -49,6 +49,7 @@ public class MultiCompetitorLeaderboardChartSettingsDialogComponent implements S Label chartSelectionLabel = new Label(stringMessages.chooseChart()); mainPanel.add(chartSelectionLabel); chartTypeSelectionListBox = dialog.createListBox(/* isMultiSelect */false); + chartTypeSelectionListBox.ensureDebugId("ChartTypeListBox"); int i = 0; for (DetailType detailType : availableDetailsTypes) { chartTypeSelectionListBox.addItem(DetailTypeFormatter.format(detailType), detailType.name()); diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/controls/listedit/ExpandedListEditorUi.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/controls/listedit/ExpandedListEditorUi.java index 63885cc8b52..0a449e282a0 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/controls/listedit/ExpandedListEditorUi.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/client/shared/controls/listedit/ExpandedListEditorUi.java @@ -30,7 +30,8 @@ public abstract class ExpandedListEditorUi extends ListEditorUi extends ListEditorUi extends ListEditorUi void addComponentToNavigationMenu(final Component component, boolean isCheckboxEnabled, String componentDisplayName, final boolean hasSettingsWhenComponentIsInvisible) { - if(hideToolbar) { - return; - } - - final String componentName = componentDisplayName != null ? componentDisplayName : component.getLocalizedShortName(); - final CheckBox checkBox= new CheckBox(componentName); - final Button settingsButton = new Button(""); - - checkBox.getElement().getStyle().setFloat(Style.Float.LEFT); - - checkBox.setEnabled(isCheckboxEnabled); - checkBox.setValue(component.isVisible()); - checkBox.setTitle(stringMessages.showHideComponent(componentName)); - checkBox.addStyleName(STYLE_VIEWER_TOOLBAR_INNERELEMENT); - - checkBox.addValueChangeHandler(new ValueChangeHandler() { - @Override - public void onValueChange(ValueChangeEvent newValue) { - boolean visible = checkBox.getValue(); - component.setVisible(visible); - - if (visible && component instanceof TimeListener) { - // trigger the component to update its data - ((TimeListener) component).timeChanged(timer.getTime(), null); - } - if(component.hasSettings() && !hasSettingsWhenComponentIsInvisible) { - settingsButton.setEnabled(visible); - } - } - }); - - componentsNavigationPanel.add(checkBox); - - if(component.hasSettings()) { - settingsButton.addClickHandler(new ClickHandler() { + if (!hideToolbar) { + final String componentName = componentDisplayName != null ? componentDisplayName : component.getLocalizedShortName(); + final String debugIdPrefix = DebugIdHelper.createDebugId(componentName); + final CheckBox checkBox = new CheckBox(componentName); + checkBox.ensureDebugId(debugIdPrefix + "DisplayCheckBox"); + final Button settingsButton = new Button(""); + settingsButton.ensureDebugId(debugIdPrefix + "SettingsButton"); + checkBox.getElement().getStyle().setFloat(Style.Float.LEFT); + checkBox.setEnabled(isCheckboxEnabled); + checkBox.setValue(component.isVisible()); + checkBox.setTitle(stringMessages.showHideComponent(componentName)); + checkBox.addStyleName(STYLE_VIEWER_TOOLBAR_INNERELEMENT); + checkBox.addValueChangeHandler(new ValueChangeHandler() { @Override - public void onClick(ClickEvent event) { - new SettingsDialog(component, stringMessages).show(); - } + public void onValueChange(ValueChangeEvent newValue) { + boolean visible = checkBox.getValue(); + component.setVisible(visible); + if (visible && component instanceof TimeListener) { + // trigger the component to update its data + ((TimeListener) component).timeChanged(timer.getTime(), null); + } + if (component.hasSettings() && !hasSettingsWhenComponentIsInvisible) { + settingsButton.setEnabled(visible); + } + } }); - } - - settingsButton.setEnabled(component.hasSettings() && hasSettingsWhenComponentIsInvisible); - settingsButton.addStyleName(STYLE_VIEWER_TOOLBAR_SETTINGS_BUTTON); - settingsButton.getElement().getStyle().setFloat(Style.Float.LEFT); - settingsButton.setTitle(stringMessages.settingsForComponent(componentName)); - - componentsNavigationPanel.add(settingsButton); + componentsNavigationPanel.add(checkBox); + if (component.hasSettings()) { + settingsButton.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + SettingsDialog dialog = new SettingsDialog(component, + stringMessages); + dialog.ensureDebugId(debugIdPrefix + "SettingsDialog"); + dialog.show(); + } + }); + } + settingsButton.setEnabled(component.hasSettings() && hasSettingsWhenComponentIsInvisible); + settingsButton.addStyleName(STYLE_VIEWER_TOOLBAR_SETTINGS_BUTTON); + settingsButton.getElement().getStyle().setFloat(Style.Float.LEFT); + settingsButton.setTitle(stringMessages.settingsForComponent(componentName)); + componentsNavigationPanel.add(settingsButton); + } } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java index 224608c70a1..ff29983de26 100644 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardEntryPoint.java @@ -33,6 +33,7 @@ import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.URLEncoder; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings.RaceColumnSelectionStrategies; import com.sap.sse.gwt.client.async.AsyncActionsExecutor; +import com.sap.sse.gwt.client.async.MarkedAsyncCallback; import com.sap.sse.gwt.client.dialog.DataEntryDialog; import com.sap.sse.gwt.client.player.Timer; import com.sap.sse.gwt.client.player.Timer.PlayModes; @@ -95,23 +96,24 @@ public class LeaderboardEntryPoint extends AbstractEntryPoint { leaderboardGroupName = Window.Location.getParameter(PARAM_LEADERBOARD_GROUP_NAME); if (leaderboardName != null) { - sailingService.checkLeaderboardName(leaderboardName, new AsyncCallback>() { - @Override - public void onSuccess(Pair leaderboardNameAndType) { - if (leaderboardNameAndType != null && leaderboardName.equals(leaderboardNameAndType.getA())) { - Window.setTitle(leaderboardName); - leaderboardType = leaderboardNameAndType.getB(); - createUI(showRaceDetails, embedded, hideToolbar); - } else { - RootPanel.get().add(new Label(stringMessages.noSuchLeaderboard())); - } - } - - @Override - public void onFailure(Throwable t) { - reportError("Error trying to obtain list of leaderboard names: " + t.getMessage()); - } - }); + sailingService.checkLeaderboardName(leaderboardName, new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onSuccess(Pair leaderboardNameAndType) { + if (leaderboardNameAndType != null && leaderboardName.equals(leaderboardNameAndType.getA())) { + Window.setTitle(leaderboardName); + leaderboardType = leaderboardNameAndType.getB(); + createUI(showRaceDetails, embedded, hideToolbar); + } else { + RootPanel.get().add(new Label(stringMessages.noSuchLeaderboard())); + } + } + + @Override + public void onFailure(Throwable t) { + reportError("Error trying to obtain list of leaderboard names: " + t.getMessage()); + } + })); } else { RootPanel.get().add(new Label(stringMessages.noSuchLeaderboard())); } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java index 81102f1937b..4b6ea02419a 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardPanel.java @@ -86,6 +86,7 @@ import com.sap.sailing.gwt.ui.leaderboard.DetailTypeColumn.LegDetailField; import com.sap.sailing.gwt.ui.leaderboard.LeaderboardSettings.RaceColumnSelectionStrategies; import com.sap.sailing.gwt.ui.shared.RaceTimesInfoDTO; import com.sap.sse.gwt.client.async.AsyncActionsExecutor; +import com.sap.sse.gwt.client.async.MarkedAsyncCallback; import com.sap.sse.gwt.client.controls.busyindicator.BusyIndicator; import com.sap.sse.gwt.client.controls.busyindicator.SimpleBusyIndicator; import com.sap.sse.gwt.client.player.PlayStateListener; @@ -790,20 +791,21 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS getSailingService().getLeaderboardByName(getLeaderboardName(), timer.getPlayMode() == PlayModes.Live ? null : getLeaderboardDisplayDate(), /* namesOfRacesForWhichToLoadLegDetails */getNamesOfExpandedRaces(), - previousLeaderboard.getId(), new AsyncCallback() { - @Override - public void onSuccess(IncrementalOrFullLeaderboardDTO result) { - updateLeaderboard(result.getLeaderboardDTO(previousLeaderboard)); - callWhenExpansionDataIsLoaded.run(); - } - - @Override - public void onFailure(Throwable caught) { - getErrorReporter().reportError( - stringMessages.errorTryingToObtainLeaderboardContents(caught.getMessage()), - true /* silentMode */); - } - }); + previousLeaderboard.getId(), new MarkedAsyncCallback( + new AsyncCallback() { + @Override + public void onSuccess(IncrementalOrFullLeaderboardDTO result) { + updateLeaderboard(result.getLeaderboardDTO(previousLeaderboard)); + callWhenExpansionDataIsLoaded.run(); + } + + @Override + public void onFailure(Throwable caught) { + getErrorReporter().reportError( + stringMessages.errorTryingToObtainLeaderboardContents(caught.getMessage()), + true /* silentMode */); + } + })); } } @@ -1435,7 +1437,7 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS TOTAL_COLUMN_STYLE = tableResources.cellTableStyle().cellTableTotalColumn(); leaderboardTable = new SortedCellTableWithStylableHeaders( /* pageSize */10000, tableResources); - leaderboardTable.ensureDebugId("LeaderboardTable"); + leaderboardTable.ensureDebugId("LeaderboardCellTable"); getLeaderboardTable().setWidth("100%"); leaderboardSelectionModel = new MultiSelectionModel(); leaderboardSelectionModel.addSelectionChangeHandler(new Handler() { @@ -1470,7 +1472,7 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS // the information panel informationPanel = new FlowPanel(); - informationPanel.setStyleName(STYLE_LEADERBOARD_INFO); + informationPanel.setStyleName(STYLE_LEADERBOARD_INFO); scoreCorrectionLastUpdateTimeLabel = new Label(""); scoreCorrectionCommentLabel = new Label(""); informationPanel.add(scoreCorrectionCommentLabel); @@ -1485,8 +1487,10 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS // the toolbar panel DockPanel toolbarPanel = new DockPanel(); - toolbarPanel.setStyleName(STYLE_LEADERBOARD_TOOLBAR); + toolbarPanel.ensureDebugId("ToolbarPanel"); + toolbarPanel.setStyleName(STYLE_LEADERBOARD_TOOLBAR); busyIndicator = new SimpleBusyIndicator(false, 0.8f); + busyIndicator.ensureDebugId("BusyIndicator"); if (!isEmbedded) { toolbarPanel.add(informationPanel, DockPanel.WEST); toolbarPanel.add(busyIndicator, DockPanel.WEST); @@ -1507,12 +1511,14 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS pauseIcon = resources.autoRefreshEnabledIcon(); playIcon = resources.autoRefreshDisabledIcon(); refreshAndSettingsPanel = new HorizontalPanel(); + refreshAndSettingsPanel.ensureDebugId("RefreshAndSettingsPanel"); refreshAndSettingsPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); FlowPanel refreshPanel = new FlowPanel(); refreshPanel.addStyleName("refreshPanel"); toolbarPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT); toolbarPanel.addStyleName("refreshAndSettings"); playPause = new Anchor(getPlayPauseImgHtml(timer.getPlayState())); + playPause.ensureDebugId("PlayAndPauseAnchor"); playPause.addClickHandler(playPauseHandler); playStateChanged(timer.getPlayState(), timer.getPlayMode()); refreshPanel.add(playPause); @@ -1750,7 +1756,7 @@ public class LeaderboardPanel extends SimplePanel implements TimeListener, PlayS getLeaderboardName(), timer.getPlayMode() == PlayModes.Live ? null : date, /* namesOfRacesForWhichToLoadLegDetails */getNamesOfExpandedRaces(), /* previousLeaderboard */ getLeaderboard(), timer, errorReporter, stringMessages); - asyncActionsExecutor.execute(getLeaderboardByNameAction, LOAD_LEADERBOARD_DATA_CATEGORY, + this.asyncActionsExecutor.execute(getLeaderboardByNameAction, LOAD_LEADERBOARD_DATA_CATEGORY, new AsyncCallback() { @Override public void onSuccess(LeaderboardDTO result) { diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettingsDialogComponent.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettingsDialogComponent.java index fdcceeb5170..b94c5f7d061 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettingsDialogComponent.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardSettingsDialogComponent.java @@ -22,6 +22,7 @@ import com.google.gwt.user.client.ui.Widget; import com.sap.sailing.domain.common.DetailType; import com.sap.sailing.domain.common.dto.RaceColumnDTO; import com.sap.sailing.domain.common.impl.Util; +import com.sap.sailing.gwt.ui.client.DebugIdHelper; import com.sap.sailing.gwt.ui.client.DetailTypeFormatter; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.components.SettingsDialogComponent; @@ -90,19 +91,19 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone dialogPanel.add(createTimingDetailsPanel(dialog)); return dialogPanel; } - + private FlowPanel createManeuverDetailsPanel(DataEntryDialog dialog) { FlowPanel meneuverPanel = new FlowPanel(); + meneuverPanel.ensureDebugId("ManeuverSettingsPanel"); meneuverPanel.add(dialog.createHeadline(stringMessages.maneuverTypes(), true)); meneuverPanel.addStyleName("SettingsDialogComponent"); FlowPanel meneuverContent = new FlowPanel(); meneuverContent.addStyleName("dialogInnerContent"); List currentMeneuverDetailSelection = maneuverDetailSelection; for (DetailType detailType : ManeuverCountRaceColumn.getAvailableManeuverDetailColumnTypes()) { - CheckBox checkbox = dialog.createCheckbox(DetailTypeFormatter.format(detailType)); - dialog.addTooltip(checkbox, DetailTypeFormatter.getTooltip(detailType)); - checkbox.setValue(currentMeneuverDetailSelection.contains(detailType)); - maneuverDetailCheckboxes.put(detailType, checkbox); + CheckBox checkbox = createAndRegisterCheckbox(dialog, detailType, + currentMeneuverDetailSelection.contains(detailType), maneuverDetailCheckboxes); + meneuverContent.add(checkbox); } meneuverPanel.add(meneuverContent); @@ -111,7 +112,9 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone private FlowPanel createTimingDetailsPanel(DataEntryDialog dialog) { FlowPanel timingPanel = new FlowPanel(); + timingPanel.ensureDebugId("TimingSettingsPanel"); refreshIntervalInSecondsBox = dialog.createLongBox(delayBetweenAutoAdvancesInMilliseconds / 1000l, 4); + refreshIntervalInSecondsBox.ensureDebugId("RefreshIntervalLongBox"); timingPanel.add(dialog.createHeadline(stringMessages.timing(), true)); timingPanel.addStyleName("SettingsDialogComponent"); @@ -132,6 +135,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone private FlowPanel createRaceDetailPanel(DataEntryDialog dialog) { FlowPanel raceDetailDialog = new FlowPanel(); + raceDetailDialog.ensureDebugId("RaceDetailsSettingsPanel"); raceDetailDialog.add(dialog.createHeadline(stringMessages.raceDetailsToShow(), true)); raceDetailDialog.addStyleName("SettingsDialogComponent"); int detailCountInCurrentFlowPanel = 0; @@ -143,10 +147,8 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone raceDetailDialogContent.addStyleName("dialogInnerContent"); raceDetailDialog.add(raceDetailDialogContent); } - CheckBox checkbox = dialog.createCheckbox(DetailTypeFormatter.format(type)); - checkbox.setValue(currentRaceDetailSelection.contains(type)); - dialog.addTooltip(checkbox, DetailTypeFormatter.getTooltip(type)); - raceDetailCheckboxes.put(type, checkbox); + CheckBox checkbox = createAndRegisterCheckbox(dialog, type, currentRaceDetailSelection.contains(type), + raceDetailCheckboxes); raceDetailDialogContent.add(checkbox); detailCountInCurrentFlowPanel++; } @@ -163,16 +165,15 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone private FlowPanel createOverallDetailPanel(DataEntryDialog dialog) { FlowPanel overallDetailDialog = new FlowPanel(); + overallDetailDialog.ensureDebugId("OverallDetailsSettingsPanel"); overallDetailDialog.add(dialog.createHeadline(stringMessages.overallDetailsToShow(), true)); overallDetailDialog.addStyleName("SettingsDialogComponent overallDetailSettings"); FlowPanel overallDetailDialogContent = new FlowPanel(); overallDetailDialogContent.addStyleName("dialogInnerContent"); List currentOverallDetailSelection = overallDetailSelection; for (DetailType type : LeaderboardPanel.getAvailableOverallDetailColumnTypes()) { - CheckBox checkbox = dialog.createCheckbox(DetailTypeFormatter.format(type)); - dialog.addTooltip(checkbox, DetailTypeFormatter.getTooltip(type)); - checkbox.setValue(currentOverallDetailSelection.contains(type)); - overallDetailCheckboxes.put(type, checkbox); + CheckBox checkbox = createAndRegisterCheckbox(dialog, type, currentOverallDetailSelection.contains(type), + overallDetailCheckboxes); overallDetailDialogContent.add(checkbox); } overallDetailDialog.add(overallDetailDialogContent); @@ -181,6 +182,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone private FlowPanel createLegDetailsPanel(DataEntryDialog dialog) { FlowPanel legDetailsToShow = new FlowPanel(); + legDetailsToShow.ensureDebugId("LegDetailsSettingsPanel"); legDetailsToShow.add(dialog.createHeadline(stringMessages.legDetailsToShow(), true)); legDetailsToShow.addStyleName("SettingsDialogComponent"); FlowPanel legDetailsContent = null; @@ -192,10 +194,8 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone legDetailsContent.addStyleName("dialogInnerContent"); legDetailsToShow.add(legDetailsContent); } - CheckBox checkbox = dialog.createCheckbox(DetailTypeFormatter.format(type)); - dialog.addTooltip(checkbox, DetailTypeFormatter.getTooltip(type)); - checkbox.setValue(currentLegDetailSelection.contains(type)); - legDetailCheckboxes.put(type, checkbox); + CheckBox checkbox = createAndRegisterCheckbox(dialog, type, currentLegDetailSelection.contains(type), + legDetailCheckboxes); legDetailsContent.add(checkbox); detailCountInCurrentFlowPanel++; } @@ -204,6 +204,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone private FlowPanel createSelectedRacesPanel(DataEntryDialog dialog) { FlowPanel selectedRacesPanel = new FlowPanel(); + selectedRacesPanel.ensureDebugId("RaceSelectionSettingsPanel"); selectedRacesPanel.addStyleName("SettingsDialogComponent"); selectedRacesPanel.add(dialog.createHeadline(stringMessages.selectedRaces(), true)); // race selection strategy elements @@ -218,12 +219,16 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone int racesCount = raceAllRaceColumns.size(); if (racesCount > 0) { final FlowPanel explicitRaceSelectionContent = new FlowPanel(); + explicitRaceSelectionContent.ensureDebugId("ExplicitRaceSelectionPanel"); final FlowPanel lastNRacesSelectionContent = new FlowPanel(); + lastNRacesSelectionContent.ensureDebugId("MostCurrentRacesSelectionPanel"); + String radioButtonGroupName = "raceSelectionStrategyGroup"; Label raceSelectionWayLabel = new Label(stringMessages.chooseTheWayYouSelectRaces() + ":"); raceSelectionWayLabel.getElement().getStyle().setPaddingRight(5, Unit.PX); racesSelectionStrategyPanel.add(raceSelectionWayLabel); explicitRaceColumnSelectionRadioBtn = dialog.createRadioButton(radioButtonGroupName, stringMessages.selectFromAllRaces()); + explicitRaceColumnSelectionRadioBtn.ensureDebugId("ExplicitRaceSelectionRadioButton"); racesSelectionStrategyPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); explicitRaceColumnSelectionRadioBtn.setValue(activeRaceColumnSelectionStrategy == RaceColumnSelectionStrategies.EXPLICIT); explicitRaceColumnSelectionRadioBtn.addClickHandler(new ClickHandler() { @@ -246,8 +251,8 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone } Grid grid = new Grid(rowCount, maxRacesPerRow); for (RaceColumnDTO expandableSortableColumn : raceAllRaceColumns) { - CheckBox checkbox = dialog.createCheckbox(expandableSortableColumn.getRaceColumnName()); - checkbox.setValue(Util.contains(raceColumnSelection, expandableSortableColumn)); + CheckBox checkbox = createCheckbox(dialog, expandableSortableColumn.getRaceColumnName(), + Util.contains(raceColumnSelection, expandableSortableColumn), null); raceColumnCheckboxes.put(expandableSortableColumn, checkbox); grid.setWidget(rowIndex, columnIndex++, checkbox); if(columnIndex == maxRacesPerRow) { @@ -260,6 +265,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone selectedRacesContent.add(explicitRaceSelectionContent); lastNRacesColumnSelectionRadioBtn = dialog.createRadioButton(radioButtonGroupName, stringMessages.selectANumberOfRaces()); + lastNRacesColumnSelectionRadioBtn.ensureDebugId("MostCurrentRacesSelectionRadioButton"); lastNRacesColumnSelectionRadioBtn.setValue(activeRaceColumnSelectionStrategy == RaceColumnSelectionStrategies.LAST_N); lastNRacesColumnSelectionRadioBtn.addClickHandler(new ClickHandler() { @Override @@ -279,6 +285,7 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone numberOfLastRacesLabel.getElement().getStyle().setPaddingRight(10, Unit.PX); hPanel.add(numberOfLastRacesLabel); numberOfLastRacesToShowBox = dialog.createIntegerBox(numberOfLastRacesToShow != null ? numberOfLastRacesToShow : racesCount, 3); + numberOfLastRacesToShowBox.ensureDebugId("NumberOfMostCurrentRacesIntegerBox"); hPanel.add(numberOfLastRacesToShowBox); dialog.alignAllPanelWidgetsVertically(hPanel, HasVerticalAlignment.ALIGN_MIDDLE); lastNRacesSelectionContent.setVisible(activeRaceColumnSelectionStrategy == RaceColumnSelectionStrategies.LAST_N); @@ -288,6 +295,28 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone } return selectedRacesPanel; } + + private CheckBox createAndRegisterCheckbox(DataEntryDialog dialog, DetailType detailType, boolean selected, + Map registry) { + CheckBox checkbox = createCheckbox(dialog, detailType, selected); + registry.put(detailType, checkbox); + return checkbox; + } + + private CheckBox createCheckbox(DataEntryDialog dialog, DetailType detailType, boolean selected) { + CheckBox checkbox = createCheckbox(dialog, DetailTypeFormatter.format(detailType), selected, + DetailTypeFormatter.getTooltip(detailType)); + checkbox.ensureDebugId(DebugIdHelper.createDebugId(detailType) + "CheckBox"); + return checkbox; + } + + private CheckBox createCheckbox(DataEntryDialog dialog, String label, boolean selected, String tooltip) { + CheckBox checkbox = dialog.createCheckbox(label); + checkbox.ensureDebugId(DebugIdHelper.createDebugId(label) + "CheckBox"); + checkbox.setValue(selected); + dialog.addTooltip(checkbox, tooltip); + return checkbox; + } @Override public LeaderboardSettings getResult() { @@ -341,16 +370,18 @@ public class LeaderboardSettingsDialogComponent implements SettingsDialogCompone return new Validator() { @Override public String getErrorMessage(LeaderboardSettings valueToValidate) { + final String result; if (valueToValidate.getLegDetailsToShow().isEmpty()) { - return stringMessages.selectAtLeastOneLegDetail(); + result = stringMessages.selectAtLeastOneLegDetail(); } else if (valueToValidate.getDelayBetweenAutoAdvancesInMilliseconds() < 1000) { - return stringMessages.chooseUpdateIntervalOfAtLeastOneSecond(); + result = stringMessages.chooseUpdateIntervalOfAtLeastOneSecond(); } else if (valueToValidate.getActiveRaceColumnSelectionStrategy() == RaceColumnSelectionStrategies.LAST_N && (numberOfLastRacesToShowBox.getValue() == null || numberOfLastRacesToShowBox.getValue() < 0)) { - return stringMessages.numberOfRacesMustBeNonNegativeNumber(); + result = stringMessages.numberOfRacesMustBeNonNegativeNumber(); } else { - return null; + result = null; } + return result; } }; } diff --git a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardViewer.java b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardViewer.java old mode 100644 new mode 100755 index a0f9fbc0ba5..bcf9f2a265b --- a/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardViewer.java +++ b/java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/leaderboard/LeaderboardViewer.java @@ -13,6 +13,7 @@ import com.sap.sailing.gwt.ui.client.SailingServiceAsync; import com.sap.sailing.gwt.ui.client.StringMessages; import com.sap.sailing.gwt.ui.client.shared.charts.MultiCompetitorLeaderboardChart; import com.sap.sse.gwt.client.async.AsyncActionsExecutor; +import com.sap.sse.gwt.client.async.MarkedAsyncCallback; import com.sap.sse.gwt.client.player.Timer; import com.sap.sse.gwt.client.player.Timer.PlayModes; import com.sap.sse.gwt.client.useragent.UserAgentDetails; @@ -63,26 +64,27 @@ public class LeaderboardViewer extends AbstractLeaderboardViewer { overallLeaderboardPanel = null; if(showOverallLeaderboard) { - sailingService.getOverallLeaderboardNamesContaining(leaderboardName, new AsyncCallback>() { - @Override - public void onSuccess(List result) { - if(result.size() == 1) { - String overallLeaderboardName = result.get(0); - overallLeaderboardPanel = new LeaderboardPanel(sailingService, asyncActionsExecutor, - leaderboardSettings, preselectedRace, competitorSelectionProvider, timer, - leaderboardGroupName, overallLeaderboardName, errorReporter, stringMessages, userAgent, - false, /* raceTimesInfoProvider */null, false, /* adjustTimerDelay */ true); - mainPanel.add(overallLeaderboardPanel); - addComponentToNavigationMenu(overallLeaderboardPanel, true, stringMessages.seriesLeaderboard(), - /* hasSettingsWhenComponentIsInvisible*/ true); - } - } - - @Override - public void onFailure(Throwable caught) { - // DO NOTHING - } - }); + sailingService.getOverallLeaderboardNamesContaining(leaderboardName, new MarkedAsyncCallback>( + new AsyncCallback>() { + @Override + public void onSuccess(List result) { + if(result.size() == 1) { + String overallLeaderboardName = result.get(0); + overallLeaderboardPanel = new LeaderboardPanel(sailingService, asyncActionsExecutor, + leaderboardSettings, preselectedRace, competitorSelectionProvider, timer, + leaderboardGroupName, overallLeaderboardName, errorReporter, stringMessages, userAgent, + false, /* raceTimesInfoProvider */null, false, /* adjustTimerDelay */ true); + mainPanel.add(overallLeaderboardPanel); + addComponentToNavigationMenu(overallLeaderboardPanel, true, stringMessages.seriesLeaderboard(), + /* hasSettingsWhenComponentIsInvisible*/ true); + } + } + + @Override + public void onFailure(Throwable caught) { + // DO NOTHING + } + })); } } diff --git a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/Leaderboard.gwt.xml b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/Leaderboard.gwt.xml index ca8dfe51451..687167bba31 100755 --- a/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/Leaderboard.gwt.xml +++ b/java/com.sap.sailing.gwt.ui/src/main/resources/com/sap/sailing/gwt/ui/Leaderboard.gwt.xml @@ -6,7 +6,9 @@ - + + + diff --git a/java/com.sap.sailing.selenium.test/META-INF/MANIFEST.MF b/java/com.sap.sailing.selenium.test/META-INF/MANIFEST.MF index 15bf89d47eb..eb259fcb76f 100644 --- a/java/com.sap.sailing.selenium.test/META-INF/MANIFEST.MF +++ b/java/com.sap.sailing.selenium.test/META-INF/MANIFEST.MF @@ -5,8 +5,9 @@ Bundle-SymbolicName: com.sap.sailing.selenium.test Bundle-Version: 1.0.0.qualifier Bundle-Vendor: SAP Bundle-RequiredExecutionEnvironment: JavaSE-1.7 -Require-Bundle: org.junit4;bundle-version="4.8.2", - org.openqa.selenium.osgi;bundle-version="2.39.0", +Require-Bundle: org.hamcrest;bundle-version="1.1.0", + org.junit4;bundle-version="4.8.2", + org.openqa.selenium.osgi;bundle-version="2.40.0", com.sap.sailing.mongodb;bundle-version="1.0.0", com.mongodb.driver;bundle-version="2.6.2", com.sap.sailing.domain.common diff --git a/java/com.sap.sailing.selenium.test/local-test-environment.xml b/java/com.sap.sailing.selenium.test/local-test-environment.xml index 8261c0668e9..fb4bceb28ce 100755 --- a/java/com.sap.sailing.selenium.test/local-test-environment.xml +++ b/java/com.sap.sailing.selenium.test/local-test-environment.xml @@ -40,7 +40,7 @@ webdriver.firefox.bin - /usr/bin/firefox + D:\Internet\Firefox\firefox.exe diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/AjaxCallsExecuted.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/AjaxCallsExecuted.java index 7438724d0d3..11a540172aa 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/AjaxCallsExecuted.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/AjaxCallsExecuted.java @@ -21,7 +21,7 @@ public class AjaxCallsExecuted implements ExpectedCondition { */ public static final String CATEGORY_GLOBAL = ""; //$NON-NLS-1$ - private static final String JAVASCRIPT = "return (window.PENDING_AJAX_CALLS.numberOfFinishedCalls(arguments[0]) === arguments[1])"; //$NON-NLS-1$ + private static final String JAVASCRIPT = "return (window.PENDING_AJAX_CALLS.numberOfFinishedCalls(arguments[0]) >= arguments[1])"; //$NON-NLS-1$ private String category; diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/WindowManager.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/WindowManager.java index ea13a0a303f..a7edd5ef488 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/WindowManager.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/core/WindowManager.java @@ -83,7 +83,11 @@ public class WindowManager { * @return */ public WebDriverWindow openNewWindow() { - return openNewWindow(""); + return openNewWindow(false); + } + + public WebDriverWindow openNewWindow(boolean focus) { + return openNewWindow("", focus); } /** @@ -93,7 +97,17 @@ public class WindowManager { * @return */ public WebDriverWindow openNewWindow(String url) { - return new WebDriverWindow(this.driver, createWindow(url)); + return openNewWindow(url, false); + } + + public WebDriverWindow openNewWindow(String url, boolean focus) { + WebDriverWindow window = new WebDriverWindow(this.driver, createWindow(url)); + + if(focus) { + window.switchToWindow(); + } + + return window; } private String createWindow(String url) { diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/leaderboard/LeaderboardConfigurationPanelPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/leaderboard/LeaderboardConfigurationPanelPO.java index bf296bb77d6..72ced3e98f2 100755 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/leaderboard/LeaderboardConfigurationPanelPO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/leaderboard/LeaderboardConfigurationPanelPO.java @@ -9,18 +9,39 @@ import org.openqa.selenium.WebElement; import com.sap.sailing.selenium.core.BySeleniumId; import com.sap.sailing.selenium.core.FindBy; - import com.sap.sailing.selenium.pages.PageArea; - import com.sap.sailing.selenium.pages.adminconsole.ActionsHelper; - import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaListCompositePO.RegattaDescriptor; - import com.sap.sailing.selenium.pages.gwt.CellTablePO; import com.sap.sailing.selenium.pages.gwt.DataEntryPO; import com.sap.sailing.selenium.pages.gwt.GenericCellTablePO; public class LeaderboardConfigurationPanelPO extends PageArea { + public static class LeaderboardEntryPO extends DataEntryPO { + public LeaderboardEntryPO(CellTablePO table, WebElement element) { + super(table, element); + } + + protected LeaderboardEntryPO() { + super(); + } + + @Override + public String getIdentifier() { + return getName(); + } + + public String getName() { + return getColumnContent(0); + } + + public String getLeaderboardURL() { + WebElement link = this.context.findElement(By.xpath(".//td/div/a")); + + return link.getAttribute("href"); + } + } + @FindBy(how = BySeleniumId.class, using = "CreateFlexibleLeaderboardButton") private WebElement createFlexibleLeaderboardButton; @@ -75,7 +96,7 @@ public class LeaderboardConfigurationPanelPO extends PageArea { } public void deleteLeaderboard(String leaderboard) { - DataEntryPO entry = findLeaderboard(leaderboard); + LeaderboardEntryPO entry = findLeaderboard(leaderboard); if(entry != null) { WebElement removeAction = ActionsHelper.findRemoveAction(entry.getWebElement()); @@ -88,12 +109,10 @@ public class LeaderboardConfigurationPanelPO extends PageArea { } public String getLeaderboardURL(String leaderboard) { - DataEntryPO entry = findLeaderboard(leaderboard); + LeaderboardEntryPO entry = findLeaderboard(leaderboard); if(entry != null) { - WebElement link = entry.getWebElement().findElement(By.xpath(".//td/div/a")); - - return link.getAttribute("href"); + return entry.getLeaderboardURL(); } return null; @@ -102,48 +121,35 @@ public class LeaderboardConfigurationPanelPO extends PageArea { public List getAvailableLeaderboards() { List leaderboards = new ArrayList<>(); - CellTablePO table = getLeaderboardTable(); - List entries = table.getEntries(); + CellTablePO table = getLeaderboardTable(); + List entries = table.getEntries(); - for(DataEntryPO entry : entries) { - leaderboards.add(entry.getColumnContent(0)); + for(LeaderboardEntryPO entry : entries) { + leaderboards.add(entry.getIdentifier()); } return leaderboards; } public LeaderboardDetailsPanelPO getLeaderboardDetails(String leaderboard) { - CellTablePO table = getLeaderboardTable(); - List entries = table.getEntries(); + LeaderboardEntryPO entry = findLeaderboard(leaderboard); - for(DataEntryPO entry : entries) { - String name = entry.getColumnContent(0); - - if(leaderboard.equals(name)) { - entry.select(); - - return new LeaderboardDetailsPanelPO(this.driver, this.leaderboardDetailsPanel); - } + if(entry == null) { + return null; } - return null; + entry.select(); + + return new LeaderboardDetailsPanelPO(this.driver, this.leaderboardDetailsPanel); } - private CellTablePO getLeaderboardTable() { - return new GenericCellTablePO<>(this.driver, this.leaderboardsCellTable, DataEntryPO.class); + private CellTablePO getLeaderboardTable() { + return new GenericCellTablePO<>(this.driver, this.leaderboardsCellTable, LeaderboardEntryPO.class); } - private DataEntryPO findLeaderboard(String leaderboard) { - CellTablePO table = getLeaderboardTable(); + private LeaderboardEntryPO findLeaderboard(String name) { + CellTablePO table = getLeaderboardTable(); - for(DataEntryPO entry : table.getEntries()) { - String name = entry.getColumnContent(0); - - if(leaderboard.equals(name)) { - return entry; - } - } - - return null; + return table.getEntry(name); } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/RegattaCreateDialogPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/RegattaCreateDialogPO.java index 76d8bf0e33d..33a47d23ff9 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/RegattaCreateDialogPO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/RegattaCreateDialogPO.java @@ -9,11 +9,11 @@ import com.sap.sailing.selenium.core.FindBy; import com.sap.sailing.selenium.pages.common.DataEntryDialogPO; public class RegattaCreateDialogPO extends DataEntryDialogPO { - @FindBy(how = BySeleniumId.class, using = "RegattaNameTextField") - private WebElement regattaNameTextField; + @FindBy(how = BySeleniumId.class, using = "NameTextBox") + private WebElement nameTextBox; - @FindBy(how = BySeleniumId.class, using = "BoatClassTextField") - private WebElement boatClassTextField; + @FindBy(how = BySeleniumId.class, using = "BoatClassTextBox") + private WebElement boatClassTextBox; // @FindBy(how = BySeleniumId.class, using = "ScoringSchemeListBox") // private WebElement scoringSystemDropDown; @@ -30,13 +30,13 @@ public class RegattaCreateDialogPO extends DataEntryDialogPO { } public void setRegattaName(String name) { - this.regattaNameTextField.clear(); - this.regattaNameTextField.sendKeys(name); + this.nameTextBox.clear(); + this.nameTextBox.sendKeys(name); } public void setBoatClass(String boatClass) { - this.boatClassTextField.clear(); - this.boatClassTextField.sendKeys(boatClass); + this.boatClassTextBox.clear(); + this.boatClassTextBox.sendKeys(boatClass); } // TODO: Scoring System, Event and Course Area diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/SeriesCreateDialogPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/SeriesCreateDialogPO.java index 1135073fbef..e51807260b4 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/SeriesCreateDialogPO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/SeriesCreateDialogPO.java @@ -9,8 +9,8 @@ import com.sap.sailing.selenium.core.FindBy; import com.sap.sailing.selenium.pages.common.DataEntryDialogPO; public class SeriesCreateDialogPO extends DataEntryDialogPO { - @FindBy(how = BySeleniumId.class, using = "NameTextField") - private WebElement seriesNameTextField; + @FindBy(how = BySeleniumId.class, using = "NameTextBox") + private WebElement nameTextBox; // @FindBy(how = BySeleniumId.class, using = "MedalSeriesCheckbox") // private WebElement medalSeriesCheckbox; @@ -32,8 +32,8 @@ public class SeriesCreateDialogPO extends DataEntryDialogPO { } public void setSeriesName(String name) { - this.seriesNameTextField.clear(); - this.seriesNameTextField.sendKeys(name); + this.nameTextBox.clear(); + this.nameTextBox.sendKeys(name); } // TODO: Checkboxes and Fleets diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/SeriesEditDialogPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/SeriesEditDialogPO.java index 4f47cf19830..7642bb25012 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/SeriesEditDialogPO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/regatta/SeriesEditDialogPO.java @@ -1,12 +1,15 @@ package com.sap.sailing.selenium.pages.adminconsole.regatta; +import java.util.Arrays; +import java.util.List; + +import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.ui.Select; import com.sap.sailing.selenium.core.BySeleniumId; import com.sap.sailing.selenium.core.FindBy; - import com.sap.sailing.selenium.pages.common.DataEntryDialogPO; public class SeriesEditDialogPO extends DataEntryDialogPO { @@ -23,8 +26,11 @@ public class SeriesEditDialogPO extends DataEntryDialogPO { @FindBy(how = BySeleniumId.class, using = "DefinesResultDiscardingRulesCheckbox") private WebElement definesResultDiscardingRulesCheckbox; - @FindBy(how = BySeleniumId.class, using = "NumberOfRacesListBox") - private WebElement numberOfRacesDropDown; + @FindBy(how = BySeleniumId.class, using = "AddRacesFromListBox") + private WebElement addRacesFromListBox; + + @FindBy(how = BySeleniumId.class, using = "AddRacesToListBox") + private WebElement addRacesToListBox; @FindBy(how = BySeleniumId.class, using = "RaceNamePrefixTextBox") private WebElement raceNamePrefixTextField; @@ -36,15 +42,27 @@ public class SeriesEditDialogPO extends DataEntryDialogPO { super(driver, element); } - public int getSetNumberOfRacesToAdd() { - Select select = new Select(this.numberOfRacesDropDown); + public int getFromNumberOfRacesToAdd() { + Select select = new Select(this.addRacesFromListBox); WebElement option = select.getFirstSelectedOption(); return Integer.parseInt(option.getAttribute("value")); } - public void setSetNumberOfRacesToAdd(int races) { - Select select = new Select(this.numberOfRacesDropDown); + public void setFromNumberOfRacesToAdd(int races) { + Select select = new Select(this.addRacesFromListBox); + select.selectByValue(Integer.toString(races)); + } + + public int getToNumberOfRacesToAdd() { + Select select = new Select(this.addRacesToListBox); + WebElement option = select.getFirstSelectedOption(); + + return Integer.parseInt(option.getAttribute("value")); + } + + public void setToNumberOfRacesToAdd(int races) { + Select select = new Select(this.addRacesToListBox); select.selectByValue(Integer.toString(races)); } @@ -61,14 +79,50 @@ public class SeriesEditDialogPO extends DataEntryDialogPO { this.addRacesButton.click(); } - public void addRaces(int races) { - setSetNumberOfRacesToAdd(races); + public void addRaces(int from, int to) { + setFromNumberOfRacesToAdd(from); + setToNumberOfRacesToAdd(to); pressAddRaces(); } - public void addRaces(int races, String prefix) { - setSetNumberOfRacesToAdd(races); + public void addRaces(int from, int to, String prefix) { + setFromNumberOfRacesToAdd(from); + setToNumberOfRacesToAdd(to); setRaceNamePrefix(prefix); pressAddRaces(); } + + public void renameRace(String race, String newName) { + for(WebElement editorRow : getRaceNameEditors()) { + WebElement valueTextBox = findElementBySeleniumId(editorRow, "ValueTextBox"); + String raceName = valueTextBox.getAttribute("value"); + + if(raceName.equals(race)) { + valueTextBox.clear(); + valueTextBox.sendKeys(newName); + } + } + } + + public void deleteRace(String race) { + deleteRaces(Arrays.asList(race)); + } + + public void deleteRaces(List races) { + for(WebElement editorRow : getRaceNameEditors()) { + WebElement valueTextBox = findElementBySeleniumId(editorRow, "ValueTextBox"); + + if(races.contains(valueTextBox.getAttribute("value"))) { + WebElement removeButton = findElementBySeleniumId(editorRow, "RemoveButton"); + removeButton.click(); + } + } + } + + private List getRaceNameEditors() { + WebElement raceNamesEditor = findElementBySeleniumId("RaceNamesStringListEditorComposite"); + WebElement raceNamesGrid = findElementBySeleniumId(raceNamesEditor, "ExpandedValuesGrid"); + + return raceNamesGrid.findElements(By.tagName("tr")); + } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesListPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesListPO.java index a89e1c4979e..993ab1374d0 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesListPO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tracking/TrackedRacesListPO.java @@ -141,7 +141,7 @@ public class TrackedRacesListPO extends PageArea { // return null; // } - public Object getStatus(TrackedRaceDescriptor race) { + public Status getStatus(TrackedRaceDescriptor race) { List status = getStatus(Arrays.asList(race)); return status.get(0); @@ -169,15 +169,19 @@ public class TrackedRacesListPO extends PageArea { } public void stopTracking(TrackedRaceDescriptor race) { - stopTracking(Arrays.asList(race)); + stopTracking(Arrays.asList(race), false); + } + + public void stopTrackingAndWaitForFinshed(TrackedRaceDescriptor race) { + stopTracking(Arrays.asList(race), true); } public void stopTracking(List races) { - selectRaces(races); - - this.stopTrackingButton.click(); - - waitForAjaxRequests(); + stopTracking(races, false); + } + + public void stopTrackingAndWaitForFinshed(List races) { + stopTracking(races, true); } public void remove(TrackedRaceDescriptor race) { @@ -198,19 +202,20 @@ public class TrackedRacesListPO extends PageArea { waitForAjaxRequests(); } - public void waitForTrackedRace(TrackedRaceDescriptor race) { - waitForTrackedRaces(Arrays.asList(race)); + public void waitForTrackedRace(TrackedRaceDescriptor race, Status status) { + waitForTrackedRaces(Arrays.asList(race), status); } - public void waitForTrackedRace(TrackedRaceDescriptor race, int timeout) { - waitForTrackedRaces(Arrays.asList(race), timeout); + public void waitForTrackedRace(TrackedRaceDescriptor race, Status status, int timeout) { + waitForTrackedRaces(Arrays.asList(race), status, timeout); } - public void waitForTrackedRaces(List races) { - waitForTrackedRaces(races, DEFAULT_WAIT_TIMEOUT); + public void waitForTrackedRaces(List races, Status status) { + waitForTrackedRaces(races, status, DEFAULT_WAIT_TIMEOUT); } - public void waitForTrackedRaces(List races, int timeout) { + public void waitForTrackedRaces(List races, Status status, int timeout) { + final Status statusToWaitFor = status; FluentWait> wait = createFluentWait(races, timeout, DEFAULT_POLLING_INTERVAL); wait.until(new Function, Object>() { @Override @@ -219,7 +224,7 @@ public class TrackedRacesListPO extends PageArea { refresh(); for(Status status : getStatus(races)) { - if(status != Status.TRACKING) + if(status != statusToWaitFor) return Boolean.FALSE; } } catch(TimeoutException exception) { @@ -244,6 +249,18 @@ public class TrackedRacesListPO extends PageArea { // } // } + public void stopTracking(List races, boolean waitForFinished) { + selectRaces(races); + + this.stopTrackingButton.click(); + + waitForAjaxRequests(); + + if(waitForFinished) { + waitForTrackedRaces(races, Status.FINISHED); + } + } + private CellTablePO getTrackedRacesTable() { // if(!this.trackedRacesTable.isDisplayed()) { // return null; diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tractrac/TracTracEventManagementPanelPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tractrac/TracTracEventManagementPanelPO.java index 4288821d5fd..ef2d7a944e5 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tractrac/TracTracEventManagementPanelPO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/adminconsole/tractrac/TracTracEventManagementPanelPO.java @@ -7,9 +7,12 @@ import java.util.LinkedList; import java.util.List; import java.util.Objects; +import org.openqa.selenium.Alert; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedCondition; +import org.openqa.selenium.support.ui.ExpectedConditions; import org.openqa.selenium.support.ui.Select; import com.sap.sailing.selenium.core.FindBy; @@ -199,10 +202,14 @@ public class TracTracEventManagementPanelPO extends PageArea { return regatta; } - public void setReggataForTracking(RegattaDescriptor regatta) { + public void setReggataForTracking(String regatta) { Select select = new Select(this.availableRegattasListBox); - select.selectByValue(regatta.toString()); + select.selectByValue(regatta); + } + + public void setReggataForTracking(RegattaDescriptor regatta) { + setReggataForTracking(regatta.toString()); } /** @@ -249,9 +256,10 @@ public class TracTracEventManagementPanelPO extends PageArea { this.startTrackingButton.click(); - // TODO: Dialog ignore + ExpectedCondition condition = ExpectedConditions.alertIsPresent(); - waitForAjaxRequests(); + if(condition.apply(this.driver) == null) + waitForAjaxRequests(); } public TrackedRacesListPO getTrackedRacesList() { diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/common/CSSConstants.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/common/CSSConstants.java index 5e5a45c0a85..ff5f402d004 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/common/CSSConstants.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/common/CSSConstants.java @@ -7,4 +7,6 @@ public interface CSSConstants { public static final String CSS_STYLE_ATTRIBUTE_NAME = "style"; //$NON-NLS-1$ public static final String CSS_BACKGROUND_IMAGE = "background-image"; //$NON-NLS-1$ + + public static final String CSS_BACKGROUND_COLOR = "background-color"; //$NON-NLS-1$ } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/common/CSSHelper.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/common/CSSHelper.java index e337f19514b..9757d1383e1 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/common/CSSHelper.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/common/CSSHelper.java @@ -6,31 +6,52 @@ import java.util.List; import org.openqa.selenium.WebElement; -public class CSSHelper { +public class CSSHelper { + /** + *

Creates an XPath 1.0 predicate that matches if an element has the given style sheet class in its "class" + * attribute.

+ * + * @param className + * The name of the style sheet class to check for. + * @return + * An XPath predicate that matches if an element has the given style sheet class in its "class" attribute. + */ + public static String containsCSSClassPredicate(String className) { + return "contains(concat(' ',normalize-space(@class),' '),' " + className + " ')"; + } + + public static String containsCSSClassesPredicate(String... classNames) { + StringBuilder builder = new StringBuilder(70 * classNames.length); + for(String className : classNames) { + builder.append(containsCSSClassPredicate(className)); + builder.append(" and "); + } + return builder.substring(0, builder.length() - 5); + } + public static List getCSSClassNames(WebElement element) { String cssClasses = element.getAttribute(CSSConstants.CSS_CLASS_ATTRIBUTE_NAME); - - if(cssClasses == null) - return Collections.emptyList(); - - ArrayList cssClassNames = new ArrayList<>(); - - for(String part : cssClasses.split(" ")) { - String cssClass = part.trim(); - - if(!cssClass.isEmpty()) - cssClassNames.add(cssClass); + final List result; + if (cssClasses == null) { + result = Collections.emptyList(); + } else { + ArrayList cssClassNames = new ArrayList<>(); + for (String part : cssClasses.split(" ")) { + String cssClass = part.trim(); + if (!cssClass.isEmpty()) { + cssClassNames.add(cssClass); + } + } + result = cssClassNames; } - - return cssClassNames; + return result; } public static boolean hasCSSClass(WebElement element, String cssClass) { - if(cssClass == null || cssClass.isEmpty()) + if (cssClass == null || cssClass.isEmpty()) { return true; - + } List cssClasses = getCSSClassNames(element); - return cssClasses.contains(cssClass); } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/common/DataEntryDialogPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/common/DataEntryDialogPO.java index 4a85312d0e2..504786e69e4 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/common/DataEntryDialogPO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/common/DataEntryDialogPO.java @@ -1,7 +1,10 @@ package com.sap.sailing.selenium.pages.common; +import org.openqa.selenium.Alert; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedCondition; +import org.openqa.selenium.support.ui.ExpectedConditions; import com.sap.sailing.selenium.core.BySeleniumId; import com.sap.sailing.selenium.core.FindBy; @@ -46,12 +49,24 @@ public abstract class DataEntryDialogPO extends PageArea { return this.cancelButton.isEnabled(); } - // QUESTION: What should we do, if the button is not enabled? public void pressOk() { + pressOk(false); + } + + public void pressOk(boolean accept) { this.okButton.click(); - // Wait, since we do a callback usually - waitForAjaxRequests(); + ExpectedCondition condition = ExpectedConditions.alertIsPresent(); + Alert alert = condition.apply(this.driver); + + if(alert != null && accept) { + alert.accept(); + } + + if(alert == null || accept) { + // Wait, since we do a callback usually + waitForAjaxRequests(); + } } public void pressCancel() { diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/CellTablePO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/CellTablePO.java index a450fb9d692..84a24a31fe2 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/CellTablePO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/CellTablePO.java @@ -1,9 +1,9 @@ package com.sap.sailing.selenium.pages.gwt; import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Objects; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; @@ -43,11 +43,13 @@ public abstract class CellTablePO extends PageArea { protected static final String FOOT_TAG_NAME = "tfoot"; //$NON-NLS-1$ - private static final String TABLE_HEADER_XPATH = "./thead/tr/th"; + protected static final String TABLE_HEADER_XPATH = "./thead/tr/th"; + + protected static final String GWT_HEADER_XPATH = "./thead/tr//*[@__gwt_header]"; private static final String SORTING_INDICATOR_XPATH = ".//div/div/img"; - private static final String LOADING_ANIMATION_XPATH = ".//td/div/div/div/img"; + private static final String LOADING_ANIMATION_XPATH = "./td/div/div/div/img"; // It seems that the css class is not allways the same //private static final String CELL_TABLE_CSS_CLASS = "GJTB2DRDFQ"; //$NON-NLS-1$ @@ -187,6 +189,28 @@ public abstract class CellTablePO extends PageArea { return entries; } + public T getEntry(Object identifier) { + for(T entry : getEntries()) { + if(Objects.equals(identifier, entry.getIdentifier())) { + return entry; + } + } + + return null; + } + + public List getEntries(List identifiers) { + List entries = new ArrayList<>(); + + for(T entry : getEntries()) { + if(identifiers.contains(entry.getIdentifier())) { + entries.add(entry); + } + } + + return entries; + } + /** *

Selects the specified entry.

* @@ -261,27 +285,17 @@ public abstract class CellTablePO extends PageArea { } protected List getRows() { - List bodies = this.context.findElements(By.tagName(BODY_TAG_NAME)); - - for(WebElement body : bodies) { - if(!body.isDisplayed()) - continue; + List rows = this.context.findElements(By.xpath("./tbody/tr")); + Iterator iterator = rows.iterator(); - List rows = body.findElements(By.tagName("tr")); + while(iterator.hasNext()) { + WebElement row = iterator.next(); - Iterator iterator = rows.iterator(); - - while(iterator.hasNext()) { - WebElement row = iterator.next(); - - if(isRowForLoadingIndicatorOrEmptyTableWidget(row)) - iterator.remove(); - } - - return rows; + if(!row.isDisplayed() || isRowForLoadingIndicatorOrEmptyTableWidget(row)) + iterator.remove(); } - return Collections.emptyList(); + return rows; } protected abstract T createDataEntry(WebElement element); @@ -294,7 +308,7 @@ public abstract class CellTablePO extends PageArea { private boolean isRowForLoadingIndicatorOrEmptyTableWidget(WebElement row) { List images = row.findElements(By.xpath(LOADING_ANIMATION_XPATH)); - if(images.isEmpty() || images.size() > 1) + if(images.size() != 1) return false; String image = images.get(0).getAttribute("src"); diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/CheckBoxPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/CheckBoxPO.java index 4f7f0578bee..defe9811517 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/CheckBoxPO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/CheckBoxPO.java @@ -10,12 +10,12 @@ import com.sap.sailing.selenium.pages.PageArea; import com.sap.sailing.selenium.pages.common.CSSHelper; public class CheckBoxPO extends PageArea { - protected static final String CHECKBOX_TAG_NAME = "span"; //$NON-NLS-1$ + protected static final String TAG_NAME = "span"; //$NON-NLS-1$ private static final String CHECKBOX_CSS_CLASS = "gwt-CheckBox"; @FindBy(how = ByTagName.class, using = "input") - private WebElement checkbox; + private WebElement input; @FindBy(how = ByTagName.class, using = "label") private WebElement label; @@ -29,12 +29,12 @@ public class CheckBoxPO extends PageArea { WebElement element = (WebElement) this.context; String tagName = element.getTagName(); - if(!CHECKBOX_TAG_NAME.equalsIgnoreCase(tagName) || !CSSHelper.hasCSSClass(element, CHECKBOX_CSS_CLASS)) + if(!TAG_NAME.equalsIgnoreCase(tagName) || !CSSHelper.hasCSSClass(element, getCssClassName())) throw new IllegalArgumentException("WebElement does not represent a CheckBox"); } public boolean isEnabled() { - return this.checkbox.isEnabled(); + return this.input.isEnabled(); } public String getLabel() { @@ -42,11 +42,15 @@ public class CheckBoxPO extends PageArea { } public boolean isSelected() { - return this.checkbox.isSelected(); + return this.input.isSelected(); } public void setSelected(boolean selected) { if(selected != isSelected()) - this.checkbox.click(); + this.input.click(); + } + + protected String getCssClassName() { + return CHECKBOX_CSS_CLASS; } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/DataEntryPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/DataEntryPO.java index 9df1b57561b..a1df817df27 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/DataEntryPO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/DataEntryPO.java @@ -2,48 +2,61 @@ package com.sap.sailing.selenium.pages.gwt; import java.util.List; -import org.openqa.selenium.By.ByTagName; +import org.openqa.selenium.By.ByXPath; import org.openqa.selenium.Keys; import org.openqa.selenium.WebElement; - import org.openqa.selenium.interactions.Action; -import org.openqa.selenium.interactions.ClickAction; +import org.openqa.selenium.interactions.Actions; import org.openqa.selenium.interactions.CompositeAction; import org.openqa.selenium.interactions.HasInputDevices; import org.openqa.selenium.interactions.KeyDownAction; import org.openqa.selenium.interactions.KeyUpAction; import org.openqa.selenium.interactions.Keyboard; import org.openqa.selenium.interactions.Mouse; -import org.openqa.selenium.interactions.MoveToOffsetAction; - -import org.openqa.selenium.internal.Locatable; import com.sap.sailing.selenium.core.FindBy; - import com.sap.sailing.selenium.pages.common.CSSHelper; public class DataEntryPO extends CellTableRowPO { protected static final String CELL_TAG_NAME = "td"; //$NON-NLS-1$ - @FindBy(how = ByTagName.class, using = CELL_TAG_NAME) + @FindBy(how = ByXPath.class, using = "./td") private List columns; public DataEntryPO(CellTablePO table, WebElement element) { super(table, element); } - public DataEntryPO() { + protected DataEntryPO() { super(); } + public int getNumberOfColumns() { + return this.columns.size(); + } + public String getColumnContent(int column) { - return this.columns.get(column).getText(); + return this.columns.get(column).getText().trim(); } public String getColumnContent(String name) { return getColumnContent(this.table.getColumnIndex(name)); } + /** + *

Returns an identifier for data entry that uniquely identifies the entry in the containing table. The default + * implementation simply returns the underlying web element, but subclasses should overwrite this method and + * return a more meaningful value. An example would be the String value of one ore more columns.

+ * + * @return + * An identifier that uniquely identifies the entry in the containing table. + */ + public Object getIdentifier() { + // TODO: Test if its valid to return the context (the web element) + // To verify this take the key of an entry and ask the table for the entry with this key! + return this.context; + } + public boolean isSelected() { return CSSHelper.hasCSSClass((WebElement) this.context, CellTablePO.SELECTED_ROW_CSS_CLASS); } @@ -68,26 +81,33 @@ public class DataEntryPO extends CellTableRowPO { } protected Action getSelectAction() { - HasInputDevices devices = (HasInputDevices) this.driver; - Mouse mouse = devices.getMouse(); - Locatable locatable = getLocatableForSelect(); + Actions actions = new Actions(this.driver); + actions.moveToElement(getElementForSelect(), 1, 1); + actions.click(); - CompositeAction action = new CompositeAction(); - action.addAction(new MoveToOffsetAction(mouse, locatable, 1, 1)); - action.addAction(new ClickAction(mouse, null)); - - return action; + return actions.build(); } - protected Locatable getLocatableForSelect() { - return (Locatable) (this.columns.isEmpty() ? this.context : this.columns.get(0)); + /** + *

Returns the element on which to click to select or deselect the data entry in the table. The default + * implementation returns the first column or the row if there are no columns. It may be necessary to overwrite + * this method for the case the first column contains a widget that should not be clicked accidentally.

+ * + * @return + * The element on which to click to select or deselect the data entry in the table. + */ + protected WebElement getElementForSelect() { + return (this.columns.isEmpty() ? getWebElement() : this.columns.get(0)); } protected Action getModifiedSelectAction() { - CompositeAction action = getModifiedCompositeActionAction(); - action.addAction(getSelectAction()); + Actions actions = new Actions(this.driver); + actions.keyDown(Keys.CONTROL); + actions.moveToElement(getElementForSelect(), 1, 1); + actions.click(); + actions.keyUp(Keys.CONTROL); - return action; + return actions.build(); } protected CompositeAction getModifiedCompositeActionAction() { diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/GenericCellTablePO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/GenericCellTablePO.java index 745b511ec2d..3941f2198f8 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/GenericCellTablePO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/GenericCellTablePO.java @@ -65,19 +65,19 @@ public class GenericCellTablePO extends CellTablePO { */ @Override public > T createEntry(S table, WebElement element) { - Class clazz = table.getClass(); - - while(clazz != null) { - try { - Constructor constructor = this.type.getConstructor(clazz, WebElement.class); - + Class clazz = table.getClass(); + + while(clazz != null) { + try { + Constructor constructor = this.type.getConstructor(clazz, WebElement.class); + return constructor.newInstance(table, element); - } catch (Exception exception) { - clazz = clazz.getSuperclass(); - } - } - - throw new RuntimeException("Can't create DataEntry of type " + this.type); + } catch (Exception exception) { + clazz = clazz.getSuperclass(); + } + } + + throw new RuntimeException("Can't create DataEntry of type " + this.type); } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/RadioButtonPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/RadioButtonPO.java new file mode 100644 index 00000000000..ea02498a507 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/gwt/RadioButtonPO.java @@ -0,0 +1,16 @@ +package com.sap.sailing.selenium.pages.gwt; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +public class RadioButtonPO extends CheckBoxPO { + private static final String RADIO_BUTTON_CSS_CLASS = "gwt-RadioButton"; + + public RadioButtonPO(WebDriver driver, WebElement element) { + super(driver, element); + } + + protected String getCssClassName() { + return RADIO_BUTTON_CSS_CLASS; + } +} diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/highcharts/Chart.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/highcharts/Chart.java new file mode 100644 index 00000000000..bd15798ab43 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/highcharts/Chart.java @@ -0,0 +1,25 @@ +package com.sap.sailing.selenium.pages.highcharts; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import com.sap.sailing.selenium.pages.PageArea; +import com.sap.sailing.selenium.pages.common.CSSHelper; + +public class Chart extends PageArea { + private static final String TAG_NAME = "div"; + private static final String CSS_CLASS = "highcharts-container"; + + public Chart(WebDriver driver, WebElement element) { + super(driver, element); + } + + @Override + protected void verify() { + WebElement element = getWebElement(); + + if(!TAG_NAME.equals(element.getTagName()) || !CSSHelper.hasCSSClass(element, CSS_CLASS)) { + throw new IllegalArgumentException("The element " + element + " does not represent a Highchart"); + } + } +} diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/highcharts/LineChart.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/highcharts/LineChart.java new file mode 100644 index 00000000000..013b4a8e3e7 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/highcharts/LineChart.java @@ -0,0 +1,10 @@ +package com.sap.sailing.selenium.pages.highcharts; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +public class LineChart extends Chart { + public LineChart(WebDriver driver, WebElement element) { + super(driver, element); + } +} diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboard/CompetitorChartsSettingsDialogPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboard/CompetitorChartsSettingsDialogPO.java new file mode 100644 index 00000000000..71faa7ee966 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboard/CompetitorChartsSettingsDialogPO.java @@ -0,0 +1,39 @@ +package com.sap.sailing.selenium.pages.leaderboard; + +import java.util.ArrayList; +import java.util.List; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.Select; + +import com.sap.sailing.selenium.core.BySeleniumId; +import com.sap.sailing.selenium.core.FindBy; +import com.sap.sailing.selenium.pages.PageArea; + +public class CompetitorChartsSettingsDialogPO extends PageArea { + + @FindBy(how = BySeleniumId.class, using = "ChartTypeListBox") + private WebElement chartTypeListBox; + + public CompetitorChartsSettingsDialogPO(WebDriver driver, WebElement element) { + super(driver, element); + } + + public void selectChartType(String type) { + Select select = new Select(this.chartTypeListBox); + //select.selectByVisibleText(type); + select.selectByValue(type); + } + + public List getChartTypes() { + List types = new ArrayList<>(); + + Select select = new Select(this.chartTypeListBox); + for(WebElement option : select.getOptions()) { + types.add(option.getAttribute("value")); + } + + return types; + } +} diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboard/LeaderboardPage.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboard/LeaderboardPage.java index 41afdea9cc1..800994bb52b 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboard/LeaderboardPage.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboard/LeaderboardPage.java @@ -1,16 +1,16 @@ package com.sap.sailing.selenium.pages.leaderboard; import org.openqa.selenium.By; +import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import com.sap.sailing.selenium.core.BySeleniumId; import com.sap.sailing.selenium.core.FindBy; - import com.sap.sailing.selenium.pages.HostPage; - import com.sap.sailing.selenium.pages.common.CSSConstants; import com.sap.sailing.selenium.pages.common.HTMLConstants; +import com.sap.sailing.selenium.pages.gwt.CheckBoxPO; /** *

The page object representing the leaderboard.

@@ -19,9 +19,9 @@ import com.sap.sailing.selenium.pages.common.HTMLConstants; * D049941 */ public class LeaderboardPage extends HostPage { - private static final String PAGE_TITLE = "SAP Sailing Analytics Leaderboard"; //$NON-NLS-1$ private static final String LEADERBOAR_PARAMTER_NAME = "name"; //$NON-NLS-1$ + private static final String SHOW_RACE_DETAILS_PARAMTER_NAME = "showRaceDetails"; //$NON-NLS-1$ private static final String AUTO_REFRESH_ENABLED_IMAGE = "url(\"data:image/png;base64," + //$NON-NLS-1$ "iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAR0lEQVR42mOoqan5T2vMMGoJxZZUV1fPB9IOWDC" + //$NON-NLS-1$ @@ -32,6 +32,10 @@ public class LeaderboardPage extends HostPage { "nDQxAAKQDgBbep6klIFBfXy9QW1vbT1NLYKCqqsoAKH6eppbAADD4CoDy72lqCTQIFYhNGGRbAgPEJAyKLSEmYV" + //$NON-NLS-1$ "DFEhgAWpQwdH1C0ziheeqiaT6haY6nedlF01KYXvXJaB0/MJYAANIIBwANoTb3AAAAAElFTkSuQmCC\")"; //$NON-NLS-1$ + public static LeaderboardPage goToPage(WebDriver driver, String root, String leaderboard) { + return goToPage(driver, root, leaderboard, false); + } + /** *

Goes to the specified leaderboard and returns the representing page object.

* @@ -44,29 +48,49 @@ public class LeaderboardPage extends HostPage { * @return * The page object for the administration console. */ - public static LeaderboardPage goToPage(WebDriver driver, String root, String leaderboard) { + public static LeaderboardPage goToPage(WebDriver driver, String root, String leaderboard, boolean raceDetails) { driver.get(root + "gwt/Leaderboard.html?" + getLeaderboard(leaderboard) + //$NON-NLS-1$ - "&" + getGWTCodeServer()); //$NON-NLS-1$ + "&" + getGWTCodeServer() + "&" + getShowRaceDeatails(raceDetails)); //$NON-NLS-1$ - return new LeaderboardPage(driver); + return new LeaderboardPage(driver, leaderboard); } private static String getLeaderboard(String leaderboard) { return LEADERBOAR_PARAMTER_NAME + "=" + leaderboard; //$NON-NLS-1$ } - @FindBy(how = BySeleniumId.class, using = "AutoRefreshToggleButton") - private WebElement autoRefreshToggleButton; + private static String getShowRaceDeatails(boolean raceDetails) { + return SHOW_RACE_DETAILS_PARAMTER_NAME + "=" + raceDetails; //$NON-NLS-1$ + } - @FindBy(how = BySeleniumId.class, using = "LeaderboardTable") - private WebElement leaderboardTable; + @FindBy(how = BySeleniumId.class, using = "LeaderboardDisplayCheckBox") + private WebElement leaderboardDisplayCheckBox; - private LeaderboardPage(WebDriver driver) { + @FindBy(how = BySeleniumId.class, using = "LeaderboardSettingsButton") + private WebElement leaderboardSettingsButton; + + @FindBy(how = BySeleniumId.class, using = "CompetitorChartsDisplayCheckBox") + private WebElement competitorChartsDisplayCheckBox; + + @FindBy(how = BySeleniumId.class, using = "CompetitorChartsSettingsButton") + private WebElement competitorChartsSettingsButton; + + @FindBy(how = BySeleniumId.class, using = "PlayAndPauseAnchor") + private WebElement playAndPauseAnchor; + + @FindBy(how = BySeleniumId.class, using = "LeaderboardCellTable") + private WebElement leaderboardCellTable; + + private LeaderboardPage(WebDriver driver, String leaderboard) { super(driver); + + if(!this.driver.getTitle().equals(leaderboard)) { + throw new IllegalStateException("This is not the leaderboard"); //$NON-NLS-1$ + } } public boolean isAutoRefreshEnabled() { - WebElement image = this.autoRefreshToggleButton.findElement(By.tagName(HTMLConstants.IMAGE_TAG_NAME)); + WebElement image = this.playAndPauseAnchor.findElement(By.tagName(HTMLConstants.IMAGE_TAG_NAME)); String background = image.getCssValue(CSSConstants.CSS_BACKGROUND_IMAGE); if(AUTO_REFRESH_ENABLED_IMAGE.equals(background)) @@ -78,18 +102,60 @@ public class LeaderboardPage extends HostPage { throw new RuntimeException("Can not determine auto refresh state"); //$NON-NLS-1$ } - public void setAutoRefreshEnabled(boolean enabled) { - if(isAutoRefreshEnabled() != enabled) - this.autoRefreshToggleButton.click(); + public void refresh() { + JavascriptExecutor executor = (JavascriptExecutor) driver; + Long finishedCalls = (Long) executor.executeScript( + "return window.PENDING_AJAX_CALLS.numberOfFinishedCalls(arguments[0])", "loadLeaderboardData"); + + this.playAndPauseAnchor.click(); + + waitForAjaxRequestsExecuted("loadLeaderboardData", finishedCalls.intValue() + 1); + + this.playAndPauseAnchor.click(); } - /** - *

Verifies that the current page is the leaderboard by checking the title of the page.

- */ + public CompetitorChartsSettingsDialogPO getCompetitorChartsSettings() { + this.competitorChartsSettingsButton.click(); + + return new CompetitorChartsSettingsDialogPO(this.driver, + findElementBySeleniumId(this.driver, "CompetitorChartsSettingsDialog")); + } + + public LeaderboardSettingsDialogPO getLeaderboardSettings() { + this.leaderboardSettingsButton.click(); + + return new LeaderboardSettingsDialogPO(this.driver, + findElementBySeleniumId(this.driver, "LeaderboardSettingsDialog")); + } + + public LeaderboardTablePO getLeaderboardTable() { + return new LeaderboardTablePO(this.driver, this.leaderboardCellTable); + } + + public void showCompetitorChart(String chart) { + this.competitorChartsSettingsButton.click(); + CompetitorChartsSettingsDialogPO dialog = new CompetitorChartsSettingsDialogPO(this.driver, + findElementBySeleniumId(this.driver, "CompetitorChartsSettingsDialog")); + dialog.selectChartType(chart); + + CheckBoxPO checkbox = new CheckBoxPO(this.driver, this.competitorChartsDisplayCheckBox); + checkbox.setSelected(true); + } + + public void hideCompetitorChart() { + CheckBoxPO checkbox = new CheckBoxPO(this.driver, this.competitorChartsDisplayCheckBox); + checkbox.setSelected(false); + } + +// public LineChart getCompetitorChart() { +// return new LineChart(this.driver, findElementBySeleniumId("CompetitorChart")); +// } + @Override - protected void verify() { - if(!PAGE_TITLE.equals(this.driver.getTitle())) { - throw new IllegalStateException("This is not the leaderboard"); //$NON-NLS-1$ - } + protected void initElements() { + super.initElements(); + + // Wait for the initial loading of the data + waitForAjaxRequestsExecuted("loadLeaderboardData", 1); } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboard/LeaderboardSettingsDialogPO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboard/LeaderboardSettingsDialogPO.java new file mode 100644 index 00000000000..9922a72e74b --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboard/LeaderboardSettingsDialogPO.java @@ -0,0 +1,110 @@ +package com.sap.sailing.selenium.pages.leaderboard; + +import java.util.List; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import com.sap.sailing.selenium.core.BySeleniumId; +import com.sap.sailing.selenium.core.FindBy; +import com.sap.sailing.selenium.pages.common.CSSHelper; +import com.sap.sailing.selenium.pages.common.DataEntryDialogPO; +import com.sap.sailing.selenium.pages.gwt.CheckBoxPO; +import com.sap.sailing.selenium.pages.gwt.RadioButtonPO; + +public class LeaderboardSettingsDialogPO extends DataEntryDialogPO { + @FindBy(how = BySeleniumId.class, using = "RaceSelectionSettingsPanel") + private WebElement raceSelectionSettingsPanel; + + @FindBy(how = BySeleniumId.class, using = "ExplicitRaceSelectionRadioButton") + private WebElement explicitRaceSelectionRadioButton; + + @FindBy(how = BySeleniumId.class, using = "MostCurrentRacesSelectionRadioButton") + private WebElement mostCurrentRacesSelectionRadioButton; + + @FindBy(how = BySeleniumId.class, using = "OverallDetailsSettingsPanel") + private WebElement overallDetailsSettingsPanel; + + @FindBy(how = BySeleniumId.class, using = "RaceDetailsSettingsPanel") + private WebElement raceDetailsSettingsPanel; + + @FindBy(how = BySeleniumId.class, using = "LegDetailsSettingsPanel") + private WebElement legDetailsSettingsPanel; + + @FindBy(how = BySeleniumId.class, using = "ManeuverSettingsPanel") + private WebElement maneuverSettingsPanel; + + public LeaderboardSettingsDialogPO(WebDriver driver, WebElement element) { + super(driver, element); + } + + public void setRacesToDisplay(List races) { + RadioButtonPO button = new RadioButtonPO(this.driver, this.explicitRaceSelectionRadioButton); + + if(!button.isSelected()) { + button.setSelected(true); + } + + for(WebElement element : findAllCheckboxesForSettings(this.raceSelectionSettingsPanel)) { + CheckBoxPO checkbox = new CheckBoxPO(this.driver, element); + checkbox.setSelected(races.contains(checkbox.getLabel())); + } + } + + public void setNumberOfRacesToDisplay(int numberOfRaces) { + RadioButtonPO button = new RadioButtonPO(this.driver, this.mostCurrentRacesSelectionRadioButton); + + if(!button.isSelected()) { + button.setSelected(true); + } + + WebElement textField = findElementBySeleniumId(this.raceSelectionSettingsPanel, "NumberOfMostCurrentRacesIntegerBox"); + textField.clear(); + textField.sendKeys(Integer.toString(numberOfRaces)); + } + + public void setOverallDetails() { + + } + + public void showAllOverallDetails() { + setSelectionForAllSettings(this.overallDetailsSettingsPanel, true); + } + + public void setRaceDetails() { + + } + + public void showAllRaceDetails() { + setSelectionForAllSettings(this.raceDetailsSettingsPanel, true); + } + + public void setLegDetails() { + + } + + public void showAllLegDetails() { + setSelectionForAllSettings(this.legDetailsSettingsPanel, true); + } + + public void setManeuverDetails() { + + } + + public void showAllManeuverDetails() { + setSelectionForAllSettings(this.maneuverSettingsPanel, true); + } + + private void setSelectionForAllSettings(WebElement settingsPanel, boolean selected) { + for(WebElement element : findAllCheckboxesForSettings(settingsPanel)) { + CheckBoxPO checkbox = new CheckBoxPO(this.driver, element); + checkbox.setSelected(selected); + } + } + + private List findAllCheckboxesForSettings(WebElement settingsPanel) { + List e = settingsPanel.findElements(By.xpath(".//span[" + CSSHelper.containsCSSClassPredicate("gwt-CheckBox") + "]")); + return e; + } +} diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboard/LeaderboardTablePO.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboard/LeaderboardTablePO.java index bed046d8804..6485d3c4849 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboard/LeaderboardTablePO.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboard/LeaderboardTablePO.java @@ -1,65 +1,196 @@ package com.sap.sailing.selenium.pages.leaderboard; +import java.util.ArrayList; +import java.util.List; + +import org.openqa.selenium.By; +import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import com.sap.sailing.selenium.pages.common.CSSHelper; + import com.sap.sailing.selenium.pages.gwt.CellTablePO; import com.sap.sailing.selenium.pages.gwt.DataEntryPO; import com.sap.sailing.selenium.pages.leaderboard.LeaderboardTablePO.LeaderboardEntry; public class LeaderboardTablePO extends CellTablePO { - public class LeaderboardEntry extends DataEntryPO { - private static final String TOTAL_RANK = "Total rank"; - private static final String COMPETITOR = "Competitor"; - private static final String NAME = "Name"; + public static class LeaderboardEntry extends DataEntryPO { + private static final int TOTAL_RANK_COLUMN = 0; + private static final int COMPETITOR_COLUMN = 1; + private static final int NAME_COLUMN = 2; - protected LeaderboardEntry(WebElement element) { - super(LeaderboardTablePO.this, element); + private static final String TOTAL_POINTS_COLUMN = "Σ"; + + protected LeaderboardEntry(LeaderboardTablePO table, WebElement element) { + super(table, element); } - - public String getDescriptor() { + @Override + public String getIdentifier() { return getCompetitor(); } - public int getTotalRank() { - return Integer.parseInt(getColumnContent(TOTAL_RANK)); + public Integer getTotalRank() { + return Integer.valueOf(getColumnContent(TOTAL_RANK_COLUMN)); } public String getCompetitor() { - return getColumnContent(COMPETITOR); + return getColumnContent(COMPETITOR_COLUMN); } public String getName() { - return getColumnContent(NAME); + return getColumnContent(NAME_COLUMN); } -// public int getTotalSailedDistance() { -// } -// public void getAverageSpeedOverGround() { -// } -// public void getMaximumSpeedOverGround() { -// } -// public int getTotalDownwindTime() { -// } -// public int getTotalUpwindTime() { -// } -// public int getTotalReachingLegsTime() { -// } -// public int getTotalSailingTime() { -// } -// public int getTotalPoints() { -// } + // Overall details + // ... + + // Race details + // ... + + public Integer getPointsForRace(String race) { + String points = getColumnContent(race); + + if(points == null || points.isEmpty()) { + return null; + } + + try { + return Integer.valueOf(points); + } catch(NumberFormatException exception) { + return Integer.valueOf(-1); + } + } + + // Leg details + // ... + + public Integer getTotalPoints() { + return Integer.valueOf(getColumnContent(TOTAL_POINTS_COLUMN)); + } } + // Style classes to find columns in different levels (children of expanded columns) + // We don't use the style classes for the second and third level at the moment, but they may be needed if more + // functionality is added to the page object soon. + //private static final String FIRST_LEVEL_COLUMN_STYLE_CLASS = ".GCKY0V4BLK"; //$NON-NLS-1$ + //private static final String SECOND_LEVEL_COLUMN_STYLE_CLASS = ".GCKY0V4BFL"; //$NON-NLS-1$ + //private static final String THIRD_LEVEL_COLUMN_STYLE_CLASS = ".GCKY0V4BHL"; //$NON-NLS-1$ + + //private static final String RACE_COLUMN_STYLE_CLASS = ".GCKY0V4BML"; //$NON-NLS-1$ + + private static final String EXPANDABLE_COLUMN_STYLE_CLASS = "openColumn"; //$NON-NLS-1$ + + private static final String RACE_NAME_STYLE_CLASS = "race-name"; //$NON-NLS-1$ + + private static final String EXPANDED_IMAGE = "data:image/png;base64," + //$NON-NLS-1$ + "iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAAj0lEQVR42u2SPQrEIBgFc2JjJQF/Cm0SzxDRE6a" + //$NON-NLS-1$ + "xEQvf8lksW2QlC9slwlS+mUYnpRT+yfQE7xaUUoJzDsbYJeZ57s5pkC6MMdj3HSklxBiH0CaE0J3P6Du4LAuccy" + //$NON-NLS-1$ + "il4OqhLTnkngattTiOA6011FqH0Cbn/D1IaK2xriu895fYtq07w1cWQvzE87HvGHwB11fK7fckleMAAAAASUVOR" + //$NON-NLS-1$ + "K5CYII="; + + private static final String COLLAPSED_IMAGE = "data:image/png;base64," + //$NON-NLS-1$ + "iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAABMUlEQVR42tWUzYqDQAzH+6x6U7Dag60f9bPQ6kk" + //$NON-NLS-1$ + "PraVV1IMP0IOv5cWLeGiWBBzs1rLFXRYa+MMwSX4zk4RZmKYJf6nFZwO32y1omgaSJJFwjXuzgbquw263gyzLSJ" + //$NON-NLS-1$ + "7nEXQ2UFEUAg2WJAnIsjwfuFqt4Hq9MuDpdKJD3gYahkE3GGrG8zxEUcSAYRgCx3HMv1wuKWcSiA7LsiBNUyiKA" + //$NON-NLS-1$ + "vI8h/P5DHVdM+DtdqNnow9jsByYM4Yy4GazAd/3oes6GNv9foe+70m4HhvGYg7mTgKxi03TPEBeCWPatn0NHObu" + //$NON-NLS-1$ + "cDhQrVCu60JVVexGZVmC4zjMHwTB01w+dVlVVSZRFKmzg8VxDIIgPMT879hMAS+XCwMej8ffAXEcbNuG/X5P+j4" + //$NON-NLS-1$ + "is34bBKzXa9JPsM/4D78ABqXmiURzXL4AAAAASUVORK5CYII="; + + // QUESTION: Do we need this predicate in the RACE_COLUMN_XPATH and in the RACE_NAMES_XPATH? + //private static final String RACE_COLUMN_PREDICATE = CSSHelper.containsCSSClassesPredicate(FIRST_LEVEL_COLUMN_STYLE_CLASS, + // RACE_COLUMN_STYLE_CLASS); + + private static final String RACE_COLUMN_XPATH = "./thead/tr/th[//*[@__gwt_header] and .//span[" + + CSSHelper.containsCSSClassPredicate(RACE_NAME_STYLE_CLASS) + " and text() = '%s']]"; + private static final String RACE_NAMES_XPATH = "./thead/tr//*[@__gwt_header]//span[" + + CSSHelper.containsCSSClassPredicate(RACE_NAME_STYLE_CLASS) + "]"; + + private static final String EXPANSION_BUTTON_XPATH = "./span/div[" + + CSSHelper.containsCSSClassPredicate(EXPANDABLE_COLUMN_STYLE_CLASS) + "]/img"; + public LeaderboardTablePO(WebDriver driver, WebElement element) { super(driver, element); } + public boolean isColumnExpandable(int column) { + List headers = this.context.findElements(By.xpath(TABLE_HEADER_XPATH)); + WebElement header = headers.get(column); + + return !header.findElements(By.xpath(EXPANSION_BUTTON_XPATH)).isEmpty(); + } + + public boolean isColumnExpanded(int column) { + List headers = this.context.findElements(By.xpath(TABLE_HEADER_XPATH)); + WebElement header = headers.get(column); + List elements = header.findElements(By.xpath(EXPANSION_BUTTON_XPATH)); + + if(elements.isEmpty() || COLLAPSED_IMAGE.equals(elements.get(0).getAttribute("src"))) + return false; + + return true; + } + + public void expandColumn(int column) { + List headers = this.context.findElements(By.xpath(TABLE_HEADER_XPATH)); + setExpansionState(headers.get(column), true); + } + + public void collapseColumn(int column) { + List headers = this.context.findElements(By.xpath(TABLE_HEADER_XPATH)); + setExpansionState(headers.get(column), false); + } + + public List getRaceNames() { + List raceNames = new ArrayList<>(); + + List elements = this.context.findElements(By.xpath(RACE_NAMES_XPATH)); + + for(WebElement element : elements) { + raceNames.add(element.getText()); + } + + return raceNames; + } + + public void expandRace(String name) { + setExpansionState(getRaceColumn(name), true); + } + + public void collapseRace(String name) { + setExpansionState(getRaceColumn(name), false); + } + @Override protected LeaderboardEntry createDataEntry(WebElement element) { - return new LeaderboardEntry(element); + return new LeaderboardEntry(this, element); + } + + private WebElement getRaceColumn(String race) { + return this.context.findElement(By.xpath(String.format(RACE_COLUMN_XPATH, race))); + } + + private void setExpansionState(WebElement column, boolean expanded) { + try { + WebElement button = getExpansionButton(column); + String image = button.getAttribute("src"); + + boolean toggleSate = (expanded ? COLLAPSED_IMAGE.equals(image) : EXPANDED_IMAGE.equals(image)); + + if(toggleSate) { + button.click(); + + waitForAjaxRequests(); + } + } catch(NoSuchElementException excpetion) { + // The column is not expandable. For a race this happens if its not linked to a tracked race yet. + } + } + + private WebElement getExpansionButton(WebElement header) { + return header.findElement(By.xpath(EXPANSION_BUTTON_XPATH)); } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboardedit/LeaderboardEditingPage.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboardedit/LeaderboardEditingPage.java index 0cc23094a48..a6710fee377 100755 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboardedit/LeaderboardEditingPage.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/pages/leaderboardedit/LeaderboardEditingPage.java @@ -44,7 +44,7 @@ public class LeaderboardEditingPage extends HostPage { } public LeaderboardTable getLeaderboardTable() { - return new LeaderboardTable(this.driver, findElementBySeleniumId(context, "LeaderboardTable")); + return new LeaderboardTable(this.driver, findElementBySeleniumId(context, "LeaderboardCellTable")); } @Override diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestLeaderboardFilterInLeaderboardGroupConfig.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestLeaderboardFilterInLeaderboardGroupConfig.java index 28b5bc282a8..6ca3945bfb4 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestLeaderboardFilterInLeaderboardGroupConfig.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestLeaderboardFilterInLeaderboardGroupConfig.java @@ -34,7 +34,7 @@ public class TestLeaderboardFilterInLeaderboardGroupConfig extends AbstractSelen leaderboardConfiguration.createFlexibleLeaderboard("Test"); leaderboardGroupConfiguration = adminConsole.goToLeaderboardGroupConfiguration(); - LeaderboardGroupDetailsPanelPO leaderboardGroupDetails = leaderboardGroupConfiguration.getLeaderboardGroupDetails(); + LeaderboardGroupDetailsPanelPO leaderboardGroupDetails = leaderboardGroupConfiguration.getLeaderboardGroupDetails("Test"); leaderboardGroupDetails.refreshLeaderboards(); DataEntryPO leaderboardEntry = leaderboardGroupDetails.findLeaderboardEntry("Test"); assertNotNull(leaderboardEntry); diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestStartAndStopTrackingForTracTracEvents.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestStartAndStopTrackingForTracTracEvents.java index 78eeb24e10d..f721b0f90bb 100644 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestStartAndStopTrackingForTracTracEvents.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/adminconsole/TestStartAndStopTrackingForTracTracEvents.java @@ -1,9 +1,27 @@ package com.sap.sailing.selenium.test.adminconsole; +import static org.hamcrest.Matchers.*; + +import static org.junit.Assert.*; + +import org.junit.Before; + import org.junit.Test; +import org.openqa.selenium.Alert; +import org.openqa.selenium.WebDriver.TargetLocator; import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage; + +import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaListCompositePO.RegattaDescriptor; +import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaStructureManagementPanelPO; + +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.Status; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.TrackedRaceDescriptor; + import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO; +import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO.TrackableRaceDescriptor; + import com.sap.sailing.selenium.test.AbstractSeleniumTest; /** @@ -14,30 +32,121 @@ import com.sap.sailing.selenium.test.AbstractSeleniumTest; */ public class TestStartAndStopTrackingForTracTracEvents extends AbstractSeleniumTest { private static final String BMW_CUP_JSON_URL = "http://kml.skitrac.traclive.dk/events/event_20120803_BMWCup/jsonservice.php"; //$NON-NLS-1$ - + + private static final String BMW_CUP_EVENT = "BMW Cup"; + private static final String IDM_2013_EVENT = "IDM 5O5 2013"; + + private static final String BMW_CUP_BOAT_CLASS = "J80"; + private static final String IDM_2013_BOAT_CLASS = "505"; + + private static final String DEFAULT_REGATTA = "Default regatta"; + private static final String BMW_CUP_REGATTA = "BMW Cup (J80)"; //$NON-NLS-1$ + private static final String IDM_2013_REGATTA = "IDM 5O5 2013 (505)"; //$NON-NLS-1$ + + private static final String RACE = "BMW Cup Race %d"; + + private TrackableRaceDescriptor trackableRace; + private TrackedRaceDescriptor trackedRace; + // TODO see below: Complete the test case // private static final String NO_REGATTA = "No regatta"; -// private static final String BMW_CUP_REGATTA = "BMW Cup (J80)"; + // private static final String BMW_CUP_RACE_8 = "BMW Cup Race 8"; + @Before + public void setUp() { + this.trackableRace = new TrackableRaceDescriptor(BMW_CUP_EVENT, String.format(RACE, 1), BMW_CUP_BOAT_CLASS); + this.trackedRace = new TrackedRaceDescriptor(BMW_CUP_REGATTA, BMW_CUP_BOAT_CLASS, String.format(RACE, 1)); + + clearState(getContextRoot()); + } /** *

Test for the correct start and stop of a tracking.

*/ @Test public void testStartAndStopTrackingWithCorrectRegatta() { + RegattaDescriptor bmwCupDescriptor = new RegattaDescriptor(BMW_CUP_EVENT, BMW_CUP_BOAT_CLASS); + AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); + RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure(); + regattaStructure.createRegatta(bmwCupDescriptor); + TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents(); tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL); - // TODO: Complete the test case! - //tracTracEvents.startTracking(BMW_CUP_RACE_8, BMW_CUP_REGATTA, false, false, false); + tracTracEvents.setReggataForTracking(bmwCupDescriptor); + tracTracEvents.setTrackSettings(false, false, false); + tracTracEvents.startTrackingForRace(this.trackableRace); - //assertThat(tracTracEvents.getTrackedRaces(), hasItem(12)); + TrackedRacesListPO trackedRacesList = tracTracEvents.getTrackedRacesList(); + trackedRacesList.waitForTrackedRace(this.trackedRace, Status.TRACKING); - //tracTracEvents.stopTracking("BMW_CUP_RACE_8"); + assertThat(trackedRacesList.getStatus(this.trackedRace), equalTo(Status.TRACKING)); - //assertThat(tracTracEvents.getTrackedRaces(), not(hasItem(12))); + trackedRacesList.stopTracking(this.trackedRace); + trackedRacesList.waitForTrackedRace(this.trackedRace, Status.FINISHED); + + assertThat(trackedRacesList.getStatus(this.trackedRace), equalTo(Status.FINISHED)); + } + + @Test + public void testStartTrackingWithDefaultReggataWhileReggataForBoatClassExists() { + AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); + + RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure(); + regattaStructure.createRegatta(new RegattaDescriptor(BMW_CUP_EVENT, BMW_CUP_BOAT_CLASS)); + + TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents(); + tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL); + + tracTracEvents.setReggataForTracking(DEFAULT_REGATTA); + tracTracEvents.setTrackSettings(false, false, false); + tracTracEvents.startTrackingForRace(this.trackableRace); + + TargetLocator locator = getWebDriver().switchTo(); + Alert alert = locator.alert(); + String text = alert.getText(); + + alert.dismiss(); + + String message = "There is at least one regatta for the selected boat classes. Do you really want " + + "to use the 'no regatta' selection?"; + + assertThat(text, containsString("WARNING")); + assertThat(text, containsString(message)); + } + + @Test + public void testStartTrackingWithReggataAndNoneMatchingBoatClass() { + RegattaDescriptor bmwCupDescriptor = new RegattaDescriptor(BMW_CUP_EVENT, BMW_CUP_BOAT_CLASS); + RegattaDescriptor idm2013Descriptor = new RegattaDescriptor(IDM_2013_EVENT, IDM_2013_BOAT_CLASS); + + AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); + + RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure(); + regattaStructure.createRegatta(bmwCupDescriptor); + regattaStructure.createRegatta(idm2013Descriptor); + + TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents(); + tracTracEvents.listTrackableRaces(BMW_CUP_JSON_URL); + + tracTracEvents.setReggataForTracking(idm2013Descriptor); + tracTracEvents.setTrackSettings(false, false, false); + tracTracEvents.startTrackingForRace(this.trackableRace); + + TargetLocator locator = getWebDriver().switchTo(); + Alert alert = locator.alert(); + String text = alert.getText(); + + alert.dismiss(); + + String message = String.format("The selected races contain boat classes which are not the same as " + + "the boat class '%s' of the selected regatta. Do you really want to use the regatta '%s'?", + IDM_2013_BOAT_CLASS, IDM_2013_REGATTA); + + assertThat(text, containsString("WARNING")); + assertThat(text, containsString(message)); } } diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestColumnsInLeaderboard.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestColumnsInLeaderboard.java new file mode 100644 index 00000000000..cff94a91402 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestColumnsInLeaderboard.java @@ -0,0 +1,126 @@ +package com.sap.sailing.selenium.test.leaderboard; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage; +import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardConfigurationPanelPO; +import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO; +import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO.RaceDescriptor; +import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaDetailsCompositePO; +import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaListCompositePO.RegattaDescriptor; +import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaStructureManagementPanelPO; +import com.sap.sailing.selenium.pages.adminconsole.regatta.SeriesEditDialogPO; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.Status; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.TrackedRaceDescriptor; +import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO; +import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO.TrackableRaceDescriptor; +import com.sap.sailing.selenium.pages.leaderboard.LeaderboardPage; +import com.sap.sailing.selenium.pages.leaderboard.LeaderboardSettingsDialogPO; +import com.sap.sailing.selenium.pages.leaderboard.LeaderboardTablePO; +import com.sap.sailing.selenium.pages.leaderboard.LeaderboardTablePO.LeaderboardEntry; +import com.sap.sailing.selenium.test.AbstractSeleniumTest; + +public class TestColumnsInLeaderboard extends AbstractSeleniumTest { + private static final String KIELER_WOCHE_2013_JSON_URL = + "http://secondary.traclive.dk/events/event_20130621_KielerWoch/jsonservice.php"; //$NON-NLS-1$ + + private static final String REGATTA = "KW 2013 Offshore Kaiser-Pokal"; //$NON-NLS-1$ + + private static final String LEADERBOARD = "KW 2013 Offshore Kaiser-Pokal (ORC)"; //$NON-NLS-1$ + + private static final String EVENT = "Kieler Woche 2013"; //$NON-NLS-1$ + private static final String BOAT_CLASS = "ORC"; //$NON-NLS-1$ + private static final String RACE = "Kaiserpokal"; //$NON-NLS-1$ + + private RegattaDescriptor regatta; + + private TrackableRaceDescriptor trackableRace; + private TrackedRaceDescriptor trackedRace; + private RaceDescriptor raceColumn; + + + @Before + public void setUp() { + this.regatta = new RegattaDescriptor(REGATTA, BOAT_CLASS); + + this.trackableRace = new TrackableRaceDescriptor(EVENT, RACE, BOAT_CLASS); + this.trackedRace = new TrackedRaceDescriptor(this.regatta.toString(), BOAT_CLASS, RACE); + this.raceColumn = new RaceDescriptor("R1", "Default", false, false, 0.0); + + clearState(getContextRoot()); + configureLeaderboard(); + } + + @Test + public void testCorrectDisplayOfAllColumns() { + LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, true); + LeaderboardTablePO leaderboardTabel = leaderboard.getLeaderboardTable(); + + LeaderboardSettingsDialogPO settings = leaderboard.getLeaderboardSettings(); + settings.setRacesToDisplay(leaderboardTabel.getRaceNames()); + settings.showAllOverallDetails(); + settings.showAllRaceDetails(); + settings.showAllLegDetails(); + settings.showAllManeuverDetails(); + settings.pressOk(); + + boolean stateHasChanged; + + do { + List headers = leaderboardTabel.getColumnHeaders(); + stateHasChanged = false; + + // Since this test is very expensive we iterate from the end to the beginning because the lower + // indexes are still valid after the expansion of a column. + for(int i = headers.size() - 1; i >= 0; i--) { + if(leaderboardTabel.isColumnExpandable(i) && !leaderboardTabel.isColumnExpanded(i)) { + leaderboardTabel.expandColumn(i); + stateHasChanged = true; + + List entries = leaderboardTabel.getEntries(); + // NOTE: We have to resolve the headers again for the assertion since there should be more now + // because of the expansion + assertThat(entries.get(0).getNumberOfColumns(), equalTo(leaderboardTabel.getColumnHeaders().size())); + } + } + } while(stateHasChanged); + } + + private void configureLeaderboard() { + // Open the admin console for some configuration steps + AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); + + // Create a regatta with 1 series and 5 races as well as a leaderborad + RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure(); + regattaStructure.createRegatta(this.regatta); + + RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta); + SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME); + seriesDialog.addRaces(1, 1); + seriesDialog.pressOk(); + + // Start the tracking for the races and wait until they are ready to use + TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents(); + tracTracEvents.listTrackableRaces(KIELER_WOCHE_2013_JSON_URL); + tracTracEvents.setReggataForTracking(this.regatta); + tracTracEvents.setTrackSettings(false, false, false); + tracTracEvents.startTrackingForRace(this.trackableRace); + + TrackedRacesListPO trackedRacesList = tracTracEvents.getTrackedRacesList(); + trackedRacesList.waitForTrackedRace(this.trackedRace, Status.TRACKING); + trackedRacesList.stopTracking(this.trackedRace); + + LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration(); + leaderboardConfiguration.createRegattaLeaderboard(this.regatta); + + LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(LEADERBOARD); + leaderboardDetails.linkRace(this.raceColumn, this.trackedRace); + } +} diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestLeaderboardConfiguration.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestLeaderboardConfiguration.java new file mode 100644 index 00000000000..7ae0d84e739 --- /dev/null +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboard/TestLeaderboardConfiguration.java @@ -0,0 +1,245 @@ +package com.sap.sailing.selenium.test.leaderboard; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +import com.sap.sailing.selenium.core.WebDriverWindow; +import com.sap.sailing.selenium.core.WindowManager; +import com.sap.sailing.selenium.pages.adminconsole.AdminConsolePage; +import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardConfigurationPanelPO; +import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO; +import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO.RaceDescriptor; +import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaDetailsCompositePO; +import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaListCompositePO.RegattaDescriptor; +import com.sap.sailing.selenium.pages.adminconsole.regatta.RegattaStructureManagementPanelPO; +import com.sap.sailing.selenium.pages.adminconsole.regatta.SeriesEditDialogPO; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.Status; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.TrackedRaceDescriptor; +import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO; +import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO.TrackableRaceDescriptor; +import com.sap.sailing.selenium.pages.leaderboard.LeaderboardPage; +import com.sap.sailing.selenium.pages.leaderboard.LeaderboardTablePO; +import com.sap.sailing.selenium.pages.leaderboard.LeaderboardTablePO.LeaderboardEntry; +import com.sap.sailing.selenium.test.AbstractSeleniumTest; + +public class TestLeaderboardConfiguration extends AbstractSeleniumTest { + private static final String IDM_5O5_2013_JSON_URL = + "http://traclive.dk/events/event_20130917_IDMO/jsonservice.php"; //$NON-NLS-1$ + + private static final String REGATTA = "IDM 2013"; //$NON-NLS-1$ + + private static final String LEADERBOARD = "IDM 2013 (505)"; //$NON-NLS-1$ + + private static final String EVENT = "IDM 5O5 2013"; //$NON-NLS-1$ + private static final String BOAT_CLASS = "505"; //$NON-NLS-1$ + private static final String RACE = "Race %d"; //$NON-NLS-1$ + + private RegattaDescriptor regatta; + + private List trackableRaces; + private List trackedRaces; + private List leaderboardRaces; + + @Before + public void setUp() { + this.regatta = new RegattaDescriptor(REGATTA, BOAT_CLASS); + + this.trackableRaces = new ArrayList<>(); + this.trackedRaces = new ArrayList<>(); + this.leaderboardRaces = new ArrayList<>(); + + for(int i = 1; i <= 5; i++) { + TrackableRaceDescriptor trackableRace = new TrackableRaceDescriptor(EVENT, String.format(RACE, i), BOAT_CLASS); + TrackedRaceDescriptor trackedRace = new TrackedRaceDescriptor(this.regatta.toString(), BOAT_CLASS, String.format(RACE, i)); + RaceDescriptor leaderboardRace = new RaceDescriptor(String.format("R%s", i), "Default", false, false, 0); + + this.trackableRaces.add(trackableRace); + this.trackedRaces.add(trackedRace); + this.leaderboardRaces.add(leaderboardRace); + } + + clearState(getContextRoot()); + + configureLeaderboard(); + } + + @Test + public void testDynamicRaceLinking() { + // Open a second window which we use for the leaderboard later + WindowManager manager = this.environment.getWindowManager(); + WebDriverWindow leaderboardWindow = manager.getCurrentWindow(); + WebDriverWindow adminConsoleWindow = manager.openNewWindow(); + + // Open the leaderboard and check for "empty" leaderboard + LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, false); + LeaderboardTablePO table = leaderboard.getLeaderboardTable(); + List races = table.getRaceNames(); + + assertThat(races.size(), equalTo(5)); + assertThat(table.getEntries().size(), equalTo(0)); + + adminConsoleWindow.switchToWindow(); + AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); + LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration(); + LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(this.regatta.toString()); + + Integer[] expectedPointsForFindelJens = new Integer[] {2, 18, 12, 4, 7}; + Integer[] expectedRankForFindelJens = new Integer[] {2, 8, 10, 6, 5}; + + // Link the races and check the leaderboard again + for(int i = 0; i < 5; i++) { + leaderboardDetails.linkRace(this.leaderboardRaces.get(i), this.trackedRaces.get(i)); + + leaderboardWindow.switchToWindow(); + + leaderboard.refresh(); + + List allEntries = table.getEntries(); + LeaderboardEntry findelJens = table.getEntry("8875"); + Integer points = findelJens.getPointsForRace(String.format("R%s", i + 1)); + Integer rank = findelJens.getTotalRank(); + + // Assertions + assertThat("Number of competitors does not match", + allEntries.size(), equalTo(28)); + assertThat("Points for race 'R" + (i + 1) + "' do not match for competitor '8875' (Findel, Jens)", + points, equalTo(expectedPointsForFindelJens[i])); + assertThat("Total rank after " + (i + 1) + " race(s) does not match for competitor '8875' (Findel, Jens)", + rank, equalTo(expectedRankForFindelJens[i])); + + adminConsoleWindow.switchToWindow(); + } + } + + @Test + public void testDynamicRaceDeletion() { + WindowManager manager = this.environment.getWindowManager(); + WebDriverWindow adminConsoleWindow = manager.getCurrentWindow(); + WebDriverWindow leaderboardWindow = manager.openNewWindow(); + + // Go to the administration console and link al 5 races + AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); + LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration(); + LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(this.regatta.toString()); + + leaderboardDetails.linkRace(this.leaderboardRaces.get(0), this.trackedRaces.get(0)); + leaderboardDetails.linkRace(this.leaderboardRaces.get(1), this.trackedRaces.get(1)); + leaderboardDetails.linkRace(this.leaderboardRaces.get(2), this.trackedRaces.get(2)); + leaderboardDetails.linkRace(this.leaderboardRaces.get(3), this.trackedRaces.get(3)); + leaderboardDetails.linkRace(this.leaderboardRaces.get(4), this.trackedRaces.get(4)); + + // Open the leaderboard in our second window + leaderboardWindow.switchToWindow(); + + LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, false); + LeaderboardTablePO table = leaderboard.getLeaderboardTable(); + + // Go back to the administration console and delete third race + adminConsoleWindow.switchToWindow(); + + RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure(); + RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta); + SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME); + seriesDialog.deleteRace("R3"); + seriesDialog.pressOk(true); + + // Now we can check the result with our expectation + leaderboardWindow.switchToWindow(); + + leaderboard.refresh(); + + assertThat("Race names do not match after deletion of race 'R3'", + table.getRaceNames(), equalTo(Arrays.asList("R1", "R2", "R4", "R5"))); + } + + @Ignore("This test belongs to bug 1892 and currently fails. It is currently enabled on branch bug1892.") + @Test + public void testDynamicRenamingOfRace() { + WindowManager manager = this.environment.getWindowManager(); + WebDriverWindow adminConsoleWindow = manager.getCurrentWindow(); + WebDriverWindow leaderboardWindow = manager.openNewWindow(); + + // Go to the administration console and link al 5 races + AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); + LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration(); + LeaderboardDetailsPanelPO leaderboardDetails = leaderboardConfiguration.getLeaderboardDetails(this.regatta.toString()); + + leaderboardDetails.linkRace(this.leaderboardRaces.get(0), this.trackedRaces.get(0)); + leaderboardDetails.linkRace(this.leaderboardRaces.get(1), this.trackedRaces.get(1)); + leaderboardDetails.linkRace(this.leaderboardRaces.get(2), this.trackedRaces.get(2)); + leaderboardDetails.linkRace(this.leaderboardRaces.get(3), this.trackedRaces.get(3)); + leaderboardDetails.linkRace(this.leaderboardRaces.get(4), this.trackedRaces.get(4)); + + // Open the leaderboard in our second window + leaderboardWindow.switchToWindow(); + + LeaderboardPage leaderboard = LeaderboardPage.goToPage(getWebDriver(), getContextRoot(), LEADERBOARD, false); + LeaderboardTablePO table = leaderboard.getLeaderboardTable(); + + // Go back to the administration console and rename the first race + adminConsoleWindow.switchToWindow(); + + RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure(); + RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta); + SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME); + seriesDialog.renameRace("R1", "Q"); + seriesDialog.pressOk(true); + + // Now we can check the result with our expectation + leaderboardWindow.switchToWindow(); + + leaderboard.refresh(); + + List races = table.getRaceNames(); + + assertThat("Race names do not match after renaming race 'R1' to 'Q'", + races, equalTo(Arrays.asList("Q", "R2", "R3", "R4", "R5"))); + } + + private void configureLeaderboard() { + // Open the admin console for some configuration steps + AdminConsolePage adminConsole = AdminConsolePage.goToPage(getWebDriver(), getContextRoot()); + + // Create a regatta with 1 series and 5 races as well as a leaderborad + RegattaStructureManagementPanelPO regattaStructure = adminConsole.goToRegattaStructure(); + regattaStructure.createRegatta(this.regatta); + + RegattaDetailsCompositePO regattaDetails = regattaStructure.getRegattaDetails(this.regatta); + SeriesEditDialogPO seriesDialog = regattaDetails.editSeries(RegattaStructureManagementPanelPO.DEFAULT_SERIES_NAME); + seriesDialog.addRaces(1, 5); + seriesDialog.pressOk(); + + LeaderboardConfigurationPanelPO leaderboardConfiguration = adminConsole.goToLeaderboardConfiguration(); + leaderboardConfiguration.createRegattaLeaderboard(this.regatta); + + // Start the tracking for the races and wait until they are ready to use + TracTracEventManagementPanelPO tracTracEvents = adminConsole.goToTracTracEvents(); + tracTracEvents.listTrackableRaces(IDM_5O5_2013_JSON_URL); + tracTracEvents.setReggataForTracking(this.regatta); + tracTracEvents.setTrackSettings(false, false, false); + // TODO: There exists a bug in Selenium with key modifiers (Issue 3734 and 6817), so we can't use multi + // selection (Firefox on Windows) + //tracTracEvents.startTrackingForRaces(this.trackableRaces); + for(TrackableRaceDescriptor race : this.trackableRaces) { + tracTracEvents.startTrackingForRace(race); + } + + TrackedRacesListPO trackedRacesList = tracTracEvents.getTrackedRacesList(); + trackedRacesList.waitForTrackedRaces(this.trackedRaces, Status.TRACKING); + // TODO: There exists a bug in Selenium with key modifiers (Issue 3734 and 6817), so we can't use multi + // selection (Firefox on Windows) + //trackedRacesList.stopTracking(this.trackedRaces); + for(TrackedRaceDescriptor race : this.trackedRaces) { + trackedRacesList.stopTracking(race); + } + } +} diff --git a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboardedit/TestLeaderboardEditing.java b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboardedit/TestLeaderboardEditing.java index b5163b5c646..d2ece6d8938 100755 --- a/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboardedit/TestLeaderboardEditing.java +++ b/java/com.sap.sailing.selenium.test/src/com/sap/sailing/selenium/test/leaderboardedit/TestLeaderboardEditing.java @@ -12,6 +12,7 @@ import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardConfig import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO; import com.sap.sailing.selenium.pages.adminconsole.leaderboard.LeaderboardDetailsPanelPO.RaceDescriptor; import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO; +import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.Status; import com.sap.sailing.selenium.pages.adminconsole.tracking.TrackedRacesListPO.TrackedRaceDescriptor; import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO; import com.sap.sailing.selenium.pages.adminconsole.tractrac.TracTracEventManagementPanelPO.TrackableRaceDescriptor; @@ -70,7 +71,7 @@ public class TestLeaderboardEditing extends AbstractSeleniumTest { tracTracEvents.startTrackingForRace(trackableRace); TrackedRacesListPO trackedRacesList = tracTracEvents.getTrackedRacesList(); - trackedRacesList.waitForTrackedRace(trackedRace); + trackedRacesList.waitForTrackedRace(trackedRace, Status.TRACKING); trackedRacesList.stopTracking(trackedRace); } diff --git a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/async/MarkedAsyncCallback.java b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/async/MarkedAsyncCallback.java index 0b56dfcf8cb..9313bef647f 100644 --- a/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/async/MarkedAsyncCallback.java +++ b/java/com.sap.sse.gwt/src/com/sap/sse/gwt/client/async/MarkedAsyncCallback.java @@ -7,7 +7,7 @@ import com.google.gwt.user.client.rpc.AsyncCallback; *

Decorator for asynchronous remote procedure calls which should be marked as pending until they complete. * Such calls will be marked using a counter, which is necessary in UI tests to be able able to tell exactly when an * asynchronous request has finished. With this counter a test which triggers a request (which can cause additional - * request) can wait until the requests have finished. It's guaranteed that the counter is decremented no matter if + * requests) can wait until the requests have finished. It's guaranteed that the counter is decremented no matter if * the call was successful or not.

* *

Note: Since the counter for pending Ajax requests is incremented as soon as an instance of this class is created diff --git a/java/org.openqa.selenium.osgi/.classpath b/java/org.openqa.selenium.osgi/.classpath index 59bd94e2a9e..ba51e2993d9 100644 --- a/java/org.openqa.selenium.osgi/.classpath +++ b/java/org.openqa.selenium.osgi/.classpath @@ -1,6 +1,7 @@ - + + @@ -30,7 +31,6 @@ - diff --git a/java/org.openqa.selenium.osgi/META-INF/MANIFEST.MF b/java/org.openqa.selenium.osgi/META-INF/MANIFEST.MF index b26eb65cd44..5ec6954ee96 100644 --- a/java/org.openqa.selenium.osgi/META-INF/MANIFEST.MF +++ b/java/org.openqa.selenium.osgi/META-INF/MANIFEST.MF @@ -2,8 +2,8 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Selenium Bundle-SymbolicName: org.openqa.selenium.osgi -Bundle-Version: 2.39.0 -Bundle-ClassPath: selenium-java-2.39.0.jar, +Bundle-Version: 2.40.0 +Bundle-ClassPath: selenium-java-2.40.0.jar, lib/apache-mime4j-0.6.jar, lib/bsh-1.3.0.jar, lib/cglib-nodep-2.1_3.jar, @@ -33,7 +33,7 @@ Bundle-ClassPath: selenium-java-2.39.0.jar, lib/nekohtml-1.9.19.jar, lib/netty-3.5.7.Final.jar, lib/operadriver-1.5.jar, - lib/phantomjsdriver-1.0.4.jar, + lib/phantomjsdriver-1.1.0.jar, lib/protobuf-java-2.4.1.jar, lib/sac-1.3.jar, lib/serializer-2.7.1.jar, @@ -44,6 +44,7 @@ Bundle-ClassPath: selenium-java-2.39.0.jar, Bundle-Vendor: openqa Export-Package: com.google.common.annotations, com.google.common.base, + com.google.common.base.internal, com.google.common.cache, com.google.common.collect, com.google.common.eventbus, @@ -55,7 +56,6 @@ Export-Package: com.google.common.annotations, com.google.common.reflect, com.google.common.util.concurrent, org.openqa.selenium, - org.openqa.selenium.android, org.openqa.selenium.browserlaunchers, org.openqa.selenium.browserlaunchers.locators, org.openqa.selenium.chrome, @@ -68,9 +68,7 @@ Export-Package: com.google.common.annotations, org.openqa.selenium.interactions.internal, org.openqa.selenium.interactions.touch, org.openqa.selenium.internal, - org.openqa.selenium.internal.seleniumemulation, org.openqa.selenium.io, - org.openqa.selenium.iphone, org.openqa.selenium.lift, org.openqa.selenium.lift.find, org.openqa.selenium.lift.match, diff --git a/java/org.openqa.selenium.osgi/build.properties b/java/org.openqa.selenium.osgi/build.properties index c5389a34626..ea974378c79 100644 --- a/java/org.openqa.selenium.osgi/build.properties +++ b/java/org.openqa.selenium.osgi/build.properties @@ -28,7 +28,6 @@ bin.includes = META-INF/,\ lib/nekohtml-1.9.19.jar,\ lib/netty-3.5.7.Final.jar,\ lib/operadriver-1.5.jar,\ - lib/phantomjsdriver-1.0.4.jar,\ lib/protobuf-java-2.4.1.jar,\ lib/sac-1.3.jar,\ lib/serializer-2.7.1.jar,\ @@ -36,4 +35,5 @@ bin.includes = META-INF/,\ lib/xalan-2.7.1.jar,\ lib/xercesImpl-2.10.0.jar,\ lib/xml-apis-1.4.01.jar,\ - selenium-java-2.39.0.jar + selenium-java-2.40.0.jar,\ + lib/phantomjsdriver-1.1.0.jar diff --git a/java/org.openqa.selenium.osgi/lib/phantomjsdriver-1.0.4.jar b/java/org.openqa.selenium.osgi/lib/phantomjsdriver-1.1.0.jar similarity index 62% rename from java/org.openqa.selenium.osgi/lib/phantomjsdriver-1.0.4.jar rename to java/org.openqa.selenium.osgi/lib/phantomjsdriver-1.1.0.jar index 9d5965e42bd..579f2b391e8 100644 Binary files a/java/org.openqa.selenium.osgi/lib/phantomjsdriver-1.0.4.jar and b/java/org.openqa.selenium.osgi/lib/phantomjsdriver-1.1.0.jar differ diff --git a/java/org.openqa.selenium.osgi/pom.xml b/java/org.openqa.selenium.osgi/pom.xml index aac8c64571b..80d28b3b37b 100644 --- a/java/org.openqa.selenium.osgi/pom.xml +++ b/java/org.openqa.selenium.osgi/pom.xml @@ -8,6 +8,6 @@ 1.0.0-SNAPSHOT org.openqa.selenium.osgi - 2.39.0 + 2.40.0 eclipse-plugin diff --git a/java/org.openqa.selenium.osgi/selenium-java-2.39.0.jar b/java/org.openqa.selenium.osgi/selenium-java-2.39.0.jar deleted file mode 100644 index 4add771e4da..00000000000 Binary files a/java/org.openqa.selenium.osgi/selenium-java-2.39.0.jar and /dev/null differ diff --git a/java/org.openqa.selenium.osgi/selenium-java-2.40.0.jar b/java/org.openqa.selenium.osgi/selenium-java-2.40.0.jar new file mode 100644 index 00000000000..15abbb56368 Binary files /dev/null and b/java/org.openqa.selenium.osgi/selenium-java-2.40.0.jar differ