Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,30 @@ Then context element has CSS property `$cssName` with value that $comparisonRule
When I change context to element located by `id(rainbow)`
Then context element has CSS property `color` with value that is equal to `rgba(0, 0, 0, 1)`
----

=== Check an element CSS properties

Checks the context element has the expected CSS properties.

The context can be set by the <<_change_context,corresponding steps>>.

[source,gherkin]
----
Then context element does have CSS properties matching rules:$parameters
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does have but not has?

----

* `$parameters` - The xref:ROOT:glossary.adoc#_examplestable[ExamplesTable] containing the following columns:
** [subs=+quotes]`*cssProperty*` - A name of the CSS property.
** [subs=+quotes]`*comparisonRule*` - CSS property xref:parameters:string-comparison-rule.adoc[comparison rule].
** [subs=+quotes]`*expectedValue*` - The expected value of the CSS property.

.Change context to element and verify several CSS properties
[source,gherkin]
----
When I change context to element located by `id(block)`
Then context element does have CSS properties matching rules:
|cssProperty |comparisonRule |expectedValue |
|align-items |is equal to |center |
|border |contains |solid |
|font-size |contains |20 |
----
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright 2019-2025 the original author or authors.
*
* 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
*
* https://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.vividus.steps.ui.web;

import org.jbehave.core.annotations.AsParameters;
import org.vividus.steps.StringComparisonRule;

