From 1b88096ef2575bafad2c3796c589c3e4c60c767f Mon Sep 17 00:00:00 2001 From: Genaro Madrid Date: Mon, 24 Aug 2026 20:15:24 -0600 Subject: [PATCH 1/4] upgrade junit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a74e7c0..6ec6849 100644 --- a/pom.xml +++ b/pom.xml @@ -62,7 +62,7 @@ junit junit - 4.8.1 + 4.13.2 test From 0442ba1448e2e8aa704ca3ea11e8a6dae7a241ca Mon Sep 17 00:00:00 2001 From: Genaro Madrid Date: Mon, 24 Aug 2026 20:15:45 -0600 Subject: [PATCH 2/4] mock tests --- src/main/java/com/mifiel/api/ApiClient.java | 2 +- .../java/com/mifiel/api/DocumentsTest.java | 161 ++++++++++-------- .../java/com/mifiel/api/FakeApiClient.java | 84 +++++++++ 3 files changed, 172 insertions(+), 75 deletions(-) create mode 100644 src/test/java/com/mifiel/api/FakeApiClient.java diff --git a/src/main/java/com/mifiel/api/ApiClient.java b/src/main/java/com/mifiel/api/ApiClient.java index 7b27fef..21b4bb8 100644 --- a/src/main/java/com/mifiel/api/ApiClient.java +++ b/src/main/java/com/mifiel/api/ApiClient.java @@ -25,7 +25,7 @@ import com.mifiel.api.rest.HttpMethod; import com.mifiel.api.utils.MifielUtils; -public final class ApiClient { +public class ApiClient { private final static String HMAC_SHA1_ALGORITHM = "HmacSHA1"; private final String DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss z"; diff --git a/src/test/java/com/mifiel/api/DocumentsTest.java b/src/test/java/com/mifiel/api/DocumentsTest.java index da3989b..b6d0cb7 100644 --- a/src/test/java/com/mifiel/api/DocumentsTest.java +++ b/src/test/java/com/mifiel/api/DocumentsTest.java @@ -1,11 +1,17 @@ package com.mifiel.api; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import java.io.File; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; -import org.junit.BeforeClass; +import org.apache.http.HttpEntity; +import org.apache.http.entity.StringEntity; +import org.junit.Before; import org.junit.Test; import com.mifiel.api.dao.Documents; @@ -14,141 +20,148 @@ import com.mifiel.api.objects.Signature; import com.mifiel.api.objects.SignatureResponse; import com.mifiel.api.utils.MifielUtils; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; public class DocumentsTest { - private static ApiClient apiClient; - private static Documents docs; - private final String pdfFilePath; - private final String mifielBase = "https://app-sandbox.mifiel.com"; - private static final String appId = "APP_ID"; // TODO: replace with your access token - private static final String appSecret = "APP_SECRET"; // TODO: replace with your access token - private static final String fileTest = "my_file.pdf"; - private final String path; + private static final String DOCUMENT_ID = "doc-123"; + private static final String FILE_TEST = "my_file.pdf"; - ClassLoader classLoader = getClass().getClassLoader(); + private FakeApiClient apiClient; + private Documents docs; + private String pdfFilePath; - @BeforeClass - public static void beforeClass() throws MifielException { - apiClient = new ApiClient(appId, appSecret); + @Before + public void setUp() { + apiClient = new FakeApiClient(); docs = new Documents(apiClient); - } - - public DocumentsTest() { - this.pdfFilePath = classLoader.getResource(fileTest).getFile(); - this.path = classLoader.getResource(fileTest).getPath().replace(fileTest, ""); + pdfFilePath = getClass().getClassLoader().getResource(FILE_TEST).getFile(); } @Test(expected = MifielException.class) public void testWrongUrlShouldThorwAnException() throws MifielException { - apiClient.setUrl("www.google.com"); + new ApiClient("app-id", "app-secret").setUrl("www.google.com"); } @Test public void testCorrectUrlShouldNotThorwAnException() throws MifielException { - apiClient.setUrl("https://app-sandbox.mifiel.com"); + new ApiClient("app-id", "app-secret").setUrl("https://app-sandbox.mifiel.com"); } @Test - public void testGetAllDocumentsShouldReturnAList() throws MifielException { - setSandboxUrl(); + public void testGetAllDocumentsShouldReturnAList() throws Exception { + apiClient.setNextResponse(jsonEntity("[{\"id\":\"" + DOCUMENT_ID + "\",\"name\":\"doc.pdf\"}]")); + final List allDocuments = docs.findAll(); - assertTrue(allDocuments != null); + + assertNotNull(allDocuments); + assertEquals(1, allDocuments.size()); + assertEquals(DOCUMENT_ID, allDocuments.get(0).getId()); + assertEquals("GET", apiClient.getLastMethod()); + assertEquals(Documents.DOCUMENTS_PATH, apiClient.getLastPath()); } @Test - public void testSaveADocumentWithFilePath() throws MifielException { - setSandboxUrl(); + public void testSaveADocumentWithFilePath() throws Exception { + apiClient.setNextResponse(jsonEntity("{\"id\":\"" + DOCUMENT_ID + "\",\"name\":\"my_file.pdf\"}")); + Document doc = new Document(); doc.setFile(pdfFilePath); List signatures = new ArrayList(); - Signature signature = new Signature(); - signature.setEmail("ja.zavala.aguilar@gmail.com"); + signature.setEmail("signer@example.com"); signature.setTaxId("ZAAJ8301061E0"); - signature.setSignature("Juan Antonio Zavala Aguilar"); + signature.setSignature("Test Signer"); signatures.add(signature); doc.setSignatures(signatures); + doc = docs.save(doc); - assertTrue(doc != null); + + assertNotNull(doc); + assertEquals(DOCUMENT_ID, doc.getId()); + assertEquals(1, doc.getSignatures().size()); + assertEquals("signer@example.com", doc.getSignatures().get(0).getEmail()); + assertEquals("POST", apiClient.getLastMethod()); + assertEquals(Documents.DOCUMENTS_PATH, apiClient.getLastPath()); + assertNotNull(apiClient.getLastBody()); } @Test - public void testSaveADocumentWithOriginalHashAndFileName() throws MifielException { - setSandboxUrl(); + public void testSaveADocumentWithOriginalHashAndFileName() throws Exception { + apiClient.setNextResponse(jsonEntity("{\"id\":\"" + DOCUMENT_ID + "\",\"name\":\"20170201-50147577\"}")); + Document doc = new Document(); doc.setOriginalHash(MifielUtils.getDocumentHash(pdfFilePath)); doc.setFileName("20170201-50147577"); doc = docs.save(doc); - assertTrue(doc != null); + + assertNotNull(doc); + assertEquals(DOCUMENT_ID, doc.getId()); + assertEquals("POST", apiClient.getLastMethod()); + assertEquals(Documents.DOCUMENTS_PATH, apiClient.getLastPath()); } @Test(expected = MifielException.class) - public void testSaveADocumentWithoutRequiredFieldsShouldThrowAnException() throws MifielException { - setSandboxUrl(); + public void testSaveADocumentWithoutRequiredFieldsShouldThrowAnException() throws Exception { Document doc = new Document(); doc.setCallbackUrl("http://www.google.com"); - docs.save(doc); + try { + docs.save(doc); + } finally { + assertEquals(0, apiClient.getPostCount()); + } } @Test - public void testGetDocumentShouldReturnADocument() throws MifielException { - setSandboxUrl(); - testSaveADocumentWithOriginalHashAndFileName(); - final List allDocuments = docs.findAll(); - if (allDocuments.size() > 0) { - Document doc1 = docs.find(allDocuments.get(0).getId()); - assertTrue(doc1 != null); - } else { - throw new MifielException("No documents found"); - } + public void testGetDocumentShouldReturnADocument() throws Exception { + apiClient.setNextResponse(jsonEntity("{\"id\":\"" + DOCUMENT_ID + "\",\"name\":\"doc.pdf\"}")); + + Document doc = docs.find(DOCUMENT_ID); + + assertNotNull(doc); + assertEquals(DOCUMENT_ID, doc.getId()); + assertEquals("GET", apiClient.getLastMethod()); + assertEquals(Documents.DOCUMENTS_PATH + "/" + DOCUMENT_ID, apiClient.getLastPath()); } @Test - public void testDeleteShouldRemoveADocument() throws MifielException { - setSandboxUrl(); + public void testDeleteShouldRemoveADocument() throws Exception { + apiClient.setNextResponse(jsonEntity("")); - Document doc = new Document(); - doc.setOriginalHash(MifielUtils.getDocumentHash(pdfFilePath)); - doc.setFileName("20170201-50147577"); - doc = docs.save(doc); + docs.delete(DOCUMENT_ID); - docs.delete(doc.getId()); + assertEquals("DELETE", apiClient.getLastMethod()); + assertEquals(Documents.DOCUMENTS_PATH + "/" + DOCUMENT_ID, apiClient.getLastPath()); } @Test - public void testRequestSignatureShouldReturnASignatureResponse() throws MifielException { - setSandboxUrl(); - - Document doc = new Document(); - doc.setOriginalHash(MifielUtils.getDocumentHash(pdfFilePath)); - doc.setFileName("20170201-50147577"); - doc = docs.save(doc); + public void testRequestSignatureShouldReturnASignatureResponse() throws Exception { + apiClient.setNextResponse(jsonEntity("{\"status\":\"success\",\"message\":\"Signature requested\"}")); - SignatureResponse sig = docs.requestSignature(doc.getId(), "enrique@test.com", "enrique2@test.com"); + SignatureResponse sig = docs.requestSignature(DOCUMENT_ID, "enrique@test.com", "enrique2@test.com"); - assertTrue(sig != null); + assertNotNull(sig); + assertEquals("success", sig.getStatus()); + assertEquals("POST", apiClient.getLastMethod()); + assertEquals(Documents.DOCUMENTS_PATH + "/" + DOCUMENT_ID + "/request_signature", apiClient.getLastPath()); } @Test - public void testSaveFileShouldSaveFileOnSpecifiedPath() throws MifielException, IOException { - setSandboxUrl(); - Document doc = new Document(); - doc.setFile(pdfFilePath); - doc = docs.save(doc); + public void testSaveFileShouldSaveFileOnSpecifiedPath() throws Exception { + File output = File.createTempFile("mifiel-doc-", ".bin"); + output.deleteOnExit(); + + apiClient.setNextResponse(new StringEntity("pdf-bytes", StandardCharsets.UTF_8)); - String outputPath = this.path + doc.getId(); - docs.saveFile(doc.getId(), outputPath); + docs.saveFile(DOCUMENT_ID, output.getAbsolutePath()); - assertTrue(Files.deleteIfExists(Paths.get(outputPath))); + assertTrue(output.length() > 0); + assertEquals("GET", apiClient.getLastMethod()); + assertEquals(Documents.DOCUMENTS_PATH + "/" + DOCUMENT_ID + "/file", apiClient.getLastPath()); } - private void setSandboxUrl() throws MifielException { - apiClient.setUrl(mifielBase); + private static HttpEntity jsonEntity(String json) throws Exception { + return new StringEntity(json, StandardCharsets.UTF_8); } } diff --git a/src/test/java/com/mifiel/api/FakeApiClient.java b/src/test/java/com/mifiel/api/FakeApiClient.java new file mode 100644 index 0000000..b1d5879 --- /dev/null +++ b/src/test/java/com/mifiel/api/FakeApiClient.java @@ -0,0 +1,84 @@ +package com.mifiel.api; + +import org.apache.http.HttpEntity; + +import com.mifiel.api.exception.MifielException; + +/** + * In-memory {@link ApiClient} that never opens a network connection. + */ +class FakeApiClient extends ApiClient { + + private HttpEntity nextResponse; + private MifielException nextException; + private String lastMethod; + private String lastPath; + private HttpEntity lastBody; + private int postCount; + + FakeApiClient() { + super("test-app-id", "test-app-secret"); + } + + void setNextResponse(final HttpEntity response) { + this.nextResponse = response; + this.nextException = null; + } + + void setNextException(final MifielException exception) { + this.nextException = exception; + this.nextResponse = null; + } + + String getLastMethod() { + return lastMethod; + } + + String getLastPath() { + return lastPath; + } + + HttpEntity getLastBody() { + return lastBody; + } + + int getPostCount() { + return postCount; + } + + @Override + public HttpEntity get(final String path) throws MifielException { + return record("GET", path, null); + } + + @Override + public HttpEntity post(final String path, final HttpEntity content) throws MifielException { + postCount++; + return record("POST", path, content); + } + + @Override + public HttpEntity delete(final String path) throws MifielException { + return record("DELETE", path, null); + } + + @Override + public HttpEntity put(final String path, final HttpEntity content) throws MifielException { + return record("PUT", path, content); + } + + @Override + public HttpEntity patch(final String path, final HttpEntity content) throws MifielException { + return record("PATCH", path, content); + } + + private HttpEntity record(final String method, final String path, final HttpEntity body) throws MifielException { + lastMethod = method; + lastPath = path; + lastBody = body; + if (nextException != null) { + throw nextException; + } + return nextResponse; + } +} From fc894e26c173efa183ee3851b47831bd6f537162 Mon Sep 17 00:00:00 2001 From: Genaro Madrid Date: Mon, 24 Aug 2026 20:16:23 -0600 Subject: [PATCH 3/4] improve --- .github/workflows/ci.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3b9f27e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,17 @@ +name: CI + +on: + push: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-java@v5 + with: + distribution: temurin + java-version: "17" + cache: maven + - name: Run unit tests + run: mvn -B test From f48257b824b6ffda1a659dae546cd9eddf3164b6 Mon Sep 17 00:00:00 2001 From: Genaro Madrid Date: Mon, 24 Aug 2026 20:24:19 -0600 Subject: [PATCH 4/4] improve security in github ci --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3b9f27e..5a3aa2a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,8 +6,12 @@ on: jobs: test: runs-on: ubuntu-latest + permissions: + contents: read steps: - uses: actions/checkout@v5 + with: + persist-credentials: false - uses: actions/setup-java@v5 with: distribution: temurin