Skip to content

Commit

Permalink
Add AccessScope enum, reorder CreateAgreementRequest constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
RobinTTY committed May 3, 2024
1 parent eb4ca3f commit c71ce83
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ public async Task GetAgreementsPaged()
AssertionHelpers.AssertNordigenApiResponseIsSuccessful(existingAgreements, HttpStatusCode.OK);

// Create 3 example agreements
var agreementRequest = new CreateAgreementRequest(90, 90,
["balances", "details", "transactions"], "SANDBOXFINANCE_SFIN0000");
var agreementRequest = new CreateAgreementRequest("SANDBOXFINANCE_SFIN0000",
[AccessScope.Balances, AccessScope.Details, AccessScope.Transactions]);
var ids = new List<string>();

var existingIds = existingAgreements.Result!.Results.Select(agreement => agreement.Id.ToString()).ToList();
Expand Down Expand Up @@ -83,8 +83,8 @@ public async Task GetAgreementsPaged()
public async Task GetAgreement()
{
// Create agreement
var agreementRequest = new CreateAgreementRequest(90, 90,
["balances", "details", "transactions"], "SANDBOXFINANCE_SFIN0000");
var agreementRequest = new CreateAgreementRequest("SANDBOXFINANCE_SFIN0000",
[AccessScope.Balances, AccessScope.Details, AccessScope.Transactions]);
var createResponse = await _apiClient.AgreementsEndpoint.CreateAgreement(agreementRequest);
AssertionHelpers.AssertNordigenApiResponseIsSuccessful(createResponse, HttpStatusCode.Created);
var id = createResponse.Result!.Id;
Expand All @@ -108,8 +108,8 @@ public async Task GetAgreement()
public async Task CreateAcceptAndDeleteAgreement()
{
// Create the agreement
var agreement = new CreateAgreementRequest(90, 90, ["balances", "details", "transactions"],
"SANDBOXFINANCE_SFIN0000");
var agreement = new CreateAgreementRequest("SANDBOXFINANCE_SFIN0000",
[AccessScope.Balances, AccessScope.Details, AccessScope.Transactions]);
var response = await _apiClient.AgreementsEndpoint.CreateAgreement(agreement);
AssertionHelpers.AssertNordigenApiResponseIsSuccessful(response, HttpStatusCode.Created);

Expand All @@ -119,7 +119,9 @@ public async Task CreateAcceptAndDeleteAgreement()
Assert.That(result.Id, Is.Not.EqualTo(Guid.Empty));
Assert.That(result.Created - DateTime.UtcNow, Is.AtMost(TimeSpan.FromSeconds(5)));
Assert.That(result.Accepted, Is.Null);
Assert.That(result.AccessScope.Except(new[] {"balances", "details", "transactions"}), Is.Empty);
Assert.That(
result.AccessScope.Except([AccessScope.Balances, AccessScope.Details, AccessScope.Transactions]),
Is.Empty);
Assert.That(result.MaxHistoricalDays, Is.EqualTo(90));
Assert.That(result.AccessValidForDays, Is.EqualTo(90));
});
Expand Down Expand Up @@ -166,8 +168,8 @@ public async Task GetAgreementWithInvalidGuid()
[Test]
public async Task CreateAgreementWithInvalidInstitutionId()
{
var agreement = new CreateAgreementRequest(90, 90,
["balances", "details", "transactions"], "invalid_institution");
var agreement = new CreateAgreementRequest("invalid_institution",
[AccessScope.Balances, AccessScope.Details, AccessScope.Transactions]);

var response = await _apiClient.AgreementsEndpoint.CreateAgreement(agreement);

Expand All @@ -188,7 +190,7 @@ public async Task CreateAgreementWithInvalidInstitutionId()
[Test]
public async Task CreateAgreementWithEmptyInstitutionIdAndAccessScopes()
{
var agreement = new CreateAgreementRequest(90, 90, null!, null!);
var agreement = new CreateAgreementRequest(null!, null!);

var response = await _apiClient.AgreementsEndpoint.CreateAgreement(agreement);

Expand All @@ -210,8 +212,8 @@ public async Task CreateAgreementWithEmptyInstitutionIdAndAccessScopes()
[Test]
public async Task CreateAgreementWithInvalidParams()
{
var agreement = new CreateAgreementRequest(200, 200,
["balances", "details", "transactions", "invalid", "invalid2"], "SANDBOXFINANCE_SFIN0000");
var agreement = new CreateAgreementRequest("SANDBOXFINANCE_SFIN0000",
[AccessScope.Balances, AccessScope.Details, AccessScope.Transactions], 200, 200);

var response = await _apiClient.AgreementsEndpoint.CreateAgreement(agreement);
var result = response.Error!;
Expand All @@ -233,8 +235,7 @@ public async Task CreateAgreementWithInvalidParams()
[Test]
public async Task CreateAgreementWithInvalidParamsAtPolishInstitution()
{
var agreement = new CreateAgreementRequest(90, 90,
["balances", "transactions"], "PKO_BPKOPLPW");
var agreement = new CreateAgreementRequest("PKO_BPKOPLPW", [AccessScope.Balances, AccessScope.Transactions]);

var response = await _apiClient.AgreementsEndpoint.CreateAgreement(agreement);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ public async Task GetRequisitionsPaged()
const string institutionId = "SANDBOXFINANCE_SFIN0000";

// Create required agreement first
var agreementRequest = new CreateAgreementRequest(90, 90,
new List<string> {"balances", "details", "transactions"}, institutionId);
var agreementRequest = new CreateAgreementRequest(institutionId, [AccessScope.Balances, AccessScope.Details, AccessScope.Transactions]);
var agreementResponse = await _apiClient.AgreementsEndpoint.CreateAgreement(agreementRequest);
AssertionHelpers.AssertNordigenApiResponseIsSuccessful(agreementResponse, HttpStatusCode.Created);
var agreementId = agreementResponse.Result!.Id;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using FakeItEasy;
using RobinTTY.NordigenApiClient.Models.Requests;
using RobinTTY.NordigenApiClient.Models.Responses;
using RobinTTY.NordigenApiClient.Tests.Shared;

namespace RobinTTY.NordigenApiClient.Tests.Mocks.Endpoints;
Expand Down Expand Up @@ -42,7 +43,7 @@ public async Task GetAgreements()
Assert.That(responseAgreement.AccessValidForDays, Is.EqualTo(90));
Assert.That(responseAgreement.AccessScope, Has.Count.EqualTo(3));

var expectedAccessScopes = new[] {"balances", "details", "transactions"};
var expectedAccessScopes = new[] {AccessScope.Balances, AccessScope.Details, AccessScope.Transactions};
Assert.That(responseAgreement.AccessScope, Is.EqualTo(expectedAccessScopes));
});
}
Expand All @@ -69,7 +70,7 @@ public async Task GetAgreement()
Is.EqualTo(DateTime.Parse("2024-04-08T22:54:54.869Z").ToUniversalTime()));
Assert.That(((DateTime) agreement.Result!.Accepted!).ToUniversalTime(),
Is.EqualTo(DateTime.Parse("2024-04-08T22:54:54.869Z").ToUniversalTime()));
var expectedAccessScopes = new[] {"balances", "details", "transactions"};
var expectedAccessScopes = new[] {AccessScope.Balances, AccessScope.Details, AccessScope.Transactions};
Assert.That(agreement.Result!.AccessScope, Is.EqualTo(expectedAccessScopes));
});
}
Expand All @@ -83,8 +84,8 @@ public async Task CreateAgreement()
var apiClient = TestHelpers.GetMockClient(TestHelpers.MockData.AgreementsEndpointMockData.CreateAgreement,
HttpStatusCode.Created);

