96 lines
5.5 KiB
C#
96 lines
5.5 KiB
C#
using Xunit;
|
|
using Newtonsoft.Json.Linq;
|
|
using FluentAssertions;
|
|
|
|
namespace raven_integration
|
|
{
|
|
|
|
public class ContractCrud
|
|
{
|
|
|
|
/// <summary>
|
|
/// Full CRUD for a Contract, including a concurrency violation check.
|
|
/// Contract has a richer required-field set than most objects (billing override
|
|
/// type enums, response time, etc.) so this test exercises the full model round-trip.
|
|
///
|
|
/// ContractOverrideType enum: PriceDiscount = 1, CostMarkup = 2
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task CRUD()
|
|
{
|
|
var token = await Util.GetTokenAsync("BizAdmin");
|
|
|
|
// -------------------------------------------------------------------
|
|
// CREATE
|
|
// responseTime: TimeSpan JSON format is "HH:MM:SS"
|
|
// partsOverrideType / serviceRatesOverrideType / travelRatesOverrideType:
|
|
// 1 = PriceDiscount, 2 = CostMarkup
|
|
// -------------------------------------------------------------------
|
|
var name = Util.Uniquify("Test Contract");
|
|
var payload = $$"""
|
|
{"id":0,"concurrency":0,"name":"{{name}}","active":true,"notes":"The quick brown fox jumped over the six lazy dogs!","wiki":null,"customFields":"{}","tags":[],"responseTime":"01:00:00","contractServiceRatesOnly":false,"contractTravelRatesOnly":false,"partsOverridePct":10.0,"partsOverrideType":1,"serviceRatesOverridePct":5.0,"serviceRatesOverrideType":1,"travelRatesOverridePct":0.0,"travelRatesOverrideType":1,"alertNotes":"Contract alert text"}
|
|
""";
|
|
|
|
ApiResponse a = await Util.PostAsync("contract", token, payload);
|
|
Util.ValidateDataReturnResponseOk(a);
|
|
long Id = a.ObjectResponse["data"]["id"].Value<long>();
|
|
Id.Should().BeGreaterThan(0);
|
|
a.ObjectResponse["data"]["name"].Value<string>().Should().Be(name);
|
|
a.ObjectResponse["data"]["partsOverrideType"].Value<int>().Should().Be(1);
|
|
|
|
// -------------------------------------------------------------------
|
|
// GET
|
|
// -------------------------------------------------------------------
|
|
a = await Util.GetAsync($"contract/{Id}", token);
|
|
Util.ValidateDataReturnResponseOk(a);
|
|
a.ObjectResponse["data"]["name"].Value<string>().Should().Be(name);
|
|
a.ObjectResponse["data"]["alertNotes"].Value<string>().Should().Be("Contract alert text");
|
|
var concurrency = a.ObjectResponse["data"]["concurrency"].Value<uint>();
|
|
|
|
// -------------------------------------------------------------------
|
|
// PUT — Contract PUT returns the full updated object (not just concurrency)
|
|
// -------------------------------------------------------------------
|
|
var updatedName = Util.Uniquify("Updated Contract");
|
|
var putPayload = $$"""
|
|
{"id":{{Id}},"concurrency":{{concurrency}},"name":"{{updatedName}}","active":true,"notes":"Updated notes","wiki":null,"customFields":"{}","tags":[],"responseTime":"02:00:00","contractServiceRatesOnly":false,"contractTravelRatesOnly":false,"partsOverridePct":15.0,"partsOverrideType":2,"serviceRatesOverridePct":0.0,"serviceRatesOverrideType":1,"travelRatesOverridePct":5.0,"travelRatesOverrideType":1,"alertNotes":"Updated alert"}
|
|
""";
|
|
a = await Util.PutAsync("contract", token, putPayload);
|
|
Util.ValidateHTTPStatusCode(a, 200);
|
|
// PUT returns the full updated contract object
|
|
a.ObjectResponse["data"]["name"].Value<string>().Should().Be(updatedName);
|
|
a.ObjectResponse["data"]["partsOverrideType"].Value<int>().Should().Be(2, "should have changed to CostMarkup");
|
|
var newConcurrency = a.ObjectResponse["data"]["concurrency"].Value<uint>();
|
|
newConcurrency.Should().NotBe(concurrency, "concurrency should have been bumped");
|
|
|
|
// Verify update persisted
|
|
a = await Util.GetAsync($"contract/{Id}", token);
|
|
Util.ValidateDataReturnResponseOk(a);
|
|
a.ObjectResponse["data"]["name"].Value<string>().Should().Be(updatedName);
|
|
a.ObjectResponse["data"]["contractServiceRatesOnly"].Value<bool>().Should().BeFalse();
|
|
|
|
// -------------------------------------------------------------------
|
|
// CONCURRENCY VIOLATION: PUT with stale concurrency should return 409
|
|
// -------------------------------------------------------------------
|
|
a = await Util.PutAsync("contract", token, putPayload); // putPayload has the old concurrency
|
|
Util.ValidateConcurrencyError(a);
|
|
|
|
// -------------------------------------------------------------------
|
|
// DELETE
|
|
// -------------------------------------------------------------------
|
|
a = await Util.DeleteAsync($"contract/{Id}", token);
|
|
Util.ValidateHTTPStatusCode(a, 204);
|
|
|
|
// Confirm deleted
|
|
//bugbug case 4652 TO be fixed for this test to pass
|
|
//bug at server causing 500 to be returned instead of 404
|
|
//do not want to fix yet until ready for refactor in general
|
|
//deployed UI unaffected as it wouldn't attempt this normally
|
|
//this problem likely exhibits in any other object that has a 'populatedisplayfields' call at the server
|
|
//in their get routine that doesn't guard against null record
|
|
a = await Util.GetAsync($"contract/{Id}", token);
|
|
Util.ValidateResponseNotFound(a);
|
|
}
|
|
|
|
}//eoc
|
|
}//eons
|