Set encoding to UTF-8 and Fix Comparison Tests (#27)
* Fixed issue with UTF-8 encodings not being picked up from the Windows console * Additional fixes to comparison tests * Added tests for Integer comparisons * Added String comparison tests * Added timestamp comparison tests * Renamed test files to match conventions * Added Fractional Date Part tests * Generated automated acceptance tests for remainder of compare() operations in TestUtils * Checked in new Commander build
This commit is contained in:
parent
59c409d37d
commit
cd3fd1ab84
File diff suppressed because it is too large
Load Diff
|
@ -10,6 +10,7 @@ plugins {
|
||||||
mainClassName = 'org.reso.commander.Main'
|
mainClassName = 'org.reso.commander.Main'
|
||||||
sourceCompatibility = 1.8
|
sourceCompatibility = 1.8
|
||||||
targetCompatibility = 1.8
|
targetCompatibility = 1.8
|
||||||
|
compileJava.options.encoding = 'UTF-8'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
// Use jcenter for resolving your dependencies.
|
// Use jcenter for resolving your dependencies.
|
||||||
|
|
Binary file not shown.
|
@ -3,6 +3,7 @@ package org.reso.certification.stepdefs;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.fasterxml.jackson.databind.node.POJONode;
|
import com.fasterxml.jackson.databind.node.POJONode;
|
||||||
import io.cucumber.java8.En;
|
import io.cucumber.java8.En;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.olingo.client.api.communication.ODataClientErrorException;
|
import org.apache.olingo.client.api.communication.ODataClientErrorException;
|
||||||
|
@ -254,20 +255,34 @@ public class WebAPIServer_1_0_2 implements En {
|
||||||
Then("^the server responds with a status code of (\\d+)$", (Integer assertedResponseCode) -> {
|
Then("^the server responds with a status code of (\\d+)$", (Integer assertedResponseCode) -> {
|
||||||
try {
|
try {
|
||||||
LOG.info("Asserted Response Code: " + assertedResponseCode + ", Server Response Code: " + getTestContainer().getResponseCode());
|
LOG.info("Asserted Response Code: " + assertedResponseCode + ", Server Response Code: " + getTestContainer().getResponseCode());
|
||||||
assertTrue(getTestContainer().getResponseCode() > 0 && assertedResponseCode > 0);
|
|
||||||
|
|
||||||
if (assertedResponseCode.intValue() != getTestContainer().getResponseCode().intValue()) {
|
//TODO: clean up logic
|
||||||
|
if (getTestContainer().getResponseCode() != null && assertedResponseCode.intValue() != getTestContainer().getResponseCode().intValue()) {
|
||||||
if (getTestContainer().getODataClientErrorException() != null) {
|
if (getTestContainer().getODataClientErrorException() != null) {
|
||||||
|
|
||||||
if (getTestContainer().getODataClientErrorException().getODataError().getMessage() != null) {
|
if (getTestContainer().getODataClientErrorException().getODataError().getMessage() != null) {
|
||||||
LOG.error("Request failed with the following message: "
|
LOG.error(getDefaultErrorMessage("Request failed with the following message:",
|
||||||
+ getTestContainer().getODataClientErrorException().getODataError().getMessage());
|
getTestContainer().getODataClientErrorException().getODataError().getMessage()));
|
||||||
} else if (getTestContainer().getODataClientErrorException().getMessage() != null) {
|
} else if (getTestContainer().getODataClientErrorException().getMessage() != null) {
|
||||||
LOG.error("Request failed with the following message: "
|
LOG.error(getDefaultErrorMessage("Request failed with the following message:",
|
||||||
+ getTestContainer().getODataClientErrorException().getMessage());
|
getTestContainer().getODataClientErrorException().getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (getTestContainer().getODataServerErrorException() != null) {
|
||||||
|
LOG.error(getDefaultErrorMessage("Request failed with the following message:",
|
||||||
|
getTestContainer().getODataServerErrorException().toString()));
|
||||||
|
|
||||||
|
if (getTestContainer().getODataServerErrorException().toString().contains(String.valueOf(HttpStatus.SC_INTERNAL_SERVER_ERROR))) {
|
||||||
|
getTestContainer().setResponseCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//fail for all inner conditions
|
||||||
fail(getAssertResponseCodeErrorMessage(assertedResponseCode, getTestContainer().getResponseCode()));
|
fail(getAssertResponseCodeErrorMessage(assertedResponseCode, getTestContainer().getResponseCode()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if we make it through without failing, things are good
|
||||||
|
assertTrue(getTestContainer().getResponseCode() > 0 && assertedResponseCode > 0);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
fail(getDefaultErrorMessage(ex));
|
fail(getDefaultErrorMessage(ex));
|
||||||
}
|
}
|
||||||
|
@ -329,11 +344,9 @@ public class WebAPIServer_1_0_2 implements En {
|
||||||
|
|
||||||
//iterate through response data and ensure that with data, the statement fieldName "op" assertValue is true
|
//iterate through response data and ensure that with data, the statement fieldName "op" assertValue is true
|
||||||
from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
|
from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
|
||||||
assertNotNull("ERROR: '" + fieldName + "' cannot be null!", item.get(fieldName));
|
fieldValue.set(item.get(fieldName) != null ? new Integer(item.get(fieldName).toString()) : null);
|
||||||
fieldValue.set(Integer.parseInt(item.get(fieldName).toString()));
|
|
||||||
result.set(result.get() && TestUtils.compare(fieldValue.get(), op, assertedValue));
|
result.set(result.get() && TestUtils.compare(fieldValue.get(), op, assertedValue));
|
||||||
});
|
});
|
||||||
|
|
||||||
assertTrue(result.get());
|
assertTrue(result.get());
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
fail(getDefaultErrorMessage(ex));
|
fail(getDefaultErrorMessage(ex));
|
||||||
|
|
|
@ -202,6 +202,7 @@ public class App {
|
||||||
if (cmd.hasOption(APP_OPTIONS.ACTIONS.GET_METADATA)) {
|
if (cmd.hasOption(APP_OPTIONS.ACTIONS.GET_METADATA)) {
|
||||||
APP_OPTIONS.validateAction(cmd, APP_OPTIONS.ACTIONS.GET_METADATA);
|
APP_OPTIONS.validateAction(cmd, APP_OPTIONS.ACTIONS.GET_METADATA);
|
||||||
|
|
||||||
|
//TODO: this isn't the metadata but the entity data model (edm), change to XML Metadata
|
||||||
metadata = commander.prepareEdmMetadataRequest().execute().getBody();
|
metadata = commander.prepareEdmMetadataRequest().execute().getBody();
|
||||||
getMetadataReport(metadata);
|
getMetadataReport(metadata);
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,8 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static org.reso.commander.common.ErrorMsg.getDefaultErrorMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Most of the work done by the WebAPI commander is done by this class. Its public methods are, therefore,
|
* Most of the work done by the WebAPI commander is done by this class. Its public methods are, therefore,
|
||||||
* the ones the Client programmer is expected to use.
|
* the ones the Client programmer is expected to use.
|
||||||
|
@ -102,15 +104,16 @@ public class Commander {
|
||||||
XMLReader reader = parser.getXMLReader();
|
XMLReader reader = parser.getXMLReader();
|
||||||
reader.setErrorHandler(new SimpleErrorHandler());
|
reader.setErrorHandler(new SimpleErrorHandler());
|
||||||
InputSource inputSource = new InputSource(new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8)));
|
InputSource inputSource = new InputSource(new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8)));
|
||||||
|
inputSource.setEncoding(StandardCharsets.UTF_8.toString());
|
||||||
reader.parse(inputSource);
|
reader.parse(inputSource);
|
||||||
return true;
|
return true;
|
||||||
} catch (SAXException saxEx) {
|
} catch (SAXException saxEx) {
|
||||||
if (saxEx.getMessage() != null) {
|
if (saxEx.getMessage() != null) {
|
||||||
LOG.error(saxEx);
|
LOG.error(getDefaultErrorMessage(saxEx));
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
LOG.error(ex);
|
LOG.error(getDefaultErrorMessage("general error validating XML!"));
|
||||||
|
LOG.debug("Exception in validateXML: " + ex);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -153,8 +156,7 @@ public class Commander {
|
||||||
JSON_FULL_METADATA = "JSON_FULL_METADATA",
|
JSON_FULL_METADATA = "JSON_FULL_METADATA",
|
||||||
XML = "XML";
|
XML = "XML";
|
||||||
|
|
||||||
final ContentType DEFAULT_CONTENT_TYPE = ContentType.JSON;
|
ContentType type = ContentType.JSON;
|
||||||
ContentType type = DEFAULT_CONTENT_TYPE;
|
|
||||||
|
|
||||||
if (contentType == null) {
|
if (contentType == null) {
|
||||||
return type;
|
return type;
|
||||||
|
@ -471,7 +473,8 @@ public class Commander {
|
||||||
//require the XML Document to be valid XML before trying to validate it with the OData validator
|
//require the XML Document to be valid XML before trying to validate it with the OData validator
|
||||||
if (validateXML(xmlString)) {
|
if (validateXML(xmlString)) {
|
||||||
// deserialize metadata from given file
|
// deserialize metadata from given file
|
||||||
XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML).toMetadata(new ByteArrayInputStream(xmlString.getBytes()));
|
XMLMetadata metadata = client.getDeserializer(ContentType.APPLICATION_XML)
|
||||||
|
.toMetadata(new ByteArrayInputStream(xmlString.getBytes(StandardCharsets.UTF_8)));
|
||||||
if (metadata != null) {
|
if (metadata != null) {
|
||||||
return validateMetadata(metadata);
|
return validateMetadata(metadata);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -23,11 +23,11 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.sql.Time;
|
import java.sql.Time;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
import java.time.Year;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
@ -132,17 +132,17 @@ public final class TestUtils {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
|
|
||||||
if (operator.contentEquals(Operators.GREATER_THAN)) {
|
if (operator.contentEquals(Operators.GREATER_THAN)) {
|
||||||
result = lhs > rhs;
|
result = lhs != null && rhs != null && lhs > rhs;
|
||||||
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
|
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
|
||||||
result = lhs >= rhs;
|
result = Objects.equals(lhs, rhs) || (lhs != null && rhs != null && lhs > rhs);
|
||||||
} else if (operator.contentEquals(Operators.EQ)) {
|
} else if (operator.contentEquals(Operators.EQ)) {
|
||||||
result = lhs.equals(rhs);
|
result = Objects.equals(lhs, rhs);
|
||||||
} else if (operator.contentEquals(Operators.NE)) {
|
} else if (operator.contentEquals(Operators.NE)) {
|
||||||
result = !lhs.equals(rhs);
|
result = !Objects.equals(lhs, rhs);
|
||||||
} else if (operator.contentEquals(Operators.LESS_THAN)) {
|
} else if (operator.contentEquals(Operators.LESS_THAN)) {
|
||||||
result = lhs < rhs;
|
result = lhs != null && rhs != null && lhs < rhs;
|
||||||
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
|
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
|
||||||
result = lhs <= rhs;
|
result = Objects.equals(lhs, rhs) || (lhs != null && rhs != null && lhs < rhs);
|
||||||
}
|
}
|
||||||
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
|
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
|
||||||
return result;
|
return result;
|
||||||
|
@ -161,15 +161,15 @@ public final class TestUtils {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
|
|
||||||
if (operator.contentEquals(Operators.CONTAINS)) {
|
if (operator.contentEquals(Operators.CONTAINS)) {
|
||||||
result = lhs.contains(rhs);
|
result = Objects.equals(lhs, rhs) || (lhs != null && rhs != null && lhs.contains(rhs));
|
||||||
} else if (operator.contentEquals(Operators.STARTS_WITH)) {
|
} else if (operator.contentEquals(Operators.STARTS_WITH)) {
|
||||||
result = lhs.startsWith(rhs);
|
result = lhs != null && rhs != null && lhs.startsWith(rhs);
|
||||||
} else if (operator.contentEquals(Operators.ENDS_WITH)) {
|
} else if (operator.contentEquals(Operators.ENDS_WITH)) {
|
||||||
result = lhs.endsWith(rhs);
|
result = lhs != null && rhs != null && lhs.endsWith(rhs);
|
||||||
} else if (operator.contentEquals(Operators.TO_LOWER)) {
|
} else if (operator.contentEquals(Operators.TO_LOWER)) {
|
||||||
result = lhs.toLowerCase().equals(rhs);
|
result = lhs != null && lhs.toLowerCase().contentEquals(rhs);
|
||||||
} else if (operator.contentEquals(Operators.TO_UPPER)) {
|
} else if (operator.contentEquals(Operators.TO_UPPER)) {
|
||||||
result = lhs.toUpperCase().equals(rhs);
|
result = lhs != null && lhs.toUpperCase().contentEquals(rhs);
|
||||||
}
|
}
|
||||||
LOG.info("Compare: \"" + lhs + "\" " + operator + " \"" + rhs + "\" ==> " + result);
|
LOG.info("Compare: \"" + lhs + "\" " + operator + " \"" + rhs + "\" ==> " + result);
|
||||||
return result;
|
return result;
|
||||||
|
@ -188,46 +188,17 @@ public final class TestUtils {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
|
|
||||||
if (operator.contentEquals(Operators.GREATER_THAN)) {
|
if (operator.contentEquals(Operators.GREATER_THAN)) {
|
||||||
result = lhs.after(rhs);
|
result = lhs != null && rhs != null && lhs.after(rhs);
|
||||||
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
|
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
|
||||||
result = lhs.after(rhs) || lhs.equals(rhs);
|
result = Objects.equals(lhs, rhs) || (lhs != null && rhs != null && lhs.after(rhs));
|
||||||
} else if (operator.contentEquals(Operators.EQ)) {
|
} else if (operator.contentEquals(Operators.EQ)) {
|
||||||
result = lhs.equals(rhs);
|
result = Objects.equals(lhs, rhs);
|
||||||
} else if (operator.contentEquals(Operators.NE)) {
|
} else if (operator.contentEquals(Operators.NE)) {
|
||||||
result = !lhs.equals(rhs);
|
result = !Objects.equals(lhs, rhs);
|
||||||
} else if (operator.contentEquals(Operators.LESS_THAN)) {
|
} else if (operator.contentEquals(Operators.LESS_THAN)) {
|
||||||
result = lhs.before(rhs);
|
result = lhs != null && rhs != null && lhs.before(rhs);
|
||||||
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
|
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
|
||||||
result = lhs.before(rhs) || lhs.equals(rhs);
|
result = Objects.equals(lhs, rhs) || (lhs != null && rhs != null && lhs.before(rhs));
|
||||||
}
|
|
||||||
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Year Comparator
|
|
||||||
*
|
|
||||||
* @param lhs Year to compare
|
|
||||||
* @param op an OData binary operator to use for comparisons
|
|
||||||
* @param rhs Timestamp to compare
|
|
||||||
* @return true if lhs op rhs, false otherwise
|
|
||||||
*/
|
|
||||||
public static boolean compare(Year lhs, String op, Year rhs) {
|
|
||||||
String operator = op.toLowerCase();
|
|
||||||
boolean result = false;
|
|
||||||
|
|
||||||
if (operator.contentEquals(Operators.GREATER_THAN)) {
|
|
||||||
result = lhs.isAfter(rhs);
|
|
||||||
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
|
|
||||||
result = lhs.isAfter(rhs) || lhs.equals(rhs);
|
|
||||||
} else if (operator.contentEquals(Operators.EQ)) {
|
|
||||||
result = lhs.equals(rhs);
|
|
||||||
} else if (operator.contentEquals(Operators.NE)) {
|
|
||||||
result = !lhs.equals(rhs);
|
|
||||||
} else if (operator.contentEquals(Operators.LESS_THAN)) {
|
|
||||||
result = lhs.isBefore(rhs);
|
|
||||||
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
|
|
||||||
result = lhs.isBefore(rhs) || lhs.equals(rhs);
|
|
||||||
}
|
}
|
||||||
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
|
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
|
||||||
return result;
|
return result;
|
||||||
|
@ -246,17 +217,17 @@ public final class TestUtils {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
|
|
||||||
if (operator.contentEquals(Operators.GREATER_THAN)) {
|
if (operator.contentEquals(Operators.GREATER_THAN)) {
|
||||||
result = lhs.toLocalTime().isAfter(rhs.toLocalTime());
|
result = lhs != null && rhs != null && lhs.toLocalTime().isAfter(rhs.toLocalTime());
|
||||||
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
|
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
|
||||||
result = lhs.toLocalTime().isAfter(rhs.toLocalTime()) || lhs.toLocalTime().equals(rhs.toLocalTime());
|
result = Objects.equals(lhs, rhs) || lhs.toLocalTime().isAfter(rhs.toLocalTime()) || lhs.toLocalTime().equals(rhs.toLocalTime());
|
||||||
} else if (operator.contentEquals(Operators.EQ)) {
|
} else if (operator.contentEquals(Operators.EQ)) {
|
||||||
result = lhs.toLocalTime().equals(rhs.toLocalTime());
|
result = Objects.equals(lhs, rhs) || lhs.toLocalTime().equals(rhs.toLocalTime());
|
||||||
} else if (operator.contentEquals(Operators.NE)) {
|
} else if (operator.contentEquals(Operators.NE)) {
|
||||||
result = !lhs.toLocalTime().equals(rhs.toLocalTime());
|
result = !Objects.equals(lhs, rhs) || !lhs.toLocalTime().equals(rhs.toLocalTime());
|
||||||
} else if (operator.contentEquals(Operators.LESS_THAN)) {
|
} else if (operator.contentEquals(Operators.LESS_THAN)) {
|
||||||
result = lhs.toLocalTime().isBefore(rhs.toLocalTime());
|
result = lhs != null && rhs != null && lhs.toLocalTime().isBefore(rhs.toLocalTime());
|
||||||
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
|
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
|
||||||
result = lhs.toLocalTime().isBefore(rhs.toLocalTime()) || lhs.toLocalTime().equals(rhs.toLocalTime());
|
result = Objects.equals(lhs, rhs) || lhs.toLocalTime().isBefore(rhs.toLocalTime()) || lhs.toLocalTime().equals(rhs.toLocalTime());
|
||||||
}
|
}
|
||||||
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
|
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
|
||||||
return result;
|
return result;
|
||||||
|
@ -275,17 +246,17 @@ public final class TestUtils {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
|
|
||||||
if (operator.contentEquals(Operators.GREATER_THAN)) {
|
if (operator.contentEquals(Operators.GREATER_THAN)) {
|
||||||
result = lhs.after(rhs);
|
result = lhs != null && lhs.after(rhs);
|
||||||
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
|
} else if (operator.contentEquals(Operators.GREATER_THAN_OR_EQUAL)) {
|
||||||
result = lhs.after(rhs) || lhs.equals(rhs);
|
result = Objects.equals(lhs, rhs) || (lhs != null && rhs != null && lhs.after(rhs));
|
||||||
} else if (operator.contentEquals(Operators.EQ)) {
|
} else if (operator.contentEquals(Operators.EQ)) {
|
||||||
result = lhs.equals(rhs);
|
result = Objects.equals(lhs, rhs);
|
||||||
} else if (operator.contentEquals(Operators.NE)) {
|
} else if (operator.contentEquals(Operators.NE)) {
|
||||||
result = !lhs.equals(rhs);
|
result = !Objects.equals(lhs, rhs);
|
||||||
} else if (operator.contentEquals(Operators.LESS_THAN)) {
|
} else if (operator.contentEquals(Operators.LESS_THAN)) {
|
||||||
result = lhs.before(rhs);
|
result = lhs != null && lhs.before(rhs);
|
||||||
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
|
} else if (operator.contentEquals(Operators.LESS_THAN_OR_EQUAL)) {
|
||||||
result = lhs.before(rhs) || lhs.equals(rhs);
|
result = Objects.equals(lhs, rhs) || (lhs != null && rhs != null && lhs.before(rhs));
|
||||||
}
|
}
|
||||||
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
|
LOG.info("Compare: " + lhs + " " + operator + " " + rhs + " ==> " + result);
|
||||||
return result;
|
return result;
|
||||||
|
@ -426,7 +397,7 @@ public final class TestUtils {
|
||||||
* @param datePart the timestamp part, "Year", "Month", "Day", etc. to try and parse
|
* @param datePart the timestamp part, "Year", "Month", "Day", etc. to try and parse
|
||||||
* @param value the value to try and parse
|
* @param value the value to try and parse
|
||||||
* @return the Integer portion of the date if successful, otherwise throws an Exception
|
* @return the Integer portion of the date if successful, otherwise throws an Exception
|
||||||
* @exception throws an exception if value cannot be parsed into a date.
|
* @exception EdmPrimitiveTypeException an exception if value cannot be parsed into a date.
|
||||||
*/
|
*/
|
||||||
public static Integer getDatePart(String datePart, Object value) throws EdmPrimitiveTypeException {
|
public static Integer getDatePart(String datePart, Object value) throws EdmPrimitiveTypeException {
|
||||||
LocalDate date = LocalDate.parse(parseDateFromEdmDateString(value.toString()).toString());
|
LocalDate date = LocalDate.parse(parseDateFromEdmDateString(value.toString()).toString());
|
||||||
|
@ -449,25 +420,28 @@ public final class TestUtils {
|
||||||
* @return the Integer portion of the date if successful, otherwise throws an Exception
|
* @return the Integer portion of the date if successful, otherwise throws an Exception
|
||||||
*/
|
*/
|
||||||
public static Integer getTimestampPart(String timestampPart, Object value) throws EdmPrimitiveTypeException {
|
public static Integer getTimestampPart(String timestampPart, Object value) throws EdmPrimitiveTypeException {
|
||||||
|
if (timestampPart == null || value == null) return null;
|
||||||
|
|
||||||
//Turns nanoseconds into two most significant 2 digits for fractional comparisons
|
//Turns nanoseconds into two most significant 2 digits for fractional comparisons
|
||||||
Integer ADJUSTMENT_FACTOR = 10000000;
|
int ADJUSTMENT_FACTOR = 10000000;
|
||||||
OffsetDateTime offsetDateTime = OffsetDateTime.parse(value.toString());
|
OffsetDateTime offsetDateTime = OffsetDateTime.parse(value.toString());
|
||||||
|
|
||||||
if (timestampPart.equals(DateParts.YEAR)) {
|
switch (timestampPart) {
|
||||||
|
case DateParts.YEAR:
|
||||||
return offsetDateTime.getYear();
|
return offsetDateTime.getYear();
|
||||||
} else if (timestampPart.equals(DateParts.MONTH)) {
|
case DateParts.MONTH:
|
||||||
return offsetDateTime.getMonthValue();
|
return offsetDateTime.getMonthValue();
|
||||||
} else if (timestampPart.equals(DateParts.DAY)) {
|
case DateParts.DAY:
|
||||||
return offsetDateTime.getDayOfMonth();
|
return offsetDateTime.getDayOfMonth();
|
||||||
} else if (timestampPart.equals(DateParts.HOUR)) {
|
case DateParts.HOUR:
|
||||||
return offsetDateTime.getHour();
|
return offsetDateTime.getHour();
|
||||||
} else if (timestampPart.equals(DateParts.MINUTE)) {
|
case DateParts.MINUTE:
|
||||||
return offsetDateTime.getMinute();
|
return offsetDateTime.getMinute();
|
||||||
} else if (timestampPart.equals(DateParts.SECOND)) {
|
case DateParts.SECOND:
|
||||||
return offsetDateTime.getSecond();
|
return offsetDateTime.getSecond();
|
||||||
} else if (timestampPart.equals(DateParts.FRACTIONAL)) {
|
case DateParts.FRACTIONAL:
|
||||||
return offsetDateTime.getNano() / ADJUSTMENT_FACTOR;
|
return offsetDateTime.getNano() / ADJUSTMENT_FACTOR;
|
||||||
} else {
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -479,11 +453,11 @@ public final class TestUtils {
|
||||||
* @return the string value contained in the stream.
|
* @return the string value contained in the stream.
|
||||||
*/
|
*/
|
||||||
public static String convertInputStreamToString(InputStream inputStream) {
|
public static String convertInputStreamToString(InputStream inputStream) {
|
||||||
InputStreamReader isReader = new InputStreamReader(inputStream);
|
try {
|
||||||
|
InputStreamReader isReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8.name());
|
||||||
BufferedReader reader = new BufferedReader(isReader);
|
BufferedReader reader = new BufferedReader(isReader);
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
String str;
|
String str;
|
||||||
try {
|
|
||||||
while ((str = reader.readLine()) != null) {
|
while ((str = reader.readLine()) != null) {
|
||||||
sb.append(str);
|
sb.append(str);
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,8 @@ public class Parameters {
|
||||||
public static final String
|
public static final String
|
||||||
RESOURCE_NAME = "EndpointResource",
|
RESOURCE_NAME = "EndpointResource",
|
||||||
DATASYSTEM_ENDPOINT = "EndpointDataSystem",
|
DATASYSTEM_ENDPOINT = "EndpointDataSystem",
|
||||||
EXPAND_FIELD = "ExpandField";
|
EXPAND_FIELD = "ExpandField",
|
||||||
|
INTEGER_FIELD = "IntegerField";
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -17,7 +17,6 @@ Feature: Commander XML and Metadata Validation
|
||||||
When XML validation is performed on the resource data
|
When XML validation is performed on the resource data
|
||||||
Then XML validation fails
|
Then XML validation fails
|
||||||
|
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# XML Metadata Validation Tests
|
# XML Metadata Validation Tests
|
||||||
#######################################
|
#######################################
|
||||||
|
@ -31,7 +30,6 @@ Feature: Commander XML and Metadata Validation
|
||||||
When XML Metadata validation is performed on the resource data
|
When XML Metadata validation is performed on the resource data
|
||||||
Then XML Metadata validation fails
|
Then XML Metadata validation fails
|
||||||
|
|
||||||
|
|
||||||
#######################################
|
#######################################
|
||||||
# Edm Validation Tests
|
# Edm Validation Tests
|
||||||
#######################################
|
#######################################
|
||||||
|
|
|
@ -2,24 +2,33 @@ package org.reso.commander.test.stepdefs;
|
||||||
|
|
||||||
import io.cucumber.java8.En;
|
import io.cucumber.java8.En;
|
||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.reso.commander.certfication.containers.WebAPITestContainer;
|
import org.reso.commander.certfication.containers.WebAPITestContainer;
|
||||||
import org.reso.commander.common.TestUtils;
|
import org.reso.commander.common.TestUtils;
|
||||||
import org.reso.models.Settings;
|
import org.reso.models.Settings;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import static io.restassured.path.json.JsonPath.from;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.reso.commander.common.ErrorMsg.getDefaultErrorMessage;
|
import static org.reso.commander.common.ErrorMsg.getDefaultErrorMessage;
|
||||||
|
import static org.reso.commander.common.TestUtils.JSON_VALUE_PATH;
|
||||||
|
import static org.reso.commander.common.TestUtils.parseTimestampFromEdmDateTimeOffsetString;
|
||||||
|
|
||||||
public class TestWebAPITestContainer implements En {
|
public class TestWebAPITestContainer implements En {
|
||||||
|
private static final Logger LOG = LogManager.getLogger(TestWebAPITestContainer.class);
|
||||||
AtomicReference<WebAPITestContainer> testContainer = new AtomicReference<>();
|
AtomicReference<WebAPITestContainer> testContainer = new AtomicReference<>();
|
||||||
|
|
||||||
public TestWebAPITestContainer() {
|
public TestWebAPITestContainer() {
|
||||||
|
|
||||||
//background
|
/*
|
||||||
|
* Background
|
||||||
|
*/
|
||||||
Given("^a Web API test container was created using the RESOScript \"([^\"]*)\"$", (String fileName) -> {
|
Given("^a Web API test container was created using the RESOScript \"([^\"]*)\"$", (String fileName) -> {
|
||||||
try {
|
try {
|
||||||
//get settings from mock RESOScript file
|
//get settings from mock RESOScript file
|
||||||
|
@ -50,8 +59,9 @@ public class TestWebAPITestContainer implements En {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* auth settings validation
|
* Auth settings validation
|
||||||
*/
|
*/
|
||||||
When("^an auth token is provided in \"([^\"]*)\"$", (String clientSettingsAuthToken) -> {
|
When("^an auth token is provided in \"([^\"]*)\"$", (String clientSettingsAuthToken) -> {
|
||||||
String token = Settings.resolveParametersString(clientSettingsAuthToken, getTestContainer().getSettings());
|
String token = Settings.resolveParametersString(clientSettingsAuthToken, getTestContainer().getSettings());
|
||||||
|
@ -82,30 +92,194 @@ public class TestWebAPITestContainer implements En {
|
||||||
assertNotNull(getDefaultErrorMessage("settings were not found in the Web API test container!"),
|
assertNotNull(getDefaultErrorMessage("settings were not found in the Web API test container!"),
|
||||||
getTestContainer().getSettings());
|
getTestContainer().getSettings());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Metadata validation
|
||||||
|
*/
|
||||||
Then("^metadata are valid$", () -> {
|
Then("^metadata are valid$", () -> {
|
||||||
getTestContainer().validateMetadata();
|
getTestContainer().validateMetadata();
|
||||||
assertTrue(getDefaultErrorMessage("getIsMetadataValid() returned false when true was expected!"),
|
assertTrue(getDefaultErrorMessage("getIsMetadataValid() returned false when true was expected!"),
|
||||||
getTestContainer().hasValidMetadata());
|
getTestContainer().hasValidMetadata());
|
||||||
});
|
});
|
||||||
|
|
||||||
Then("^metadata are invalid$", () -> {
|
Then("^metadata are invalid$", () -> {
|
||||||
getTestContainer().validateMetadata();
|
getTestContainer().validateMetadata();
|
||||||
assertFalse(getDefaultErrorMessage("getIsMetadataValid() returned true when false was expected!"),
|
assertFalse(getDefaultErrorMessage("getIsMetadataValid() returned true when false was expected!"),
|
||||||
getTestContainer().hasValidMetadata());
|
getTestContainer().hasValidMetadata());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DataSystem validation
|
||||||
|
*/
|
||||||
When("^sample JSON data from \"([^\"]*)\" are loaded into the test container$", (String resourceName) -> {
|
When("^sample JSON data from \"([^\"]*)\" are loaded into the test container$", (String resourceName) -> {
|
||||||
getTestContainer().setResponseCode(HttpStatus.SC_OK);
|
getTestContainer().setResponseCode(HttpStatus.SC_OK);
|
||||||
getTestContainer().setResponseData(loadResourceAsString(resourceName));
|
getTestContainer().setResponseData(loadResourceAsString(resourceName));
|
||||||
});
|
});
|
||||||
|
|
||||||
Then("^schema validation passes for the sample DataSystem data$", () -> {
|
Then("^schema validation passes for the sample DataSystem data$", () -> {
|
||||||
assertTrue(getDefaultErrorMessage("expected DataSystem to pass validation, but it failed!"),
|
assertTrue(getDefaultErrorMessage("expected DataSystem to pass validation, but it failed!"),
|
||||||
getTestContainer().validateDataSystem().getIsValidDataSystem());
|
getTestContainer().validateDataSystem().getIsValidDataSystem());
|
||||||
});
|
});
|
||||||
|
|
||||||
Then("^schema validation fails for the sample DataSystem data$", () -> {
|
Then("^schema validation fails for the sample DataSystem data$", () -> {
|
||||||
assertFalse(getDefaultErrorMessage("expected DataSystem to fail validation, but it passed!"),
|
assertFalse(getDefaultErrorMessage("expected DataSystem to fail validation, but it passed!"),
|
||||||
getTestContainer().validateDataSystem().getIsValidDataSystem());
|
getTestContainer().validateDataSystem().getIsValidDataSystem());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Integer Response Testing
|
||||||
|
*/
|
||||||
|
Then("^Integer comparisons of \"([^\"]*)\" \"([^\"]*)\" (\\d+) return \"([^\"]*)\"$", (String fieldName, String op, Integer assertedValue, String expectedValue) -> {
|
||||||
|
final boolean expected = Boolean.parseBoolean(expectedValue),
|
||||||
|
result = testIntegerComparisons(fieldName, op, assertedValue);
|
||||||
|
if (expected) {
|
||||||
|
assertTrue(result);
|
||||||
|
} else {
|
||||||
|
assertFalse(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Then("^Integer comparisons of \"([^\"]*)\" \"([^\"]*)\" null return \"([^\"]*)\"$", (String fieldName, String op, String expectedValue) -> {
|
||||||
|
final boolean expected = Boolean.parseBoolean(expectedValue),
|
||||||
|
result = testIntegerComparisons(fieldName, op, null);
|
||||||
|
if (expected) {
|
||||||
|
assertTrue(result);
|
||||||
|
} else {
|
||||||
|
assertFalse(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* String Response Testing
|
||||||
|
*/
|
||||||
|
Then("^String data in \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" returns \"([^\"]*)\"$", (String fieldName, String op, String assertedValue, String expectedValue) -> {
|
||||||
|
final boolean expected = Boolean.parseBoolean(expectedValue),
|
||||||
|
result = testStringComparisons(fieldName, op, assertedValue);
|
||||||
|
if (expected) {
|
||||||
|
assertTrue(result);
|
||||||
|
} else {
|
||||||
|
assertFalse(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Then("^String data in \"([^\"]*)\" \"([^\"]*)\" null returns \"([^\"]*)\"$", (String fieldName, String op, String expectedValue) -> {
|
||||||
|
final boolean expected = Boolean.parseBoolean(expectedValue),
|
||||||
|
result = testStringComparisons(fieldName, op, null);
|
||||||
|
if (expected) {
|
||||||
|
assertTrue(result);
|
||||||
|
} else {
|
||||||
|
assertFalse(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Then("^String data in \"([^\"]*)\" \"([^\"]*)\" equals \"([^\"]*)\"$", (String fieldName, String op, String assertedValue) -> {
|
||||||
|
assertTrue(testStringComparisons(fieldName, op, assertedValue));
|
||||||
|
});
|
||||||
|
|
||||||
|
Then("^String data in \"([^\"]*)\" \"([^\"]*)\" does not equal \"([^\"]*)\"$", (String fieldName, String op, String assertedValue) -> {
|
||||||
|
assertFalse(testStringComparisons(fieldName, op, assertedValue));
|
||||||
|
});
|
||||||
|
|
||||||
|
Then("^String data in \"([^\"]*)\" \"([^\"]*)\" is null$", (String fieldName, String op) -> {
|
||||||
|
assertFalse(testStringComparisons(fieldName, op, null));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Timestamp Response Testing
|
||||||
|
*/
|
||||||
|
Then("^Timestamp comparisons of \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" return \"([^\"]*)\"$", (String fieldName, String op, String assertedValue, String expectedValue) -> {
|
||||||
|
final boolean expected = Boolean.parseBoolean(expectedValue),
|
||||||
|
result = testTimestampComparisons(fieldName, op, assertedValue);
|
||||||
|
if (expected) {
|
||||||
|
assertTrue(result);
|
||||||
|
} else {
|
||||||
|
assertFalse(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Then("^Timestamp comparisons of \"([^\"]*)\" \"([^\"]*)\" null return \"([^\"]*)\"$", (String fieldName, String op, String expectedValue) -> {
|
||||||
|
final boolean expected = Boolean.parseBoolean(expectedValue),
|
||||||
|
result = testTimestampComparisons(fieldName, op, null);
|
||||||
|
if (expected) {
|
||||||
|
assertTrue(result);
|
||||||
|
} else {
|
||||||
|
assertFalse(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Date Part Response Testing
|
||||||
|
*/
|
||||||
|
Then("^\"([^\"]*)\" comparisons of \"([^\"]*)\" \"([^\"]*)\" (\\d+) return \"([^\"]*)\"$", (String datePart, String fieldName, String op, Integer assertedValue, String expectedValue) -> {
|
||||||
|
final boolean expected = Boolean.parseBoolean(expectedValue),
|
||||||
|
result = testDatePartComparisons(datePart, fieldName, op, assertedValue);
|
||||||
|
if (expected) {
|
||||||
|
assertTrue(result);
|
||||||
|
} else {
|
||||||
|
assertFalse(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Then("^\"([^\"]*)\" comparisons of \"([^\"]*)\" \"([^\"]*)\" null return \"([^\"]*)\"$", (String datePart, String fieldName, String op, String expectedValue) -> {
|
||||||
|
final boolean expected = Boolean.parseBoolean(expectedValue),
|
||||||
|
result = testDatePartComparisons(datePart, fieldName, op, null);
|
||||||
|
if (expected) {
|
||||||
|
assertTrue(result);
|
||||||
|
} else {
|
||||||
|
assertFalse(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean testStringComparisons(String fieldName, String op, String assertedValue) {
|
||||||
|
AtomicBoolean result = new AtomicBoolean(false);
|
||||||
|
//iterate over the items and count the number of fields with data to determine whether there are data present
|
||||||
|
from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
|
||||||
|
result.compareAndSet(result.get(), TestUtils.compare((String)item.get(fieldName), op, assertedValue));
|
||||||
|
});
|
||||||
|
return result.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean testIntegerComparisons(String fieldName, String op, Integer assertedValue) {
|
||||||
|
AtomicBoolean result = new AtomicBoolean(false);
|
||||||
|
//iterate over the items and count the number of fields with data to determine whether there are data present
|
||||||
|
from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
|
||||||
|
result.compareAndSet(result.get(), TestUtils.compare((Integer) item.get(fieldName), op, assertedValue));
|
||||||
|
});
|
||||||
|
return result.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean testTimestampComparisons(String fieldName, String op, String offsetDateTime) {
|
||||||
|
AtomicBoolean result = new AtomicBoolean(false);
|
||||||
|
//iterate over the items and count the number of fields with data to determine whether there are data present
|
||||||
|
from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
|
||||||
|
try {
|
||||||
|
result.compareAndSet(result.get(), TestUtils.compare(
|
||||||
|
parseTimestampFromEdmDateTimeOffsetString((String)item.get(fieldName)), op,
|
||||||
|
parseTimestampFromEdmDateTimeOffsetString(offsetDateTime)));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
fail(getDefaultErrorMessage(ex));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean testDatePartComparisons(String datePart, String fieldName, String op, Integer assertedValue) {
|
||||||
|
AtomicBoolean result = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
from(getTestContainer().getResponseData()).getList(JSON_VALUE_PATH, HashMap.class).forEach(item -> {
|
||||||
|
try {
|
||||||
|
result.compareAndSet(result.get(), TestUtils.compare(TestUtils.getTimestampPart(datePart, item.get(fieldName)), op, assertedValue));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
fail(getDefaultErrorMessage(ex));
|
||||||
|
}});
|
||||||
|
return result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -35,7 +35,7 @@ public class TestXMLAndMetadataValidation implements En {
|
||||||
* Background
|
* Background
|
||||||
*/
|
*/
|
||||||
Given("^an OData test client has been created$", () -> {
|
Given("^an OData test client has been created$", () -> {
|
||||||
commander.set(Commander.Builder.class.newInstance().build());
|
commander.set(new Commander.Builder().build());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ public class TestXMLAndMetadataValidation implements En {
|
||||||
assertTrue(getDefaultErrorMessage("expected XML validation to succeed but it failed!"), isXMLValid.get());
|
assertTrue(getDefaultErrorMessage("expected XML validation to succeed but it failed!"), isXMLValid.get());
|
||||||
});
|
});
|
||||||
Then("^XML validation fails$", () -> {
|
Then("^XML validation fails$", () -> {
|
||||||
assertFalse(getDefaultErrorMessage("expected XML validation to succeed but it failed!"), isXMLValid.get());
|
assertFalse(getDefaultErrorMessage("expected XML validation to fail but it succeeded!"), isXMLValid.get());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"@odata.context": "https://test.reso.org",
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"ListingKeyNumeric": 1,
|
||||||
|
"BedroomsTotal": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"@odata.context": "https://test.reso.org",
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"ListingKeyNumeric": 1,
|
||||||
|
"BedroomsTotal": 5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"@odata.context": "https://test.reso.org",
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"ListingKeyNumeric": 1,
|
||||||
|
"StreetName": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"@odata.context": "https://test.reso.org",
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"ListingKeyNumeric": 1,
|
||||||
|
"StreetName": "Main"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"@odata.context": "https://test.reso.org",
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"ListingKeyNumeric": 1,
|
||||||
|
"ModificationTimestamp": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"@odata.context": "https://test.reso.org",
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"ListingKeyNumeric": 1,
|
||||||
|
"ModificationTimestamp": "2020-04-02T02:02:02.02Z"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue