mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-17 12:40:44 +00:00
Many tests. small refactors to support.
This commit is contained in:
@ -34,10 +34,6 @@
|
||||
<properties>
|
||||
<!-- props specifically to this module -->
|
||||
<!-- none at this time -->
|
||||
|
||||
<!-- todo - remove this once module is further built out and we can hit standard ratio -->
|
||||
<coverage.instructionCoveredRatioMinimum>0.00</coverage.instructionCoveredRatioMinimum>
|
||||
<coverage.classCoveredRatioMinimum>0.00</coverage.classCoveredRatioMinimum>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -634,7 +634,7 @@ public class BaseAPIActionUtil
|
||||
request.setEntity(new StringEntity(postBody));
|
||||
request.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
|
||||
|
||||
HttpResponse response = client.execute(request);
|
||||
HttpResponse response = executeOAuthTokenRequest(client, request);
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
HttpEntity entity = response.getEntity();
|
||||
String resultString = EntityUtils.toString(entity);
|
||||
@ -669,6 +669,16 @@ public class BaseAPIActionUtil
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** one-line method, factored out so mock/tests can override
|
||||
*******************************************************************************/
|
||||
protected CloseableHttpResponse executeOAuthTokenRequest(CloseableHttpClient client, HttpPost request) throws IOException
|
||||
{
|
||||
return client.execute(request);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** As part of making a request - set up its content-type header.
|
||||
*******************************************************************************/
|
||||
@ -880,7 +890,7 @@ public class BaseAPIActionUtil
|
||||
LOG.info("POST contents [" + ((HttpPost) request).getEntity().toString() + "]");
|
||||
}
|
||||
|
||||
try(CloseableHttpResponse response = httpClient.execute(request))
|
||||
try(CloseableHttpResponse response = executeHttpRequest(request, httpClient))
|
||||
{
|
||||
QHttpResponse qResponse = new QHttpResponse(response);
|
||||
|
||||
@ -924,7 +934,7 @@ public class BaseAPIActionUtil
|
||||
rateLimitsCaught++;
|
||||
if(rateLimitsCaught > getMaxAllowedRateLimitErrors())
|
||||
{
|
||||
LOG.error("Giving up POST to [" + table.getName() + "] after too many rate-limit errors (" + getMaxAllowedRateLimitErrors() + ")");
|
||||
LOG.error("Giving up " + request.getMethod() + " to [" + table.getName() + "] after too many rate-limit errors (" + getMaxAllowedRateLimitErrors() + ")");
|
||||
throw (new QException(rle));
|
||||
}
|
||||
|
||||
@ -950,6 +960,16 @@ public class BaseAPIActionUtil
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** one-line method, factored out so mock/tests can override
|
||||
*******************************************************************************/
|
||||
protected CloseableHttpResponse executeHttpRequest(HttpRequestBase request, CloseableHttpClient httpClient) throws IOException
|
||||
{
|
||||
return httpClient.execute(request);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
@ -32,6 +32,8 @@ import com.kingsrook.qqq.backend.core.model.metadata.code.QCodeUsage;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldType;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.modules.backend.implementations.memory.MemoryBackendModule;
|
||||
import com.kingsrook.qqq.backend.module.api.mocks.MockApiActionUtils;
|
||||
import com.kingsrook.qqq.backend.module.api.model.AuthorizationType;
|
||||
import com.kingsrook.qqq.backend.module.api.model.metadata.APIBackendMetaData;
|
||||
import com.kingsrook.qqq.backend.module.api.model.metadata.APITableBackendDetails;
|
||||
@ -42,7 +44,10 @@ import com.kingsrook.qqq.backend.module.api.model.metadata.APITableBackendDetail
|
||||
*******************************************************************************/
|
||||
public class TestUtils
|
||||
{
|
||||
public static final String MEMORY_BACKEND_NAME = "memory";
|
||||
public static final String EASYPOST_BACKEND_NAME = "easypost";
|
||||
public static final String MOCK_BACKEND_NAME = "mock";
|
||||
public static final String MOCK_TABLE_NAME = "mock";
|
||||
|
||||
|
||||
|
||||
@ -52,14 +57,69 @@ public class TestUtils
|
||||
public static QInstance defineInstance()
|
||||
{
|
||||
QInstance qInstance = new QInstance();
|
||||
qInstance.addBackend(defineBackend());
|
||||
qInstance.addTable(defineTableEasypostTracker());
|
||||
qInstance.setAuthentication(defineAuthentication());
|
||||
|
||||
qInstance.addBackend(defineMemoryBackend());
|
||||
|
||||
qInstance.addBackend(defineMockBackend());
|
||||
qInstance.addTable(defineMockTable());
|
||||
|
||||
qInstance.addBackend(defineEasypostBackend());
|
||||
qInstance.addTable(defineTableEasypostTracker());
|
||||
|
||||
return (qInstance);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define the in-memory backend used in standard tests
|
||||
*******************************************************************************/
|
||||
public static QBackendMetaData defineMemoryBackend()
|
||||
{
|
||||
return new QBackendMetaData()
|
||||
.withName(MEMORY_BACKEND_NAME)
|
||||
.withBackendType(MemoryBackendModule.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static QBackendMetaData defineMockBackend()
|
||||
{
|
||||
return (new APIBackendMetaData()
|
||||
.withName(MOCK_BACKEND_NAME)
|
||||
.withAuthorizationType(AuthorizationType.API_KEY_HEADER)
|
||||
.withBaseUrl("http://localhost:9999/mock")
|
||||
.withContentType("application/json")
|
||||
.withActionUtil(new QCodeReference(MockApiActionUtils.class, QCodeUsage.CUSTOMIZER))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static QTableMetaData defineMockTable()
|
||||
{
|
||||
return (new QTableMetaData()
|
||||
.withName(MOCK_TABLE_NAME)
|
||||
.withBackendName(MOCK_BACKEND_NAME)
|
||||
.withField(new QFieldMetaData("id", QFieldType.STRING))
|
||||
.withField(new QFieldMetaData("name", QFieldType.STRING))
|
||||
.withPrimaryKeyField("id")
|
||||
.withBackendDetails(new APITableBackendDetails()
|
||||
.withTablePath("mock")
|
||||
.withTableWrapperObjectName("mocks")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Define the authentication used in standard tests - using 'mock' type.
|
||||
**
|
||||
@ -76,7 +136,7 @@ public class TestUtils
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public static QBackendMetaData defineBackend()
|
||||
public static QBackendMetaData defineEasypostBackend()
|
||||
{
|
||||
String apiKey = new QMetaDataVariableInterpreter().interpret("${env.EASYPOST_API_KEY}");
|
||||
|
||||
|
@ -0,0 +1,672 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2023. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.module.api.actions;
|
||||
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.CountAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.GetAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.InsertAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.QueryAction;
|
||||
import com.kingsrook.qqq.backend.core.actions.tables.UpdateAction;
|
||||
import com.kingsrook.qqq.backend.core.context.QContext;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.count.CountOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.get.GetOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.insert.InsertOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.query.QueryOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateInput;
|
||||
import com.kingsrook.qqq.backend.core.model.actions.tables.update.UpdateOutput;
|
||||
import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.QInstance;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.UniqueKey;
|
||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||
import com.kingsrook.qqq.backend.module.api.BaseTest;
|
||||
import com.kingsrook.qqq.backend.module.api.TestUtils;
|
||||
import com.kingsrook.qqq.backend.module.api.exceptions.RateLimitException;
|
||||
import com.kingsrook.qqq.backend.module.api.mocks.MockApiActionUtils;
|
||||
import com.kingsrook.qqq.backend.module.api.mocks.MockApiUtilsHelper;
|
||||
import com.kingsrook.qqq.backend.module.api.model.AuthorizationType;
|
||||
import com.kingsrook.qqq.backend.module.api.model.OutboundAPILog;
|
||||
import com.kingsrook.qqq.backend.module.api.model.OutboundAPILogMetaDataProvider;
|
||||
import com.kingsrook.qqq.backend.module.api.model.metadata.APIBackendMetaData;
|
||||
import org.apache.http.Header;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Unit test for com.kingsrook.qqq.backend.module.api.actions.BaseAPIActionUtil
|
||||
*******************************************************************************/
|
||||
class BaseAPIActionUtilTest extends BaseTest
|
||||
{
|
||||
private static MockApiUtilsHelper mockApiUtilsHelper = new MockApiUtilsHelper();
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@BeforeEach
|
||||
void beforeEach()
|
||||
{
|
||||
mockApiUtilsHelper = new MockApiUtilsHelper();
|
||||
mockApiUtilsHelper.setUseMock(true);
|
||||
MockApiActionUtils.mockApiUtilsHelper = mockApiUtilsHelper;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testCount() throws QException
|
||||
{
|
||||
mockApiUtilsHelper.enqueueMockResponse("""
|
||||
[
|
||||
{"id": 1, "name": "Homer"},
|
||||
{"id": 2, "name": "Marge"},
|
||||
{"id": 3, "name": "Bart"},
|
||||
{"id": 4, "name": "Lisa"},
|
||||
{"id": 5, "name": "Maggie"}
|
||||
]
|
||||
""");
|
||||
|
||||
CountInput countInput = new CountInput();
|
||||
countInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
CountOutput countOutput = new CountAction().execute(countInput);
|
||||
assertEquals(5, countOutput.getCount());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testCountError() throws QException
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// avoid the fully mocked makeRequest //
|
||||
////////////////////////////////////////
|
||||
mockApiUtilsHelper.setUseMock(false);
|
||||
mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(500).withContent("""
|
||||
{"error": "Server error"}
|
||||
"""));
|
||||
|
||||
CountInput countInput = new CountInput();
|
||||
countInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
assertThatThrownBy(() -> new CountAction().execute(countInput)).hasRootCauseInstanceOf(Exception.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testGet() throws QException
|
||||
{
|
||||
mockApiUtilsHelper.enqueueMockResponse("""
|
||||
{"id": 3, "name": "Bart"},
|
||||
""");
|
||||
|
||||
GetInput getInput = new GetInput();
|
||||
getInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
getInput.setPrimaryKey(3);
|
||||
GetOutput getOutput = new GetAction().execute(getInput);
|
||||
assertEquals(3, getOutput.getRecord().getValueInteger("id"));
|
||||
assertEquals("Bart", getOutput.getRecord().getValueString("name"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testGetByKey() throws QException
|
||||
{
|
||||
QContext.getQInstance().getTable(TestUtils.MOCK_TABLE_NAME).withUniqueKey(new UniqueKey("id"));
|
||||
|
||||
mockApiUtilsHelper.enqueueMockResponse("""
|
||||
{"id": 3, "name": "Bart"},
|
||||
""");
|
||||
|
||||
GetInput getInput = new GetInput();
|
||||
getInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
getInput.setUniqueKey(Map.of("id", 3));
|
||||
GetOutput getOutput = new GetAction().execute(getInput);
|
||||
assertEquals(3, getOutput.getRecord().getValueInteger("id"));
|
||||
assertEquals("Bart", getOutput.getRecord().getValueString("name"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testQuery() throws QException
|
||||
{
|
||||
mockApiUtilsHelper.enqueueMockResponse("""
|
||||
[
|
||||
{"id": 1, "name": "Homer"},
|
||||
{"id": 2, "name": "Marge"},
|
||||
{"id": 3, "name": "Bart"},
|
||||
{"id": 4, "name": "Lisa"},
|
||||
{"id": 5, "name": "Maggie"}
|
||||
]
|
||||
""");
|
||||
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(5, queryOutput.getRecords().size());
|
||||
assertEquals(1, queryOutput.getRecords().get(0).getValueInteger("id"));
|
||||
assertEquals("Homer", queryOutput.getRecords().get(0).getValueString("name"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testQueryObjectWrappingList() throws QException
|
||||
{
|
||||
mockApiUtilsHelper.enqueueMockResponse("""
|
||||
{"mocks": [
|
||||
{"id": 1, "name": "Homer"},
|
||||
{"id": 2, "name": "Marge"},
|
||||
{"id": 3, "name": "Bart"},
|
||||
{"id": 4, "name": "Lisa"},
|
||||
{"id": 5, "name": "Maggie"}
|
||||
]}
|
||||
""");
|
||||
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(5, queryOutput.getRecords().size());
|
||||
assertEquals(1, queryOutput.getRecords().get(0).getValueInteger("id"));
|
||||
assertEquals("Homer", queryOutput.getRecords().get(0).getValueString("name"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testQueryObjectWrappingSingleObject() throws QException
|
||||
{
|
||||
mockApiUtilsHelper.enqueueMockResponse("""
|
||||
{"mocks":
|
||||
{"id": 1, "name": "Homer"}
|
||||
}
|
||||
""");
|
||||
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(1, queryOutput.getRecords().size());
|
||||
assertEquals(1, queryOutput.getRecords().get(0).getValueInteger("id"));
|
||||
assertEquals("Homer", queryOutput.getRecords().get(0).getValueString("name"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testQueryPaginate() throws QException
|
||||
{
|
||||
String oneObject = """
|
||||
{"id": 1, "name": "Homer"}
|
||||
""";
|
||||
StringBuilder response = new StringBuilder("[");
|
||||
for(int i = 0; i < 19; i++)
|
||||
{
|
||||
response.append(oneObject).append(",");
|
||||
}
|
||||
response.append(oneObject);
|
||||
response.append("]");
|
||||
mockApiUtilsHelper.enqueueMockResponse(response.toString());
|
||||
mockApiUtilsHelper.enqueueMockResponse(response.toString());
|
||||
mockApiUtilsHelper.enqueueMockResponse(response.toString());
|
||||
mockApiUtilsHelper.enqueueMockResponse("[]");
|
||||
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
QueryOutput queryOutput = new QueryAction().execute(queryInput);
|
||||
assertEquals(60, queryOutput.getRecords().size());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testQueryError() throws QException
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// avoid the fully mocked makeRequest //
|
||||
////////////////////////////////////////
|
||||
mockApiUtilsHelper.setUseMock(false);
|
||||
mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(500).withContent("""
|
||||
{"error": "Server error"}
|
||||
"""));
|
||||
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
assertThatThrownBy(() -> new QueryAction().execute(queryInput)).hasRootCauseInstanceOf(Exception.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testInsert() throws QException
|
||||
{
|
||||
mockApiUtilsHelper.enqueueMockResponse("""
|
||||
{"id": 6}
|
||||
""");
|
||||
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
insertInput.setRecords(List.of(new QRecord().withValue("name", "Milhouse")));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
assertEquals(6, insertOutput.getRecords().get(0).getValueInteger("id"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testInsertEmptyInputList() throws QException
|
||||
{
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
insertInput.setRecords(List.of());
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testInsertError() throws QException
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// avoid the fully mocked makeRequest //
|
||||
////////////////////////////////////////
|
||||
mockApiUtilsHelper.setUseMock(false);
|
||||
mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(500).withContent("""
|
||||
{"error": "Server error"}
|
||||
"""));
|
||||
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setRecords(List.of(new QRecord().withValue("name", "Milhouse")));
|
||||
insertInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
assertTrue(CollectionUtils.nullSafeHasContents(insertOutput.getRecords().get(0).getErrors()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testUpdate() throws QException
|
||||
{
|
||||
mockApiUtilsHelper.enqueueMockResponse("");
|
||||
|
||||
mockApiUtilsHelper.setMockRequestAsserter(httpRequestBase ->
|
||||
{
|
||||
String requestBody = MockApiUtilsHelper.readRequestBody(httpRequestBase);
|
||||
JSONObject requestObject = new JSONObject(requestBody);
|
||||
|
||||
JSONArray mocks = requestObject.getJSONArray("mocks");
|
||||
JSONObject record = mocks.getJSONObject(0);
|
||||
|
||||
assertEquals("Bartholomew", record.getString("name"));
|
||||
assertEquals(3, record.getInt("id"));
|
||||
});
|
||||
|
||||
UpdateInput updateInput = new UpdateInput();
|
||||
updateInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
updateInput.setRecords(List.of(new QRecord().withValue("id", "3").withValue("name", "Bartholomew")));
|
||||
UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
|
||||
|
||||
// not sure what to assert in here...
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testUpdateEmptyInputList() throws QException
|
||||
{
|
||||
UpdateInput updateInput = new UpdateInput();
|
||||
updateInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
updateInput.setRecords(List.of());
|
||||
UpdateOutput updateOutput = new UpdateAction().execute(updateInput);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testUpdateError() throws QException
|
||||
{
|
||||
////////////////////////////////////////
|
||||
// avoid the fully mocked makeRequest //
|
||||
////////////////////////////////////////
|
||||
mockApiUtilsHelper.setUseMock(false);
|
||||
mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(500).withContent("""
|
||||
{"error": "Server error"}
|
||||
"""));
|
||||
|
||||
UpdateInput updateInput = new UpdateInput();
|
||||
updateInput.setRecords(List.of(new QRecord().withValue("name", "Milhouse")));
|
||||
updateInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// note - right now this is inconsistent with insertAction (and rdbms update), //
|
||||
// where errors are placed in the records, rather than thrown... //
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
assertThatThrownBy(() -> new UpdateAction().execute(updateInput)).hasRootCauseInstanceOf(Exception.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testMakeRequest() throws QException
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// this will make it not use the mock makeRequest method, //
|
||||
// but instead the mock executeHttpRequest, so we can test code from the base makeRequest //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
mockApiUtilsHelper.setUseMock(false);
|
||||
mockApiUtilsHelper.enqueueMockResponse("""
|
||||
{"id": 3, "name": "Bart"},
|
||||
""");
|
||||
|
||||
GetInput getInput = new GetInput();
|
||||
getInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
getInput.setPrimaryKey(3);
|
||||
GetOutput getOutput = new GetAction().execute(getInput);
|
||||
assertEquals(3, getOutput.getRecord().getValueInteger("id"));
|
||||
assertEquals("Bart", getOutput.getRecord().getValueString("name"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void test429Then200() throws QException
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// this will make it not use the mock makeRequest method, //
|
||||
// but instead the mock executeHttpRequest, so we can test code from the base makeRequest //
|
||||
// specifically, that we can get one 429, and then eventually a 200 //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
mockApiUtilsHelper.setUseMock(false);
|
||||
mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(429).withContent("Try again"));
|
||||
mockApiUtilsHelper.enqueueMockResponse("""
|
||||
{"id": 3, "name": "Bart"},
|
||||
""");
|
||||
|
||||
GetInput getInput = new GetInput();
|
||||
getInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
getInput.setPrimaryKey(3);
|
||||
GetOutput getOutput = new GetAction().execute(getInput);
|
||||
assertEquals(3, getOutput.getRecord().getValueInteger("id"));
|
||||
assertEquals("Bart", getOutput.getRecord().getValueString("name"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testTooMany429() throws QException
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// this will make it not use the mock makeRequest method, //
|
||||
// but instead the mock executeHttpRequest, so we can test code from the base makeRequest //
|
||||
// specifically, that after too many 429's we get an error //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
mockApiUtilsHelper.setUseMock(false);
|
||||
mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(429).withContent("Try again"));
|
||||
mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(429).withContent("Try again"));
|
||||
mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(429).withContent("Try again"));
|
||||
mockApiUtilsHelper.enqueueMockResponse(new QHttpResponse().withStatusCode(429).withContent("Try again"));
|
||||
|
||||
GetInput getInput = new GetInput();
|
||||
getInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
getInput.setPrimaryKey(3);
|
||||
|
||||
assertThatThrownBy(() -> new GetAction().execute(getInput)).hasRootCauseInstanceOf(RateLimitException.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testApiLogs() throws QException
|
||||
{
|
||||
QInstance qInstance = QContext.getQInstance();
|
||||
OutboundAPILogMetaDataProvider.defineAll(qInstance, TestUtils.MEMORY_BACKEND_NAME, null);
|
||||
|
||||
mockApiUtilsHelper.setUseMock(false);
|
||||
mockApiUtilsHelper.enqueueMockResponse("""
|
||||
{"id": 6}
|
||||
""");
|
||||
|
||||
InsertInput insertInput = new InsertInput();
|
||||
insertInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
insertInput.setRecords(List.of(new QRecord().withValue("name", "Milhouse")));
|
||||
InsertOutput insertOutput = new InsertAction().execute(insertInput);
|
||||
assertEquals(6, insertOutput.getRecords().get(0).getValueInteger("id"));
|
||||
|
||||
QueryInput queryInput = new QueryInput();
|
||||
queryInput.setTableName(OutboundAPILog.TABLE_NAME);
|
||||
QueryOutput apiLogRecords = new QueryAction().execute(queryInput);
|
||||
assertEquals(1, apiLogRecords.getRecords().size());
|
||||
assertEquals("POST", apiLogRecords.getRecords().get(0).getValueString("method"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testBasicAuthApiKey() throws QException
|
||||
{
|
||||
APIBackendMetaData backend = (APIBackendMetaData) QContext.getQInstance().getBackend(TestUtils.MOCK_BACKEND_NAME);
|
||||
backend.setAuthorizationType(AuthorizationType.BASIC_AUTH_API_KEY);
|
||||
backend.setApiKey("9876-WXYZ");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// this will make it not use the mock makeRequest method, //
|
||||
// but instead the mock executeHttpRequest, so we can test code from the base makeRequest //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
mockApiUtilsHelper.setUseMock(false);
|
||||
mockApiUtilsHelper.enqueueMockResponse("""
|
||||
{"id": 3, "name": "Bart"},
|
||||
""");
|
||||
|
||||
mockApiUtilsHelper.setMockRequestAsserter(request ->
|
||||
{
|
||||
Header authHeader = request.getFirstHeader("Authorization");
|
||||
assertTrue(authHeader.getValue().startsWith("Basic "));
|
||||
String apiKey = new String(Base64.getDecoder().decode(authHeader.getValue().replace("Basic ", "")), StandardCharsets.UTF_8);
|
||||
assertEquals("9876-WXYZ", apiKey);
|
||||
});
|
||||
|
||||
runSimpleGetAction();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testBasicAuthUsernamePassword() throws QException
|
||||
{
|
||||
APIBackendMetaData backend = (APIBackendMetaData) QContext.getQInstance().getBackend(TestUtils.MOCK_BACKEND_NAME);
|
||||
backend.setAuthorizationType(AuthorizationType.BASIC_AUTH_USERNAME_PASSWORD);
|
||||
backend.setUsername("god");
|
||||
backend.setPassword("5fingers");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// this will make it not use the mock makeRequest method, //
|
||||
// but instead the mock executeHttpRequest, so we can test code from the base makeRequest //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
mockApiUtilsHelper.setUseMock(false);
|
||||
mockApiUtilsHelper.enqueueMockResponse("""
|
||||
{"id": 3, "name": "Bart"},
|
||||
""");
|
||||
|
||||
mockApiUtilsHelper.setMockRequestAsserter(request ->
|
||||
{
|
||||
Header authHeader = request.getFirstHeader("Authorization");
|
||||
assertTrue(authHeader.getValue().startsWith("Basic "));
|
||||
String usernamePassword = new String(Base64.getDecoder().decode(authHeader.getValue().replace("Basic ", "")), StandardCharsets.UTF_8);
|
||||
assertEquals("god:5fingers", usernamePassword);
|
||||
});
|
||||
|
||||
runSimpleGetAction();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOAuth2ValidToken() throws QException
|
||||
{
|
||||
APIBackendMetaData backend = (APIBackendMetaData) QContext.getQInstance().getBackend(TestUtils.MOCK_BACKEND_NAME);
|
||||
backend.setAuthorizationType(AuthorizationType.OAUTH2);
|
||||
backend.withCustomValue("accessToken", "validToken");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// this will make it not use the mock makeRequest method, //
|
||||
// but instead the mock executeHttpRequest, so we can test code from the base makeRequest //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
mockApiUtilsHelper.setUseMock(false);
|
||||
mockApiUtilsHelper.enqueueMockResponse("""
|
||||
{"id": 3, "name": "Bart"},
|
||||
""");
|
||||
|
||||
mockApiUtilsHelper.setMockRequestAsserter(request ->
|
||||
{
|
||||
Header authHeader = request.getFirstHeader("Authorization");
|
||||
assertTrue(authHeader.getValue().startsWith("Bearer "));
|
||||
String token = authHeader.getValue().replace("Bearer ", "");
|
||||
assertEquals("validToken", token);
|
||||
});
|
||||
|
||||
runSimpleGetAction();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Test
|
||||
void testOAuth2NullToken() throws QException
|
||||
{
|
||||
APIBackendMetaData backend = (APIBackendMetaData) QContext.getQInstance().getBackend(TestUtils.MOCK_BACKEND_NAME);
|
||||
backend.setAuthorizationType(AuthorizationType.OAUTH2);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// this will make it not use the mock makeRequest method, //
|
||||
// but instead the mock executeHttpRequest, so we can test code from the base makeRequest //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
mockApiUtilsHelper.setUseMock(false);
|
||||
mockApiUtilsHelper.enqueueMockResponse("""
|
||||
{"access_token": "myNewToken"}
|
||||
""");
|
||||
mockApiUtilsHelper.enqueueMockResponse("""
|
||||
{"id": 3, "name": "Bart"},
|
||||
""");
|
||||
|
||||
GetOutput getOutput = runSimpleGetAction();
|
||||
assertEquals(3, getOutput.getRecord().getValueInteger("id"));
|
||||
assertEquals("Bart", getOutput.getRecord().getValueString("name"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static GetOutput runSimpleGetAction() throws QException
|
||||
{
|
||||
GetInput getInput = new GetInput();
|
||||
getInput.setTableName(TestUtils.MOCK_TABLE_NAME);
|
||||
getInput.setPrimaryKey(3);
|
||||
return (new GetAction().execute(getInput));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2023. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.module.api.mocks;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.module.api.actions.BaseAPIActionUtil;
|
||||
import com.kingsrook.qqq.backend.module.api.actions.QHttpResponse;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class MockApiActionUtils extends BaseAPIActionUtil
|
||||
{
|
||||
public static MockApiUtilsHelper mockApiUtilsHelper;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
public QHttpResponse makeRequest(QTableMetaData table, HttpRequestBase request) throws QException
|
||||
{
|
||||
return (mockApiUtilsHelper.defaultMockMakeRequest(mockApiUtilsHelper, table, request, () -> super.makeRequest(table, request)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
protected CloseableHttpResponse executeHttpRequest(HttpRequestBase request, CloseableHttpClient httpClient) throws IOException
|
||||
{
|
||||
runMockAsserter(request);
|
||||
return new MockHttpResponse(mockApiUtilsHelper);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
private static void runMockAsserter(HttpRequestBase request)
|
||||
{
|
||||
if(mockApiUtilsHelper.getMockRequestAsserter() != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
mockApiUtilsHelper.getMockRequestAsserter().run(request);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw (new RuntimeException("Error running mock request asserter", e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@Override
|
||||
protected CloseableHttpResponse executeOAuthTokenRequest(CloseableHttpClient client, HttpPost request) throws IOException
|
||||
{
|
||||
runMockAsserter(request);
|
||||
return new MockHttpResponse(mockApiUtilsHelper);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
protected int getInitialRateLimitBackoffMillis()
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,226 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2023. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.module.api.mocks;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import com.kingsrook.qqq.backend.core.exceptions.QException;
|
||||
import com.kingsrook.qqq.backend.core.logging.QLogger;
|
||||
import com.kingsrook.qqq.backend.core.model.metadata.tables.QTableMetaData;
|
||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
||||
import com.kingsrook.qqq.backend.core.utils.lambdas.UnsafeConsumer;
|
||||
import com.kingsrook.qqq.backend.core.utils.lambdas.UnsafeSupplier;
|
||||
import com.kingsrook.qqq.backend.module.api.actions.QHttpResponse;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpRequestBase;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class MockApiUtilsHelper
|
||||
{
|
||||
private static final QLogger LOG = QLogger.getLogger(MockApiUtilsHelper.class);
|
||||
|
||||
private boolean useMock = true;
|
||||
private Deque<QHttpResponse> mockResponseQueue = new ArrayDeque<>();
|
||||
private UnsafeConsumer<HttpRequestBase, ? extends Throwable> mockRequestAsserter = null;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void enqueueMockResponse(String json)
|
||||
{
|
||||
mockResponseQueue.addLast(new QHttpResponse()
|
||||
.withStatusCode(200)
|
||||
.withContent(json)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public void enqueueMockResponse(QHttpResponse qHttpResponse)
|
||||
{
|
||||
mockResponseQueue.addLast(qHttpResponse);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QHttpResponse returnMockResponseFromQueue(HttpRequestBase request) throws QException
|
||||
{
|
||||
if(getMockRequestAsserter() != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
getMockRequestAsserter().run(request);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw (new QException("Error running mock request asserter", e));
|
||||
}
|
||||
}
|
||||
|
||||
if(mockResponseQueue.isEmpty())
|
||||
{
|
||||
fail("No mock response is in the queue for " + request.getMethod() + " " + request.getURI());
|
||||
}
|
||||
|
||||
LOG.info("Returning mock http response for " + request.getMethod() + " " + request.getURI());
|
||||
return (mockResponseQueue.removeFirst());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for useMock
|
||||
*******************************************************************************/
|
||||
public boolean getUseMock()
|
||||
{
|
||||
return (this.useMock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for useMock
|
||||
*******************************************************************************/
|
||||
public void setUseMock(boolean useMock)
|
||||
{
|
||||
this.useMock = useMock;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for useMock
|
||||
*******************************************************************************/
|
||||
public MockApiUtilsHelper withUseMock(boolean useMock)
|
||||
{
|
||||
this.useMock = useMock;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for mockResponseQueue
|
||||
*******************************************************************************/
|
||||
public Deque<QHttpResponse> getMockResponseQueue()
|
||||
{
|
||||
return (this.mockResponseQueue);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for mockResponseQueue
|
||||
*******************************************************************************/
|
||||
public void setMockResponseQueue(Deque<QHttpResponse> mockResponseQueue)
|
||||
{
|
||||
this.mockResponseQueue = mockResponseQueue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for mockResponseQueue
|
||||
*******************************************************************************/
|
||||
public MockApiUtilsHelper withMockResponseQueue(Deque<QHttpResponse> mockResponseQueue)
|
||||
{
|
||||
this.mockResponseQueue = mockResponseQueue;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Getter for mockRequestAsserter
|
||||
*******************************************************************************/
|
||||
public UnsafeConsumer<HttpRequestBase, ? extends Throwable> getMockRequestAsserter()
|
||||
{
|
||||
return (this.mockRequestAsserter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Setter for mockRequestAsserter
|
||||
*******************************************************************************/
|
||||
public void setMockRequestAsserter(UnsafeConsumer<HttpRequestBase, ? extends Throwable> mockRequestAsserter)
|
||||
{
|
||||
this.mockRequestAsserter = mockRequestAsserter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Fluent setter for mockRequestAsserter
|
||||
*******************************************************************************/
|
||||
public MockApiUtilsHelper withMockRequestAsserter(UnsafeConsumer<HttpRequestBase, ? extends Throwable> mockRequestAsserter)
|
||||
{
|
||||
this.mockRequestAsserter = mockRequestAsserter;
|
||||
return (this);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public QHttpResponse defaultMockMakeRequest(MockApiUtilsHelper mockApiUtilsHelper, QTableMetaData table, HttpRequestBase request, UnsafeSupplier<QHttpResponse, QException> superMethod) throws QException
|
||||
{
|
||||
if(!mockApiUtilsHelper.getUseMock())
|
||||
{
|
||||
QHttpResponse superResponse = superMethod.get();
|
||||
System.out.println("== non-mock response content: ==");
|
||||
System.out.println("Code: " + superResponse.getStatusCode());
|
||||
System.out.println(superResponse.getContent());
|
||||
System.out.println("== ==");
|
||||
return (superResponse);
|
||||
}
|
||||
|
||||
return mockApiUtilsHelper.returnMockResponseFromQueue(request);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static String readRequestBody(HttpRequestBase request) throws IOException
|
||||
{
|
||||
return (StringUtils.join("\n", IOUtils.readLines(((HttpPost) request).getEntity().getContent())));
|
||||
}
|
||||
}
|
@ -0,0 +1,302 @@
|
||||
/*
|
||||
* QQQ - Low-code Application Framework for Engineers.
|
||||
* Copyright (C) 2021-2023. Kingsrook, LLC
|
||||
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
|
||||
* contact@kingsrook.com
|
||||
* https://github.com/Kingsrook/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.kingsrook.qqq.backend.module.api.mocks;
|
||||
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import com.kingsrook.qqq.backend.module.api.actions.QHttpResponse;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HeaderIterator;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.ProtocolVersion;
|
||||
import org.apache.http.StatusLine;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.entity.BasicHttpEntity;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
import org.apache.http.params.HttpParams;
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
*******************************************************************************/
|
||||
public class MockHttpResponse implements CloseableHttpResponse
|
||||
{
|
||||
private final MockApiUtilsHelper mockApiUtilsHelper;
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
** Constructor
|
||||
**
|
||||
*******************************************************************************/
|
||||
public MockHttpResponse(MockApiUtilsHelper mockApiUtilsHelper)
|
||||
{
|
||||
this.mockApiUtilsHelper = mockApiUtilsHelper;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public StatusLine getStatusLine()
|
||||
{
|
||||
ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1);
|
||||
|
||||
if(!mockApiUtilsHelper.getMockResponseQueue().isEmpty())
|
||||
{
|
||||
QHttpResponse qHttpResponse = mockApiUtilsHelper.getMockResponseQueue().peekFirst();
|
||||
return (new BasicStatusLine(protocolVersion, qHttpResponse.getStatusCode(), qHttpResponse.getStatusReasonPhrase()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return (new BasicStatusLine(protocolVersion, 200, "OK"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setStatusLine(StatusLine statusLine)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setStatusLine(ProtocolVersion protocolVersion, int i)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setStatusLine(ProtocolVersion protocolVersion, int i, String s)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setStatusCode(int i) throws IllegalStateException
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setReasonPhrase(String s) throws IllegalStateException
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public HttpEntity getEntity()
|
||||
{
|
||||
BasicHttpEntity basicHttpEntity = new BasicHttpEntity();
|
||||
|
||||
if(!mockApiUtilsHelper.getMockResponseQueue().isEmpty())
|
||||
{
|
||||
QHttpResponse qHttpResponse = mockApiUtilsHelper.getMockResponseQueue().removeFirst();
|
||||
basicHttpEntity.setContent(new ByteArrayInputStream(qHttpResponse.getContent().getBytes()));
|
||||
}
|
||||
else
|
||||
{
|
||||
basicHttpEntity.setContent(new ByteArrayInputStream("".getBytes()));
|
||||
}
|
||||
return (basicHttpEntity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setEntity(HttpEntity httpEntity)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Locale getLocale()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setLocale(Locale locale)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public ProtocolVersion getProtocolVersion()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean containsHeader(String s)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Header[] getHeaders(String s)
|
||||
{
|
||||
return new Header[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Header getFirstHeader(String s)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Header getLastHeader(String s)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Header[] getAllHeaders()
|
||||
{
|
||||
return new Header[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void addHeader(Header header)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void addHeader(String s, String s1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setHeader(Header header)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setHeader(String s, String s1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setHeaders(Header[] headers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void removeHeader(Header header)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void removeHeaders(String s)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public HeaderIterator headerIterator()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public HeaderIterator headerIterator(String s)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public HttpParams getParams()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void setParams(HttpParams httpParams)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user