/******************************************************************************* * Copyright 2014 JHC Systems Limited * * 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 jhc.redsniff.webdriver.matchers; import static jhc.redsniff.webdriver.WebDriverMatchers.isString; import static jhc.redsniff.webdriver.matchers.SimpleAttributeMatcher.hasSimpleAttribute; import static org.hamcrest.core.DescribedAs.describedAs; import jhc.redsniff.internal.locators.MatcherLocator; import jhc.redsniff.internal.matchers.CheckAndDiagnoseTogetherMatcher; import jhc.redsniff.internal.util.StringDiffFormatter; import org.hamcrest.Description; import org.hamcrest.Factory; import org.hamcrest.Matcher; import org.openqa.selenium.By; import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebElement; public class CssClassNameMatcher extends MatcherByLocator { private static final int specificity = Specifities.specifityOf(CssClassNameMatcher.class); public CssClassNameMatcher(Matcher<String> cssClassNameMatcher) { super(wrapMatcher(cssClassNameMatcher)); } public CssClassNameMatcher(String literalClassName) { super(wrapMatcher(describedAs("\""+literalClassName+"\"", containsWord(literalClassName))), literalClassName); } @Override public String nameOfAttributeUsed() { return "cssClass"; } @Override public By getByLocator(String literalName) { return By.className(literalName); } private static Matcher<WebElement> wrapMatcher(Matcher<String> cssClassNameMatcher) { return hasSimpleAttribute("class", "css class", cssClassNameMatcher); } @Factory public static MatcherLocator<WebElement, SearchContext> hasCssClass(String value) { return new CssClassNameMatcher(value); } @Factory public static Matcher<WebElement> hasCssClass(Matcher<String> cssClassNameMatcher) { return new CssClassNameMatcher(cssClassNameMatcher); } private static class ContainsWord extends CheckAndDiagnoseTogetherMatcher<String>{ private final String word; public ContainsWord(String word) { this.word = word; } @Override public void describeTo(Description description) { description.appendText(word); } @Override protected boolean matchesSafely(String actual, Description mismatchDescription) { String[] actualSplit = actual.split("\\s+"); boolean matches = expectedWordContainedIn(actualSplit); if(!matches){ if(actualSplit.length<=1){ // String diff = new ComparisonCompactor(20, word, actual) // .compact(" was:\n '%2$s'\ninstead of:\n '%1$s'"); String diff = new StringDiffFormatter().formatDifference(word, actual, " was:\n '%1$s'\ninstead of:\n '%2$s'"); mismatchDescription.appendText( diff); } else mismatchDescription.appendText("was '" + actual + "'"); } return matches; } public boolean expectedWordContainedIn(String[] split) { Matcher<String> stringMatcher = isString(word); for(String actualWord:split) if(stringMatcher.matches(actualWord)) return true; return false; } } private static ContainsWord containsWord(String word){ return new ContainsWord(word); } @Override public int specifity() { return specificity; } }