var agreementRequest = new CreateAgreementRequest(145, 145,
["balances", "details", "transactions"], "SANDBOXFINANCE_SFIN0000");
var agreementRequest = new CreateAgreementRequest("SANDBOXFINANCE_SFIN0000",
[AccessScope.Balances, AccessScope.Details, AccessScope.Transactions], 145, 145);
var createResponse = await apiClient.AgreementsEndpoint.CreateAgreement(agreementRequest);
AssertionHelpers.AssertNordigenApiResponseIsSuccessful(createResponse, HttpStatusCode.Created);

Expand All @@ -95,7 +96,7 @@ public async Task CreateAgreement()
Assert.That(createResponse.Result!.MaxHistoricalDays, Is.EqualTo(145));
Assert.That(createResponse.Result!.AccessValidForDays, Is.EqualTo(145));

var expectedAccessScopes = new[] {"balances", "details", "transactions"};
var expectedAccessScopes = new[] {AccessScope.Balances, AccessScope.Details, AccessScope.Transactions};
Assert.That(createResponse.Result!.AccessScope, Is.EqualTo(expectedAccessScopes));
});
}
Expand Down Expand Up @@ -153,8 +154,8 @@ public async Task CreateAgreementWithInvalidInstitutionId()
var apiClient = TestHelpers.GetMockClient(
TestHelpers.MockData.AgreementsEndpointMockData.CreateAgreementWithInvalidInstitutionId,
HttpStatusCode.BadRequest);
var agreement = new CreateAgreementRequest(90, 90,
["balances", "details", "transactions"], "invalid_institution");
var agreement = new CreateAgreementRequest("invalid_institution",
[AccessScope.Balances, AccessScope.Details, AccessScope.Transactions]);

