Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/FMData.Rest/FileMakerRestClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,6 @@ public override async Task<IResponse> SendAsync(IDeleteRequest req)
/// <inheritdoc />
public override async Task<(IEnumerable<TResponse>, DataInfoModel)> SendAsync<TResponse, TRequest>(
IFindRequest<TRequest> req,
bool includeDataInfo,
Func<TResponse, int, object> fmId = null,
Func<TResponse, int, object> modId = null)
{
Expand Down
1 change: 0 additions & 1 deletion src/FMData.Xml/FileMakerXmlClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ public override async Task<IEditResponse> SendAsync<T>(IEditRequest<T> req)
/// <inheritdoc />
public override async Task<(IEnumerable<TResponse>, DataInfoModel)> SendAsync<TResponse, TRequest>(
IFindRequest<TRequest> req,
bool includeDataInfo,
Func<TResponse, int, object> fmId = null,
Func<TResponse, int, object> modId = null)
{
Expand Down
13 changes: 6 additions & 7 deletions src/FMData/FileMakerApiClientBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ public Task<IEnumerable<T>> FindAsync<T>(
.SetOffset(skip);
req.Script = script;
req.ScriptParameter = scriptParameter;
return SendAsync(req, fmIdFunc, fmModIdFunc);
return SendAsync<T>(req, fmIdFunc, fmModIdFunc);
}

/// <summary>
Expand Down Expand Up @@ -642,7 +642,7 @@ public virtual Task<IEnumerable<T>> SendAsync<T>(
/// </summary>
public virtual Task<IEnumerable<T>> SendAsync<T>(
IFindRequest<T> req,
Func<T, int, object> fmId) where T : class, new() => SendAsync(req, fmId, null);
Func<T, int, object> fmId) where T : class, new() => SendAsync<T>(req, fmId, null);

/// <summary>
/// Send a Find Record request to the FileMaker API.
Expand All @@ -652,7 +652,7 @@ public virtual async Task<IEnumerable<T>> SendAsync<T>(
Func<T, int, object> fmId,
Func<T, int, object> modId) where T : class, new()
{
var (data, _) = await SendAsync<T, T>(req, false, fmId, modId).ConfigureAwait(false);
var (data, _) = await SendAsync<T, T>(req, fmId, modId).ConfigureAwait(false);
return data;
}

Expand All @@ -663,15 +663,14 @@ public virtual async Task<IEnumerable<T>> SendAsync<T>(
Func<T, int, object> fmId = null,
Func<T, int, object> modId = null) where T : class, new()
{
return await SendAsync<T, T>(req, includeDataInfo, fmId, modId).ConfigureAwait(false);
return await SendAsync<T, T>(req, fmId, modId).ConfigureAwait(false);
}

/// <inheritdoc />
public abstract Task<(IEnumerable<TResponse>, DataInfoModel)> SendAsync<TResponse, TRequest>(
IFindRequest<TRequest> req,
bool includeDataInfo,
Func<TResponse, int, object> fmId = null,
Func<TResponse, int, object> modId = null) where TResponse : class, new();
Func<TResponse, int, object> fmId,
Func<TResponse, int, object> modId) where TResponse : class, new();

#endregion

Expand Down
9 changes: 4 additions & 5 deletions src/FMData/IFileMakerApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -491,21 +491,20 @@ Task<IEnumerable<T>> SendAsync<T>(
Func<T, int, object> modId = null) where T : class, new();

/// <summary>
/// Find a record or records matching the request and include a data info model as well as the response.
/// Find a record or records matching the request and include a data info model as well as the response.
/// </summary>
/// <typeparam name="TResponse">The Response type.</typeparam>
/// <typeparam name="TRequest">The Request type.</typeparam>
/// <param name="req">The find request parameters.</param>
/// <param name="fmId">Function to assign the FileMaker RecordId to each instance of {T}.</param>
/// <param name="modId">Function to assign the FileMaker ModId to each instance of {T}.</param>
/// <param name="includeDataInfo">Indicates whether the data information portion should be parsed.</param>
/// <returns>An <see cref="IEnumerable{T}"/> matching the request parameters.</returns>
/// <remarks>The data info portion of the response is always returned when correctly parsed.</remarks>
/// <remarks>This method allows using separate Request and Response generics, which is useful when querying with dynamic input, but static output.</remarks>
Task<(IEnumerable<TResponse>, DataInfoModel)> SendAsync<TResponse, TRequest>(
IFindRequest<TRequest> req,
bool includeDataInfo,
Func<TResponse, int, object> fmId = null,
Func<TResponse, int, object> modId = null) where TResponse : class, new();
Func<TResponse, int, object> fmId,
Func<TResponse, int, object> modId) where TResponse : class, new();

/// <summary>
/// Edit record.
Expand Down
155 changes: 154 additions & 1 deletion tests/FMData.Rest.Tests/Find.SendAsync.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,66 @@ public async Task SendAsync_Find_Should_Have_DataInfo()
Assert.Equal(123, info.FoundCount);
}

[Fact]
public async Task SendAsync_Find_Should_Have_DataInfo_FirstOverload()
{
// arrange
var mockHttp = new MockHttpMessageHandler();
Func<User, int, object> FMRecordIdMapper = (o, id) => o.FileMakerRecordId = id;

var layout = "the-layout";

mockHttp.When(HttpMethod.Post, $"{FindTestsHelpers.Server}/fmi/data/v1/databases/{FindTestsHelpers.File}/sessions")
.Respond("application/json", DataApiResponses.SuccessfulAuthentication());

mockHttp.When(HttpMethod.Post, $"{FindTestsHelpers.Server}/fmi/data/v1/databases/{FindTestsHelpers.File}/layouts/{layout}/_find")
.Respond(HttpStatusCode.OK, "application/json", DataApiResponses.SuccessfulFindWithDataInfo());

var fdc = new FileMakerRestClient(mockHttp.ToHttpClient(), FindTestsHelpers.Connection);

var toFind = new User() { Id = 35 };
var req = new FindRequest<User>() { Layout = layout };
req.AddQuery(toFind, false);

// act
var (data, info) = await fdc.SendAsync(req, true, FMRecordIdMapper, null);

// assert
Assert.NotEmpty(data);
Assert.Equal(1, info.ReturnedCount);
Assert.Equal(123, info.FoundCount);
}

[Fact]
public async Task SendAsync_Find_Should_Have_DataInfo_SecondOverload()
{
// arrange
var mockHttp = new MockHttpMessageHandler();
Func<User, int, object> ModMap = (o, id) => o.FileMakerModId = id;

var layout = "the-layout";

mockHttp.When(HttpMethod.Post, $"{FindTestsHelpers.Server}/fmi/data/v1/databases/{FindTestsHelpers.File}/sessions")
.Respond("application/json", DataApiResponses.SuccessfulAuthentication());

mockHttp.When(HttpMethod.Post, $"{FindTestsHelpers.Server}/fmi/data/v1/databases/{FindTestsHelpers.File}/layouts/{layout}/_find")
.Respond(HttpStatusCode.OK, "application/json", DataApiResponses.SuccessfulFindWithDataInfo());

var fdc = new FileMakerRestClient(mockHttp.ToHttpClient(), FindTestsHelpers.Connection);

var toFind = new User() { Id = 35 };
var req = new FindRequest<User>() { Layout = layout };
req.AddQuery(toFind, false);

// act
var (data, info) = await fdc.SendAsync(req, true, null, ModMap);

// assert
Assert.NotEmpty(data);
Assert.Equal(1, info.ReturnedCount);
Assert.Equal(123, info.FoundCount);
}

[Fact]
public async Task SendAsync_Using_Dictionary_Find_Should_Have_DataInfo()
{
Expand All @@ -248,7 +308,100 @@ public async Task SendAsync_Using_Dictionary_Find_Should_Have_DataInfo()
req.AddQuery(toFind, false);

// act
var (data, info) = await fdc.SendAsync<User, Dictionary<string, string>>(req, true);
var (data, info) = await fdc.SendAsync<User, Dictionary<string, string>>(req, null, null);

// assert
Assert.NotEmpty(data);
Assert.Equal(1, info.ReturnedCount);
Assert.Equal(123, info.FoundCount);
}

