package org.xmlunit.matchers;
import org.junit.Assert;
import org.junit.Before;
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 javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.util.HashMap;
import static org.hamcrest.CoreMatchers.both;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.Matchers.isEmptyString;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.assertThat;
import static org.xmlunit.matchers.HasXPathMatcher.hasXPath;
public class HasXPathMatcherTest {
private DocumentBuilder db;
@Before
public void setup() throws ParserConfigurationException {
DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
f.setNamespaceAware(true);
db = f.newDocumentBuilder();
}
@Test
public void testXPathIsFoundInDocumentWithASingleOccurence() throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<feed>" +
" <title>title</title>" +
" <entry>" +
" <title>title1</title>" +
" <id>id1</id>" +
" </entry>" +
"</feed>";
Element xmlRootElement = db.parse(
new InputSource(new ByteArrayInputStream(xml.getBytes("utf-8")))).getDocumentElement();
assertThat(xmlRootElement, hasXPath("entry/id"));
assertThat(xmlRootElement, hasXPath("entry/title"));
assertThat(xmlRootElement, not(hasXPath("entry/description")));
}
@Test
public void testXPathIsFoundInStringWithASingleOccurence() throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<feed>" +
" <title>title</title>" +
" <entry>" +
" <title>title1</title>" +
" <id>id1</id>" +
" </entry>" +
"</feed>";
assertThat(xml, hasXPath("//feed/entry/id"));
assertThat(xml, hasXPath("//feed/entry/title"));
assertThat(xml, not(hasXPath("//feed/entry/description")));
}
@Test
public void testXPathIsFoundInStringWithMultipleOccurences() throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<feed>" +
" <title>title</title>" +
" <entry>" +
" <title>title1</title>" +
" <id>id1</id>" +
" </entry>" +
" <entry>" +
" <title>title2</title>" +
" <id>id2</id>" +
" </entry>" +
"</feed>";
assertThat(xml, hasXPath("//feed/entry/id"));
assertThat(xml, hasXPath("//feed/entry/title"));
assertThat(xml, not(hasXPath("//feed/entry/description")));
}
@Test
public void textXPathAttributeIsFound() throws Exception {
String xml = "<a><b attr=\"abc\"></b></a>";
assertThat(xml, hasXPath("//a/b/@attr"));
try {
assertThat(xml, hasXPath("//a/b[@attr=\"abcd\"]"));
Assert.fail("Should throw AssertionError");
}catch(AssertionError e){
assertThat(e.getMessage(), containsString("XPath returned no results"));
}
}
@Test
public void testXPathIsFoundInDocumentWithNamespaceContextWithASingleOccurence() throws Exception {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<feed xmlns=\"http://www.w3.org/2005/Atom\">" +
" <title>title</title>" +
" <entry>" +
" <title>title1</title>" +
" <id>id1</id>" +
" </entry>" +
"</feed>";
HashMap<String, String> prefix2Uri = new HashMap<String, String>();
prefix2Uri.put("atom", "http://www.w3.org/2005/Atom");
Element xmlRootElement = db.parse(
new InputSource(new ByteArrayInputStream(xml.getBytes("utf-8")))).getDocumentElement();
assertThat(xmlRootElement, hasXPath("//atom:feed/atom:entry/atom:id").withNamespaceContext(prefix2Uri));
assertThat(xmlRootElement, hasXPath("//atom:feed/atom:entry/atom:title").withNamespaceContext(prefix2Uri));
assertThat(xmlRootElement,
not(hasXPath("//atom:feed/atom:entry/atom:description").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")));
}
@Test
public void canBeCombinedWithPassingMatcher() {
String xml = "<a><b attr=\"abc\"></b></a>";
assertThat(xml, both(not(isEmptyString()))
.and(hasXPath("//a/b/@attr")));
}
}