var response = await apiClient.AgreementsEndpoint.CreateAgreement(agreement);

Expand All @@ -178,7 +179,7 @@ public async Task CreateAgreementWithEmptyInstitutionIdAndAccessScopes()
var apiClient = TestHelpers.GetMockClient(
TestHelpers.MockData.AgreementsEndpointMockData.CreateAgreementWithEmptyInstitutionIdAndAccessScopes,
HttpStatusCode.BadRequest);
var agreement = new CreateAgreementRequest(90, 90, null!, null!);
var agreement = new CreateAgreementRequest(null!, null!, null, null);

Check failure on line 182 in src/RobinTTY.NordigenApiClient.Tests/Mocks/Endpoints/AgreementsEndpointTests.cs

View workflow job for this annotation

GitHub Actions / Build library

Argument 3: cannot convert from '<null>' to 'uint'

Check failure on line 182 in src/RobinTTY.NordigenApiClient.Tests/Mocks/Endpoints/AgreementsEndpointTests.cs

View workflow job for this annotation

GitHub Actions / Build library

Argument 4: cannot convert from '<null>' to 'uint'

Check failure on line 182 in src/RobinTTY.NordigenApiClient.Tests/Mocks/Endpoints/AgreementsEndpointTests.cs

View workflow job for this annotation

GitHub Actions / Build library

Argument 3: cannot convert from '<null>' to 'uint'

Check failure on line 182 in src/RobinTTY.NordigenApiClient.Tests/Mocks/Endpoints/AgreementsEndpointTests.cs

View workflow job for this annotation

GitHub Actions / Build library

Argument 4: cannot convert from '<null>' to 'uint'

Check failure on line 182 in src/RobinTTY.NordigenApiClient.Tests/Mocks/Endpoints/AgreementsEndpointTests.cs

View workflow job for this annotation

GitHub Actions / Build library

Argument 3: cannot convert from '<null>' to 'uint'

Check failure on line 182 in src/RobinTTY.NordigenApiClient.Tests/Mocks/Endpoints/AgreementsEndpointTests.cs

View workflow job for this annotation

GitHub Actions / Build library

Argument 4: cannot convert from '<null>' to 'uint'

Check failure on line 182 in src/RobinTTY.NordigenApiClient.Tests/Mocks/Endpoints/AgreementsEndpointTests.cs

View workflow job for this annotation

GitHub Actions / Build library

Argument 3: cannot convert from '<null>' to 'uint'

Check failure on line 182 in src/RobinTTY.NordigenApiClient.Tests/Mocks/Endpoints/AgreementsEndpointTests.cs

View workflow job for this annotation

GitHub Actions / Build library

Argument 4: cannot convert from '<null>' to 'uint'

var response = await apiClient.AgreementsEndpoint.CreateAgreement(agreement);

Expand All @@ -191,6 +192,10 @@ public async Task CreateAgreementWithEmptyInstitutionIdAndAccessScopes()

Assert.That(response.Error!.AccessScopeError!.Summary, Is.EqualTo("This field may not be null."));
Assert.That(response.Error!.AccessScopeError!.Detail, Is.EqualTo("This field may not be null."));

Assert.That(response.Error.AccessValidForDaysError, Is.Null);
Assert.That(response.Error.MaxHistoricalDaysError, Is.Null);
Assert.That(response.Error.AgreementError, Is.Null);
});
}

Expand All @@ -203,8 +208,8 @@ public async Task CreateAgreementWithInvalidParams()
var apiClient = TestHelpers.GetMockClient(
TestHelpers.MockData.AgreementsEndpointMockData.CreateAgreementWithInvalidParams,
HttpStatusCode.BadRequest);
var agreement = new CreateAgreementRequest(200, 200,
["balances", "details", "transactions", "invalid", "invalid2"], "SANDBOXFINANCE_SFIN0000");
var agreement = new CreateAgreementRequest("SANDBOXFINANCE_SFIN0000",
[AccessScope.Balances, AccessScope.Details, AccessScope.Transactions], 200, 200);

var response = await apiClient.AgreementsEndpoint.CreateAgreement(agreement);
var result = response.Error!;
Expand All @@ -229,8 +234,7 @@ public async Task CreateAgreementWithInvalidParamsAtPolishInstitution()
var apiClient = TestHelpers.GetMockClient(
TestHelpers.MockData.AgreementsEndpointMockData.CreateAgreementWithInvalidParamsAtPolishInstitution,
HttpStatusCode.BadRequest);
var agreement = new CreateAgreementRequest(90, 90,
["balances", "transactions"], "PKO_BPKOPLPW");
var agreement = new CreateAgreementRequest("PKO_BPKOPLPW", [AccessScope.Balances, AccessScope.Transactions]);

