diff --git a/EventLog/EventLog.cs b/EventLog/EventLog.cs index f43930a..3eae7e5 100644 --- a/EventLog/EventLog.cs +++ b/EventLog/EventLog.cs @@ -4,6 +4,7 @@ using Newtonsoft.Json.Linq; using FluentAssertions; using System.Collections.Generic; using System.Collections.Concurrent; +using System.ComponentModel.DataAnnotations; namespace raven_integration { @@ -19,26 +20,34 @@ namespace raven_integration [Fact] public async Task ObjectLogWorks() { - //CRUD a widget and confirm it logs properly + //CRUD a project and confirm it logs properly //http://localhost:7575/api/v8.0/event-log/userlog?AyType=3&AyId=1 //http://localhost:7575/api/v8.0/event-log/objectlog?AyType=2&AyId=242 //http://localhost:7575/api/v8.0/event-log/userlog?AyType=3&AyId=1&StartDate=2018-08-23&EndDate=2018-08-24 - dynamic w = new JObject(); - w.name = Util.Uniquify("EventLog Test WIDGET"); - w.customFields = Util.WidgetRequiredCustomFieldsJsonString(); - w.notes = "blah"; - w.created = DateTime.Now.ToString(); - w.dollarAmount = 2.22m; - w.active = true; - w.usertype = 1; + //dynamic w = new JObject(); + // w.name = Util.Uniquify("EventLog Test Project"); + // w.notes = "blah"; + // w.created = DateTime.Now.ToString(); + // w.dollarAmount = 2.22m; + // w.active = true; + // w.usertype = 1; + + + var projectName = Util.Uniquify("EventLogTestProject"); + var dateStarted = DateTime.Now.ToString("o"); + var payload = $$""" + {"id":0,"concurrency":0,"name":"{{projectName}}","active":true,"notes":null,"wiki":null,"customFields":"{}","tags":[],"dateStarted":"{{dateStarted}}","dateCompleted":null,"projectOverseerId":null,"accountNumber":null} + """; + //DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ") + //*** CREATED - ApiResponse r2 = await Util.PostAsync("widget", await Util.GetTokenAsync("Inventory"), w.ToString()); + ApiResponse r2 = await Util.PostAsync("project", await Util.GetTokenAsync("Service"), payload); Util.ValidateDataReturnResponseOk(r2); - long w2Id = r2.ObjectResponse["data"]["id"].Value(); + long projectId = r2.ObjectResponse["data"]["id"].Value(); - ApiResponse EventLogResponse = await Util.GetAsync($"event-log/objectlog?AyaType=2&AyId={w2Id}", await Util.GetTokenAsync("BizAdmin")); + ApiResponse EventLogResponse = await Util.GetAsync($"event-log/objectlog?AyaType=25&AyId={projectId}", await Util.GetTokenAsync("BizAdmin")); Util.ValidateHTTPStatusCode(EventLogResponse, 200); ((JArray)EventLogResponse.ObjectResponse["data"]["events"]).Count.Should().Be(1);//only one event so far @@ -52,13 +61,13 @@ namespace raven_integration //*** RETRIEVED //Get one - ApiResponse r3 = await Util.GetAsync("widget/" + w2Id.ToString(), await Util.GetTokenAsync("Inventory")); + ApiResponse r3 = await Util.GetAsync("project/" + projectId.ToString(), await Util.GetTokenAsync("Service")); Util.ValidateDataReturnResponseOk(r3); - r3.ObjectResponse["data"]["name"].Value().Should().Be(w.name.ToString()); - w = r3.ObjectResponse["data"]; + r3.ObjectResponse["data"]["name"].Value().Should().Be(projectName); + //w = r3.ObjectResponse["data"]; - EventLogResponse = await Util.GetAsync($"event-log/objectlog?AyaType=2&AyId={w2Id}", await Util.GetTokenAsync("BizAdmin")); + EventLogResponse = await Util.GetAsync($"event-log/objectlog?AyaType=25&AyId={projectId}", await Util.GetTokenAsync("BizAdmin")); Util.ValidateHTTPStatusCode(EventLogResponse, 200); //confirm event count, type and sort order (descending by date most recent first) ((JArray)EventLogResponse.ObjectResponse["data"]["events"]).Count.Should().Be(2); @@ -69,21 +78,25 @@ namespace raven_integration //*** MODIFIED //PUT - //update w2id - w.name = Util.Uniquify("UPDATED VIA PUT EVENTLOG TEST WIDGET"); - w.UserId = 1; - w.concurrency = r2.ObjectResponse["data"]["concurrency"].Value(); - ApiResponse PUTTestResponse = await Util.PutAsync("widget", await Util.GetTokenAsync("Inventory"), w.ToString()); + var newName = Util.Uniquify("UPDATED VIA PUT EVENTLOG TEST PROJECT"); + payload = $$""" + {"id":{{projectId}},"concurrency":{{r2.ObjectResponse["data"]["concurrency"].Value()}},"name":"{{newName}}","active":true,"notes":null,"wiki":null,"customFields":"{}","tags":[],"dateStarted":"{{dateStarted}}","dateCompleted":null,"projectOverseerId":null,"projectOverseerViz":null,"accountNumber":null} + """; + + // w.name = Util.Uniquify("UPDATED VIA PUT EVENTLOG TEST PROJECT"); + // w.UserId = 1; + // w.concurrency = r2.ObjectResponse["data"]["concurrency"].Value(); + ApiResponse PUTTestResponse = await Util.PutAsync("project", await Util.GetTokenAsync("Service"), payload); Util.ValidateHTTPStatusCode(PUTTestResponse, 200); //*** RETRIEVED //check PUT worked - ApiResponse checkPUTWorked = await Util.GetAsync("widget/" + w2Id.ToString(), await Util.GetTokenAsync("Inventory")); + ApiResponse checkPUTWorked = await Util.GetAsync("project/" + projectId, await Util.GetTokenAsync("Service")); Util.ValidateNoErrorInResponse(checkPUTWorked); - checkPUTWorked.ObjectResponse["data"]["name"].Value().Should().Be(w.name.ToString()); + checkPUTWorked.ObjectResponse["data"]["name"].Value().Should().Be(newName); uint concurrency = PUTTestResponse.ObjectResponse["data"]["concurrency"].Value(); - EventLogResponse = await Util.GetAsync($"event-log/objectlog?AyaType=2&AyId={w2Id}", await Util.GetTokenAsync("BizAdmin")); + EventLogResponse = await Util.GetAsync($"event-log/objectlog?AyaType=25&AyId={projectId}", await Util.GetTokenAsync("BizAdmin")); Util.ValidateHTTPStatusCode(EventLogResponse, 200); ((JArray)EventLogResponse.ObjectResponse["data"]["events"]).Count.Should().Be(4); //put op is the second item in the list, top item is the recent fetch @@ -101,17 +114,17 @@ namespace raven_integration //DELETE - ApiResponse DELETETestResponse = await Util.DeleteAsync("widget/" + w2Id.ToString(), await Util.GetTokenAsync("Inventory")); + ApiResponse DELETETestResponse = await Util.DeleteAsync("project/" + projectId, await Util.GetTokenAsync("Service")); Util.ValidateHTTPStatusCode(DELETETestResponse, 204); //All events should be cleared up on deletion with the sole exception of the deleted event - EventLogResponse = await Util.GetAsync($"event-log/objectlog?AyaType=2&AyId={w2Id}", await Util.GetTokenAsync("BizAdmin")); + EventLogResponse = await Util.GetAsync($"event-log/objectlog?AyaType=25&AyId={projectId}", await Util.GetTokenAsync("BizAdmin")); Util.ValidateHTTPStatusCode(EventLogResponse, 200); ((JArray)EventLogResponse.ObjectResponse["data"]["events"]).Count.Should().Be(1); EventLogResponse.ObjectResponse["data"]["events"][0]["date"].Value().Should().BeLessThan(new TimeSpan(1, 0, 0)).Before(DateTime.UtcNow);//should be less than one hour before now EventLogResponse.ObjectResponse["data"]["events"][0]["userId"].Should().NotBeNull(); EventLogResponse.ObjectResponse["data"]["events"][0]["event"].Value().Should().Be(0);//AyEvent 0 = deleted - EventLogResponse.ObjectResponse["data"]["events"][0]["textra"].Value().Should().Be(w.name.ToString()); + EventLogResponse.ObjectResponse["data"]["events"][0]["textra"].Value().Should().Contain(newName); } @@ -137,37 +150,25 @@ namespace raven_integration public async Task EventLogLimitOffSetWorks() { - var UniqueName = Util.Uniquify("EventLogLimitOffSetWorks"); - //CREATE - dynamic d = new JObject(); - d.name = UniqueName; + //CREATE USER + var userName = Util.Uniquify("EventLogLimitOffSetWorks"); + var payload = $$""" + {"id":0,"concurrency":0,"active":true,"allowLogin":true,"name":"{{userName}}","roles":8,"userType":1,"employeeNumber":null,"notes":null,"customerId":null,"headOfficeId":null,"vendorId":null,"wiki":null,"customFields":"{}","tags":[],"lastLogin":null,"password":"{{userName}}","login":"{{userName}}"} + """; - d.active = true; - d.login = UniqueName; - d.password = UniqueName; - d.roles = 2;//BizAdmin needs widget rights - d.userType = 2;// not service type user - - //Required by form custom rules - d.notes = "notes"; - d.customFields = Util.UserRequiredCustomFieldsJsonString(); - - ApiResponse a = await Util.PostAsync("User", await Util.GetTokenAsync("superuser", "l3tm3in"), d.ToString()); + ApiResponse a = await Util.PostAsync("User", await Util.GetTokenAsync("superuser", "l3tm3in"), payload); Util.ValidateDataReturnResponseOk(a); long UserId = a.ObjectResponse["data"]["id"].Value(); + var dateStarted = DateTime.Now.ToString("o"); - - //Loop and make 10 widgets + //CREATE SOME PROJECTS FOR EVENT LOG for (int i = 0; i < 10; i++) { - d = new JObject(); - d.name = Util.Uniquify("EventLogLimitOffSetWorks"); - d.customFields = Util.WidgetRequiredCustomFieldsJsonString(); - d.dollarAmount = 1.11m; - d.active = true; - d.usertype = 1; - d.notes = "note here"; - a = await Util.PostAsync("widget", await Util.GetTokenAsync(UniqueName, UniqueName), d.ToString()); + + payload = $$""" + {"id":0,"concurrency":0,"name":"{{Util.Uniquify("EventLogLimitOffSetWorks")}}","active":true,"notes":null,"wiki":null,"customFields":"{}","tags":[],"dateStarted":"{{dateStarted}}","dateCompleted":null,"projectOverseerId":null,"accountNumber":null} + """; + a = await Util.PostAsync("project", await Util.GetTokenAsync(userName, userName), payload); Util.ValidateDataReturnResponseOk(a); } @@ -178,7 +179,7 @@ namespace raven_integration List allEvents = new List(9); foreach (JObject o in eventList) { - allEvents.Add(o["date"].Value() + o["objectType"].Value() + allEvents.Add(o["date"].Value() + o["aType"].Value() + o["objectId"].Value() + o["name"].Value() + o["event"].Value() ); } @@ -188,7 +189,7 @@ namespace raven_integration var pageEventList = ((JArray)a.ObjectResponse["data"]["events"]); foreach (JObject o in pageEventList) { - allEvents.Should().Contain(o["date"].Value() + o["objectType"].Value() + allEvents.Should().Contain(o["date"].Value() + o["aType"].Value() + o["objectId"].Value() + o["name"].Value() + o["event"].Value() ); } @@ -198,7 +199,7 @@ namespace raven_integration pageEventList = ((JArray)a.ObjectResponse["data"]["events"]); foreach (JObject o in pageEventList) { - allEvents.Should().Contain(o["date"].Value() + o["objectType"].Value() + allEvents.Should().Contain(o["date"].Value() + o["aType"].Value() + o["objectId"].Value() + o["name"].Value() + o["event"].Value() ); } @@ -209,7 +210,7 @@ namespace raven_integration pageEventList = ((JArray)a.ObjectResponse["data"]["events"]); foreach (JObject o in pageEventList) { - allEvents.Should().Contain(o["date"].Value() + o["objectType"].Value() + allEvents.Should().Contain(o["date"].Value() + o["aType"].Value() + o["objectId"].Value() + o["name"].Value() + o["event"].Value() ); } diff --git a/FormCustom/FormCustom.cs b/FormCustom/FormCustom.cs index 057a3d0..5e33c58 100644 --- a/FormCustom/FormCustom.cs +++ b/FormCustom/FormCustom.cs @@ -1,9 +1,6 @@ -using System; using Xunit; using Newtonsoft.Json.Linq; using FluentAssertions; -using System.Collections.Generic; -using System.Collections.Concurrent; namespace raven_integration { @@ -40,12 +37,12 @@ namespace raven_integration */ dynamic d = new JObject(); - d.formkey = "User"; + d.formkey = "Vendor"; dynamic dtemplate = new JArray(); dynamic dt = new JObject(); - dt.fld = "UserCustom1"; + dt.fld = "VendorCustom1"; dt.hide = false; dt.required = true; dt.type = AyaUiFieldDataType.Text; @@ -58,7 +55,7 @@ namespace raven_integration dtemplate.Add(dt); dt = new JObject(); - dt.fld = "UserCustom2"; + dt.fld = "VendorCustom2"; dt.hide = true; dt.required = false; dt.type = AyaUiFieldDataType.Bool; @@ -69,23 +66,23 @@ namespace raven_integration //RETRIEVE //Get the current one (server will create if non-existent) - ApiResponse a = await Util.GetAsync("form-custom/User", await Util.GetTokenAsync("BizAdmin")); + ApiResponse a = await Util.GetAsync("form-custom/Vendor", await Util.GetTokenAsync("BizAdmin")); //Update d.concurrency = a.ObjectResponse["data"]["concurrency"].Value(); - a = await Util.PutAsync("form-custom/User", await Util.GetTokenAsync("BizAdmin"), d.ToString()); + a = await Util.PutAsync("form-custom/Vendor", await Util.GetTokenAsync("BizAdmin"), d.ToString()); Util.ValidateHTTPStatusCode(a, 200); //check the concurrency token cache scheme uint token = a.ObjectResponse["data"]["concurrency"].Value(); //This should return a 304 not modified - a = await Util.GetAsync($"form-custom/User?concurrency={token}", await Util.GetTokenAsync("BizAdmin")); + a = await Util.GetAsync($"form-custom/Vendor?concurrency={token}", await Util.GetTokenAsync("BizAdmin")); Util.ValidateHTTPStatusCode(a, 304); //and this should return the whole object token--;//make the token not match //This should return a 200 and the whole object - a = await Util.GetAsync($"form-custom/User?concurrency={token}", await Util.GetTokenAsync("BizAdmin")); + a = await Util.GetAsync($"form-custom/Vendor?concurrency={token}", await Util.GetTokenAsync("BizAdmin")); Util.ValidateDataReturnResponseOk(a); } @@ -100,7 +97,7 @@ namespace raven_integration { dynamic d = new JObject(); - d.formkey = "User"; + d.formkey = "Vendor"; dynamic dtemplate = new JArray(); @@ -123,20 +120,20 @@ namespace raven_integration dtemplate.Add(dt); dt = new JObject(); - dt.fld = "UserCustom1";//expected ApiErrorCode.VALIDATION_INVALID_VALUE type missing for custom field + dt.fld = "VendorCustom1";//expected ApiErrorCode.VALIDATION_INVALID_VALUE type missing for custom field dt.hide = false; dt.required = false; dtemplate.Add(dt); dt = new JObject(); - dt.fld = "EmployeeNumber";//expect ApiErrorCode.VALIDATION_INVALID_VALUE not custom field but type specified anyway + dt.fld = "AccountNumber";//expect ApiErrorCode.VALIDATION_INVALID_VALUE not custom field but type specified anyway dt.hide = true; dt.required = false; dt.type = AyaUiFieldDataType.EmailAddress;//type specified (doesn't matter what type) dtemplate.Add(dt); dt = new JObject(); - dt.fld = "UserCustom2";//expected ApiErrorCode.VALIDATION_INVALID_VALUE type missing for custom field + dt.fld = "VendorCustom2";//expected ApiErrorCode.VALIDATION_INVALID_VALUE type missing for custom field dt.hide = false; dt.required = false; dtemplate.Add(dt); @@ -153,32 +150,71 @@ namespace raven_integration //RETRIEVE //Get the current one (server will create if non-existent) - ApiResponse a = await Util.GetAsync("form-custom/User", await Util.GetTokenAsync("BizAdmin")); + ApiResponse a = await Util.GetAsync("form-custom/Vendor", await Util.GetTokenAsync("BizAdmin")); //Update d.concurrency = a.ObjectResponse["data"]["concurrency"].Value(); - a = await Util.PutAsync("form-custom/User", await Util.GetTokenAsync("BizAdmin"), d.ToString()); + a = await Util.PutAsync("form-custom/Vendor", await Util.GetTokenAsync("BizAdmin"), d.ToString()); Util.ValidateHTTPStatusCode(a, 400); Util.ShouldContainValidationError(a, "Template", "2201", "Template array item 0, \"fld\" property exists but is empty, a value is required"); Util.ShouldContainValidationError(a, "Template", "2203", "Template array item 0, fld property value \"\" is not a valid form field value for formKey specified"); Util.ShouldContainValidationError(a, "Template", "2203", "Template array item 1, fld property value \"ThisFieldKeyDoesNotExist\" is not a valid form field value for formKey specified"); - Util.ShouldContainValidationError(a, "Template", "2203", "Template array item 2 (\"Name\"), \"hide\" property value of \"True\" is not valid, this field is core and cannot be hidden"); - Util.ShouldContainValidationError(a, "Template", "2203", "Template array item 3 (\"UserCustom1\"), \"type\" property value is MISSING for custom field, Custom fields MUST have types specified"); - Util.ShouldContainValidationError(a, "Template", "2203", "Template array item 4 (\"EmployeeNumber\"), \"type\" property value is not valid, only Custom fields can have types specified"); - Util.ShouldContainValidationError(a, "Template", "2203", "Template array item 5 (\"UserCustom2\"), \"type\" property value of \"999\" is not a valid custom field type"); + Util.ShouldContainValidationError(a, "Template", "2203", "Template array item 2, fld property value \"Name\" is not a valid form field value for formKey specified"); + Util.ShouldContainValidationError(a, "Template", "2203", "Template array item 3 (\"VendorCustom1\"), \"type\" property value is MISSING for custom field, Custom fields MUST have types specified"); + Util.ShouldContainValidationError(a, "Template", "2203", "Template array item 4 (\"AccountNumber\"), \"type\" property value is not valid, only Custom fields can have types specified"); + Util.ShouldContainValidationError(a, "Template", "2203", "Template array item 5 (\"VendorCustom2\"), \"type\" property value of \"999\" is not a valid custom field type"); Util.ShouldContainValidationError(a, "Template", "2201", "Template array item 6, object is missing \"required\" property. All items must contain this property."); /* - "{\"error\":{\"code\":\"2200\",\"details\":[ - {\"message\":\"Template array item 0, \\\"fld\\\" property exists but is empty, a value is required\",\"target\":\"Template\",\"error\":\"2201\"}, - {\"message\":\"Template array item 0, fld property value \\\"\\\" is not a valid form field value for formKey specified\",\"target\":\"Template\",\"error\":\"2203\"}, - {\"message\":\"Template array item 1, fld property value \\\"ThisFieldKeyDoesNotExist\\\" is not a valid form field value for formKey specified\",\"target\":\"Template\",\"error\":\"2203\"}, - {\"message\":\"Template array item 2 (\\\"Name\\\"), \\\"hide\\\" property value of \\\"True\\\" is not valid, this field is core and cannot be hidden\",\"target\":\"Template\",\"error\":\"2203\"}, - {\"message\":\"Template array item 3 (\\\"UserCustom1\\\"), \\\"type\\\" property value is MISSING for custom filed, Custom fields MUST have types specified\",\"target\":\"Template\",\"error\":\"2203\"}, - {\"message\":\"Template array item 4 (\\\"EmployeeNumber\\\"), \\\"type\\\" property value is not valid, only Custom fields can have types specified\",\"target\":\"Template\",\"error\":\"2203\"}, - {\"message\":\"Template array item 5 (\\\"UserCustom2\\\"), \\\"type\\\" property value of \\\"999\\\" is not a valid custom field type\",\"target\":\"Template\",\"error\":\"2203\"}, - {\"message\":\"Template array item 6, object is missing \\\"required\\\" property. All items must contain this property. \",\"target\":\"Template\",\"error\":\"2201\"} - ],\"message\":\"Object did not pass validation\"}}" + + {{ + "error": { + "code": "2200", + "details": [ + { + "message": "Template array item 0, \"fld\" property exists but is empty, a value is required", + "target": "Template", + "error": "2201" + }, + { + "message": "Template array item 0, fld property value \"\" is not a valid form field value for formKey specified", + "target": "Template", + "error": "2203" + }, + { + "message": "Template array item 1, fld property value \"ThisFieldKeyDoesNotExist\" is not a valid form field value for formKey specified", + "target": "Template", + "error": "2203" + }, + { + "message": "Template array item 2, fld property value \"Name\" is not a valid form field value for formKey specified", + "target": "Template", + "error": "2203" + }, + { + "message": "Template array item 3 (\"VendorCustom1\"), \"type\" property value is MISSING for custom field, Custom fields MUST have types specified", + "target": "Template", + "error": "2203" + }, + { + "message": "Template array item 4 (\"AccountNumber\"), \"type\" property value is not valid, only Custom fields can have types specified", + "target": "Template", + "error": "2203" + }, + { + "message": "Template array item 5 (\"VendorCustom2\"), \"type\" property value of \"999\" is not a valid custom field type", + "target": "Template", + "error": "2203" + }, + { + "message": "Template array item 6, object is missing \"required\" property. All items must contain this property. ", + "target": "Template", + "error": "2201" + } + ], + "message": "ErrorAPI2200" + } +}} */ } @@ -189,8 +225,8 @@ namespace raven_integration [Fact] public async Task InvalidObjectFieldsFormKeyShouldFail() { - ApiResponse a = await Util.GetAsync("form-field-definition/nonexistent", await Util.GetTokenAsync("BizAdmin")); - Util.ValidateErrorCodeResponse(a, 2010, 404); + ApiResponse a = await Util.GetAsync("form-field-reference/nonexistent", await Util.GetTokenAsync("BizAdmin")); + Util.ValidateHTTPStatusCode(a, 404); } @@ -200,7 +236,7 @@ namespace raven_integration [Fact] public async Task ObjectFieldsWorks() { - ApiResponse a = await Util.GetAsync("form-field-definition/Widget", await Util.GetTokenAsync("BizAdmin")); + ApiResponse a = await Util.GetAsync("form-field-reference/Vendor", await Util.GetTokenAsync("BizAdmin")); Util.ValidateDataReturnResponseOk(a); ((JArray)a.ObjectResponse["data"]).Count.Should().BeGreaterThan(25); }