Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Complete repository APIs #14

Merged
merged 24 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d94ccc7
chore: add integration tests to the nuget
alirezaeiji Jul 18, 2024
5cef8c4
chore: dummy commit
alirezaeiji Jul 18, 2024
6ab1ee9
chore: correct the integration tests
alirezaeiji Jul 18, 2024
469661b
Merge branch 'refs/heads/master' into feature/DATALM-104307_add_integ…
alirezaeiji Jul 18, 2024
1a85fb6
chore: branch integration tests started
alirezaeiji Jul 18, 2024
d4934cb
chore: remove branch tests
alirezaeiji Jul 18, 2024
0228a87
chore: add class fixture for branch
alirezaeiji Jul 18, 2024
f2bf2c0
chore: correct the integration test for branch creation
alirezaeiji Jul 19, 2024
b282bb7
feat: search repository
alirezaeiji Jul 19, 2024
2bfd86f
chore: refactor integration tests logic
alirezaeiji Jul 19, 2024
7f59aba
Merge branch 'refs/heads/feature/DATALM-104307_add_integration_tests'…
alirezaeiji Jul 19, 2024
5cd377f
chore: add class fixture for repository integration tests
alirezaeiji Jul 19, 2024
287ab7e
feat: add integration test for search repository feature
alirezaeiji Jul 20, 2024
70c5687
feat: add integration tests for the repository api new feature
alirezaeiji Jul 20, 2024
527d821
Merge branch 'refs/heads/master' into feature/complete_repository_apis
alirezaeiji Jul 22, 2024
8f371ca
correct unit tests and integration tests of repository apis; merge wi…
alirezaeiji Jul 22, 2024
0dd93d2
some dummy commit
alirezaeiji Jul 23, 2024
6b770b5
some comments resolved
alirezaeiji Jul 28, 2024
93a1394
some comments resolved
alirezaeiji Jul 28, 2024
4d09dac
some comments resolved
alirezaeiji Jul 28, 2024
6e1b6a3
some comments resolved
alirezaeiji Jul 28, 2024
b879f3a
Merge branch 'refs/heads/master' into feature/complete_repository_apis
alirezaeiji Jul 28, 2024
4c2a148
merge with master
alirezaeiji Jul 28, 2024
e5645d2
correct the build
alirezaeiji Jul 30, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System.Net;
using FluentAssertions;
using FluentValidation;
using Microsoft.Extensions.DependencyInjection;
using Mohaymen.GiteaClient.Gitea.Client.Abstractions;
using Mohaymen.GiteaClient.Gitea.Repository.DeleteRepository.Dto;
using Mohaymen.GiteaClient.IntegrationTests.Common.Assertions.Abstractions;
using Mohaymen.GiteaClient.IntegrationTests.Common.Collections.Gitea;

namespace Mohaymen.GiteaClient.IntegrationTests.Gitea.Repository.DeleteRepository;