[Fact]
public async Task SendAsync_Using_Dictionary_Find_Should_Have_DataInfo_OverloadOne()
{
// arrange
var mockHttp = new MockHttpMessageHandler();
Func<User, int, object> IdMap = (o, id) => o.FileMakerRecordId = id;
Func<User, int, object> ModMap = (o, id) => o.FileMakerModId = id;

var layout = "the-layout";

mockHttp.When(HttpMethod.Post, $"{FindTestsHelpers.Server}/fmi/data/v1/databases/{FindTestsHelpers.File}/sessions")
.Respond("application/json", DataApiResponses.SuccessfulAuthentication());

mockHttp.When(HttpMethod.Post, $"{FindTestsHelpers.Server}/fmi/data/v1/databases/{FindTestsHelpers.File}/layouts/{layout}/_find")
.Respond(HttpStatusCode.OK, "application/json", DataApiResponses.SuccessfulFindWithDataInfo());

var fdc = new FileMakerRestClient(mockHttp.ToHttpClient(), FindTestsHelpers.Connection);

var toFind = new Dictionary<string, string>() { { "Id", "35" } };
var req = new FindRequest<Dictionary<string, string>>() { Layout = layout };
req.AddQuery(toFind, false);

// act
var (data, info) = await fdc.SendAsync<User, Dictionary<string, string>>(req, IdMap, null);

// assert
Assert.NotEmpty(data);
Assert.Equal(1, info.ReturnedCount);
Assert.Equal(123, info.FoundCount);
}

[Fact]
public async Task SendAsync_Using_Dictionary_Find_Should_Have_DataInfo_OverloadTwo()
{
// arrange
var mockHttp = new MockHttpMessageHandler();
Func<User, int, object> IdMap = (o, id) => o.FileMakerRecordId = id;
Func<User, int, object> ModMap = (o, id) => o.FileMakerModId = id;

var layout = "the-layout";

mockHttp.When(HttpMethod.Post, $"{FindTestsHelpers.Server}/fmi/data/v1/databases/{FindTestsHelpers.File}/sessions")
.Respond("application/json", DataApiResponses.SuccessfulAuthentication());

mockHttp.When(HttpMethod.Post, $"{FindTestsHelpers.Server}/fmi/data/v1/databases/{FindTestsHelpers.File}/layouts/{layout}/_find")
.Respond(HttpStatusCode.OK, "application/json", DataApiResponses.SuccessfulFindWithDataInfo());

var fdc = new FileMakerRestClient(mockHttp.ToHttpClient(), FindTestsHelpers.Connection);

var toFind = new Dictionary<string, string>() { { "Id", "35" } };
var req = new FindRequest<Dictionary<string, string>>() { Layout = layout };
req.AddQuery(toFind, false);

// act
var (data, info) = await fdc.SendAsync<User, Dictionary<string, string>>(req, null, ModMap);

// assert
Assert.NotEmpty(data);
Assert.Equal(1, info.ReturnedCount);
Assert.Equal(123, info.FoundCount);
}

[Fact]
public async Task SendAsync_Using_Dictionary_Find_Should_Have_DataInfo_OverloadThree()
{
// arrange
var mockHttp = new MockHttpMessageHandler();
Func<User, int, object> IdMap = (o, id) => o.FileMakerRecordId = id;
Func<User, int, object> ModMap = (o, id) => o.FileMakerModId = id;

var layout = "the-layout";

mockHttp.When(HttpMethod.Post, $"{FindTestsHelpers.Server}/fmi/data/v1/databases/{FindTestsHelpers.File}/sessions")
.Respond("application/json", DataApiResponses.SuccessfulAuthentication());

mockHttp.When(HttpMethod.Post, $"{FindTestsHelpers.Server}/fmi/data/v1/databases/{FindTestsHelpers.File}/layouts/{layout}/_find")
.Respond(HttpStatusCode.OK, "application/json", DataApiResponses.SuccessfulFindWithDataInfo());

var fdc = new FileMakerRestClient(mockHttp.ToHttpClient(), FindTestsHelpers.Connection);

var toFind = new Dictionary<string, string>() { { "Id", "35" } };
var req = new FindRequest<Dictionary<string, string>>() { Layout = layout };
req.AddQuery(toFind, false);

// act
var (data, info) = await fdc.SendAsync<User, Dictionary<string, string>>(req, IdMap, ModMap);

// assert
Assert.NotEmpty(data);
Expand Down