Skip to content
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
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: 1 addition & 0 deletions .github/instructions/csharp.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ applyTo: '**/*.cs'
- Use pattern matching and switch expressions wherever possible.
- Use `nameof` instead of string literals when referring to member names.
- Ensure that XML doc comments are created for any public APIs. When applicable, include `<example>` and `<code>` documentation in the comments.
- Use simplified `new()` expressions when the type is evident from the declaration (e.g., `List<string> items = new();` instead of `List<string> items = new List<string>();`) to prevent IDE0090 warnings.

## Project Setup and Structure

Expand Down
453 changes: 453 additions & 0 deletions .github/instructions/meziantou-analyzer-rules.instructions.md

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions Client.Tests/BaseTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ protected BaseTest()
// Initialize SiteState with proper data
var siteState = new SiteState();
TestContext.Services.AddSingleton(siteState);

TestContext.Services.AddLogging();

TestContext.Services.AddScoped<ILogService, MockLogService>();
TestContext.Services.AddScoped<ISampleModuleService, MockSampleModuleService>();
TestContext.Services.AddScoped<ICategoryService, MockCategoryService>();
TestContext.Services.AddScoped<IUserService, MockUserService>();
TestContext.Services.AddScoped<ISettingService, MockSettingService>();
TestContext.Services.AddScoped<IModuleService, MockModuleService>();
Expand All @@ -56,7 +57,7 @@ protected BaseTest()
TestContext.Services.AddScoped<IThemeService, MockThemeService>();
TestContext.Services.AddScoped<IModuleDefinitionService, MockModuleDefinitionService>();
TestContext.Services.AddScoped<Microsoft.AspNetCore.Authorization.IAuthorizationService, MockAuthorizationService>();

// Add authentication state provider
TestContext.Services.AddScoped<Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider, MockAuthenticationStateProvider>();

Expand Down
205 changes: 205 additions & 0 deletions Client.Tests/Mocks/MockCategoryService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
// Licensed to ICTAce under the MIT license.

namespace ICTAce.FileHub.Client.Tests.Mocks;

