package io.konik.sdk.invoice; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.api.client.http.HttpRequestFactory; import com.google.api.client.http.LowLevelHttpRequest; import com.google.api.client.http.LowLevelHttpResponse; import com.google.api.client.testing.http.MockHttpTransport; import com.google.api.client.testing.http.MockLowLevelHttpRequest; import com.google.api.client.testing.http.MockLowLevelHttpResponse; import com.google.common.io.ByteStreams; import io.konik.InvoiceTransformer; import io.konik.sdk.ZinvoiceApiConfig; import io.konik.sdk.http.BadRequestException; import io.konik.sdk.http.ZinvoiceHttpClient; import io.konik.zugferd.Invoice; import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; import org.unitils.thirdparty.org.apache.commons.io.IOUtils; import java.io.IOException; import java.io.StringWriter; import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown; import static org.mockito.Mockito.*; public class RestInvoiceApiTest { private static final String INVOICE_ID = "4fd7563db62c4234a500b09be34e07dd"; private final ZinvoiceApiConfig apiConfig = new ZinvoiceApiConfig(UUID.randomUUID().toString(), "http://localhost"); private final ZinvoiceHttpClient getInvoiceMockHttpClient = new ZinvoiceHttpClient(apiConfig, mockHttpRequestFactory(new MockLowLevelHttpRequest() { @Override public LowLevelHttpResponse execute() throws IOException { StringWriter writer = new StringWriter(); IOUtils.copy(getClass().getResourceAsStream("/json/RestInvoiceApiTest_getInvoice.json"), writer, "UTF-8"); String json = writer.toString(); MockLowLevelHttpResponse response = new MockLowLevelHttpResponse(); response.setStatusCode(200); response.setContentType("application/json"); response.setContent(json); return response; } }), apiConfig.getDefaulObjectMapper()); private final ZinvoiceHttpClient createInvoiceFailHttpClient = new ZinvoiceHttpClient(apiConfig, mockHttpRequestFactory(new MockLowLevelHttpRequest(){ @Override public LowLevelHttpResponse execute() throws IOException { String json = "{\"path\": \"/invoice\", \"message\": \"Your request contains errors\", \"errors\": {\"trade.settlement.monetarySummation.chargeTotal\": \"may not be null\"}}"; MockLowLevelHttpResponse response = new MockLowLevelHttpResponse(); response.setStatusCode(400); response.setContentType("application/json"); response.setContent(json); return response; } }), apiConfig.getDefaulObjectMapper()); private HttpRequestFactory mockHttpRequestFactory(final MockLowLevelHttpRequest request) { return new MockHttpTransport() { @Override public LowLevelHttpRequest buildRequest(String method, String url) throws IOException { return request; } }.createRequestFactory(); } @Test public void shouldLoadDocumentAndReturnsItsId() { //given: InvoiceApi invoiceApi = new RestInvoiceApi(getInvoiceMockHttpClient); //when: InvoiceDocument invoiceDocument = invoiceApi.getInvoice(INVOICE_ID); //then: assertThat(invoiceDocument.getId()).isEqualTo(INVOICE_ID); } @Test public void shouldLoadDocumentAndReturnGuidelineNamespace() { //given: InvoiceApi invoiceApi = new RestInvoiceApi(getInvoiceMockHttpClient); //when: InvoiceDocument invoiceDocument = invoiceApi.getInvoice(INVOICE_ID); //then: assertThat(invoiceDocument.getInvoice().getContext().getGuideline().getNamespace()).isEqualTo("urn:ferd:CrossIndustryDocument:invoice:"); } @Test public void shouldLoadDocumentAndReturnItsInvoiceNumber() { //given: InvoiceApi invoiceApi = new RestInvoiceApi(getInvoiceMockHttpClient); //when: InvoiceDocument invoiceDocument = invoiceApi.getInvoice(INVOICE_ID); //then: assertThat(invoiceDocument.getInvoice().getHeader().getInvoiceNumber()).isEqualTo("20150201"); } @Test public void shouldLoadDocumentAndReturnSellerTaxNumber() { //given: InvoiceApi invoiceApi = new RestInvoiceApi(getInvoiceMockHttpClient); //when: InvoiceDocument invoiceDocument = invoiceApi.getInvoice(INVOICE_ID); //then: assertThat(invoiceDocument.getInvoice().getTrade().getAgreement().getSeller().getTaxRegistrations().get(0).getTaxNumber()).isEqualTo("7732393669"); } @Test public void shouldWrapBadRequestIntoException() { //given: InvoiceApi invoiceApi = new RestInvoiceApi(createInvoiceFailHttpClient); //when: try { invoiceApi.createInvoice(mock(Invoice.class)); failBecauseExceptionWasNotThrown(BadRequestException.class); } catch (BadRequestException e) { //then: assertThat(e.getErrorResponse().getMessage()).isEqualTo("Your request contains errors"); assertThat(e.getErrorResponse().getErrors()).containsEntry("trade.settlement.monetarySummation.chargeTotal", "may not be null"); } } @Test @Ignore("Ticket created") public void shouldUseInvoiceTransformerToGenerateZugferdXmlInvoiceRepresentationDuringCreateRequest() throws IOException { //given: ZinvoiceHttpClient zinvoiceHttpClient = mock(ZinvoiceHttpClient.class); InvoiceTransformer invoiceTransformer = mock(InvoiceTransformer.class); Invoice invoice = mock(Invoice.class); InvoiceApi invoiceApi = new RestInvoiceApi(zinvoiceHttpClient, invoiceTransformer); byte[] mockXml = ByteStreams.toByteArray(getClass().getResourceAsStream("/ZUGFeRD-invoice.sample.xml")); when(invoiceTransformer.fromModel(invoice)).thenReturn(mockXml); when(zinvoiceHttpClient.post("/invoice", mockXml, "application/xml", InvoiceResponse.class)) .thenReturn(mock(InvoiceResponse.class)); //when: invoiceApi.createInvoice(invoice); //then: verify(invoiceTransformer, times(1)).fromModel(invoice); verify(zinvoiceHttpClient, times(1)).post(Mockito.eq("/invoice"), Mockito.<byte[]>anyObject(), Mockito.eq("application/xml"), Mockito.eq(InvoiceResponse.class)); } @Test @Ignore("Ticket created") public void shouldCallRemoteZInvoiceServiceToUpdateInvoiceStatus() { //given: ZinvoiceApiConfig apiConfig = new ZinvoiceApiConfig(UUID.randomUUID().toString(), "http://localhost:8080"); ObjectMapper objectMapper = new ObjectMapper(); MockHttpTransport httpTransport = new MockHttpTransport.Builder() .setLowLevelHttpRequest( new MockLowLevelHttpRequest("/invoice/123/status") .setResponse(new MockLowLevelHttpResponse().setContent("{\"invoiceId\": \"123\", \"status\": \"BOOKED\"}")) ) .build(); HttpRequestFactory requestFactory = httpTransport.createRequestFactory(); ZinvoiceHttpClient httpClient = new ZinvoiceHttpClient(apiConfig, requestFactory, objectMapper); InvoiceApi invoiceApi = new RestInvoiceApi(httpClient, new InvoiceTransformer()); //when: StatusResponse statusResponse = invoiceApi.updateStatus("123", Status.BOOKED); //then: assertThat(statusResponse.getInvoiceId()).isEqualTo("123"); assertThat(statusResponse.getStatus()).isEqualTo(Status.BOOKED); } }