From 6a78545e95e1f0c7e05acdb23d5c1e714c949935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Ka=C5=82u=C5=BCny?= Date: Thu, 17 May 2018 23:33:55 +0200 Subject: [PATCH 01/14] Add example of XmlAssert.hasXPath() to README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1f9bae23..a0aad80b 100644 --- a/README.md +++ b/README.md @@ -118,12 +118,13 @@ String content = xpath.evaluate("/foo/text()", source); assert "bar".equals(content); ``` -or using `HasXPathMatcher` and `EvaluateXPathMatcher` +or using `HasXPathMatcher`, `EvaluateXPathMatcher` and `XmlAssert` ```java assertThat("bar", HasXPathMatcher.hasXPath("/foo")); assertThat("bar", EvaluateXPathMatcher.hasXPath("/foo/text()", equalTo("bar"))); +XmlAssert.assertThat("bar").hasXPath("/foo"); ``` ### Validating a Document Against an XML Schema From 02bf9893dd434d6785380ef8eef0cdbd549f99c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Ka=C5=82u=C5=BCny?= Date: Tue, 22 May 2018 23:46:48 +0200 Subject: [PATCH 02/14] Add MultipleNodeAssert factory method --- .../xmlunit/assertj/MultipleNodeAssert.java | 20 ++++++++++++++++++- .../java/org/xmlunit/assertj/XmlAssert.java | 14 ++----------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java index b39f2d2e..b1f43440 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java @@ -13,8 +13,15 @@ */ package org.xmlunit.assertj; +import org.assertj.core.api.Assertions; import org.assertj.core.api.FactoryBasedNavigableIterableAssert; import org.w3c.dom.Node; +import org.xmlunit.builder.Input; +import org.xmlunit.util.Convert; +import org.xmlunit.xpath.XPathEngine; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Source; /** * Assertion methods for {@link Iterable} of {@link Node}. @@ -36,10 +43,21 @@ interface SingleNodeAssertConsumer { void accept(SingleNodeAssert t); } - MultipleNodeAssert(Iterable nodes) { + private MultipleNodeAssert(Iterable nodes) { super(nodes, MultipleNodeAssert.class, new NodeAssertFactory()); } + static MultipleNodeAssert create(Object xmlSource, XPathEngine xPathEngine, DocumentBuilderFactory dbf, String xPath) { + + Assertions.assertThat(xPath).isNotBlank(); + + Source s = Input.from(xmlSource).build(); + Node root = dbf != null ? Convert.toNode(s, dbf) : Convert.toNode(s); + Iterable nodes = xPathEngine.selectNodes(xPath, root); + + return new MultipleNodeAssert(nodes); + } + /** * Equivalent for {@link #isNotEmpty()}. */ diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java index 4c5b0d64..079a718e 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java @@ -15,14 +15,11 @@ import org.assertj.core.api.AbstractAssert; import org.assertj.core.api.Assertions; -import org.w3c.dom.Node; import org.xmlunit.builder.Input; -import org.xmlunit.util.Convert; import org.xmlunit.xpath.JAXPXPathEngine; import org.xmlunit.xpath.XPathEngine; import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.Source; import java.util.Map; import static org.xmlunit.assertj.error.ShouldNotHaveThrown.shouldNotHaveThrown; @@ -78,6 +75,7 @@ private XmlAssert(Object o) { /** * Factory method for {@link XmlAssert} + * * @param o object with type supported by {@link Input#from(Object)} */ public static XmlAssert assertThat(Object o) { @@ -93,16 +91,9 @@ public static XmlAssert assertThat(Object o) { public MultipleNodeAssert nodesByXPath(String xPath) { isNotNull(); - Assertions.assertThat(xPath).isNotBlank(); - try { XPathEngine xPathEngine = createXPathEngine(); - - Source s = Input.from(actual).build(); - Node root = dbf != null ? Convert.toNode(s, dbf) : Convert.toNode(s); - Iterable nodes = xPathEngine.selectNodes(xPath, root); - - return new MultipleNodeAssert(nodes); + return MultipleNodeAssert.create(actual, xPathEngine, dbf, xPath); } catch (Exception e) { @@ -143,7 +134,6 @@ public XmlAssert withDocumentBuildFactory(DocumentBuilderFactory dbf) { * * @param prefix2Uri prefix2Uri maps from prefix to namespace URI. It is used to resolve * XML namespace prefixes in the XPath expression - * * @throws AssertionError if the actual value is {@code null}. */ public XmlAssert withNamespaceContext(Map prefix2Uri) { From d6d4304951f3c07a80b05146f3913e05df954210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Ka=C5=82u=C5=BCny?= Date: Wed, 23 May 2018 00:27:03 +0200 Subject: [PATCH 03/14] Add ValidationAssert --- .../org/xmlunit/assertj/ValidationAssert.java | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java new file mode 100644 index 00000000..8fd50f46 --- /dev/null +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java @@ -0,0 +1,74 @@ +package org.xmlunit.assertj; + +import org.assertj.core.api.AbstractAssert; +import org.assertj.core.api.Assertions; +import org.xmlunit.builder.Input; +import org.xmlunit.validation.JAXPValidator; +import org.xmlunit.validation.Languages; +import org.xmlunit.validation.ValidationResult; + +import javax.xml.transform.Source; +import javax.xml.validation.Schema; + +public class ValidationAssert extends AbstractAssert { + + private final Source[] schemaSource; + private final Schema schema; + private ValidationResult result; + + private ValidationAssert(Object actual, Source[] schemaSource, Schema schema) { + super(actual, ValidationAssert.class); + this.schemaSource = schemaSource; + this.schema = schema; + } + + static ValidationAssert create(Object xmlSource, Object... schemaSource) { + + Assertions.assertThat(schemaSource) + .isNotNull() + .isNotEmpty() + .doesNotContainNull(); + + Source[] sources = new Source[schemaSource.length]; + + for (int i = 0; i < schemaSource.length; i++) { + sources[i] = Input.from(schemaSource[i]).build(); + } + + return new ValidationAssert(xmlSource, sources, null); + } + + static ValidationAssert create(Object xmlSource, Schema schema) { + Assertions.assertThat(schema).isNotNull(); + + return new ValidationAssert(xmlSource, null, schema); + } + + private void validate() { + if (result == null) { + Source source = Input.from(actual).build(); + JAXPValidator validator = new JAXPValidator(Languages.W3C_XML_SCHEMA_NS_URI); + if (schema != null) { + validator.setSchema(schema); + } else { + validator.setSchemaSources(schemaSource); + } + this.result = validator.validateInstance(source); + } + } + + public ValidationAssert isValid() { + validate(); + if (!result.isValid()) { + failWithMessage("dupa"); + } + return this; + } + + public void isNotValid() { + validate(); + if (result.isValid()) { + failWithMessage("dupa"); + } + } +} From 9a91fefcf53d8b24dfdb30478c2a0568a457102e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Ka=C5=82u=C5=BCny?= Date: Wed, 23 May 2018 00:40:24 +0200 Subject: [PATCH 04/14] Remove validation result field --- .../org/xmlunit/assertj/ValidationAssert.java | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java index 8fd50f46..13362b8a 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java @@ -14,7 +14,6 @@ public class ValidationAssert extends AbstractAssert { private final Source[] schemaSource; private final Schema schema; - private ValidationResult result; private ValidationAssert(Object actual, Source[] schemaSource, Schema schema) { super(actual, ValidationAssert.class); @@ -44,31 +43,34 @@ static ValidationAssert create(Object xmlSource, Schema schema) { return new ValidationAssert(xmlSource, null, schema); } - private void validate() { - if (result == null) { - Source source = Input.from(actual).build(); - JAXPValidator validator = new JAXPValidator(Languages.W3C_XML_SCHEMA_NS_URI); - if (schema != null) { - validator.setSchema(schema); - } else { - validator.setSchemaSources(schemaSource); - } - this.result = validator.validateInstance(source); + private ValidationResult validate() { + + Source source = Input.from(actual).build(); + JAXPValidator validator = new JAXPValidator(Languages.W3C_XML_SCHEMA_NS_URI); + if (schema != null) { + validator.setSchema(schema); + } else { + validator.setSchemaSources(schemaSource); } + return validator.validateInstance(source); } public ValidationAssert isValid() { - validate(); - if (!result.isValid()) { - failWithMessage("dupa"); + ValidationResult validationResult = validate(); + if (!validationResult.isValid()) { + failWithMessage("error message"); } return this; } public void isNotValid() { - validate(); - if (result.isValid()) { - failWithMessage("dupa"); + ValidationResult validateResult = validate(); + if (validateResult.isValid()) { + failWithMessage("error message"); } } + + public void isInvalid() { + isNotValid(); + } } From 8af516b177187884ff220aafdfb04961ecdcf5c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Ka=C5=82u=C5=BCny?= Date: Sun, 27 May 2018 18:45:19 +0200 Subject: [PATCH 05/14] Expose ValidationAssert via XmlAssert --- .../xmlunit/assertj/MultipleNodeAssert.java | 4 +- .../org/xmlunit/assertj/ValidationAssert.java | 51 ++++--- .../java/org/xmlunit/assertj/XmlAssert.java | 32 +++++ .../assertj/error/ShouldBeInvalid.java | 15 ++ .../xmlunit/assertj/error/ShouldBeValid.java | 36 +++++ .../assertj/error/ShouldHaveAttribute.java | 13 +- .../xmlunit/assertj/ExpectedException.java | 35 ++++- .../SingleNodeAssertHasAttributeTest.java | 1 + .../assertj/XmlAssertValidationTest.java | 129 ++++++++++++++++++ 9 files changed, 285 insertions(+), 31 deletions(-) create mode 100644 xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeInvalid.java create mode 100644 xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeValid.java create mode 100644 xmlunit-assertj/src/test/java/org/xmlunit/assertj/XmlAssertValidationTest.java diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java index b1f43440..c32d6cce 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java @@ -13,7 +13,6 @@ */ package org.xmlunit.assertj; -import org.assertj.core.api.Assertions; import org.assertj.core.api.FactoryBasedNavigableIterableAssert; import org.w3c.dom.Node; import org.xmlunit.builder.Input; @@ -35,6 +34,7 @@ * * assertThat(xml).nodesByXPath("//a/b").haveAttribute("attr"). * + * * @since XMLUnit 2.6.1 */ public class MultipleNodeAssert extends FactoryBasedNavigableIterableAssert, Node, SingleNodeAssert> { @@ -49,8 +49,6 @@ private MultipleNodeAssert(Iterable nodes) { static MultipleNodeAssert create(Object xmlSource, XPathEngine xPathEngine, DocumentBuilderFactory dbf, String xPath) { - Assertions.assertThat(xPath).isNotBlank(); - Source s = Input.from(xmlSource).build(); Node root = dbf != null ? Convert.toNode(s, dbf) : Convert.toNode(s); Iterable nodes = xPathEngine.selectNodes(xPath, root); diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java index 13362b8a..8eea841d 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java @@ -10,67 +10,80 @@ import javax.xml.transform.Source; import javax.xml.validation.Schema; -public class ValidationAssert extends AbstractAssert { +import static org.xmlunit.assertj.error.ShouldBeInvalid.shouldBeInvalid; +import static org.xmlunit.assertj.error.ShouldBeValid.shouldBeValid; + +public class ValidationAssert extends AbstractAssert { private final Source[] schemaSource; private final Schema schema; - private ValidationAssert(Object actual, Source[] schemaSource, Schema schema) { + private ValidationAssert(Source actual, Source[] schemaSource, Schema schema) { super(actual, ValidationAssert.class); this.schemaSource = schemaSource; this.schema = schema; } - static ValidationAssert create(Object xmlSource, Object... schemaSource) { + static ValidationAssert create(Object xmlSource, Object... schemaSources) { + + Assertions.assertThat(xmlSource).isNotNull(); - Assertions.assertThat(schemaSource) + Assertions.assertThat(schemaSources) .isNotNull() .isNotEmpty() .doesNotContainNull(); - Source[] sources = new Source[schemaSource.length]; + Source source = Input.from(xmlSource).build(); - for (int i = 0; i < schemaSource.length; i++) { - sources[i] = Input.from(schemaSource[i]).build(); + Source[] sources = new Source[schemaSources.length]; + + for (int i = 0; i < schemaSources.length; i++) { + sources[i] = Input.from(schemaSources[i]).build(); } - return new ValidationAssert(xmlSource, sources, null); + return new ValidationAssert(source, sources, null); } static ValidationAssert create(Object xmlSource, Schema schema) { + + Assertions.assertThat(xmlSource).isNotNull(); Assertions.assertThat(schema).isNotNull(); - return new ValidationAssert(xmlSource, null, schema); + Source source = Input.from(xmlSource).build(); + + return new ValidationAssert(source, null, schema); + } + + static ValidationAssert create(Object xmlSource) { + + Source source = Input.from(xmlSource).build(); + + return new ValidationAssert(source, null, null); } private ValidationResult validate() { - Source source = Input.from(actual).build(); JAXPValidator validator = new JAXPValidator(Languages.W3C_XML_SCHEMA_NS_URI); if (schema != null) { validator.setSchema(schema); } else { validator.setSchemaSources(schemaSource); } - return validator.validateInstance(source); + return validator.validateInstance(actual); } public ValidationAssert isValid() { ValidationResult validationResult = validate(); if (!validationResult.isValid()) { - failWithMessage("error message"); + throwAssertionError(shouldBeValid(actual.getSystemId(), validationResult.getProblems())); } return this; } - public void isNotValid() { - ValidationResult validateResult = validate(); + public void isInvalid() { + ValidationResult validateResult = validate(); if (validateResult.isValid()) { - failWithMessage("error message"); + throwAssertionError(shouldBeInvalid(actual.getSystemId())); } } - - public void isInvalid() { - isNotValid(); - } } diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java index 079a718e..e073004f 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java @@ -20,6 +20,7 @@ import org.xmlunit.xpath.XPathEngine; import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.validation.Schema; import java.util.Map; import static org.xmlunit.assertj.error.ShouldNotHaveThrown.shouldNotHaveThrown; @@ -90,6 +91,7 @@ public static XmlAssert assertThat(Object o) { */ public MultipleNodeAssert nodesByXPath(String xPath) { isNotNull(); + Assertions.assertThat(xPath).isNotBlank(); try { XPathEngine xPathEngine = createXPathEngine(); @@ -142,6 +144,36 @@ public XmlAssert withNamespaceContext(Map prefix2Uri) { return this; } + public ValidationAssert isValid() { + isNotNull(); + return ValidationAssert.create(actual).isValid(); + } + + public void isInvalid() { + isNotNull(); + ValidationAssert.create(actual).isInvalid(); + } + + public ValidationAssert isValidAgainst(Schema schema) { + isNotNull(); + return ValidationAssert.create(actual, schema).isValid(); + } + + public void isNotValidAgainst(Schema schema) { + isNotNull(); + ValidationAssert.create(actual, schema).isInvalid(); + } + + public ValidationAssert isValidAgainst(Object... schemaSources) { + isNotNull(); + return ValidationAssert.create(actual, schemaSources).isValid(); + } + + public void isNotValidAgainst(Object... schemaSources) { + isNotNull(); + ValidationAssert.create(actual, schemaSources).isInvalid(); + } + private XPathEngine createXPathEngine() { final JAXPXPathEngine engine = new JAXPXPathEngine(); diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeInvalid.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeInvalid.java new file mode 100644 index 00000000..61d20f85 --- /dev/null +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeInvalid.java @@ -0,0 +1,15 @@ +package org.xmlunit.assertj.error; + +import org.assertj.core.error.BasicErrorMessageFactory; + +public class ShouldBeInvalid extends BasicErrorMessageFactory { + + public static ShouldBeInvalid shouldBeInvalid(String systemId) { + + return new ShouldBeInvalid(systemId != null ? systemId : "instance"); + } + + private ShouldBeInvalid(String systemId) { + super("%nExpecting:%n <%s>%nto be invalid", unquotedString(systemId)); + } +} diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeValid.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeValid.java new file mode 100644 index 00000000..e4b273b1 --- /dev/null +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeValid.java @@ -0,0 +1,36 @@ +package org.xmlunit.assertj.error; + +import org.assertj.core.error.BasicErrorMessageFactory; +import org.xmlunit.validation.ValidationProblem; + +public class ShouldBeValid extends BasicErrorMessageFactory { + + public static ShouldBeValid shouldBeValid(String systemId, Iterable problems) { + StringBuilder builder = new StringBuilder(); + int index = 1; + + for (ValidationProblem problem : problems) { + builder.append(index++).append("."); + + if (problem.getLine() != ValidationProblem.UNKNOWN) { + builder.append(" line=").append(problem.getLine()); + } + if (problem.getColumn() != ValidationProblem.UNKNOWN) { + builder.append(" column=").append(problem.getColumn()); + } + + builder.append(" type=").append(problem.getType()); + builder.append(" message=").append(problem.getMessage()); + builder.append("%n"); + } + + return new ShouldBeValid(systemId != null ? systemId : "instance", builder.toString()); + } + + + private ShouldBeValid(String systemId, String problems) { + super("%nExpecting:%n <%s>%nto be valid but found following problems:%n%s", + unquotedString(systemId), + unquotedString(problems)); + } +} diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldHaveAttribute.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldHaveAttribute.java index 811aafd6..c1abc63d 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldHaveAttribute.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldHaveAttribute.java @@ -22,18 +22,23 @@ public class ShouldHaveAttribute extends BasicErrorMessageFactory { public static ErrorMessageFactory shouldHaveAttribute(String nodeName, String attributeName) { - return new ShouldHaveAttribute(nodeName, attributeName, null); + return new ShouldHaveAttribute(nodeName, attributeName); } public static ErrorMessageFactory shouldHaveAttributeWithValue(String nodeName, String attributeName, String attributeValue) { return new ShouldHaveAttribute(nodeName, attributeName, attributeValue); } + private ShouldHaveAttribute(String nodeName, String attributeName) { + super("%nExpecting:%n <%s>%nto have attribute:%n <%s>", + unquotedString(nodeName), + unquotedString(attributeName)); + } + private ShouldHaveAttribute(String nodeName, String attributeName, String attributeValue) { - super("%nExpecting:%n <%s>%nto have attribute:%n <%s>" + - (attributeValue != null ? "%nwith value:%n <%s>" : ""), + super("%nExpecting:%n <%s>%nto have attribute:%n <%s>%nwith value:%n <%s>", unquotedString(nodeName), unquotedString(attributeName), - (attributeValue != null ? unquotedString(attributeValue) : null)); + unquotedString(attributeValue)); } } diff --git a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ExpectedException.java b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ExpectedException.java index c6311fd1..b0e3e3bb 100644 --- a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ExpectedException.java +++ b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ExpectedException.java @@ -13,10 +13,15 @@ */ package org.xmlunit.assertj; +import org.hamcrest.TypeSafeMatcher; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; +import java.util.regex.Pattern; + +import static org.junit.internal.matchers.ThrowableMessageMatcher.hasMessage; + public class ExpectedException implements TestRule { private final org.junit.rules.ExpectedException delegate = org.junit.rules.ExpectedException.none(); @@ -25,7 +30,8 @@ public static ExpectedException none() { return new ExpectedException(); } - private ExpectedException() {} + private ExpectedException() { + } @Override public Statement apply(Statement base, Description description) { @@ -33,11 +39,30 @@ public Statement apply(Statement base, Description description) { } public void expectAssertionError(String message) { - expect(AssertionError.class, message); + delegate.expect(AssertionError.class); + delegate.expectMessage(message); } - void expect(Class type, String message) { - delegate.expect(type); - delegate.expectMessage(message); + public void expectAssertionErrorPattern(String messageRegex) { + delegate.expect(AssertionError.class); + delegate.expect(hasMessage(new MatchesPattern(messageRegex))); + } + + private class MatchesPattern extends TypeSafeMatcher { + private String regex; + + MatchesPattern(String regex) { + this.regex = regex; + } + + @Override + protected boolean matchesSafely(String item) { + return Pattern.compile(regex).matcher(item).matches(); + } + + @Override + public void describeTo(org.hamcrest.Description description) { + description.appendText("a string matching the regex '" + regex + "'"); + } } } diff --git a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/SingleNodeAssertHasAttributeTest.java b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/SingleNodeAssertHasAttributeTest.java index 5879772e..185f0e61 100644 --- a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/SingleNodeAssertHasAttributeTest.java +++ b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/SingleNodeAssertHasAttributeTest.java @@ -129,6 +129,7 @@ public void testHasAttribute_withMultipleMatchingNodes_shouldPass() { .element(2) .hasAttribute("attr3", "value3"); } + @Test public void testHasAttribute_withAnyValue_shouldFailed() { diff --git a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/XmlAssertValidationTest.java b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/XmlAssertValidationTest.java new file mode 100644 index 00000000..c8b7c635 --- /dev/null +++ b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/XmlAssertValidationTest.java @@ -0,0 +1,129 @@ +package org.xmlunit.assertj; + +import org.junit.Rule; +import org.junit.Test; +import org.xmlunit.validation.Languages; + +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import java.io.File; + +import static org.xmlunit.assertj.ExpectedException.none; +import static org.xmlunit.assertj.XmlAssert.assertThat; + +public class XmlAssertValidationTest { + + @Rule + public ExpectedException thrown = none(); + + @Test + public void testIsValidateAgainst_shouldPass() { + StreamSource xml = new StreamSource(new File("../test-resources/BookXsdGenerated.xml")); + StreamSource xsd = new StreamSource(new File("../test-resources/Book.xsd")); + + assertThat(xml).isValidAgainst(xsd); + } + + @Test + public void testIsValidateAgainst_withExternallyCreatedSchemaInstance_shouldPass() throws Exception { + StreamSource xml = new StreamSource(new File("../test-resources/BookXsdGenerated.xml")); + StreamSource xsd = new StreamSource(new File("../test-resources/Book.xsd")); + + SchemaFactory factory = SchemaFactory.newInstance(Languages.W3C_XML_SCHEMA_NS_URI); + Schema schema = factory.newSchema(xsd); + + assertThat(xml).isValidAgainst(schema); + } + + @Test + public void testIsNotValidateAgainst_withBrokenXml_shouldPass() { + final StreamSource xml = new StreamSource(new File("../test-resources/invalidBook.xml")); + final StreamSource xsd = new StreamSource(new File("../test-resources/Book.xsd")); + + assertThat(xml).isNotValidAgainst(xsd); + } + + @Test + public void testIsNotValidateAgainst_withBrokenXml_andExternallyCreatedSchemaInstance_shouldPass() throws Exception { + StreamSource xml = new StreamSource(new File("../test-resources/invalidBook.xml")); + StreamSource xsd = new StreamSource(new File("../test-resources/Book.xsd")); + + SchemaFactory factory = SchemaFactory.newInstance(Languages.W3C_XML_SCHEMA_NS_URI); + Schema schema = factory.newSchema(xsd); + + assertThat(xml).isNotValidAgainst(schema); + } + + @Test + public void testIsValidateAgainst_withBrokenXml_shouldFailed() { + + thrown.expectAssertionErrorPattern("^\\nExpecting:\\n <.*\\.\\.\\/test-resources\\/invalidBook.xml>\\nto be valid but found following problems:\\n.*"); + thrown.expectAssertionError("1. line=9 column=8 type=ERROR " + + "message=cvc-complex-type.2.4.b: The content of element 'Book' is not complete. " + + "One of '{\"https://www.xmlunit.org/publishing\":Publisher}' is expected."); + + StreamSource xml = new StreamSource(new File("../test-resources/invalidBook.xml")); + StreamSource xsd = new StreamSource(new File("../test-resources/Book.xsd")); + + assertThat(xml).isValidAgainst(xsd); + } + + @Test + public void testIsValid_shouldPass() { + + StreamSource xml = new StreamSource(new File("../test-resources/BookXsdGenerated.xml")); + + assertThat(xml).isValid(); + } + + @Test + public void testIsValid_withBrokenXml_shouldPass() { + + thrown.expectAssertionError("1. line=9 column=8 type=ERROR " + + "message=cvc-complex-type.2.4.b: The content of element 'Book' is not complete. " + + "One of '{\"https://www.xmlunit.org/publishing\":Publisher}' is expected."); + + StreamSource xml = new StreamSource(new File("../test-resources/invalidBook.xml")); + + assertThat(xml).isValid(); + } + + @Test + public void testIsInValid_withBrokenXml_shouldPass() { + + StreamSource xml = new StreamSource(new File("../test-resources/invalidBook.xml")); + + assertThat(xml).isInvalid(); + } + + @Test + public void testIsInvalid_shouldPass() { + + thrown.expectAssertionErrorPattern("^\\nExpecting:\\n <.*\\.\\.\\/test-resources\\/BookXsdGenerated.xml>\\nto be invalid"); + + StreamSource xml = new StreamSource(new File("../test-resources/BookXsdGenerated.xml")); + + assertThat(xml).isInvalid(); + } + + @Test + public void testIsValidAgainst_withNullSchemaSources_shouldFailed() { + + thrown.expectAssertionError("actual not to be null"); + + StreamSource xml = new StreamSource(new File("../test-resources/BookXsdGenerated.xml")); + + assertThat(xml).isValidAgainst((Object[]) null); + } + + @Test + public void testIsValidAgainst_withNullSchema_shouldFailed() { + + thrown.expectAssertionError("actual not to be null"); + + StreamSource xml = new StreamSource(new File("../test-resources/BookXsdGenerated.xml")); + + assertThat(xml).isValidAgainst((Schema) null); + } +} From e4cb68e0e4021b535d75b5dc01bc8d967e7c4ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Ka=C5=82u=C5=BCny?= Date: Sun, 27 May 2018 19:02:25 +0200 Subject: [PATCH 06/14] Move xPath not null assertion and XPathEngine creation to MultipleNodeAssert --- .../xmlunit/assertj/MultipleNodeAssert.java | 15 ++++- .../java/org/xmlunit/assertj/XmlAssert.java | 64 ++++++++----------- 2 files changed, 38 insertions(+), 41 deletions(-) diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java index c32d6cce..9c6e1ed5 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java @@ -13,14 +13,16 @@ */ package org.xmlunit.assertj; +import org.assertj.core.api.Assertions; import org.assertj.core.api.FactoryBasedNavigableIterableAssert; import org.w3c.dom.Node; import org.xmlunit.builder.Input; import org.xmlunit.util.Convert; -import org.xmlunit.xpath.XPathEngine; +import org.xmlunit.xpath.JAXPXPathEngine; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Source; +import java.util.Map; /** * Assertion methods for {@link Iterable} of {@link Node}. @@ -47,11 +49,18 @@ private MultipleNodeAssert(Iterable nodes) { super(nodes, MultipleNodeAssert.class, new NodeAssertFactory()); } - static MultipleNodeAssert create(Object xmlSource, XPathEngine xPathEngine, DocumentBuilderFactory dbf, String xPath) { + static MultipleNodeAssert create(Object xmlSource, Map prefix2Uri, DocumentBuilderFactory dbf, String xPath) { + + Assertions.assertThat(xPath).isNotBlank(); + + final JAXPXPathEngine engine = new JAXPXPathEngine(); + if (prefix2Uri != null) { + engine.setNamespaceContext(prefix2Uri); + } Source s = Input.from(xmlSource).build(); Node root = dbf != null ? Convert.toNode(s, dbf) : Convert.toNode(s); - Iterable nodes = xPathEngine.selectNodes(xPath, root); + Iterable nodes = engine.selectNodes(xPath, root); return new MultipleNodeAssert(nodes); } diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java index e073004f..49c83aca 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java @@ -83,6 +83,31 @@ public static XmlAssert assertThat(Object o) { return new XmlAssert(o); } + /** + * Sets the {@link DocumentBuilderFactory} to use when creating a + * {@link org.w3c.dom.Document} from the XML input. + * + * @throws AssertionError if the actual value is {@code null}. + */ + public XmlAssert withDocumentBuildFactory(DocumentBuilderFactory dbf) { + isNotNull(); + this.dbf = dbf; + return this; + } + + /** + * Utility method used for creating a namespace context mapping to be used in XPath matching. + * + * @param prefix2Uri prefix2Uri maps from prefix to namespace URI. It is used to resolve + * XML namespace prefixes in the XPath expression + * @throws AssertionError if the actual value is {@code null}. + */ + public XmlAssert withNamespaceContext(Map prefix2Uri) { + isNotNull(); + this.prefix2Uri = prefix2Uri; + return this; + } + /** * Create {@link MultipleNodeAssert} from nodes selecting by given xPath. * @@ -91,11 +116,9 @@ public static XmlAssert assertThat(Object o) { */ public MultipleNodeAssert nodesByXPath(String xPath) { isNotNull(); - Assertions.assertThat(xPath).isNotBlank(); try { - XPathEngine xPathEngine = createXPathEngine(); - return MultipleNodeAssert.create(actual, xPathEngine, dbf, xPath); + return MultipleNodeAssert.create(actual, prefix2Uri, dbf, xPath); } catch (Exception e) { @@ -119,31 +142,6 @@ public void doesNotHaveXPath(String xPath) { nodesByXPath(xPath).doNotExist(); } - /** - * Sets the {@link DocumentBuilderFactory} to use when creating a - * {@link org.w3c.dom.Document} from the XML input. - * - * @throws AssertionError if the actual value is {@code null}. - */ - public XmlAssert withDocumentBuildFactory(DocumentBuilderFactory dbf) { - isNotNull(); - this.dbf = dbf; - return this; - } - - /** - * Utility method used for creating a namespace context mapping to be used in XPath matching. - * - * @param prefix2Uri prefix2Uri maps from prefix to namespace URI. It is used to resolve - * XML namespace prefixes in the XPath expression - * @throws AssertionError if the actual value is {@code null}. - */ - public XmlAssert withNamespaceContext(Map prefix2Uri) { - isNotNull(); - this.prefix2Uri = prefix2Uri; - return this; - } - public ValidationAssert isValid() { isNotNull(); return ValidationAssert.create(actual).isValid(); @@ -173,14 +171,4 @@ public void isNotValidAgainst(Object... schemaSources) { isNotNull(); ValidationAssert.create(actual, schemaSources).isInvalid(); } - - private XPathEngine createXPathEngine() { - - final JAXPXPathEngine engine = new JAXPXPathEngine(); - if (prefix2Uri != null) { - engine.setNamespaceContext(prefix2Uri); - } - - return engine; - } } From a1c56406a3b8aeecf93b483cd0a827af4819bd30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Ka=C5=82u=C5=BCny?= Date: Sun, 27 May 2018 22:22:27 +0200 Subject: [PATCH 07/14] Fix shouldBeValid message --- .../xmlunit/assertj/error/ShouldBeValid.java | 14 +++++++---- .../xmlunit/assertj/ExpectedException.java | 3 ++- .../assertj/XmlAssertValidationTest.java | 24 +++++++++---------- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeValid.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeValid.java index e4b273b1..4d0e3b5a 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeValid.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeValid.java @@ -3,9 +3,13 @@ import org.assertj.core.error.BasicErrorMessageFactory; import org.xmlunit.validation.ValidationProblem; +import static java.lang.String.format; + public class ShouldBeValid extends BasicErrorMessageFactory { public static ShouldBeValid shouldBeValid(String systemId, Iterable problems) { + String systemId1 = systemId != null ? systemId : "instance"; + StringBuilder builder = new StringBuilder(); int index = 1; @@ -13,18 +17,20 @@ public static ShouldBeValid shouldBeValid(String systemId, Iterable { @Override protected boolean matchesSafely(String item) { - return Pattern.compile(regex).matcher(item).matches(); + return Pattern.compile(regex, DOTALL).matcher(item).matches(); } @Override diff --git a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/XmlAssertValidationTest.java b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/XmlAssertValidationTest.java index c8b7c635..01403cea 100644 --- a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/XmlAssertValidationTest.java +++ b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/XmlAssertValidationTest.java @@ -18,7 +18,7 @@ public class XmlAssertValidationTest { public ExpectedException thrown = none(); @Test - public void testIsValidateAgainst_shouldPass() { + public void testIsValidAgainst_shouldPass() { StreamSource xml = new StreamSource(new File("../test-resources/BookXsdGenerated.xml")); StreamSource xsd = new StreamSource(new File("../test-resources/Book.xsd")); @@ -26,7 +26,7 @@ public void testIsValidateAgainst_shouldPass() { } @Test - public void testIsValidateAgainst_withExternallyCreatedSchemaInstance_shouldPass() throws Exception { + public void testIsValidAgainst_withExternallyCreatedSchemaInstance_shouldPass() throws Exception { StreamSource xml = new StreamSource(new File("../test-resources/BookXsdGenerated.xml")); StreamSource xsd = new StreamSource(new File("../test-resources/Book.xsd")); @@ -37,7 +37,7 @@ public void testIsValidateAgainst_withExternallyCreatedSchemaInstance_shouldPass } @Test - public void testIsNotValidateAgainst_withBrokenXml_shouldPass() { + public void testIsNotValidAgainst_withBrokenXml_shouldPass() { final StreamSource xml = new StreamSource(new File("../test-resources/invalidBook.xml")); final StreamSource xsd = new StreamSource(new File("../test-resources/Book.xsd")); @@ -45,7 +45,7 @@ public void testIsNotValidateAgainst_withBrokenXml_shouldPass() { } @Test - public void testIsNotValidateAgainst_withBrokenXml_andExternallyCreatedSchemaInstance_shouldPass() throws Exception { + public void testIsNotValidAgainst_withBrokenXml_andExternallyCreatedSchemaInstance_shouldPass() throws Exception { StreamSource xml = new StreamSource(new File("../test-resources/invalidBook.xml")); StreamSource xsd = new StreamSource(new File("../test-resources/Book.xsd")); @@ -56,12 +56,12 @@ public void testIsNotValidateAgainst_withBrokenXml_andExternallyCreatedSchemaIns } @Test - public void testIsValidateAgainst_withBrokenXml_shouldFailed() { + public void testIsValidAgainst_withBrokenXml_shouldFailed() { thrown.expectAssertionErrorPattern("^\\nExpecting:\\n <.*\\.\\.\\/test-resources\\/invalidBook.xml>\\nto be valid but found following problems:\\n.*"); - thrown.expectAssertionError("1. line=9 column=8 type=ERROR " + - "message=cvc-complex-type.2.4.b: The content of element 'Book' is not complete. " + - "One of '{\"https://www.xmlunit.org/publishing\":Publisher}' is expected."); + thrown.expectAssertionError("1. line=9; column=8; type=ERROR;" + + " message=cvc-complex-type.2.4.b: The content of element 'Book' is not complete." + + " One of '{\"https://www.xmlunit.org/publishing\":Publisher}' is expected."); StreamSource xml = new StreamSource(new File("../test-resources/invalidBook.xml")); StreamSource xsd = new StreamSource(new File("../test-resources/Book.xsd")); @@ -80,9 +80,9 @@ public void testIsValid_shouldPass() { @Test public void testIsValid_withBrokenXml_shouldPass() { - thrown.expectAssertionError("1. line=9 column=8 type=ERROR " + - "message=cvc-complex-type.2.4.b: The content of element 'Book' is not complete. " + - "One of '{\"https://www.xmlunit.org/publishing\":Publisher}' is expected."); + thrown.expectAssertionError("1. line=9; column=8; type=ERROR;" + + " message=cvc-complex-type.2.4.b: The content of element 'Book' is not complete." + + " One of '{\"https://www.xmlunit.org/publishing\":Publisher}' is expected."); StreamSource xml = new StreamSource(new File("../test-resources/invalidBook.xml")); @@ -90,7 +90,7 @@ public void testIsValid_withBrokenXml_shouldPass() { } @Test - public void testIsInValid_withBrokenXml_shouldPass() { + public void testIsInvalid_withBrokenXml_shouldPass() { StreamSource xml = new StreamSource(new File("../test-resources/invalidBook.xml")); From 33bed7bdd3ec1ba7b858f564f067f13abd3a86c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Ka=C5=82u=C5=BCny?= Date: Mon, 28 May 2018 00:53:02 +0200 Subject: [PATCH 08/14] Add ValueAssert --- .../xmlunit/assertj/MultipleNodeAssert.java | 3 +- .../java/org/xmlunit/assertj/ValueAssert.java | 75 ++++++++++ .../java/org/xmlunit/assertj/XmlAssert.java | 13 +- .../assertj/error/ShouldBeConvertible.java | 17 +++ .../xmlunit/assertj/ExpectedException.java | 3 +- .../org/xmlunit/assertj/ValueAssertTest.java | 133 ++++++++++++++++++ 6 files changed, 239 insertions(+), 5 deletions(-) create mode 100644 xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java create mode 100644 xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeConvertible.java create mode 100644 xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java index 9c6e1ed5..b8cc1cd4 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java @@ -62,7 +62,8 @@ static MultipleNodeAssert create(Object xmlSource, Map prefix2Ur Node root = dbf != null ? Convert.toNode(s, dbf) : Convert.toNode(s); Iterable nodes = engine.selectNodes(xPath, root); - return new MultipleNodeAssert(nodes); + return new MultipleNodeAssert(nodes) + .describedAs("XPath \"%s\" evaluated to node set", xPath); } /** diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java new file mode 100644 index 00000000..39d3a996 --- /dev/null +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java @@ -0,0 +1,75 @@ +package org.xmlunit.assertj; + +import org.assertj.core.api.AbstractCharSequenceAssert; +import org.assertj.core.api.AbstractDoubleAssert; +import org.assertj.core.api.AbstractIntegerAssert; +import org.assertj.core.api.Assertions; +import org.w3c.dom.Node; +import org.xmlunit.builder.Input; +import org.xmlunit.util.Convert; +import org.xmlunit.xpath.JAXPXPathEngine; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Source; +import java.util.Map; + +import static org.xmlunit.assertj.error.ShouldBeConvertible.shouldBeConvertible; + +public class ValueAssert extends AbstractCharSequenceAssert { + + private ValueAssert(String value) { + super(value, ValueAssert.class); + } + + static ValueAssert create(Object xmlSource, Map prefix2Uri, DocumentBuilderFactory dbf, String xPath) { + Assertions.assertThat(xPath).isNotBlank(); + + final JAXPXPathEngine engine = new JAXPXPathEngine(); + if (prefix2Uri != null) { + engine.setNamespaceContext(prefix2Uri); + } + + Source s = Input.from(xmlSource).build(); + Node root = dbf != null ? Convert.toNode(s, dbf) : Convert.toNode(s); + String value = engine.evaluate(xPath, root); + + return new ValueAssert(value) + .describedAs("XPath \"%s\" evaluated to value", xPath); + } + + public AbstractIntegerAssert asInt() { + isNotNull(); + int value = 0; + try { + value = Integer.parseInt(actual); + } catch (NumberFormatException e) { + throwAssertionError(shouldBeConvertible(actual, "int")); + } + + return Assertions.assertThat(value); + } + + public AbstractDoubleAssert asDouble() { + isNotNull(); + double value = 0; + try { + value = Double.parseDouble(actual); + } catch (NumberFormatException e) { + throwAssertionError(shouldBeConvertible(actual, "double")); + } + + return Assertions.assertThat(value); + } + + public ValueAssert isEqualTo(int expected) { + asInt().isEqualTo(expected); + + return this; + } + + public ValueAssert isEqualTo(double expected) { + asDouble().isEqualTo(expected); + + return this; + } +} diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java index 49c83aca..703f020a 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java @@ -14,10 +14,7 @@ package org.xmlunit.assertj; import org.assertj.core.api.AbstractAssert; -import org.assertj.core.api.Assertions; import org.xmlunit.builder.Input; -import org.xmlunit.xpath.JAXPXPathEngine; -import org.xmlunit.xpath.XPathEngine; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.validation.Schema; @@ -142,6 +139,16 @@ public void doesNotHaveXPath(String xPath) { nodesByXPath(xPath).doNotExist(); } + public ValueAssert valueByXPath(String xPath) { + isNotNull(); + try { + return ValueAssert.create(actual, prefix2Uri, dbf, xPath); + } catch (Exception e) { + throwAssertionError(shouldNotHaveThrown(e)); + } + return null; + } + public ValidationAssert isValid() { isNotNull(); return ValidationAssert.create(actual).isValid(); diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeConvertible.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeConvertible.java new file mode 100644 index 00000000..0730028a --- /dev/null +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeConvertible.java @@ -0,0 +1,17 @@ +package org.xmlunit.assertj.error; + +import org.assertj.core.error.BasicErrorMessageFactory; + +public class ShouldBeConvertible extends BasicErrorMessageFactory { + + public static ShouldBeConvertible shouldBeConvertible(String value, String targetType) { + + return new ShouldBeConvertible(value,targetType); + } + + private ShouldBeConvertible(String value, String targetType) { + super("%nExpecting:%n <%s>%nto be convertible to%n <%s>", + unquotedString(value), + unquotedString(targetType)); + } +} diff --git a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ExpectedException.java b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ExpectedException.java index 4fd18b1a..8467ff4c 100644 --- a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ExpectedException.java +++ b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ExpectedException.java @@ -20,6 +20,7 @@ import java.util.regex.Pattern; +import static java.lang.String.*; import static java.util.regex.Pattern.DOTALL; import static org.junit.internal.matchers.ThrowableMessageMatcher.hasMessage; @@ -41,7 +42,7 @@ public Statement apply(Statement base, Description description) { public void expectAssertionError(String message) { delegate.expect(AssertionError.class); - delegate.expectMessage(message); + delegate.expectMessage(format(message)); } public void expectAssertionErrorPattern(String messageRegex) { diff --git a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java new file mode 100644 index 00000000..ba1b18e0 --- /dev/null +++ b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java @@ -0,0 +1,133 @@ +package org.xmlunit.assertj; + +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.w3c.dom.Element; +import org.xml.sax.InputSource; +import org.xmlunit.XMLUnitException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; + +import static org.xmlunit.assertj.ExpectedException.none; +import static org.xmlunit.assertj.XmlAssert.assertThat; + +public class ValueAssertTest { + @Rule + public ExpectedException thrown = none(); + + @Test + public void testIsEqualTo_withCountExpression_shouldPass() { + + String xml = "" + + "" + + "" + + "" + + "" + + ""; + assertThat(xml).valueByXPath("count(//fruits/fruit)").isEqualTo(3); + assertThat(xml).valueByXPath("count(//fruits/fruit[@name=\"orange\"])").isEqualTo(1); + assertThat(xml).valueByXPath("count(//fruits/fruit[@name=\"apricot\"])").isEqualTo(0); + } + + @Test + public void testAsInt_withCountExpression_shouldPass() { + + String xml = "" + + "" + + "" + + "" + + "" + + ""; + assertThat(xml).valueByXPath("count(//fruits/fruit)").asInt().isEqualTo(3); + assertThat(xml).valueByXPath("count(//fruits/fruit[@name=\"orange\"])").asInt().isEqualTo(1); + assertThat(xml).valueByXPath("count(//fruits/fruit[@name=\"apricot\"])").asInt().isEqualTo(0); + } + + @Test + public void testAsInt_shouldFailed() { + + thrown.expectAssertionError("Expecting:%n %nto be convertible to%n "); + + String xml = "" + + "" + + "" + + "" + + "" + + ""; + + assertThat(xml).valueByXPath("//fruits/fruit/@name").asInt(); + } + + + @Test + public void testIsEqualTo_withAttributeValueExpression_shouldPass() { + + String xml = ""; + + assertThat(xml).valueByXPath("//a/b/@attr").isEqualTo("abc"); + } + + @Test + public void testIsEqualTo_withAttributeValueExpression_shouldFailed() { + + thrown.expectAssertionError("expected:<\"[something]\"> but was:<\"[abc]\">"); + + String xml = ""; + + assertThat(xml).valueByXPath("//a/b/@attr").isEqualTo("something"); + } + + @Test + public void testIsEqualTo_withAttributeValueExpression_fromElementClass_shouldPass() throws Exception { + + String xml = ""; + + DocumentBuilderFactory f = DocumentBuilderFactory.newInstance(); + f.setNamespaceAware(true); + DocumentBuilder db = f.newDocumentBuilder(); + Element xmlRootElement = db.parse(new InputSource(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)))).getDocumentElement(); + + assertThat(xmlRootElement).valueByXPath("//a/b/@attr").isEqualTo("abc"); + } + + @Test + public void testIsEqualTo_withNamespaceContext_shouldPass() { + + String xml = "" + + "" + + " Search Engine Feed" + + " " + + " " + + " Google" + + " goog" + + " " + + " " + + " Bing" + + " msft" + + " " + + ""; + + HashMap prefix2Uri = new HashMap<>(); + prefix2Uri.put("atom", "http://www.w3.org/2005/Atom"); + + assertThat(xml).withNamespaceContext(prefix2Uri) + .valueByXPath("count(//atom:feed/atom:entry)").isEqualTo("2"); + assertThat(xml).withNamespaceContext(prefix2Uri) + .valueByXPath("//atom:feed/atom:entry/atom:title/text()").isEqualTo("Google"); + assertThat(xml).withNamespaceContext(prefix2Uri) + .valueByXPath("//atom:feed/atom:entry[2]/atom:title/text()").isEqualTo("Bing"); + } + + @Test + public void testValueByXpath_withInvalidXml_shouldFailed() { + thrown.expectAssertionErrorPattern(".*Expecting code not to raise a throwable but caught.*Content is not allowed in prolog.*"); + + assertThat("not empty").valueByXPath("count(//atom:feed/atom:entry)").isEmpty(); + } +} From 01206f10e8d2cf05f54add094cdbbb99865c7021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Ka=C5=82u=C5=BCny?= Date: Wed, 27 Jun 2018 22:22:05 +0200 Subject: [PATCH 09/14] Add ValueAssert.isEqualTo(double) test --- .../org/xmlunit/assertj/ValueAssertTest.java | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java index ba1b18e0..46a079c6 100644 --- a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java +++ b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java @@ -1,16 +1,13 @@ package org.xmlunit.assertj; -import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.w3c.dom.Element; import org.xml.sax.InputSource; -import org.xmlunit.XMLUnitException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.ByteArrayInputStream; -import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.HashMap; @@ -22,7 +19,7 @@ public class ValueAssertTest { public ExpectedException thrown = none(); @Test - public void testIsEqualTo_withCountExpression_shouldPass() { + public void testAsInt_withCountExpression_shouldPass() { String xml = "" + "" + @@ -30,13 +27,15 @@ public void testIsEqualTo_withCountExpression_shouldPass() { "" + "" + ""; - assertThat(xml).valueByXPath("count(//fruits/fruit)").isEqualTo(3); - assertThat(xml).valueByXPath("count(//fruits/fruit[@name=\"orange\"])").isEqualTo(1); - assertThat(xml).valueByXPath("count(//fruits/fruit[@name=\"apricot\"])").isEqualTo(0); + assertThat(xml).valueByXPath("count(//fruits/fruit)").asInt().isEqualTo(3); + assertThat(xml).valueByXPath("count(//fruits/fruit[@name=\"orange\"])").asInt().isEqualTo(1); + assertThat(xml).valueByXPath("count(//fruits/fruit[@name=\"apricot\"])").asInt().isEqualTo(0); } @Test - public void testAsInt_withCountExpression_shouldPass() { + public void testAsInt_shouldFailed() { + + thrown.expectAssertionError("Expecting:%n %nto be convertible to%n "); String xml = "" + "" + @@ -44,15 +43,12 @@ public void testAsInt_withCountExpression_shouldPass() { "" + "" + ""; - assertThat(xml).valueByXPath("count(//fruits/fruit)").asInt().isEqualTo(3); - assertThat(xml).valueByXPath("count(//fruits/fruit[@name=\"orange\"])").asInt().isEqualTo(1); - assertThat(xml).valueByXPath("count(//fruits/fruit[@name=\"apricot\"])").asInt().isEqualTo(0); + + assertThat(xml).valueByXPath("//fruits/fruit/@name").asInt(); } @Test - public void testAsInt_shouldFailed() { - - thrown.expectAssertionError("Expecting:%n %nto be convertible to%n "); + public void testIsEqualTo_withInt_shouldPass() { String xml = "" + "" + @@ -60,10 +56,24 @@ public void testAsInt_shouldFailed() { "" + "" + ""; - - assertThat(xml).valueByXPath("//fruits/fruit/@name").asInt(); + assertThat(xml).valueByXPath("count(//fruits/fruit)").isEqualTo(3); + assertThat(xml).valueByXPath("count(//fruits/fruit[@name=\"orange\"])").isEqualTo(1); + assertThat(xml).valueByXPath("count(//fruits/fruit[@name=\"apricot\"])").isEqualTo(0); } + @Test + public void testIsEqualTo_withDouble_shouldPass() { + + String xml = "" + + "" + + "" + + "" + + "" + + ""; + assertThat(xml).valueByXPath("//fruits/fruit[@name=\"apple\"]/@weight").isEqualTo(23.3); + assertThat(xml).valueByXPath("//fruits/fruit[@name=\"orange\"]/@weight").isEqualTo(0.0); + assertThat(xml).valueByXPath("//fruits/fruit[@name=\"banana\"]/@weight").isEqualTo(7.0); + } @Test public void testIsEqualTo_withAttributeValueExpression_shouldPass() { From e126bd79f978c3ea8f0141f8605ae172b740c6b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Ka=C5=82u=C5=BCny?= Date: Wed, 27 Jun 2018 22:45:33 +0200 Subject: [PATCH 10/14] Add ValueAssert.asXml --- .../main/java/org/xmlunit/assertj/ValueAssert.java | 4 ++++ .../java/org/xmlunit/assertj/ValueAssertTest.java | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java index 39d3a996..0852145f 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java @@ -61,6 +61,10 @@ public AbstractDoubleAssert asDouble() { return Assertions.assertThat(value); } + public XmlAssert asXml() { + return XmlAssert.assertThat(actual); + } + public ValueAssert isEqualTo(int expected) { asInt().isEqualTo(expected); diff --git a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java index 46a079c6..e9dd5fb2 100644 --- a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java +++ b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java @@ -75,6 +75,19 @@ public void testIsEqualTo_withDouble_shouldPass() { assertThat(xml).valueByXPath("//fruits/fruit[@name=\"banana\"]/@weight").isEqualTo(7.0); } + @Test + public void testAsXml_shouldPass() { + + String xml ="" + + "" + + "]]>" + + ""; + + assertThat(xml).valueByXPath("//a/b/text()") + .isEqualTo("") + .asXml().hasXPath("/c/d"); + } + @Test public void testIsEqualTo_withAttributeValueExpression_shouldPass() { From 19ab49bcc64476c6e6bdeed4df6d6c67fd63ffa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Ka=C5=82u=C5=BCny?= Date: Wed, 27 Jun 2018 23:01:23 +0200 Subject: [PATCH 11/14] Return XmlAssert from isValid/isInvalid methods instead ValidationAssert --- .../org/xmlunit/assertj/ValidationAssert.java | 8 +++---- .../java/org/xmlunit/assertj/XmlAssert.java | 24 ++++++++++++------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java index 8eea841d..f39a5bf9 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java @@ -15,12 +15,12 @@ public class ValidationAssert extends AbstractAssert { - private final Source[] schemaSource; + private final Source[] schemaSources; private final Schema schema; - private ValidationAssert(Source actual, Source[] schemaSource, Schema schema) { + private ValidationAssert(Source actual, Source[] schemaSources, Schema schema) { super(actual, ValidationAssert.class); - this.schemaSource = schemaSource; + this.schemaSources = schemaSources; this.schema = schema; } @@ -67,7 +67,7 @@ private ValidationResult validate() { if (schema != null) { validator.setSchema(schema); } else { - validator.setSchemaSources(schemaSource); + validator.setSchemaSources(schemaSources); } return validator.validateInstance(actual); } diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java index 703f020a..bfa71007 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java @@ -149,33 +149,39 @@ public ValueAssert valueByXPath(String xPath) { return null; } - public ValidationAssert isValid() { + public XmlAssert isValid() { isNotNull(); - return ValidationAssert.create(actual).isValid(); + ValidationAssert.create(actual).isValid(); + return this; } - public void isInvalid() { + public XmlAssert isInvalid() { isNotNull(); ValidationAssert.create(actual).isInvalid(); + return this; } - public ValidationAssert isValidAgainst(Schema schema) { + public XmlAssert isValidAgainst(Schema schema) { isNotNull(); - return ValidationAssert.create(actual, schema).isValid(); + ValidationAssert.create(actual, schema).isValid(); + return this; } - public void isNotValidAgainst(Schema schema) { + public XmlAssert isNotValidAgainst(Schema schema) { isNotNull(); ValidationAssert.create(actual, schema).isInvalid(); + return this; } - public ValidationAssert isValidAgainst(Object... schemaSources) { + public XmlAssert isValidAgainst(Object... schemaSources) { isNotNull(); - return ValidationAssert.create(actual, schemaSources).isValid(); + ValidationAssert.create(actual, schemaSources).isValid(); + return this; } - public void isNotValidAgainst(Object... schemaSources) { + public XmlAssert isNotValidAgainst(Object... schemaSources) { isNotNull(); ValidationAssert.create(actual, schemaSources).isInvalid(); + return this; } } From 2044d86e0d0a579ac5117da13f6ec9c4b3e62000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Ka=C5=82u=C5=BCny?= Date: Thu, 28 Jun 2018 00:27:54 +0200 Subject: [PATCH 12/14] Add ValueAssert.asBoolean --- .../java/org/xmlunit/assertj/ValueAssert.java | 28 ++++- .../org/xmlunit/assertj/ValueAssertTest.java | 102 ++++++++++++++++-- 2 files changed, 117 insertions(+), 13 deletions(-) diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java index 0852145f..78cffe00 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java @@ -1,9 +1,6 @@ package org.xmlunit.assertj; -import org.assertj.core.api.AbstractCharSequenceAssert; -import org.assertj.core.api.AbstractDoubleAssert; -import org.assertj.core.api.AbstractIntegerAssert; -import org.assertj.core.api.Assertions; +import org.assertj.core.api.*; import org.w3c.dom.Node; import org.xmlunit.builder.Input; import org.xmlunit.util.Convert; @@ -61,6 +58,23 @@ public AbstractDoubleAssert asDouble() { return Assertions.assertThat(value); } + public AbstractBooleanAssert asBoolean() { + isNotNull(); + boolean value = false; + switch (actual.toLowerCase()) { + case "1": + case "true": + value = true; break; + case "0": + case "false": + value = false; break; + default: + throwAssertionError(shouldBeConvertible(actual, "boolean")); + } + + return Assertions.assertThat(value); + } + public XmlAssert asXml() { return XmlAssert.assertThat(actual); } @@ -76,4 +90,10 @@ public ValueAssert isEqualTo(double expected) { return this; } + + public ValueAssert isEqualTo(boolean expected) { + asBoolean().isEqualTo(expected); + + return this; + } } diff --git a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java index e9dd5fb2..7b7cb259 100644 --- a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java +++ b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/ValueAssertTest.java @@ -19,7 +19,7 @@ public class ValueAssertTest { public ExpectedException thrown = none(); @Test - public void testAsInt_withCountExpression_shouldPass() { + public void testAsInt_shouldPass() { String xml = "" + "" + @@ -47,6 +47,86 @@ public void testAsInt_shouldFailed() { assertThat(xml).valueByXPath("//fruits/fruit/@name").asInt(); } + @Test + public void testAsDouble_shouldPass() { + + String xml = "" + + "" + + "" + + ""; + + assertThat(xml).valueByXPath("//fruits/fruit/@weight").asDouble().isEqualTo(66.6); + } + + @Test + public void testAsDouble_shouldFailed() { + + thrown.expectAssertionError("Expecting:%n %nto be convertible to%n "); + + String xml = "" + + "" + + "" + + ""; + + assertThat(xml).valueByXPath("//fruits/fruit/@name").asDouble(); + } + + @Test + public void testAsBoolean_shouldPass() { + + String xml = "" + + "" + + "" + + "" + + "" + + "" + + ""; + + assertThat(xml).valueByXPath("//fruits/fruit[@name=\"apple\"]/@fresh").asBoolean().isTrue(); + assertThat(xml).valueByXPath("//fruits/fruit[@name=\"orange\"]/@fresh").asBoolean().isFalse(); + assertThat(xml).valueByXPath("//fruits/fruit[@name=\"banana\"]/@fresh").asBoolean().isTrue(); + assertThat(xml).valueByXPath("//fruits/fruit[@name=\"pear\"]/@fresh").asBoolean().isFalse(); + } + + @Test + public void testAsBoolean_withNumberAsArgument_shouldFailed() { + + thrown.expectAssertionError("Expecting:%n <2>%nto be convertible to%n "); + + String xml = "" + + "" + + "" + + ""; + + assertThat(xml).valueByXPath("//fruits/fruit[@name=\"apple\"]/@fresh").asBoolean(); + } + + @Test + public void testAsBoolean_withRandomStringAsArgument_shouldFailed() { + + thrown.expectAssertionError("Expecting:%n %nto be convertible to%n "); + + String xml = "" + + "" + + "" + + ""; + + assertThat(xml).valueByXPath("//fruits/fruit[@name=\"apple\"]/@fresh").asBoolean(); + } + + @Test + public void testAsXml_shouldPass() { + + String xml ="" + + "" + + "]]>" + + ""; + + assertThat(xml).valueByXPath("//a/b/text()") + .isEqualTo("") + .asXml().hasXPath("/c/d"); + } + @Test public void testIsEqualTo_withInt_shouldPass() { @@ -76,16 +156,20 @@ public void testIsEqualTo_withDouble_shouldPass() { } @Test - public void testAsXml_shouldPass() { + public void testIsEqualTo_withBoolean_shouldPass() { - String xml ="" + - "" + - "]]>" + - ""; + String xml = "" + + "" + + "" + + "" + + "" + + "" + + ""; - assertThat(xml).valueByXPath("//a/b/text()") - .isEqualTo("") - .asXml().hasXPath("/c/d"); + assertThat(xml).valueByXPath("//fruits/fruit[@name=\"apple\"]/@fresh").isEqualTo(true); + assertThat(xml).valueByXPath("//fruits/fruit[@name=\"orange\"]/@fresh").isEqualTo(false); + assertThat(xml).valueByXPath("//fruits/fruit[@name=\"banana\"]/@fresh").isEqualTo(true); + assertThat(xml).valueByXPath("//fruits/fruit[@name=\"pear\"]/@fresh").isEqualTo(false); } @Test From 372d0ca9ef9d0c7e020099d11def4f3b254d241b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Ka=C5=82u=C5=BCny?= Date: Thu, 28 Jun 2018 01:06:31 +0200 Subject: [PATCH 13/14] Add some description --- .../org/xmlunit/assertj/ValidationAssert.java | 38 ++++++++++ .../java/org/xmlunit/assertj/ValueAssert.java | 69 +++++++++++++++++- .../java/org/xmlunit/assertj/XmlAssert.java | 72 +++++++++++++++++-- .../assertj/error/ShouldBeConvertible.java | 16 +++++ .../assertj/error/ShouldBeInvalid.java | 16 +++++ .../xmlunit/assertj/error/ShouldBeValid.java | 16 +++++ .../xmlunit/assertj/error/package-info.java | 1 + 7 files changed, 221 insertions(+), 7 deletions(-) diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java index f39a5bf9..600f8111 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java @@ -1,3 +1,16 @@ +/* + This file is licensed to You 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.xmlunit.assertj; import org.assertj.core.api.AbstractAssert; @@ -13,6 +26,21 @@ import static org.xmlunit.assertj.error.ShouldBeInvalid.shouldBeInvalid; import static org.xmlunit.assertj.error.ShouldBeValid.shouldBeValid; +/** + * Assertion methods for XML validation. + * + *

Simple Example

+ * + *
+ * import static org.xmlunit.assertj.XmlAssert.assertThat;
+ *
+ * final String xml = "<a><b attr=\"abc\"></b></a>";
+ *
+ * assertThat(xml).isValid();
+ * 
+ * + * @since XMLUnit 2.6.1 + */ public class ValidationAssert extends AbstractAssert { private final Source[] schemaSources; @@ -72,6 +100,11 @@ private ValidationResult validate() { return validator.validateInstance(actual); } + /** + * Verifies that actual value is valid against given schema + * + * @throws AssertionError if the actual value is not valid against schema + */ public ValidationAssert isValid() { ValidationResult validationResult = validate(); if (!validationResult.isValid()) { @@ -80,6 +113,11 @@ public ValidationAssert isValid() { return this; } + /** + * Verifies that actual value is not valid against given schema + * + * @throws AssertionError if the actual value is valid against schema + */ public void isInvalid() { ValidationResult validateResult = validate(); if (validateResult.isValid()) { diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java index 78cffe00..28c69e14 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java @@ -1,3 +1,16 @@ +/* + This file is licensed to You 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.xmlunit.assertj; import org.assertj.core.api.*; @@ -12,6 +25,21 @@ import static org.xmlunit.assertj.error.ShouldBeConvertible.shouldBeConvertible; +/** + * Assertion methods for {@link String} result of XPath evaluation. + * + *

Simple Example

+ * + *
+ * import static org.xmlunit.assertj.XmlAssert.assertThat;
+ *
+ * final String xml = "<a><b attr=\"abc\"></b></a>";
+ *
+ * assertThat(xml).valueByXPath("count(//a/b)").isEqualTo(3);
+ * 
+ * + * @since XMLUnit 2.6.1 + */ public class ValueAssert extends AbstractCharSequenceAssert { private ValueAssert(String value) { @@ -34,6 +62,12 @@ static ValueAssert create(Object xmlSource, Map prefix2Uri, Docu .describedAs("XPath \"%s\" evaluated to value", xPath); } + /** + * Returns an {@code Assert} object that allows performing assertions on integer value of the {@link String} under test. + * + * @throws AssertionError if the actual value is {@code null}. + * @throws AssertionError if the actual value does not contain a parsable integer + */ public AbstractIntegerAssert asInt() { isNotNull(); int value = 0; @@ -46,6 +80,12 @@ public AbstractIntegerAssert asInt() { return Assertions.assertThat(value); } + /** + * Returns an {@code Assert} object that allows performing assertions on integer value of the {@link String} under test. + * + * @throws AssertionError if the actual value is {@code null}. + * @throws AssertionError if the actual value does not contain a parsable double + */ public AbstractDoubleAssert asDouble() { isNotNull(); double value = 0; @@ -58,16 +98,26 @@ public AbstractDoubleAssert asDouble() { return Assertions.assertThat(value); } + /** + * Returns an {@code Assert} object that allows performing assertions on boolean value of the {@link String} under test. + *

+ * If actual value after lowercasing is one of the following "true", "false", "1", "0", then it can be parsed to boolean. + * + * @throws AssertionError if the actual value is {@code null}. + * @throws AssertionError if the actual value does not contain a parsable boolean + */ public AbstractBooleanAssert asBoolean() { isNotNull(); boolean value = false; switch (actual.toLowerCase()) { case "1": case "true": - value = true; break; + value = true; + break; case "0": case "false": - value = false; break; + value = false; + break; default: throwAssertionError(shouldBeConvertible(actual, "boolean")); } @@ -75,22 +125,37 @@ public AbstractBooleanAssert asBoolean() { return Assertions.assertThat(value); } + /** + * Returns an {@code XmlAssert} object that allows performing assertions on XML value of the {@link String} under test. + * + * @throws AssertionError if the actual value is {@code null}. + */ public XmlAssert asXml() { + isNotNull(); return XmlAssert.assertThat(actual); } + /** + * Try convert the {@link String} under test to int using {@link #asInt()} and compare with given value. + */ public ValueAssert isEqualTo(int expected) { asInt().isEqualTo(expected); return this; } + /** + * Try convert the {@link String} under test to double using {@link #asDouble()} and compare with given value. + */ public ValueAssert isEqualTo(double expected) { asDouble().isEqualTo(expected); return this; } + /** + * Try convert the {@link String} under test to boolean using {@link #asBoolean()} and compare with given value. + */ public ValueAssert isEqualTo(boolean expected) { asBoolean().isEqualTo(expected); diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java index bfa71007..d75162e4 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/XmlAssert.java @@ -32,13 +32,13 @@ *

Simple Example

* *
- * import static org.xmlunit.assertj.XmlAssert.assertThat;
+ *    import static org.xmlunit.assertj.XmlAssert.assertThat;
  *
- * final String xml = "<a><b attr=\"abc\"></b></a>";
+ *    final String xml = "<a><b attr=\"abc\"></b></a>";
  *
- * assertThat(xml).nodesByXPath("//a/b/@attr").exist();
- * assertThat(xml).hasXPath("//a/b/@attr");
- * assertThat(xml).doesNotHaveXPath("//a/b/c");
+ *    assertThat(xml).nodesByXPath("//a/b/@attr").exist();
+ *    assertThat(xml).hasXPath("//a/b/@attr");
+ *    assertThat(xml).doesNotHaveXPath("//a/b/c");
  * 
* *

Example with namespace mapping

@@ -60,6 +60,24 @@ * .hasXPath("//atom:feed/atom:entry/atom:id")); * * + *

Testing XPath expression value

+ * + *
+ *    String xml = "<a><b attr=\"abc\"></b></a>";
+ *
+ *    assertThat(xml).valueByXPath("//a/b/@attr").isEqualTo("abc");
+ *    assertThat(xml).valueByXPath("count(//a/b)").isEqualTo(1);
+ * 
+ * + *

Example with XML validation

+ * + *
+ *    String xml = "<a><b attr=\"abc\"></b></a>";
+ *    StreamSource xsd = new StreamSource(new File("schema.xsd"));
+ *
+ *    assertThat(xml).isValid();
+ *    assertThat(xml).isValidAgainst(xsd);
+ * 
* @since XMLUnit 2.6.1 */ public class XmlAssert extends AbstractAssert { @@ -108,6 +126,7 @@ public XmlAssert withNamespaceContext(Map prefix2Uri) { /** * Create {@link MultipleNodeAssert} from nodes selecting by given xPath. * + * @throws AssertionError if the xPath is blank. * @throws AssertionError if the actual value is {@code null}. * @throws AssertionError if the actual value provide invalid XML. */ @@ -139,6 +158,13 @@ public void doesNotHaveXPath(String xPath) { nodesByXPath(xPath).doNotExist(); } + /** + * Create {@link ValueAssert} from value of given xPath expression. + * + * @throws AssertionError if the xPath is blank. + * @throws AssertionError if the actual value is {@code null}. + * @throws AssertionError if the actual value provide invalid XML. + */ public ValueAssert valueByXPath(String xPath) { isNotNull(); try { @@ -149,36 +175,72 @@ public ValueAssert valueByXPath(String xPath) { return null; } + /** + * Check if actual value is valid against W3C XML Schema + * + * @throws AssertionError if the actual value is {@code null}. + * @throws AssertionError if the actual value is invalid + */ public XmlAssert isValid() { isNotNull(); ValidationAssert.create(actual).isValid(); return this; } + /** + * Check if actual value is not valid against W3C XML Schema + * + * @throws AssertionError if the actual value is {@code null}. + * @throws AssertionError if the actual value is valid + */ public XmlAssert isInvalid() { isNotNull(); ValidationAssert.create(actual).isInvalid(); return this; } + /** + * Check if actual value is valid against given schema + * + * @throws AssertionError if the actual value is {@code null}. + * @throws AssertionError if the actual value is invalid + */ public XmlAssert isValidAgainst(Schema schema) { isNotNull(); ValidationAssert.create(actual, schema).isValid(); return this; } + /** + * Check if actual value is not valid against given schema + * + * @throws AssertionError if the actual value is {@code null}. + * @throws AssertionError if the actual value is valid + */ public XmlAssert isNotValidAgainst(Schema schema) { isNotNull(); ValidationAssert.create(actual, schema).isInvalid(); return this; } + /** + * Check if actual value is valid against schema provided by given sources + * + * @throws AssertionError if the actual value is {@code null}. + * @throws AssertionError if the actual value is invalid + */ public XmlAssert isValidAgainst(Object... schemaSources) { isNotNull(); ValidationAssert.create(actual, schemaSources).isValid(); return this; } + /** + * Check if actual value is not valid against schema provided by given sources + * + * @throws AssertionError if the actual value is {@code null}. + * @throws AssertionError if the actual value is valid + */ public XmlAssert isNotValidAgainst(Object... schemaSources) { isNotNull(); ValidationAssert.create(actual, schemaSources).isInvalid(); diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeConvertible.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeConvertible.java index 0730028a..427c8abe 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeConvertible.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeConvertible.java @@ -1,7 +1,23 @@ +/* + This file is licensed to You 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.xmlunit.assertj.error; import org.assertj.core.error.BasicErrorMessageFactory; +/** + * @since XMLUnit 2.6.1 + */ public class ShouldBeConvertible extends BasicErrorMessageFactory { public static ShouldBeConvertible shouldBeConvertible(String value, String targetType) { diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeInvalid.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeInvalid.java index 61d20f85..815b65ab 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeInvalid.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeInvalid.java @@ -1,7 +1,23 @@ +/* + This file is licensed to You 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.xmlunit.assertj.error; import org.assertj.core.error.BasicErrorMessageFactory; +/** + * @since XMLUnit 2.6.1 + */ public class ShouldBeInvalid extends BasicErrorMessageFactory { public static ShouldBeInvalid shouldBeInvalid(String systemId) { diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeValid.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeValid.java index 4d0e3b5a..ce457e20 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeValid.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/ShouldBeValid.java @@ -1,3 +1,16 @@ +/* + This file is licensed to You 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.xmlunit.assertj.error; import org.assertj.core.error.BasicErrorMessageFactory; @@ -5,6 +18,9 @@ import static java.lang.String.format; +/** + * @since XMLUnit 2.6.1 + */ public class ShouldBeValid extends BasicErrorMessageFactory { public static ShouldBeValid shouldBeValid(String systemId, Iterable problems) { diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/package-info.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/package-info.java index d6a5c212..568b7687 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/package-info.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/error/package-info.java @@ -15,5 +15,6 @@ /** * Contains internal classes of XMLUnit's AssertJ support that are * only public as an implementation detail. + * @since XMLUnit 2.6.1 */ package org.xmlunit.assertj.error; From 6b771984fe6604ce964af7f3e8f5956397d4adeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Ka=C5=82u=C5=BCny?= Date: Thu, 28 Jun 2018 21:02:55 +0200 Subject: [PATCH 14/14] Allow to pass empty schemaSources array to isValidAgainst --- .../org/xmlunit/assertj/ValidationAssert.java | 3 +-- .../java/org/xmlunit/assertj/ValueAssert.java | 6 +++++- .../assertj/XmlAssertValidationTest.java | 21 +++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java index 600f8111..f8981530 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValidationAssert.java @@ -58,7 +58,6 @@ static ValidationAssert create(Object xmlSource, Object... schemaSources) { Assertions.assertThat(schemaSources) .isNotNull() - .isNotEmpty() .doesNotContainNull(); Source source = Input.from(xmlSource).build(); @@ -94,7 +93,7 @@ private ValidationResult validate() { JAXPValidator validator = new JAXPValidator(Languages.W3C_XML_SCHEMA_NS_URI); if (schema != null) { validator.setSchema(schema); - } else { + } else if (schemaSources != null && schemaSources.length > 0) { validator.setSchemaSources(schemaSources); } return validator.validateInstance(actual); diff --git a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java index 28c69e14..02a1cabe 100644 --- a/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java +++ b/xmlunit-assertj/src/main/java/org/xmlunit/assertj/ValueAssert.java @@ -13,7 +13,11 @@ */ package org.xmlunit.assertj; -import org.assertj.core.api.*; +import org.assertj.core.api.AbstractBooleanAssert; +import org.assertj.core.api.AbstractCharSequenceAssert; +import org.assertj.core.api.AbstractDoubleAssert; +import org.assertj.core.api.AbstractIntegerAssert; +import org.assertj.core.api.Assertions; import org.w3c.dom.Node; import org.xmlunit.builder.Input; import org.xmlunit.util.Convert; diff --git a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/XmlAssertValidationTest.java b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/XmlAssertValidationTest.java index 01403cea..3e51b0fa 100644 --- a/xmlunit-assertj/src/test/java/org/xmlunit/assertj/XmlAssertValidationTest.java +++ b/xmlunit-assertj/src/test/java/org/xmlunit/assertj/XmlAssertValidationTest.java @@ -69,6 +69,27 @@ public void testIsValidAgainst_withBrokenXml_shouldFailed() { assertThat(xml).isValidAgainst(xsd); } + @Test + public void testIsValidAgainst_withEmptySourcesArray_shouldPass() { + + StreamSource xml = new StreamSource(new File("../test-resources/BookXsdGenerated.xml")); + + assertThat(xml).isValidAgainst(); + assertThat(xml).isValidAgainst(new Object[0]); + } + + @Test + public void testIsValidAgainst_withBrokenXmlAndEmptySourcesArray_shouldFailed() { + + thrown.expectAssertionError("1. line=9; column=8; type=ERROR;" + + " message=cvc-complex-type.2.4.b: The content of element 'Book' is not complete." + + " One of '{\"https://www.xmlunit.org/publishing\":Publisher}' is expected."); + + StreamSource xml = new StreamSource(new File("../test-resources/invalidBook.xml")); + + assertThat(xml).isValidAgainst(); + } + @Test public void testIsValid_shouldPass() {