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
51 changes: 48 additions & 3 deletions NGitLab.Mock.Tests/TagTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public async Task GetTagAsync()
.WithUser("user1", isDefault: true)
.WithProject("test-project", id: 1, addDefaultUserAsMaintainer: true, configure: project => project
.WithCommit("Initial commit")
.WithCommit("Changes with tag", tags: new[] { "1.0.0" }))
.WithCommit("Changes with tag", tags: ["1.0.0"]))
.BuildServer();

var client = server.CreateClient();
Expand All @@ -32,7 +32,7 @@ public async Task GetTagAsync()
}

[Theory]
public void GetTaskAsync_CanSortByName([Values] bool useDefault)
public void GetTagsAsync_CanSortByName([Values] bool useDefault)
{
// Arrange
using var server = new GitLabConfig()
Expand Down Expand Up @@ -61,7 +61,7 @@ public void GetTaskAsync_CanSortByName([Values] bool useDefault)
}

[Test]
public void GetTagAsync_CanSortByVersion()
public void GetTagsAsync_CanSortByVersion()
{
// Arrange
using var server = new GitLabConfig()
Expand All @@ -88,4 +88,49 @@ public void GetTagAsync_CanSortByVersion()
// Assert
Assert.That(tags.AsEnumerable().Select(t => t.Name), Is.EqualTo(["not-semver", "0.0.1", "0.0.2", "0.0.10"]));
}

[Test]
public async Task SearchTags()
{
// Arrange
using var server = new GitLabConfig()
.WithUser("user1", isDefault: true)
.WithProject("test-project", id: 1, addDefaultUserAsMaintainer: true, configure: project => project
.WithCommit("First Tag", tags: ["v0.5"])
.WithCommit("Second Tag", tags: ["v0.6"]))
.BuildServer();

var client = server.CreateClient();
var tagClient = client.GetRepository(1).Tags;

(string, int)[] testCases =
[
// You can use "^term" and "term$" to find tags that begin and end with "term". No other regular expressions are supported.
// The search expression is case-insensitive.
// https://docs.gitlab.com/api/tags/#list-all-project-repository-tags
("^v0.5", 1),
("^v0", 2),
("^v", 2),
("^V", 2),
("^v1", 0),
("0.5", 1),
("0", 2),
("6", 1),
("V", 2),
("0.5$", 1),
(".5$", 1),
("\\.5$", 0),
(".[0-9]$", 0),
("0\\.", 0),
];

foreach (var (searchExpression, expectedCount) in testCases)
{
// Act
var tags = tagClient.GetAsync(new TagQuery { Search = searchExpression });

// Assert
Assert.That(tags.Count(), Is.EqualTo(expectedCount), $"Expected search expression '{searchExpression}' to return {expectedCount} results.");
}
}
}
23 changes: 19 additions & 4 deletions NGitLab.Mock/Clients/TagClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,27 +86,42 @@ public Tag ToTagClient(LibGit2Sharp.Tag tag)
using (Context.BeginOperationScope())
{
IEnumerable<LibGit2Sharp.Tag> result = GetProject(_projectId, ProjectPermission.View).Repository.GetTags();
if (query != null)
if (query is not null)
{
result = ApplyQuery(result, query.OrderBy, query.Sort);
result = ApplyQuery(result, query);
}

return GitLabCollectionResponse.Create(result.Select(ToTagClient).ToArray());
}

static IEnumerable<LibGit2Sharp.Tag> ApplyQuery(IEnumerable<LibGit2Sharp.Tag> tags, string orderBy, string direction)
static IEnumerable<LibGit2Sharp.Tag> ApplyQuery(IEnumerable<LibGit2Sharp.Tag> tags, TagQuery query)
{
// First, filter by search term if provided
if (!string.IsNullOrEmpty(query.Search))
{
tags = query.Search switch
{
string search when search.StartsWith("^", StringComparison.Ordinal) =>
tags.Where(t => t.FriendlyName.StartsWith(search[1..], StringComparison.OrdinalIgnoreCase)),
string search when search.EndsWith("$", StringComparison.Ordinal) =>
tags.Where(t => t.FriendlyName.EndsWith(search[..^1], StringComparison.OrdinalIgnoreCase)),
_ => tags.Where(t => t.FriendlyName.Contains(query.Search, StringComparison.OrdinalIgnoreCase)),
};
}

var orderBy = query.OrderBy?.ToLowerInvariant();
tags = orderBy switch
{
"name" => tags.OrderBy(t => t.FriendlyName, StringComparer.Ordinal),
"version" => tags.OrderBy(t => t.FriendlyName, SemanticVersionComparer.Instance),
null => tags,

// LibGitSharp does not really expose tag creation time, so hard to sort using that annotation,
"updated" => throw new NotSupportedException("Sorting by 'updated' is not supported since the info is not available in LibGit2Sharp."),
"updated" => throw new NotSupportedException("Sorting by 'updated' is not supported by mock, since the info is not available in LibGit2Sharp."),
_ => throw new NotSupportedException($"Sorting by '{orderBy}' is not supported."),
};

var direction = query.Sort;
if (string.IsNullOrEmpty(direction))
direction = "desc";

Expand Down
43 changes: 31 additions & 12 deletions NGitLab.Tests/TagTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,8 @@ public async Task Test_can_tag_a_project()
}

[NGitLabRetry]
[TestCase("^v0.5", 1)]
[TestCase("^v0", 2)]
[TestCase("^v1", 0)]
[TestCase("v1", 0)]
[TestCase("0.5$", 1)]
[TestCase("0\\.", 0)]
[TestCase(".5$", 1)]
[TestCase("\\.5$", 0)]
[TestCase(".[0-9]$", 0)]
public async Task SearchTags(string search, int expectedCount)
[Test]
public async Task SearchTags()
{
// Arrange
using var context = await GitLabTestContext.CreateAsync();
Expand All @@ -64,8 +56,35 @@ public async Task SearchTags(string search, int expectedCount)
Ref = project.DefaultBranch,
});

var tagFetched = tagClient.GetAsync(new TagQuery { Search = search });
Assert.That(tagFetched.Count(), Is.EqualTo(expectedCount));
(string, int)[] testCases =
[
// You can use "^term" and "term$" to find tags that begin and end with "term". No other regular expressions are supported.
// The search expression is case-insensitive.
// https://docs.gitlab.com/api/tags/#list-all-project-repository-tags
("^v0.5", 1),
("^v0", 2),
("^v", 2),
("^V", 2),
("^v1", 0),
("0.5", 1),
("0", 2),
("6", 1),
("V", 2),
("0.5$", 1),
(".5$", 1),
("\\.5$", 0),
(".[0-9]$", 0),
("0\\.", 0),
];

foreach (var (searchExpression, expectedCount) in testCases)
{
// Act
var tags = tagClient.GetAsync(new TagQuery { Search = searchExpression });

// Assert
Assert.That(tags.Count(), Is.EqualTo(expectedCount), $"Expected search expression '{searchExpression}' to return {expectedCount} results.");
}
}

[NGitLabRetry]
Expand Down
Loading