Skip to content

Commit

Permalink
test: Write/update unit, handler and integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
MH321Productions committed Dec 18, 2024
1 parent ec9b27d commit 9d95c80
Show file tree
Hide file tree
Showing 7 changed files with 273 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,37 @@ User requests multiple Tokens
Scenario Outline: Requesting a list of Tokens in a variety of scenarios
Given Identities i1, i2, i3 and i4
And the following Tokens
| tokenName | tokenOwner | forIdentity | password |
| rt1 | i1 | - | - |
| rt2 | i2 | - | - |
| rt3 | i1 | - | - |
| rt4 | i2 | - | - |
| rt5 | i1 | - | password |
| rt6 | i1 | - | password |
| rt7 | i2 | - | password |
| rt8 | i2 | - | password |
| rt9 | i1 | i1 | - |
| rt10 | i2 | i3 | - |
| rt11 | i2 | i2 | - |
| rt12 | i2 | i3 | - |
| rt13 | i2 | i3 | password |
| rt14 | i2 | i3 | password |
| tokenName | tokenOwner | forIdentity | password | allocatedBy |
| rt1 | i1 | - | - | i2, i3, i4 |
| rt2 | i2 | - | - | i1, i3, i4 |
| rt3 | i1 | - | - | i2, i3, i4 |
| rt4 | i2 | - | - | i1, i3, i4 |
| rt5 | i1 | - | password | i2, i3, i4 |
| rt6 | i1 | - | password | - |
| rt7 | i2 | - | password | i1, i3, i4 |
| rt8 | i2 | - | password | - |
| rt9 | i1 | i1 | - | - |
| rt10 | i2 | i3 | - | i3 |
| rt11 | i2 | i2 | - | - |
| rt12 | i2 | i3 | - | i3 |
| rt13 | i2 | i3 | password | i3 |
| rt14 | i2 | i3 | password | - |
When <activeIdentity> sends a GET request to the /Tokens endpoint with the following payloads
| tokenName | passwordOnGet |
| rt1 | - |
| rt2 | - |
| rt3 | password |
| rt4 | password |
| rt5 | password |
| rt6 | - |
| rt7 | password |
| rt8 | - |
| rt9 | - |
| rt10 | - |
| rt11 | - |
| rt12 | - |
| rt13 | password |
| rt14 | wordpass |
| tokenName |
| rt1 |
| rt2 |
| rt3 |
| rt4 |
| rt5 |
| rt6 |
| rt7 |
| rt8 |
| rt9 |
| rt10 |
| rt11 |
| rt12 |
| rt13 |
| rt14 |
Then the response status code is 200 (OK)
And the response contains Token(s) <retreivedTokens>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,46 @@ Feature: GET /Tokens/{id}

User requests a Token

Scenario Outline: Requesting a Token in a variety of scenarios
Given Identities <givenIdentities>
And Token t created by <tokenOwner> with password "<password>" and forIdentity <forIdentity>
When <activeIdentity> sends a GET request to the /Tokens/t.Id endpoint with password "<passwordOnGet>"
Then the response status code is <responseStatusCode>
Scenario Outline: Requesting a Token in a variety of scenarios
Given Identities <givenIdentities>
And Token t created by <tokenOwner> with password "<password>" and forIdentity <forIdentity>
When <activeIdentity> sends a GET request to the /Tokens/t.Id endpoint with password "<passwordOnGet>"
Then the response status code is <responseStatusCode>