var response = await apiClient.AgreementsEndpoint.CreateAgreement(agreement);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using RobinTTY.NordigenApiClient.Contracts;
using RobinTTY.NordigenApiClient.Models.Errors;
using RobinTTY.NordigenApiClient.Models.Requests;
Expand Down Expand Up @@ -41,7 +43,8 @@ public async Task<NordigenApiResponse<Agreement, BasicResponse>> GetAgreement(st
public async Task<NordigenApiResponse<Agreement, CreateAgreementError>> CreateAgreement(
CreateAgreementRequest agreement, CancellationToken cancellationToken = default)
{
var body = JsonContent.Create(agreement);
var body = JsonContent.Create(agreement,
options: new JsonSerializerOptions {DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull});
return await _nordigenClient.MakeRequest<Agreement, CreateAgreementError>(
NordigenEndpointUrls.AgreementsEndpoint, HttpMethod.Post, cancellationToken, body: body);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
using RobinTTY.NordigenApiClient.Models.Responses;

namespace RobinTTY.NordigenApiClient.Models.Requests;

Expand All @@ -8,6 +9,18 @@ namespace RobinTTY.NordigenApiClient.Models.Requests;
/// </summary>
public class CreateAgreementRequest
{
/// <summary>
/// The institution this agreement refers to.
/// </summary>
[JsonPropertyName("institution_id")]
public string InstitutionId { get; set; }

/// <summary>
/// The scope of information that can be accessed.
/// </summary>
[JsonPropertyName("access_scope")]
public List<AccessScope> AccessScope { get; set; }

/// <summary>
/// The length of the transaction history in days.
/// </summary>
Expand All @@ -20,28 +33,16 @@ public class CreateAgreementRequest
[JsonPropertyName("access_valid_for_days")]
public uint AccessValidForDays { get; set; }

/// <summary>
/// The scope of information that can be accessed.
/// </summary>
[JsonPropertyName("access_scope")]
public List<string> AccessScope { get; set; }

/// <summary>
/// The institution this agreement refers to.
/// </summary>
[JsonPropertyName("institution_id")]
public string InstitutionId { get; set; }

/// <summary>
/// Creates a new instance of <see cref="CreateAgreementRequest" />.
/// </summary>
/// <param name="institutionId">The institution this agreement refers to.</param>
/// <param name="accessScope">The scope of information that can be accessed.</param>
/// <param name="maxHistoricalDays">The length of the transaction history in days.</param>
/// <param name="accessValidForDays">The length the access to the account will be valid for.</param>
/// <param name="accessScope">The scope of information that can be accessed.</param>
/// <param name="institutionId">The institution this agreement refers to.</param>
[JsonConstructor]
public CreateAgreementRequest(uint maxHistoricalDays, uint accessValidForDays, List<string> accessScope,
string institutionId)
public CreateAgreementRequest(string institutionId, List<AccessScope> accessScope, uint maxHistoricalDays = 90,
uint accessValidForDays = 90)
{
MaxHistoricalDays = maxHistoricalDays;
AccessValidForDays = accessValidForDays;
Expand Down
28 changes: 28 additions & 0 deletions src/RobinTTY.NordigenApiClient/Models/Responses/AccessScope.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace RobinTTY.NordigenApiClient.Models.Responses;

/// <summary>
/// Access scopes can be used to limit the access to the 3 major data blocks the GoCardless API is offering.
/// This feature is not supported by all banks, check <see cref="Institution.SupportedFeatures"/> to verify if it is.
/// </summary>
public enum AccessScope
{
/// <summary>
/// An undefined access scope. Assigned if the scope couldn't be matched to any known types.
/// </summary>
Undefined,

/// <summary>
/// Access scope required to access the balances of an account.
/// </summary>
Balances,

/// <summary>
/// Access scope required to access the transactions of an account.
/// </summary>
Transactions,

/// <summary>
/// Access scope needed to access account details.
/// </summary>
Details
}
4 changes: 2 additions & 2 deletions src/RobinTTY.NordigenApiClient/Models/Responses/Agreement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ public class Agreement : CreateAgreementRequest
public Agreement(
uint maxHistoricalDays,
uint accessValidForDays,
List<string> accessScope,
List<AccessScope> accessScope,
string institutionId,
Guid id,
DateTime created,
DateTime? accepted
) : base(maxHistoricalDays, accessValidForDays, accessScope, institutionId)
) : base(institutionId, accessScope, maxHistoricalDays, accessValidForDays)
{
Id = id;
Created = created;
Expand Down

0 comments on commit c71ce83

Please sign in to comment.