package io.konik.zugferd; import com.google.common.io.Files; import io.konik.InvoiceTransformer; import io.konik.PrittyPrintInvoiceTransformer; import io.konik.utils.NumberDifferenceXmlComparison; import io.konik.validation.InvoiceValidator; import org.custommonkey.xmlunit.Diff; import org.custommonkey.xmlunit.XMLAssert; import org.custommonkey.xmlunit.XMLUnit; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.xml.sax.SAXException; import javax.validation.ConstraintViolation; import javax.xml.transform.stream.StreamSource; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.Set; import static java.nio.charset.Charset.forName; import static org.assertj.core.api.Assertions.assertThat; @RunWith(Parameterized.class) public class ZugferdSpecificExamplesTest { private static final String ROOT = "src/test/resources/zugferd_examples/"; @Parameterized.Parameters(name = "Invoice {0} has {1} error(s)") public static Collection<Object[]> getData() { return Arrays.asList(new Object[][]{ { "ZUGFeRD_1p0_COMFORT_Einfach_Original.xml", 0 }, { "ZUGFeRD_1p0_EXTENDED_Warenrechnung.xml", 2 }, { "large_zugferd_invoice.xml", 5 }, { "duePayable.xml", 0 }, { "productName.xml", 1 }, { "totalAllowanceCharge.xml", 5 }, { "totalAllowanceCharge2.xml", 0 }, { "totalAllowanceChargeWithDiscountAndSurcharge.xml", 0 }, { "totalAllowanceChargeWithDiscountAndSurchargeWithMissingTotalAllowanceCharge.xml", 1 }, }); } @Parameterized.Parameter public String file; @Parameterized.Parameter(1) public int expectedNumberOfErrors; InvoiceTransformer transformer = new PrittyPrintInvoiceTransformer(); private static File stringFileNameToFile(String name) { return new File(ROOT + name); } @BeforeClass public static void setup() { XMLUnit.setIgnoreWhitespace(true); XMLUnit.setIgnoreAttributeOrder(false); XMLUnit.setIgnoreComments(true); } @Test public void unmarshalInvoice() { //execute Invoice invoice = transformer.toModel(stringFileNameToFile(file)); //verify assertThat(invoice).isNotNull(); } @Test public void validateInvoiceAgainstSchema() throws SAXException, IOException { transformer.getZfSchemaValidator().validate(new StreamSource(stringFileNameToFile(file))); } @Test public void validateInvoiceAndCompareWithExpectedNumberOfErrors() { //setup: InvoiceTransformer transformer = new InvoiceTransformer(); Invoice invoice = transformer.toModel(stringFileNameToFile(file)); InvoiceValidator invoiceValidator = new InvoiceValidator(); //when: Set<ConstraintViolation<Invoice>> validationResult = invoiceValidator.validate(invoice); //then: printErrorsIfPresent(validationResult); assertThat(validationResult).hasSize(expectedNumberOfErrors); } @Test public void marshallBackInvoiceModelAndDiffXml() throws Exception { //setup: File testFile = stringFileNameToFile(file); String testFileContent = Files.toString(testFile, forName("UTF-8")); Invoice model = transformer.toModel(testFile); //when: byte[] invoiceAsByteArray = transformer.fromModel(model); //then: String remarshalledInvoice = new String(invoiceAsByteArray, "UTF-8"); Files.write(remarshalledInvoice.getBytes(), new File("./target/test_"+file)); Diff diff = new Diff(testFileContent, remarshalledInvoice); diff.overrideDifferenceListener(new NumberDifferenceXmlComparison()); XMLAssert.assertXMLEqual(diff, true); } private static void printErrorsIfPresent(final Set<ConstraintViolation<Invoice>> constraintViolations) { if (constraintViolations != null) { for (ConstraintViolation<Invoice> constraintViolation : constraintViolations) { System.out.printf("%-60s: %s | Invalid value: %s%n", constraintViolation.getPropertyPath(), constraintViolation.getMessage(), constraintViolation.getInvalidValue()); } } } }