Examples:
| givenIdentities | tokenOwner | forIdentity | password | activeIdentity | passwordOnGet | responseStatusCode | description |
| i | i | - | - | i | - | 200 (OK) | owner tries to get |
| i1 and i2 | i1 | - | - | i2 | - | 200 (OK) | non-owner tries to get |
| i | i | - | - | - | - | 200 (OK) | anonymous user tries to get |
| i | i | - | - | i | password | 200 (OK) | owner passes password even though none is set |
| i1 and i2 | i1 | - | - | i2 | password | 200 (OK) | non-owner identity passes password even though none is set |
| i | i | - | - | - | password | 200 (OK) | anonymous user passes password even though none is set |
| i | i | - | password | i | password | 200 (OK) | owner passes correct password |
| i | i | - | password | i | - | 200 (OK) | owner doesn't pass password, even though one is set |
| i1 and i2 | i1 | - | password | i2 | password | 200 (OK) | non-owner identity passes correct password |
| i1 and i2 | i1 | - | password | i2 | - | 404 (Not Found) | non-owner identity passes no password even though one is set |
| i | i | - | password | - | password | 200 (OK) | anonymous user passes correct password |
| i | i | - | password | - | - | 404 (Not Found) | anonymous user doesn't pass password, even though one is set |
| i | i | i | - | i | - | 200 (OK) | owner is forIdentity and tries to get |
| i1 and i2 | i1 | i2 | - | i1 | - | 200 (OK) | non-owner is forIdentity, creator tries to get |
| i1 and i2 | i1 | i1 | - | i2 | - | 404 (Not Found) | owner is forIdentity and non-owner tries to get |
| i | i | i | - | - | - | 404 (Not Found) | owner is forIdentity and anonymous user tries to get |
| i1 and i2 | i1 | i2 | - | i2 | - | 200 (OK) | non-owner is forIdentity and tries to get |
| i | i | i | - | - | - | 404 (Not Found) | forIdentity is set and anonymous user tries to get |
| i1 and i2 | i1 | i2 | password | i2 | password | 200 (OK) | non-owner is forIdentity and tries to get with correct password |
| i1 and i2 | i1 | i2 | password | i2 | wordpass | 404 (Not Found) | non-owner is forIdentity and tries to get with incorrect password |
| i1, i2 and i3 | i1 | i2 | password | i3 | password | 404 (Not Found) | non-owner is forIdentity, and thirdParty tries to get |
| i1 and i2 | i1 | i2 | password | - | password | 404 (Not Found) | non-owner is forIdentity, and anonymous user tries to get |
Examples:
| givenIdentities | tokenOwner | forIdentity | password | activeIdentity | passwordOnGet | responseStatusCode | description |
| i | i | - | - | i | - | 200 (OK) | owner tries to get |
| i1 and i2 | i1 | - | - | i2 | - | 200 (OK) | non-owner tries to get |
| i | i | - | - | - | - | 200 (OK) | anonymous user tries to get |
| i | i | - | - | i | password | 200 (OK) | owner passes password even though none is set |
| i1 and i2 | i1 | - | - | i2 | password | 200 (OK) | non-owner identity passes password even though none is set |
| i | i | - | - | - | password | 200 (OK) | anonymous user passes password even though none is set |
| i | i | - | password | i | password | 200 (OK) | owner passes correct password |
| i | i | - | password | i | - | 200 (OK) | owner doesn't pass password, even though one is set |
| i1 and i2 | i1 | - | password | i2 | password | 200 (OK) | non-owner identity passes correct password |
| i1 and i2 | i1 | - | password | i2 | - | 404 (Not Found) | non-owner identity passes no password even though one is set |
| i | i | - | password | - | password | 200 (OK) | anonymous user passes correct password |
| i | i | - | password | - | - | 404 (Not Found) | anonymous user doesn't pass password, even though one is set |
| i | i | i | - | i | - | 200 (OK) | owner is forIdentity and tries to get |
| i1 and i2 | i1 | i2 | - | i1 | - | 200 (OK) | non-owner is forIdentity, creator tries to get |
| i1 and i2 | i1 | i1 | - | i2 | - | 404 (Not Found) | owner is forIdentity and non-owner tries to get |
| i | i | i | - | - | - | 404 (Not Found) | owner is forIdentity and anonymous user tries to get |
| i1 and i2 | i1 | i2 | - | i2 | - | 200 (OK) | non-owner is forIdentity and tries to get |
| i | i | i | - | - | - | 404 (Not Found) | forIdentity is set and anonymous user tries to get |
| i1 and i2 | i1 | i2 | password | i2 | password | 200 (OK) | non-owner is forIdentity and tries to get with correct password |
| i1 and i2 | i1 | i2 | password | i2 | wordpass | 404 (Not Found) | non-owner is forIdentity and tries to get with incorrect password |
| i1, i2 and i3 | i1 | i2 | password | i3 | password | 404 (Not Found) | non-owner is forIdentity, and thirdParty tries to get |
| i1 and i2 | i1 | i2 | password | - | password | 404 (Not Found) | non-owner is forIdentity, and anonymous user tries to get |

Scenario: A Token owner can access a locked token
Given Identity i
And locked Token t created by i with password password
When i sends a GET request to the /Tokens/t.Id endpoint
Then the response status code is 200 (OK)

Scenario: A Non-owner identity can access a locked token, when it has an allocation
Given Identities i1, i2
And almost locked Token t created by i1 with password password and allocated by i2
When t gets locked
And i2 sends a GET request to the /Tokens/t.Id endpoint
Then the response status code is 200 (OK)
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Text;
using Backbone.BuildingBlocks.SDK.Endpoints.Common.Types;
using Backbone.ConsumerApi.Sdk.Endpoints.Tokens.Types.Requests;
using Backbone.ConsumerApi.Sdk.Endpoints.Tokens.Types.Responses;
using Backbone.ConsumerApi.Tests.Integration.Contexts;
using Backbone.ConsumerApi.Tests.Integration.Helpers;
using Microsoft.AspNetCore.Http.HttpResults;
using TechTalk.SpecFlow.Assist;