public class MockCategoryService : ICategoryService
{
private readonly List<GetCategoryDto> _categories = [];
private int _nextId = 1;

public MockCategoryService()
{
_categories.Add(new GetCategoryDto
{
Id = 1,
ModuleId = 1,
Name = "Test Category 1",
ViewOrder = 0,
ParentId = 0,
CreatedBy = "Test User",
CreatedOn = DateTime.Now.AddDays(-10),
ModifiedBy = "Test User",
ModifiedOn = DateTime.Now.AddDays(-5)
});

_categories.Add(new GetCategoryDto
{
Id = 2,
ModuleId = 1,
Name = "Test Category 2",
ViewOrder = 1,
ParentId = 0,
CreatedBy = "Test User",
CreatedOn = DateTime.Now.AddDays(-8),
ModifiedBy = "Test User",
ModifiedOn = DateTime.Now.AddDays(-3)
});

_categories.Add(new GetCategoryDto
{
Id = 3,
ModuleId = 1,
Name = "Test Category 1.1",
ViewOrder = 0,
ParentId = 1,
CreatedBy = "Test User",
CreatedOn = DateTime.Now.AddDays(-7),
ModifiedBy = "Test User",
ModifiedOn = DateTime.Now.AddDays(-2)
});

_nextId = 4;
}

public Task<GetCategoryDto> GetAsync(int id, int moduleId)
{
var category = _categories.FirstOrDefault(c => c.Id == id && c.ModuleId == moduleId);
if (category == null)
{
throw new InvalidOperationException($"Category with Id {id} and ModuleId {moduleId} not found");
}
return Task.FromResult(category);
}

public Task<PagedResult<ListCategoryDto>> ListAsync(int moduleId, int pageNumber = 1, int pageSize = 10)
{
var items = _categories
.Where(c => c.ModuleId == moduleId)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.Select(c => new ListCategoryDto
{
Id = c.Id,
Name = c.Name,
ViewOrder = c.ViewOrder,
ParentId = c.ParentId,
Children = []
})
.ToList();

var totalCount = _categories.Count(c => c.ModuleId == moduleId);

var pagedResult = new PagedResult<ListCategoryDto>
{
Items = items,
TotalCount = totalCount,
PageNumber = pageNumber,
PageSize = pageSize
};

return Task.FromResult(pagedResult);
}

public Task<int> CreateAsync(int moduleId, CreateAndUpdateCategoryDto dto)
{
var newCategory = new GetCategoryDto
{
Id = _nextId++,
ModuleId = moduleId,
Name = dto.Name,
ViewOrder = dto.ViewOrder,
ParentId = dto.ParentId,
CreatedBy = "Test User",
CreatedOn = DateTime.Now,
ModifiedBy = "Test User",
ModifiedOn = DateTime.Now
};

_categories.Add(newCategory);
return Task.FromResult(newCategory.Id);
}

public Task<int> UpdateAsync(int id, int moduleId, CreateAndUpdateCategoryDto dto)
{
var category = _categories.FirstOrDefault(c => c.Id == id && c.ModuleId == moduleId);
if (category == null)
{
throw new InvalidOperationException($"Category with Id {id} and ModuleId {moduleId} not found");
}

category.Name = dto.Name;
category.ViewOrder = dto.ViewOrder;
category.ParentId = dto.ParentId;
category.ModifiedBy = "Test User";
category.ModifiedOn = DateTime.Now;

return Task.FromResult(category.Id);
}

public Task DeleteAsync(int id, int moduleId)
{
var category = _categories.FirstOrDefault(c => c.Id == id && c.ModuleId == moduleId);
if (category != null)
{
_categories.Remove(category);
}
return Task.CompletedTask;
}

public Task<int> MoveUpAsync(int id, int moduleId)
{
var category = _categories.FirstOrDefault(c => c.Id == id && c.ModuleId == moduleId);
if (category == null)
{
return Task.FromResult(-1);
}

var siblings = _categories
.Where(c => c.ModuleId == moduleId && c.ParentId == category.ParentId)
.OrderBy(c => c.ViewOrder)
.ToList();

var currentIndex = siblings.IndexOf(category);
if (currentIndex > 0)
{
var previous = siblings[currentIndex - 1];
(category.ViewOrder, previous.ViewOrder) = (previous.ViewOrder, category.ViewOrder);
}

return Task.FromResult(category.Id);
}

public Task<int> MoveDownAsync(int id, int moduleId)
{
var category = _categories.FirstOrDefault(c => c.Id == id && c.ModuleId == moduleId);
if (category == null)
{
return Task.FromResult(-1);
}

var siblings = _categories
.Where(c => c.ModuleId == moduleId && c.ParentId == category.ParentId)
.OrderBy(c => c.ViewOrder)
.ToList();

var currentIndex = siblings.IndexOf(category);
if (currentIndex >= 0 && currentIndex < siblings.Count - 1)
{
var next = siblings[currentIndex + 1];
(category.ViewOrder, next.ViewOrder) = (next.ViewOrder, category.ViewOrder);
}

return Task.FromResult(category.Id);
}

public void ClearData()
{
_categories.Clear();
_nextId = 1;
}

public void AddTestData(GetCategoryDto category)
{
_categories.Add(category);
}

public int GetCategoryCount()
{
return _categories.Count;
}

public List<GetCategoryDto> GetAllCategories()
{
return _categories;
}
}
6 changes: 3 additions & 3 deletions Client.Tests/Mocks/MockLogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class MockLogService : ILogService

public Task<Log> GetLogAsync(int logId) => Task.FromResult(new Log());

public Task<List<Log>> GetLogsAsync(int siteId, string level, string function, int rows)
public Task<List<Log>> GetLogsAsync(int siteId, string level, string function, int rows)
=> Task.FromResult(new List<Log>());

public Task Log(int? pageId, int? moduleId, int? userId, string category, string feature, LogFunction function, Oqtane.Shared.LogLevel level, Exception? exception, string message, params object[] args)
Expand All @@ -41,7 +41,7 @@ public Task Log(int? pageId, int? moduleId, int? userId, string category, string
Args = args,
Timestamp = DateTime.UtcNow
});

return Task.CompletedTask;
}

Expand All @@ -62,7 +62,7 @@ public Task Log(Alias? alias, int? pageId, int? moduleId, int? userId, string ca
Args = args,
Timestamp = DateTime.UtcNow
});

return Task.CompletedTask;
}

Expand Down
Loading