Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 155 additions & 0 deletions src/org/labkey/test/components/ui/AppPageHeader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*
* Copyright (c) 2018-2026 LabKey Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.labkey.test.components.ui;

import org.labkey.test.Locator;
import org.labkey.test.components.Component;
import org.labkey.test.components.WebDriverComponent;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import static org.labkey.test.util.selenium.WebElementUtils.tryMapElement;

/**
* Wraps <AppPageHeader/> component
*/
public class AppPageHeader extends WebDriverComponent<AppPageHeader.ElementCache>
{
private final WebElement _el;
private final WebDriver _driver;

protected AppPageHeader(WebElement element, WebDriver driver)
{
_el = element;
_driver = driver;
}

@Override
public WebElement getComponentElement()
{
return _el;
}

@Override
public WebDriver getDriver()
{
return _driver;
}

/**
* Gets the text of the page header. If there is no header returns an empty string.
*
* @return Text from the page title, empty string if element is not there.
*/
public String getTitle()
{
return tryMapElement(elementCache().title, WebElement::getText);
}

/**
* Get the text of the subtitle of the page. If there is no subtitle, return an empty string.
*
* @return Text from the page subtitle, empty string if element is not there.
*/
public String getSubtitle()
{
return tryMapElement(elementCache().subtitle, WebElement::getText);
}

/**
* Get the text of the description of the page. If there is no description, returns an empty string.
*
* @return Text from the page description, empty string if element is not there.
*/
public String getDescription()
{
return tryMapElement(elementCache().description, WebElement::getText);
}

/**
* @throws UnsupportedOperationException Label color is not supported by AppPageHeader.
*/
public String getLabelColor()
{
throw new UnsupportedOperationException("Label color is not supported by AppPageHeader.");
}

/**
* Get the source file of the page icon. If there is no icon returns an empty string.
*
* @return The 'src' attribute header icon, empty string if element is not there.
*/
public String getIconSource()
{
return tryMapElement(elementCache().icon, el -> el.getDomAttribute("src"));
}

@Override
protected ElementCache newElementCache()
{
return new ElementCache();
}

protected class ElementCache extends Component<ElementCache>.ElementCache
{
public final WebElement icon = getIconLocator().findWhenNeeded(this);
public final WebElement title = getTitleLocator().findWhenNeeded(this);
public final WebElement subtitle = getSubtitleLocator().findWhenNeeded(this);
public final WebElement description = getDescriptionLocator().findWhenNeeded(this);

protected Locator.XPathLocator getIconLocator()
{
return Locator.byClass("app-page-header__icon");
}

protected Locator.XPathLocator getTitleLocator()
{
return Locator.byClass("app-page-header__title");
}

protected Locator.XPathLocator getSubtitleLocator()
{
return Locator.byClass("app-page-header__subtitle");
}

protected Locator.XPathLocator getDescriptionLocator()
{
return Locator.byClass("app-page-header__description");
}
}

public static class AppPageHeaderFinder extends WebDriverComponentFinder<AppPageHeader, AppPageHeaderFinder>
{
private final Locator.XPathLocator _baseLocator = Locator.byClass("app-page-header");

public AppPageHeaderFinder(WebDriver driver)
{
super(driver);
}

@Override
protected AppPageHeader construct(WebElement el, WebDriver driver)
{
return new AppPageHeader(el, driver);
}

@Override
protected Locator locator()
{
return _baseLocator;
}
}
}
107 changes: 107 additions & 0 deletions src/org/labkey/test/components/ui/PageDetailHeader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Copyright (c) 2018-2026 LabKey Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.labkey.test.components.ui;

import org.labkey.test.Locator;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import static org.labkey.test.util.selenium.WebElementUtils.tryMapElement;

/**
* Wraps <PageDetailHeader/> component
*/
public class PageDetailHeader extends AppPageHeader
{
protected PageDetailHeader(WebElement element, WebDriver driver)
{
super(element, driver);
}

/**
* Get the rgb style value for the label color in the header
*
* @return A string such as "rgb(104, 204, 202)" as used in the "color-icon__circle-small" "i" element in the detail header or the empty string if element is not there.
*/
@Override
public String getLabelColor()
{
return tryMapElement(elementCache().colorIcon, el -> el.getCssValue("background-color"));
}

@Override
protected ElementCache elementCache()
{
return (ElementCache) super.elementCache();
}

@Override
protected ElementCache newElementCache()
{
return new ElementCache();
}

protected class ElementCache extends AppPageHeader.ElementCache
{
@Override
protected Locator.XPathLocator getTitleLocator()
{
return Locator.byClass("detail__header--name");
}

@Override
protected Locator.XPathLocator getDescriptionLocator()
{
return Locator.byClass("detail__header--desc");
}

@Override
protected Locator.XPathLocator getSubtitleLocator()
{
return Locator.byClass("detail-subtitle");
}

@Override
protected Locator.XPathLocator getIconLocator()
{
return Locator.byClass("detail__header-icon");
}

final WebElement colorIcon = Locator.byClass("color-icon__circle-small").findWhenNeeded(subtitle);
}

public static class PageDetailHeaderFinder extends WebDriverComponentFinder<PageDetailHeader, PageDetailHeaderFinder>
{
private final Locator.XPathLocator _baseLocator = Locator.byClass("page-header");

public PageDetailHeaderFinder(WebDriver driver)
{
super(driver);
}

@Override
protected PageDetailHeader construct(WebElement el, WebDriver driver)
{
return new PageDetailHeader(el, driver);
}

@Override
protected Locator locator()
{
return _baseLocator;
}
}
}
31 changes: 31 additions & 0 deletions src/org/labkey/test/util/selenium/WebElementUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;

import static org.labkey.test.Locator.NBSP;

Expand Down Expand Up @@ -137,4 +138,34 @@ public static boolean checkVisibility(WebElement element)
return false;
}
}

/**
* Convenience method to extract some attribute from a WebElement. Stale or missing elements will return a default.
* @param element WebElement to inspect; may be stale or backed by a missing DOM node
* @param mapper function applied to {@code element} to extract the desired value
* @param defaultValue value returned when {@code element} is stale or missing
* @return the mapped value, or {@code defaultValue} if the element is unavailable
* @param <T> type of the extracted value
*/
public static <T> T tryMapElement(WebElement element, Function<WebElement, T> mapper, T defaultValue)
{
try
{
return mapper.apply(element);
}
catch (NoSuchElementException | StaleElementReferenceException _) { }

return defaultValue;
}

/**
* Convenience overload of {@link #tryMapElement(WebElement, Function, Object)} that defaults to an empty string.
* @param element WebElement to inspect; may be stale or backed by a missing DOM node
* @param mapper function applied to {@code element} to extract a String value
* @return the mapped value, or {@code ""} if the element is unavailable
*/
public static String tryMapElement(WebElement element, Function<WebElement, String> mapper)
{
return tryMapElement(element, mapper, "");
}
}