namespace Backbone.ConsumerApi.Tests.Integration.StepDefinitions;
Expand Down Expand Up @@ -67,14 +69,63 @@ public async Task GivenTheFollowingTokens(Table table)
var client = _clientPool.FirstForIdentityName(tokenProperties.TokenOwner);
var forClient = tokenProperties.ForIdentity != "-" ? _clientPool.FirstForIdentityName(tokenProperties.ForIdentity).IdentityData!.Address : null;
var password = tokenProperties.Password.Trim() != "-" ? Convert.FromBase64String(tokenProperties.Password.Trim()) : null;
var allocatedBy = tokenProperties.AllocatedBy.Trim() != "-" ? tokenProperties.AllocatedBy.Split(",").Select(s => s.Trim()).ToList() : [];

var response = await client.Tokens
.CreateToken(new CreateTokenRequest { Content = TestData.SOME_BYTES, ExpiresAt = TOMORROW, ForIdentity = forClient, Password = password });

_tokensContext.CreateTokenResponses[tokenProperties.TokenName] = response.Result!;

foreach (var allocatedIdentityName in allocatedBy)
{
var allocatedClient = _clientPool.FirstForIdentityName(allocatedIdentityName);
var allocatedResponse = password != null ? await allocatedClient.Tokens.GetToken(response.Result!.Id, password) : await allocatedClient.Tokens.GetToken(response.Result!.Id);
allocatedResponse.Status.Should().Be(HttpStatusCode.OK);
}
}
}

[Given($@"locked Token {RegexFor.SINGLE_THING} created by {RegexFor.SINGLE_THING} with password {RegexFor.SINGLE_THING}")]
public async Task GivenALockedTokenCreatedByIdentityWithPassword(string tokenName, string identityName, string password)
{
var client = _clientPool.FirstForIdentityName(identityName);
var passwordData = Convert.FromBase64String(password.Trim());

var response = await client.Tokens.CreateToken(
new CreateTokenRequest { Content = TestData.SOME_BYTES, ExpiresAt = TOMORROW, ForIdentity = null, Password = passwordData });

_tokensContext.CreateTokenResponses[tokenName] = response.Result!;

await SendInvalidPasswordsToToken(tokenName, 100);
}

[Given($@"almost locked Token {RegexFor.SINGLE_THING} created by {RegexFor.SINGLE_THING} with password {RegexFor.SINGLE_THING} and allocated by {RegexFor.SINGLE_THING}")]
public async Task GivenAnAlmostLockedTokenCreatedByIdentityWithPassword(string tokenName, string identityName, string password, string allocatedIdentityName)
{
var client = _clientPool.FirstForIdentityName(identityName);
var passwordData = Convert.FromBase64String(password.Trim());

var response = await client.Tokens.CreateToken(
new CreateTokenRequest { Content = TestData.SOME_BYTES, ExpiresAt = TOMORROW, ForIdentity = null, Password = passwordData });

_tokensContext.CreateTokenResponses[tokenName] = response.Result!;

var allocatorClient = _clientPool.FirstForIdentityName(allocatedIdentityName);
var allocatorResponse = await allocatorClient.Tokens.GetToken(response.Result!.Id, passwordData);
allocatorResponse.Status.Should().Be(HttpStatusCode.OK);

await SendInvalidPasswordsToToken(tokenName, 99);
}

private async Task SendInvalidPasswordsToToken(string tokenName, int numberOfInvalidRequests)
{
var client = _clientPool.Anonymous;
var token = _tokensContext.CreateTokenResponses[tokenName];

for (var i = 0; i < numberOfInvalidRequests; i++)
await client.Tokens.GetTokenUnauthenticated(token.Id);
}

#endregion

#region When
Expand Down Expand Up @@ -151,9 +202,8 @@ public async Task WhenISendsAGETRequestToTheTokensEndpointWithTheFollowingPayloa
var queryItems = getRequestPayloadSet.Select(payload =>
{
var tokenId = _tokensContext.CreateTokenResponses[payload.TokenName].Id;
var password = payload.PasswordOnGet == "-" ? null : Convert.FromBase64String(payload.PasswordOnGet.Trim());

return new ListTokensQueryItem() { Id = tokenId, Password = password };
return new ListTokensQueryItem { Id = tokenId };
}).ToList();

_responseContext.WhenResponse = _listTokensResponse = await client.Tokens.ListTokens(queryItems);
Expand All @@ -168,6 +218,12 @@ public async Task WhenISendsADeleteRequestToTheTokensIdEndpoint(string identityN
_responseContext.WhenResponse = await client.Tokens.DeleteToken(tokenId);
}

[When($@"{RegexFor.SINGLE_THING} gets locked")]
public async Task WhenTokenGetsLocked(string tokenName)
{
await SendInvalidPasswordsToToken(tokenName, 1);
}

#endregion

#region Then
Expand All @@ -190,12 +246,12 @@ file class TokenProperties
public required string TokenOwner { get; set; }
public required string ForIdentity { get; set; }
public required string Password { get; set; }
public required string AllocatedBy { get; set; }
}

// ReSharper disable once ClassNeverInstantiated.Local
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")]
file class GetRequestPayload
{
public required string TokenName { get; set; }
public required string PasswordOnGet { get; set; }
}
Loading

0 comments on commit 9d95c80

Please sign in to comment.