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 Util { 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(); private static string API_BASE_URL = "http://localhost:7575/api/v8.0/"; //private static string API_BASE_URL = "https://test.helloayanova.com/api/v8.0/"; public static string TEST_DATA_FOLDER = @"..\..\..\testdata\"; public static ConcurrentDictionary authDict = new ConcurrentDictionary();//10,32 private static AutoId Auto { get; } = new AutoId(0); public static string Uniquify(string s) { // return s + " " + Auto.GetNext().ToString(); return s + " " + (Auto.GetNext() + ((DateTimeOffset)DateTime.Now).ToUnixTimeMilliseconds()).ToString(); } public async static Task GetTokenAsync(string login, string password = null) { // Console.WriteLine($"GetTokenAsync:{login}"); //System.Diagnostics.Trace.WriteLine($"GetTokenAsync:{login}"); 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(); } 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; } public async static Task 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 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 static async Task 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 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 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 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 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 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) }; } /// /// /// /// /// private 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) { var ErrorMessage = string.Empty; var ERR = a.ObjectResponse["error"]; if (ERR != null) { 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 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); } /// /// validate a not found response /// /// 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().Should().Be(2010); } /// /// validate a concurrency error /// /// 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().Should().Be(2005); } /// /// validate that the call violates referential integrity /// /// 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().Should().Be(2200); } /// /// validate a bad ModelState response /// /// 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().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().Should().Be(CheckFirstTargetExists); } } // public enum ValidationErrorType // { // RequiredPropertyEmpty = 1, // LengthExceeded = 2, // NotUnique = 3, // StartDateMustComeBeforeEndDate = 4, // InvalidValue = 5 // } /// /// assert contains validation target and error code /// /// /// /// public static void ShouldContainValidationError(ApiResponse a, string target, string error, string message = null) { a.ObjectResponse["error"]["details"].Should().NotBeNull("There should be Details on the api call"); if (message != null) { a.ObjectResponse["error"]["details"].Should().Contain( m => m["target"].Value() == target && m["error"].Value() == error && m["message"].Value() == message); } else { a.ObjectResponse["error"]["details"].Should().Contain(m => m["target"].Value() == target && m["error"].Value() == error); } } /// /// validate server exception response /// /// 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().Should().Be(2002); } /// /// Validate an expected api error code and http code response /// /// /// /// 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().Should().Be(apiErrorCode); } }//eoc }//eons