package org.xmlunit.matchers;
import org.junit.Assert;
import org.junit.Test;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.util.HashMap;
import static org.hamcrest.CoreMatchers.both;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.Matchers.isEmptyString;
import static org.junit.Assert.assertThat;
import static org.xmlunit.matchers.EvaluateXPathMatcher.hasXPath;
public class EvaluateXPathMatcherTest {
@Test
public void testXPathCountInXmlString() throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<fruits>" +
"<fruit name=\"apple\"/>" +
"<fruit name=\"orange\"/>" +
"<fruit name=\"banana\"/>" +
"</fruits>";
assertThat(xml, hasXPath("count(//fruits/fruit)", equalTo("3")));
assertThat(xml, hasXPath("//fruits/fruit/@name", equalTo("apple")));
assertThat(xml, hasXPath("count(//fruits/fruit[@name=\"orange\"])", equalTo("1")));
assertThat(xml, hasXPath("count(//fruits/fruit[@name=\"apricot\"])", equalTo("0")));
}
@Test
public void testXPathAttributeValueMatchingInXmlString() throws Exception {
String xml = "<a><b attr=\"abc\"></b></a>";
assertThat(xml, hasXPath("//a/b/@attr", equalTo("abc")));
assertThat(xml, hasXPath("count(//a/b/c)", equalTo("0")));
try {
assertThat(xml, hasXPath("//a/b/@attr", equalTo("something")));
Assert.fail("Should throw AssertionError");
} catch(AssertionError e) {
assertThat(e.getMessage(), containsString("was \"abc\""));
}
}
@Test
public void testXPathAttributeValueMatchingInXmlElement() throws Exception {
String xml = "<a><b attr=\"abc\"></b></a>";
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
f.setNamespaceAware(true);
DocumentBuilder db = f.newDocumentBuilder();
Element xmlRootElement = db.parse(
new InputSource(new ByteArrayInputStream(xml.getBytes("utf-8")))).getDocumentElement();
assertThat(xmlRootElement, hasXPath("//a/b/@attr", equalTo("abc")));
}
@Test
public void testXPathEvaluationWithNamespaceContext() throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<feed xmlns=\"http://www.w3.org/2005/Atom\">" +
" <title>Search Engine Feed</title>" +
" <link href=\"https://en.wikipedia.org/wiki/Web_search_engine\"/>" +
" <entry>" +
" <title>Google</title>" +
" <id>goog</id>" +
" </entry>" +
" <entry>" +
" <title>Bing</title>" +
" <id>msft</id>" +
" </entry>" +
"</feed>";
HashMap<String, String> prefix2Uri = new HashMap<String, String>();
prefix2Uri.put("atom", "http://www.w3.org/2005/Atom");
assertThat(xml, hasXPath("count(//atom:feed/atom:entry)", equalTo("2")).withNamespaceContext(prefix2Uri));
assertThat(xml, hasXPath("//atom:feed/atom:entry/atom:title/text()",
equalTo("Google")).withNamespaceContext(prefix2Uri));
assertThat(xml, hasXPath("//atom:feed/atom:entry[2]/atom:title/text()",
equalTo("Bing")).withNamespaceContext(prefix2Uri));
}
/**
* Really only tests there is no NPE.
* @see "https://github.com/xmlunit/xmlunit/issues/81"
*/
@Test(expected = AssertionError.class)
public void canBeCombinedWithFailingMatcher() {
assertThat("not empty", both(isEmptyString())
.and(hasXPath("count(//atom:feed/atom:entry)", equalTo("2"))));
}
@Test
public void canBeCombinedWithPassingMatcher() {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<fruits>" +
"<fruit name=\"apple\"/>" +
"<fruit name=\"orange\"/>" +
"<fruit name=\"banana\"/>" +
"</fruits>";
assertThat(xml, both(not(isEmptyString()))
.and(hasXPath("count(//fruits/fruit)", equalTo("3"))));
}
}