[Collection("GiteaIntegrationTests")]
public class DeleteRepositoryTests : IClassFixture<RepositoryClassFixture>
{
private readonly IGiteaClient _sut;
private readonly ITestRepositoryChecker _testRepositoryChecker;
private readonly GiteaCollectionFixture _giteaCollectionFixture;

public DeleteRepositoryTests(GiteaCollectionFixture giteaCollectionFixture)
{
_giteaCollectionFixture = giteaCollectionFixture ?? throw new ArgumentNullException(nameof(giteaCollectionFixture));
_testRepositoryChecker = _giteaCollectionFixture.ServiceProvider.GetRequiredService<ITestRepositoryChecker>();
_sut = _giteaCollectionFixture.ServiceProvider.GetRequiredService<IGiteaClient>();
}

[Fact]
public async Task DeleteRepositoryAsync_ShouldReturnNotContentSuccessResponse_WhenRepositoryExistsAndDeleted()
{
// Arrange
var deletedRepositoryCommandDto = new DeleteRepositoryCommandDto
{
RepositoryName = RepositoryClassFixture.DeleteRepositoryName
};

// Act
var actual = await _sut.RepositoryClient.DeleteRepositoryAsync(deletedRepositoryCommandDto, _giteaCollectionFixture.CancellationToken);

// Assert
actual.StatusCode.Should().Be(HttpStatusCode.NoContent);
var isRepositoryExists = await _testRepositoryChecker.ContainsRepositoryAsync(RepositoryClassFixture.DeleteRepositoryName, _giteaCollectionFixture.CancellationToken);
isRepositoryExists.Should().BeFalse();
}

[Fact]
public async Task DeleteRepositoryAsync_ShouldReturnNotFound_WhenRepositoryDoesNotExist()
{
// Arrange
const string repositoryName = "sampleFakeRepo";
var deletedRepositoryCommandDto = new DeleteRepositoryCommandDto
{
RepositoryName = repositoryName
};

// Act
var actual = await _sut.RepositoryClient.DeleteRepositoryAsync(deletedRepositoryCommandDto, _giteaCollectionFixture.CancellationToken);

// Assert
actual.StatusCode.Should().Be(HttpStatusCode.NotFound);
var isRepositoryExists = await _testRepositoryChecker.ContainsRepositoryAsync(repositoryName, _giteaCollectionFixture.CancellationToken);
isRepositoryExists.Should().BeFalse();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Microsoft.Extensions.DependencyInjection;
using Mohaymen.GiteaClient.IntegrationTests.Common.Collections.Gitea;
using Mohaymen.GiteaClient.IntegrationTests.Common.Initializers.TestData.Abstractions;

namespace Mohaymen.GiteaClient.IntegrationTests.Gitea.Repository;

internal sealed class RepositoryClassFixture : IAsyncLifetime
{
public const string SearchRepositoryName = "SearchUseCaseRepository";
public const string DeleteRepositoryName = "DeleteUseCaseRepository";

private readonly ITestRepositoryCreator _testRepositoryCreator;
private readonly GiteaCollectionFixture _giteaCollectionFixture;

public RepositoryClassFixture(GiteaCollectionFixture giteaCollectionFixture)
{
_giteaCollectionFixture = giteaCollectionFixture ?? throw new ArgumentNullException(nameof(giteaCollectionFixture));
_testRepositoryCreator = giteaCollectionFixture.ServiceProvider.GetRequiredService<ITestRepositoryCreator>();
}

public async Task InitializeAsync()
{
await _testRepositoryCreator.CreateRepositoryAsync(SearchRepositoryName, _giteaCollectionFixture.CancellationToken);
await _testRepositoryCreator.CreateRepositoryAsync(DeleteRepositoryName, _giteaCollectionFixture.CancellationToken);
}

public Task DisposeAsync()
{
return Task.CompletedTask;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System.Net;
using FluentAssertions;
using FluentValidation;
using Microsoft.Extensions.DependencyInjection;
using Mohaymen.GiteaClient.Gitea.Client.Abstractions;
using Mohaymen.GiteaClient.Gitea.Repository.SearchRepository.Dtos;
using Mohaymen.GiteaClient.IntegrationTests.Common.Assertions.Abstractions;
using Mohaymen.GiteaClient.IntegrationTests.Common.Collections.Gitea;

namespace Mohaymen.GiteaClient.IntegrationTests.Gitea.Repository.SearchRepository;

[Collection("GiteaIntegrationTests")]
public class SearchRepositoryTests : IClassFixture<RepositoryClassFixture>
{
private readonly IGiteaClient _sut;
private readonly GiteaCollectionFixture _giteaCollectionFixture;

public SearchRepositoryTests(GiteaCollectionFixture giteaCollectionFixture)
{
_giteaCollectionFixture = giteaCollectionFixture ?? throw new ArgumentNullException(nameof(giteaCollectionFixture));
_sut = giteaCollectionFixture.ServiceProvider.GetRequiredService<IGiteaClient>();

}

[Fact]
public async Task SearchRepositoryAsync_ShouldReturnListOfMatchedRepositories_WhenSearchQueryIsProvidedAndHasMathc()
{
// Arrange
var searchRepositoryQuery = new SearchRepositoryQueryDto
{
Query = "Repo",
Limit = 10,
Page = 1
};

// Act
var actual = await _sut.RepositoryClient.SearchRepositoryAsync(searchRepositoryQuery, _giteaCollectionFixture.CancellationToken);

// Assert
actual.StatusCode.Should().Be(HttpStatusCode.OK);
actual.Content!.SearchResult.Select(x => x.RepositoryName).Should()
AlirezaEijiProgrammer marked this conversation as resolved.
Show resolved Hide resolved
.Contain(RepositoryClassFixture.SearchRepositoryName);
}

[Fact]
public async Task SearchRepositoryAsync_ShouldReturnEmptyList_WhenSearchQueryIsProvidedAndNotMatch()
{
// Arrange
var searchRepositoryQuery = new SearchRepositoryQueryDto
{
Query = "ahmad",
Page = 1,
Limit = 5
};

// Act
var actual = await _sut.RepositoryClient.SearchRepositoryAsync(searchRepositoryQuery, _giteaCollectionFixture.CancellationToken);

// Assert
actual.StatusCode.Should().Be(HttpStatusCode.OK);
actual.Content!.SearchResult.Should().NotBeNull();
actual.Content!.SearchResult.Should().BeEmpty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
using Mohaymen.GiteaClient.Gitea.Repository.Common.Facade.Abstractions;
using Mohaymen.GiteaClient.Gitea.Repository.CreateRepository.Commands;
using Mohaymen.GiteaClient.Gitea.Repository.CreateRepository.Dtos;
using Mohaymen.GiteaClient.Gitea.Repository.DeleteRepository.Commands;
using Mohaymen.GiteaClient.Gitea.Repository.DeleteRepository.Dto;
using Mohaymen.GiteaClient.Gitea.Repository.SearchRepository.Dtos;
using Mohaymen.GiteaClient.Gitea.Repository.SearchRepository.Queries;
using NSubstitute;
using Xunit;

Expand Down Expand Up @@ -40,5 +44,38 @@ await _mediator.Received(1).Send(Arg.Is<CreateRepositoryCommand>(x => x.DefaultB
x.Name == repositoryName &&
x.IsPrivateBranch == true), default);
}


AlirezaEijiProgrammer marked this conversation as resolved.
Show resolved Hide resolved
[Fact]
public async Task SearchRepositoryAsync_ShouldCallSend_WhenEver()
{
// Arrange
const string query = "fakeQuery";
var searchRepositoryQueryDto = new SearchRepositoryQueryDto
{
Query = query
};

// Act
await _sut.SearchRepositoryAsync(searchRepositoryQueryDto, default);

// Assert
await _mediator.Received(1).Send(Arg.Is<SearchRepositoryQuery>(x => x.Query == query));
}

[Fact]
public async Task DeleteRepositoryAsync_ShouldCallSend_WhenEver()
{
// Arrange
const string repositoryName = "fakeRepoName";
var deleteRepositoryCommandDto = new DeleteRepositoryCommandDto
{
RepositoryName = repositoryName
};

// Act
await _sut.DeleteRepositoryAsync(deleteRepositoryCommandDto, default);

// Assert
await _mediator.Received(1).Send(Arg.Is<DeleteRepositoryCommand>(x => x.RepositoryName == repositoryName), default);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using FluentAssertions;
using FluentValidation;
using MediatR;
using Microsoft.Extensions.Options;
using Mohaymen.GiteaClient.Core.Configs;
using Mohaymen.GiteaClient.Gitea.Repository.Common.ApiCall.Abstractions;
using Mohaymen.GiteaClient.Gitea.Repository.DeleteRepository.Commands;
using Mohaymen.GiteaClient.Gitea.Repository.DeleteRepository.Dto;
using NSubstitute;
using Refit;
using Xunit;

namespace Mohaymen.GiteaClient.Tests.Gitea.Repository.DeleteRepository.Commands;

public class DeleteRepositoryCommandHandlerTests
{
private readonly InlineValidator<DeleteRepositoryCommand> _validator;
private readonly IRepositoryRestClient _repositoryRestClient;
private readonly IOptions<GiteaApiConfiguration> _giteaOptions;
private readonly IRequestHandler<DeleteRepositoryCommand, ApiResponse<DeleteRepositoryResponseDto>> _sut;

public DeleteRepositoryCommandHandlerTests()
{
_validator = new InlineValidator<DeleteRepositoryCommand>();
_repositoryRestClient = Substitute.For<IRepositoryRestClient>();
_giteaOptions = Substitute.For<IOptions<GiteaApiConfiguration>>();
_sut = new DeleteRepositoryCommandHandler(_validator, _repositoryRestClient, _giteaOptions);
}

[Fact]
public async Task Handle_ShouldThrowsValidationException_WhenInputIsNotValid()
{
// Arrange
var deleteRepositoryCommand = new DeleteRepositoryCommand
{
RepositoryName = "fakeRepo"
};
_validator.RuleFor(x => x).Must(x => false);

// Act
var actual = async () => await _sut.Handle(deleteRepositoryCommand, default);

// Assert
await actual.Should().ThrowAsync<ValidationException>();
}

[Fact]
public async Task Handle_ShouldCallDeleteRepositoryAsync_WhenInputIsProvidedProperly()
{
// Arrange
const string repositoryName = "fakeRepo";
const string repositoryOwner = "fakeOwner";
var deleteRepositoryCommand = new DeleteRepositoryCommand
{
RepositoryName = repositoryName
};
var giteaConfig = new GiteaApiConfiguration
{
BaseUrl = "fakeUrl",
PersonalAccessToken = "fakeToken",
RepositoriesOwner = repositoryOwner
};
_giteaOptions.Value.Returns(giteaConfig);

// Act
await _sut.Handle(deleteRepositoryCommand, default);

// Assert
await _repositoryRestClient.Received(1).DeleteRepositoryAsync(repositoryOwner, repositoryName);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using FluentAssertions;
using FluentValidation;
using Mohaymen.GiteaClient.Core.Validation;
using Mohaymen.GiteaClient.Gitea.Repository.DeleteRepository.Commands;
using Mohaymen.GiteaClient.Gitea.Repository.DeleteRepository.Validators;
using Xunit;

namespace Mohaymen.GiteaClient.Tests.Gitea.Repository.DeleteRepository.Validators;

public class DeleteRepositoryCommandValidatorTests
{
private readonly IValidator<DeleteRepositoryCommand> _sut;

public DeleteRepositoryCommandValidatorTests()
{
_sut = new DeleteRepositoryCommandValidator();
}

[Theory]
[InlineData("")]
AlirezaEijiProgrammer marked this conversation as resolved.
Show resolved Hide resolved
AlirezaEijiProgrammer marked this conversation as resolved.
Show resolved Hide resolved
[InlineData(null)]
public void Validate_ShouldReturnEmptyRepositoryNameErrorCode_WhenRepositoryNameIsNullOrEmpty(string repositoryName)
{
// Arrange
var deleteRepositoryCommand = new DeleteRepositoryCommand
{
RepositoryName = repositoryName
};

// Act
var actual = _sut.Validate(deleteRepositoryCommand);

// Assert
actual.Errors.Select(x => x.ErrorCode).Should().Contain(ValidationErrorCodes.EmptyRepositoryNameErrorCode);
}

[Fact]
public void Validate_ShouldReturnValidResult_WhenRepositoryNameIsProvidedProperly()
{
// Arrange
var deleteRepositoryCommand = new DeleteRepositoryCommand
{
RepositoryName = "FakeRepositoryName"
};

// Act
var actual = _sut.Validate(deleteRepositoryCommand);

// Assert
actual.IsValid.Should().BeTrue();
}
}
Loading