Files
raven-test-integration/util.cs
2020-05-10 21:17:03 +00:00

655 lines
27 KiB
C#

using System;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json.Linq;
using FluentAssertions;
using System.Collections.Concurrent;
namespace raven_integration
{
public static class TimeZoneAdjustmentExtension
{
public static DateTime ToOffsetAdjustedUniversalTime(this DateTime dtIn)
{
//Date filtering tests MUST use a relative time zone adjusted to users's forced user options time zone
//or the tests that cross dst / pst boundaries will fail
//See servers spec doc core-locale-currency-numbers-time-and-dates.txt for details
//#######################################################################################################
double TIME_ZONE_ADJUSTMENT = -8;// <---=== SET THIS TO SAME AS GENERATED DATA OFFSET AT SERVER
//#######################################################################################################
return DateTime.SpecifyKind(dtIn.AddHours(((TIME_ZONE_ADJUSTMENT) * -1)), DateTimeKind.Utc);
}
}
public static class Util
{
//#######################################################################################################
public static string API_BASE_URL = "http://localhost:7575/api/v8/";
// public static string API_BASE_URL = "https://test.helloayanova.com/api/v8.0/";
public static string TEST_DATA_FOLDER = @"..\..\..\testdata\";
//#######################################################################################################
public const string OpEquality = "=";
public const string OpGreaterThan = ">";
public const string OpGreaterThanOrEqualTo = ">=";
public const string OpLessThan = "<";
public const string OpLessThanOrEqualTo = "<=";
public const string OpNotEqual = "!=";
public const string OpNotLike = "!%";
public const string OpStartsWith = "%-";
public const string OpEndsWith = "-%";
public const string OpContains = "-%-";
public const string OpNotContains = "!-%-";
private static HttpClient client { get; } = new HttpClient();
// public static ConcurrentDictionary<string, string> authDict = new ConcurrentDictionary<string, string>();//10,32
private static AutoId Auto { get; } = new AutoId(0);
//DateTime adjustment methods for relative date filter testing
// public static DateTime RelativeToday()
// {
// Double TimeZoneAdjustment = ((double)TIME_ZONE_ADJUSTMENT) * -1;
// return DateTime.Today.AddHours(TimeZoneAdjustment);
// }
// public static DateTime RelativeNow()
// {
// Double TimeZoneAdjustment = ((double)TIME_ZONE_ADJUSTMENT) * -1;
// return DateTime.Now.AddHours(TimeZoneAdjustment);
// }
// public static DateTime ToOffsetAdjustedUniversalTime(DateTime dtIn)
// {
// Double TimeZoneAdjustment = ((double)TIME_ZONE_ADJUSTMENT) * -1;
// return dtIn.AddHours(TimeZoneAdjustment).ToUniversalTime();
// }
public static string Uniquify(string s)
{
// return s + " " + Auto.GetNext().ToString();
return s + " " + (Auto.GetNext() + ((DateTimeOffset)DateTime.Now).ToUnixTimeMilliseconds()).ToString();
}
public async static Task<string> GetTokenAsync(string login, string password = null)
{
return await CredRepo.GetTokenAsync(login, password);
// if (password == null)
// password = login;
// if (!authDict.ContainsKey(login))
// {
// dynamic creds = new JObject();
// creds.login = login;
// creds.password = password;
// ApiResponse a = await Util.PostAsync("Auth", null, creds.ToString());
// //Put this in when having concurrency issue during auth and old style dl token creation during login
// ValidateDataReturnResponseOk(a);
// authDict[login] = a.ObjectResponse["data"]["token"].Value<string>();
// }
// return authDict[login];
}
static bool bInitialized = false;
private static void init()
{
if (bInitialized) return;
if (!System.IO.Directory.Exists(TEST_DATA_FOLDER))
throw new ArgumentOutOfRangeException($"Test data folder {TEST_DATA_FOLDER} not found, current folder is {System.AppDomain.CurrentDomain.BaseDirectory}");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
bInitialized = true;
}
public static string CleanApiRoute(string route)
{
route = route.TrimStart('/');
return API_BASE_URL + route;
}
/// <summary>
/// Get the path to the server root with route appended
/// this is used to fetch non-api docs etc
/// </summary>
/// <param name="route"></param>
/// <returns></returns>
public static string CleanNonApiRoute(string route)
{
// public static string API_BASE_URL = "http://localhost:7575/api/v8/";
//public static string API_BASE_URL = "https://test.helloayanova.com/api/v8.0/";
if (!route.StartsWith('/'))
{
route = "/" + route;
}
return API_BASE_URL.Split("/api/")[0] + route;
}
public async static Task<ApiResponse> GetAsync(string route, string authToken = null)//, string bodyJsonData = null)
{
init();
var requestMessage = new HttpRequestMessage(HttpMethod.Get, CleanApiRoute(route));
if (!string.IsNullOrWhiteSpace(authToken))
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
// if (!string.IsNullOrWhiteSpace(bodyJsonData))
// requestMessage.Content = new StringContent(bodyJsonData, System.Text.Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.SendAsync(requestMessage);
var responseAsString = await response.Content.ReadAsStringAsync();
return new ApiResponse() { HttpResponse = response, ObjectResponse = Parse(responseAsString) };
}
public async static Task<ApiTextResponse> GetTextResultAsync(string route, string authToken = null, string bodyJsonData = null)
{
init();
var requestMessage = new HttpRequestMessage(HttpMethod.Get, CleanApiRoute(route));
if (!string.IsNullOrWhiteSpace(authToken))
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
if (!string.IsNullOrWhiteSpace(bodyJsonData))
requestMessage.Content = new StringContent(bodyJsonData, System.Text.Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.SendAsync(requestMessage);
var responseAsString = await response.Content.ReadAsStringAsync();
return new ApiTextResponse() { HttpResponse = response, TextResponse = responseAsString };
}
public async static Task<ApiTextResponse> GetNonApiPageAsync(string route)
{
init();
var requestMessage = new HttpRequestMessage(HttpMethod.Get, CleanNonApiRoute(route));
HttpResponseMessage response = await client.SendAsync(requestMessage);
var responseAsString = await response.Content.ReadAsStringAsync();
return new ApiTextResponse() { HttpResponse = response, TextResponse = responseAsString };
}
public static async Task<HttpResponseMessage> DownloadFileAsync(string route, string authToken = null)
{
init();
var requestMessage = new HttpRequestMessage(HttpMethod.Get, CleanApiRoute(route));
if (!string.IsNullOrWhiteSpace(authToken))
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
HttpResponseMessage response = await client.SendAsync(requestMessage);
return response;
// if (response.IsSuccessStatusCode)
// {
// return await response.Content.ReadAsByteArrayAsync();
// }
// return null;
}
public async static Task<ApiResponse> PostAsync(string route, string authToken = null, string postJson = null)
{
init();
var requestMessage = new HttpRequestMessage(HttpMethod.Post, CleanApiRoute(route));
if (!string.IsNullOrWhiteSpace(authToken))
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
if (!string.IsNullOrWhiteSpace(postJson))
requestMessage.Content = new StringContent(postJson, System.Text.Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.SendAsync(requestMessage);
var responseAsString = await response.Content.ReadAsStringAsync();
return new ApiResponse() { HttpResponse = response, ObjectResponse = Parse(responseAsString) };
}
public async static Task<ApiResponse> PostFormDataAsync(string route, MultipartFormDataContent formContent, string authToken = null)
{
init();
var requestMessage = new HttpRequestMessage(HttpMethod.Post, CleanApiRoute(route));
if (!string.IsNullOrWhiteSpace(authToken))
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
requestMessage.Content = formContent;
HttpResponseMessage response = await client.SendAsync(requestMessage);
var responseAsString = await response.Content.ReadAsStringAsync();
return new ApiResponse() { HttpResponse = response, ObjectResponse = Parse(responseAsString) };
}
public async static Task<ApiResponse> PutAsync(string route, string authToken = null, string putJson = null)
{
init();
var requestMessage = new HttpRequestMessage(HttpMethod.Put, CleanApiRoute(route));
if (!string.IsNullOrWhiteSpace(authToken))
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
if (!string.IsNullOrWhiteSpace(putJson))
requestMessage.Content = new StringContent(putJson, System.Text.Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.SendAsync(requestMessage);
var responseAsString = await response.Content.ReadAsStringAsync();
return new ApiResponse() { HttpResponse = response, ObjectResponse = Parse(responseAsString) };
}
public async static Task<ApiResponse> PatchAsync(string route, string authToken = null, string patchJson = null)
{
init();
var method = new HttpMethod("PATCH");
var requestMessage = new HttpRequestMessage(method, CleanApiRoute(route));
if (!string.IsNullOrWhiteSpace(authToken))
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
if (!string.IsNullOrWhiteSpace(patchJson))
requestMessage.Content = new StringContent(patchJson, System.Text.Encoding.UTF8, "application/json-patch+json");
HttpResponseMessage response = await client.SendAsync(requestMessage);
var responseAsString = await response.Content.ReadAsStringAsync();
return new ApiResponse() { HttpResponse = response, ObjectResponse = Parse(responseAsString) };
}
public async static Task<ApiResponse> DeleteAsync(string route, string authToken = null)
{
init();
var requestMessage = new HttpRequestMessage(HttpMethod.Delete, CleanApiRoute(route));
if (!string.IsNullOrWhiteSpace(authToken))
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
HttpResponseMessage response = await client.SendAsync(requestMessage);
var responseAsString = await response.Content.ReadAsStringAsync();
return new ApiResponse() { HttpResponse = response, ObjectResponse = Parse(responseAsString) };
}
/// <summary>
///
/// </summary>
/// <param name="jsonString"></param>
/// <returns></returns>
public static JObject Parse(string jsonString)
{
if (string.IsNullOrWhiteSpace(jsonString))
{
return null;
}
return JObject.Parse(jsonString);
}
//https://www.newtonsoft.com/json/help/html/FromObject.htm
private static string ObjectToJsonString(object o)
{
JObject j = (JObject)JToken.FromObject(o);
return j.ToString();
}
public static void ValidateDataReturnResponseOk(ApiResponse a)
{
a.ObjectResponse.Should().NotBeNull("No response was found at all?! Nothing to validate");
var ErrorMessage = string.Empty;
var ERR = a.ObjectResponse["error"];
if (ERR != null)
{
ErrorMessage = a.ObjectResponse.ToString();
// var ecode = ERR["code"];
// if (ecode != null)
// ErrorMessage += $"CODE: {ecode} ";
// var emsg = ERR["message"];
// if (emsg != null)
// ErrorMessage += $"MESSAGE: {emsg} ";
// var etarget = ERR["target"];
// if (etarget != null)
// ErrorMessage += $"TARGET: {etarget} ";
}
a.ObjectResponse["error"].Should().BeNull("because there should not be an error on an api call, error result was: {0}", ErrorMessage);
a.ObjectResponse["data"].Should().NotBeNull("A result should be returned");
}
public static void ValidateNoErrorInResponse(ApiResponse a)
{
a.ObjectResponse["error"].Should().BeNull("There should not be an error on an api call");
}
public static void ValidateHTTPStatusCode(ApiResponse a, int DesiredStatusCode)
{
((int)a.HttpResponse.StatusCode).Should().Be(DesiredStatusCode);
}
public static void ValidateHTTPStatusCode(ApiTextResponse t, int DesiredStatusCode)
{
((int)t.HttpResponse.StatusCode).Should().Be(DesiredStatusCode);
}
/// <summary>
/// validate a not found response
/// </summary>
/// <param name="a"></param>
public static void ValidateResponseNotFound(ApiResponse a)
{
((int)a.HttpResponse.StatusCode).Should().Be(404);
a.ObjectResponse["error"].Should().NotBeNull("There should be an error on the api call");
a.ObjectResponse["error"]["code"].Value<int>().Should().Be(2010);
}
/// <summary>
/// validate a concurrency error
/// </summary>
/// <param name="a"></param>
public static void ValidateConcurrencyError(ApiResponse a)
{
((int)a.HttpResponse.StatusCode).Should().Be(409);
a.ObjectResponse["error"].Should().NotBeNull("There should be an error on the api call");
a.ObjectResponse["error"]["code"].Value<int>().Should().Be(2005);
}
/// <summary>
/// validate that the call violates referential integrity
/// </summary>
/// <param name="a"></param>
public static void ValidateViolatesReferentialIntegrityError(ApiResponse a)
{
((int)a.HttpResponse.StatusCode).Should().Be(400);
a.ObjectResponse["error"].Should().NotBeNull("There should be an error on the api call");
a.ObjectResponse["error"]["code"].Value<int>().Should().Be(2200);
}
/// <summary>
/// validate a bad ModelState response
/// </summary>
/// <param name="a"></param>
public static void ValidateBadModelStateResponse(ApiResponse a, string CheckFirstTargetExists = null)
{
((int)a.HttpResponse.StatusCode).Should().Be(400);
a.ObjectResponse["error"].Should().NotBeNull("There should be an error on the api call");
a.ObjectResponse["error"]["code"].Value<int>().Should().Be(2200);
a.ObjectResponse["error"]["details"].Should().NotBeNull("There should be error details on the api call");
if (!string.IsNullOrWhiteSpace(CheckFirstTargetExists))
{
a.ObjectResponse["error"]["details"][0]["target"].Value<string>().Should().Be(CheckFirstTargetExists);
}
}
// public enum ValidationErrorType
// {
// RequiredPropertyEmpty = 1,
// LengthExceeded = 2,
// NotUnique = 3,
// StartDateMustComeBeforeEndDate = 4,
// InvalidValue = 5
// }
/// <summary>
/// assert contains validation target and error code
/// </summary>
/// <param name="a"></param>
/// <param name="target"></param>
/// <param name="error"></param>
public static void ShouldContainValidationError(ApiResponse a, string target, string error, string shouldContainInMessage = null)
{
a.ObjectResponse["error"]["details"].Should().NotBeNull("There should be Details on the api call");
if (shouldContainInMessage != null)
{
a.ObjectResponse["error"]["details"].Should().Contain(
m => m["target"].Value<string>() == target &&
m["error"].Value<string>() == error &&
m["message"].Value<string>().Contains(shouldContainInMessage));
}
else
{
a.ObjectResponse["error"]["details"].Should().Contain(m => m["target"].Value<string>() == target && m["error"].Value<string>() == error);
}
}
/// <summary>
/// validate server exception response
/// </summary>
/// <param name="a"></param>
public static void ValidateServerExceptionResponse(ApiResponse a)
{
((int)a.HttpResponse.StatusCode).Should().Be(500);
a.ObjectResponse["error"].Should().NotBeNull("There should be an error on the api call");
a.ObjectResponse["error"]["code"].Value<int>().Should().Be(2002);
}
/// <summary>
/// Validate an expected api error code and http code response
/// </summary>
/// <param name="a"></param>
/// <param name="apiErrorCode"></param>
/// <param name="httpStatusCode"></param>
public static void ValidateErrorCodeResponse(ApiResponse a, int apiErrorCode, int httpStatusCode)
{
((int)a.HttpResponse.StatusCode).Should().Be(httpStatusCode);
a.ObjectResponse["error"].Should().NotBeNull("There should be an error on the api call");
a.ObjectResponse["error"]["code"].Value<int>().Should().Be(apiErrorCode);
}
public static string GenerateCustomFieldsJsonString(
string c1 = null, string c2 = null, string c3 = null, string c4 = null,
string c5 = null, string c6 = null, string c7 = null, string c8 = null, string c9 = null,
string c10 = null, string c11 = null, string c12 = null, string c13 = null,
string c14 = null, string c15 = null, string c16 = null
)
{
//Custom fields
//"[{c1:"blah"}]
dynamic dCustomField = new JObject();
dCustomField.c1 = c1;
dCustomField.c2 = c2;
dCustomField.c3 = c3;
dCustomField.c4 = c4;
dCustomField.c5 = c5;
dCustomField.c6 = c6;
dCustomField.c7 = c7;
dCustomField.c8 = c8;
dCustomField.c9 = c9;
dCustomField.c10 = c10;
dCustomField.c11 = c11;
dCustomField.c12 = c12;
dCustomField.c13 = c13;
dCustomField.c14 = c14;
dCustomField.c15 = c15;
dCustomField.c16 = c16;
return dCustomField.ToString();
}
/// <summary>
/// Generate a custom fields string that satisfies the rules in the sample test data
/// </summary>
/// <returns></returns>
public static string WidgetRequiredCustomFieldsJsonString()
{/*CURRENT TEMPLATE DEFINITION FOR WIDGET CUSTOM FIELDS, FROM SEEDER.CS SERVER PROJECT
var fc = new FormCustom()
{
FormKey = ObjectFields.WIDGET_KEY,
Template = @"[
{
""fld"": ""WidgetNotes"",
""required"": true
},
{
""fld"": ""WidgetCustom1"",
""required"": false,
""type"": 1
},
{
""fld"": ""WidgetCustom2"",
""required"": true,
""type"": 4
},
{
""fld"": ""WidgetCustom3"",
""required"": false,
""type"": 5
},
{
""fld"": ""WidgetCustom4"",
""required"": false,
""type"": 6
},
{
""fld"": ""WidgetCustom5"",
""required"": false,
""type"": 8
},
{
""fld"": ""WidgetCustom6"",
""required"": false,
""type"": 2
},
{
""fld"": ""WidgetCustom7"",
""required"": false,
""type"": 3
}
]"
};
*/
//Custom fields
//"[{c1:"blah"}]
dynamic dCustomField = new JObject();
dCustomField.c1 = "2019-02-08T06:31:48.0019809Z";
dCustomField.c2 = "c2 text";
dCustomField.c3 = "333";
dCustomField.c4 = "true";
dCustomField.c5 = "5.55";
return dCustomField.ToString();
}
/// <summary>
/// Generate a custom fields string that satisfies the rules in this project (formCustom)
/// </summary>
/// <returns></returns>
public static string UserRequiredCustomFieldsJsonString()
{
//Note c1 is only required custom, c2 is defined but is not required so skipping it here
dynamic dCustomField = new JObject();
dCustomField.c1 = "UnitTestUtilSampleText";
return dCustomField.ToString();
}
//// [{fld:"COLUMN UNIQUE KEY ID",sort:"-" or "+",filter:{any:true/false,items:[{FILTER OBJECT SEE BELOW}]} }, {key:"second column unique key"},{...etc...}]
public static object BuildSimpleFilterDataListViewColumn(string fieldKey, string filterOp, object filterValue, string sort = null)
{
dynamic d = new JObject();
d.fld = fieldKey;
if (sort != null)
d.sort = sort;
dynamic filter = new JObject();
dynamic items = new JArray();
dynamic fitem = new JObject();
fitem.op = filterOp;
fitem.value = filterValue;
items.Add(fitem);
filter.items = items;
d.filter = filter;
return d;
}
public static object BuildSimpleSortDataListViewColumn(string fieldKey, string sort)
{
dynamic d = new JObject();
d.fld = fieldKey;
d.sort = sort;
return d;
}
//t(dfilter, dsortarray, 999, 0, false, "UserDataList"));
// public static string BuildDataListRequest(object p = null, object o = null, int limit = 999, int offset = 0, bool bWhatever=false, string dataListKey = "TestWidgetDataList")
// {
// throw new System.NotImplementedException();
// }
public static string BuildDataListRequestEx(dynamic dListView = null, int limit = 999, int offset = 0, string dataListKey = "TestWidgetDataList")
{
/*
{
"offset": 0,
"limit": 3,
"dataListKey": "TestWidgetDataList",
"listView": ""
}
*/
dynamic d = new JObject();
d.offset = offset;
d.limit = limit;
d.dataListKey = dataListKey;
if (dListView != null)
d.ListView = dListView.ToString(Newtonsoft.Json.Formatting.None);
return d.ToString(Newtonsoft.Json.Formatting.None);
}
//---------
}//eoc
}//eons