@AsParameters
public class CssValidationParameters
{
private String cssProperty;
private StringComparisonRule comparisonRule;
private String expectedValue;

public CssValidationParameters()
{
}

public CssValidationParameters(String cssProperty, StringComparisonRule comparisonRule, String expectedValue)
{
this.cssProperty = cssProperty;
this.comparisonRule = comparisonRule;
this.expectedValue = expectedValue;
}

public String getCssProperty()
{
return cssProperty;
}

public void setCssProperty(String cssProperty)
{
this.cssProperty = cssProperty;
}

public StringComparisonRule getComparisonRule()
{
return comparisonRule;
}

public void setComparisonRule(StringComparisonRule comparisonRule)
{
this.comparisonRule = comparisonRule;
}

public String getExpectedValue()
{
return expectedValue;
}

public void setExpectedValue(String expectedValue)
{
this.expectedValue = expectedValue;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright 2019-2025 the original author or authors.
*
* 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
*
* https://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.vividus.steps.ui.web;

import org.vividus.steps.StringComparisonRule;

public class CssValidationResult
{
private CssValidationParameters cssValidationParameters;
private String actualValue;
private boolean passed;

public CssValidationResult(CssValidationParameters cssValidationParameters, String actualValue, boolean passed)
{
this.cssValidationParameters = cssValidationParameters;
this.actualValue = actualValue;
this.passed = passed;
}

public String getCssProperty()
{
return cssValidationParameters.getCssProperty();
}

public StringComparisonRule getComparisonRule()
{
return cssValidationParameters.getComparisonRule();
}

public String getExpectedValue()
{
return cssValidationParameters.getExpectedValue();
}

public String getActualValue()
{
return actualValue;
}

public void setActualValue(String actualValue)
{
this.actualValue = actualValue;
}

public boolean isPassed()
{
return passed;
}

public void setPassed(boolean passed)
{
this.passed = passed;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 2019-2025 the original author or authors.
*
* 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
*
* https://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.vividus.ui.web.validation;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.CaseUtils;
import org.vividus.softassert.ISoftAssert;
import org.vividus.steps.StringComparisonRule;
import org.vividus.steps.ui.web.CssValidationParameters;
import org.vividus.steps.ui.web.CssValidationResult;

public class CssValidations
{
private ISoftAssert softAssert;

public CssValidations(ISoftAssert softAssert)
{
this.softAssert = softAssert;
}

public List<CssValidationResult> validateElementCss(List<CssValidationParameters> parameters,
Map<String, String> elementCss)
{
List<CssValidationResult> cssResults = new ArrayList<>();
parameters.forEach(param ->
{
String cssName = param.getCssProperty();
String expectedValue = param.getExpectedValue();
StringComparisonRule comparisonRule = param.getComparisonRule();

String actualCssValue = getCssValue(elementCss, cssName);
boolean passed = softAssert.assertThat(String.format("CSS property '%s' value", cssName),
actualCssValue, comparisonRule.createMatcher(expectedValue));
cssResults.add(new CssValidationResult(param, actualCssValue, passed));
});
return cssResults;
}

private String getCssValue(Map<String, String> cssMap, String cssName)
{
return Optional.ofNullable(cssMap.get(cssName)).orElseGet(() -> {
String cssValueAsCamelCase = CaseUtils.toCamelCase(StringUtils.removeStart(cssName, '-'), false, '-');
return cssMap.get(cssValueAsCamelCase);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
function getComputedStyleAsMap(element) {
var computedStyle = getComputedStyle(element);
var computedStyleMap = new Map(Object.entries(computedStyle));
for (const [key] of computedStyleMap) {
if (/^\d+$/.test(key)) {
computedStyleMap.delete(key);
}
}
return Object.fromEntries(computedStyleMap);
}

return getComputedStyleAsMap(arguments[0]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<#ftl strip_whitespace=true>

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>CSS properties validation results table</title>
<link rel="stylesheet" href="../../styles.css"/>
<link rel="stylesheet" href="../../webjars/bootstrap/5.3.1/css/bootstrap.min.css"/>
</head>
<body>
<style>
.result-icon {
display: inline-block;
width: 16px;
height: 16px;
text-align: center;
}
.result-icon.pass {
color: #28a745;
}
.result-icon.fail {
color: #dc3545;
}
table {
border-collapse: collapse;
width: 100%;
}
table td:nth-child(1) {
width: 20px;
text-align: center;
}
table td:nth-child(2) {
width: 25%;
}
table td:nth-child(3) {
width: 30%;
}
table td:nth-child(4) {
width: 15%;
}
table td:nth-child(5) {
width: 30%;
}
table th {
text-align: center;
font-family: Arial, Helvetica, sans-serif;
}
</style>

<table class="table table-primary table-hover table-bordered table-sm">
<thead>
<tr>
<th />
<th>CSS Property</th>
<th>Actual Value</th>
<th>Rule</th>
<th>Expected Value</th>
</tr>
</thead>
<tbody>
<#list cssResults as cssResult>
<tr class="${cssResult.passed?string('table-success', 'table-danger')}">
<td>
<span class="result-icon ${cssResult.passed?string('pass', 'fail')}">
${cssResult.passed?string('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check-circle" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14m0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16"/>
<path d="m10.97 4.97-.02.022-3.473 4.425-2.093-2.094a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-1.071-1.05"/>
</svg>',
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-exclamation-triangle" viewBox="0 0 16 16">
<path d="M7.938 2.016A.13.13 0 0 1 8.002 2a.13.13 0 0 1 .063.016.15.15 0 0 1 .054.057l6.857 11.667c.036.06.035.124.002.183a.2.2 0 0 1-.054.06.1.1 0 0 1-.066.017H1.146a.1.1 0 0 1-.066-.017.2.2 0 0 1-.054-.06.18.18 0 0 1 .002-.183L7.884 2.073a.15.15 0 0 1 .054-.057m1.044-.45a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767z"/>
<path d="M7.002 12a1 1 0 1 1 2 0 1 1 0 0 1-2 0M7.1 5.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0z"/>
</svg>')}
</span>
</td>
<td>${cssResult.cssProperty}</td>
<td>${cssResult.actualValue!""}</td>
<td>${cssResult.comparisonRule}</td>
<td>${cssResult.expectedValue}</td>
</tr>
</#list>
</tbody>
</table>
<script src="../../webjars/bootstrap/5.3.1/js/bootstrap.min.js"></script>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

<bean id="webStorageSteps" class="org.vividus.steps.ui.web.WebStorageSteps" />

<bean id="cssValidations" class="org.vividus.ui.web.validation.CssValidations" />

<util:list id="stepBeanNames-WebApp" value-type="java.lang.String">
<idref bean="webStorageSteps" />
</util:list>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2019-2025 the original author or authors.
*
* 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
*
* https://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.vividus.steps.ui.web;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;

import org.junit.jupiter.api.Test;
import org.vividus.steps.StringComparisonRule;

class CssValidationResultTests
{
@Test
void testToCoverage()
{
final String key = "key";
final String value = "value";
final String expected = "expected";
CssValidationParameters parameters = new CssValidationParameters(key, StringComparisonRule.CONTAINS, expected);
CssValidationParameters newParameters = new CssValidationParameters();
newParameters.setCssProperty(parameters.getCssProperty());
newParameters.setComparisonRule(parameters.getComparisonRule());
newParameters.setExpectedValue(parameters.getExpectedValue());

CssValidationResult result = new CssValidationResult(newParameters, expected, true);
result.setActualValue(value);
result.setPassed(false);

assertEquals(key, result.getCssProperty());
assertEquals(value, result.getActualValue());
assertEquals(StringComparisonRule.CONTAINS, result.getComparisonRule());
assertEquals(expected, result.getExpectedValue());
assertFalse(result.isPassed());
}
}
Loading
Loading