-
Notifications
You must be signed in to change notification settings - Fork 11
#108 Refactor CrystaTask to service interface; add test fakes #109
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
Conversation
Replaced ICrystaTaskRepository with ICrystaTaskService across the codebase, updating all usages and DI registrations. Introduced CrystaTaskServiceFake for in-memory testing and updated AzureBoardSyncServiceTests to use fakes. Adjusted CrystaProgramSyncModuleServiceFake to accept configuration. Added src.sln for Visual Studio project structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR refactors the CrystaTask data access layer from a repository pattern to a service interface pattern. The refactoring renames ICrystaTaskRepository to ICrystaTaskService and introduces a fake implementation (CrystaTaskServiceFake) for in-memory testing. Additionally, the CrystaProgramSyncModuleServiceFake is updated to use constructor-based dependency injection instead of the [AutoInject] attribute.
Key changes:
- Renamed
ICrystaTaskRepositorytoICrystaTaskServiceacross all implementations and usages - Introduced
CrystaTaskServiceFakewith in-memory storage for testing scenarios - Updated all test fixtures to use the new fake implementations
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Core/CrystaLearn.Core/Services/Sync/AzureBoardSyncService.cs | Updated all references from ICrystaTaskRepository to ICrystaTaskService |
| src/Core/CrystaLearn.Core/Services/CrystaTaskServiceFake.cs | New fake implementation providing in-memory storage for testing |
| src/Core/CrystaLearn.Core/Services/CrystaTaskService.cs | Renamed class from CrystaTaskRepository to CrystaTaskService |
| src/Core/CrystaLearn.Core/Services/CrystaProgramSyncModuleServiceFake.cs | Replaced [AutoInject] with constructor injection and fixed formatting |
| src/Core/CrystaLearn.Core/Services/Contracts/ICrystaTaskService.cs | Renamed interface from ICrystaTaskRepository to ICrystaTaskService |
| src/Core/CrystaLearn.Core/Extensions/ApplicationBuilderExtensions.cs | Updated DI registration for the renamed service |
| src/Core/CrystaLearn.Core.Test/Sync/AzureBoardSyncServiceTests.cs | Updated tests to use fake services and removed commented-out notes |
| { | ||
| if (ids == null || ids.Count == 0) return Task.FromResult(new List<SyncItem>()); | ||
| var found = _comments | ||
| .Where(c => (c.Revision != null && ids.Contains(c.Revision)) || (c.ProviderTaskId != null && ids.Contains(c.ProviderTaskId)) || (c.Id != Guid.Empty && ids.Contains(c.Id.ToString()))) |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The query logic does not match the real implementation. The real implementation in CrystaTaskService.cs (line 41) filters by SyncInfo.SyncId, but this fake implementation filters by Revision, ProviderTaskId, or Id. The input 'ids' parameter contains SyncId values from SyncInfo, not these other properties. This means the fake will fail to find matching comments when they should exist, causing incorrect sync behavior in tests.
| .Where(c => (c.Revision != null && ids.Contains(c.Revision)) || (c.ProviderTaskId != null && ids.Contains(c.ProviderTaskId)) || (c.Id != Guid.Empty && ids.Contains(c.Id.ToString()))) | |
| .Where(c => c.SyncId != null && ids.Contains(c.SyncId)) |
| var found = _revisions | ||
| .Where(r => (r.Revision != null && ids.Contains(r.Revision)) || (r.ProviderTaskId != null && ids.Contains(r.ProviderTaskId)) || (r.Id != Guid.Empty && ids.Contains(r.Id.ToString()))) | ||
| .Select(r => new SyncItem { Id = r.Id }) |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The query logic does not match the real implementation. The real implementation in CrystaTaskService.cs (line 81) filters by WorkItemSyncInfo.SyncId, but this fake implementation filters by Revision, ProviderTaskId, or Id. The input 'ids' parameter contains SyncId values from WorkItemSyncInfo, not these other properties. This means the fake will fail to find matching revisions when they should exist, causing incorrect sync behavior in tests.
| private static List<CrystaProgramSyncModule> _modules = new(); | ||
|
|
||
| [AutoInject] private IConfiguration Configuration { get; set; } = default!; | ||
| private IConfiguration Configuration { get; set; } = default!; |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's an extra leading space before the 'private' keyword. This should be removed to maintain consistent indentation throughout the codebase.
| private IConfiguration Configuration { get; set; } = default!; | |
| private IConfiguration Configuration { get; set; } = default!; |
| if (ids == null || ids.Count == 0) return Task.FromResult(new List<SyncItem>()); | ||
| var found = _revisions | ||
| .Where(r => (r.Revision != null && ids.Contains(r.Revision)) || (r.ProviderTaskId != null && ids.Contains(r.ProviderTaskId)) || (r.Id != Guid.Empty && ids.Contains(r.Id.ToString()))) | ||
| .Select(r => new SyncItem { Id = r.Id }) |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The returned SyncItem objects are missing the SyncInfo property. Looking at the real implementation in CrystaTaskService.cs, GetRevisionsSyncItemsAsync should populate SyncInfo from the revision's WorkItemSyncInfo property. The current implementation only sets the Id field, but the calling code in AzureBoardSyncService expects SyncInfo.SyncId and SyncInfo.ContentHash to be populated for sync comparison logic (lines 512, 519 in AzureBoardSyncService.cs). This will cause sync operations to fail or behave incorrectly when using the fake.
| .Select(r => new SyncItem { Id = r.Id }) | |
| .Select(r => new SyncItem { Id = r.Id, SyncInfo = r.WorkItemSyncInfo }) |
| if (ids == null || ids.Count == 0) return Task.FromResult(new List<SyncItem>()); | ||
| var found = _updates | ||
| .Where(u => (u.Revision != null && ids.Contains(u.Revision)) || (u.ProviderTaskId != null && ids.Contains(u.ProviderTaskId)) || (u.Id != Guid.Empty && ids.Contains(u.Id.ToString()))) | ||
| .Select(u => new SyncItem { Id = u.Id }) |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The returned SyncItem objects are missing the SyncInfo property. Looking at the real implementation in CrystaTaskService.cs, GetUpdatesSyncItemsAsync should populate SyncInfo from the update's SyncInfo property. The current implementation only sets the Id field, but the calling code in AzureBoardSyncService expects SyncInfo.SyncId and SyncInfo.ContentHash to be populated for sync comparison logic (lines 263, 270 in AzureBoardSyncService.cs). This will cause sync operations to fail or behave incorrectly when using the fake.
| .Select(u => new SyncItem { Id = u.Id }) | |
| .Select(u => new SyncItem { Id = u.Id, SyncInfo = u.SyncInfo }) |
| var found = _tasks | ||
| .Where(t => (t.ProviderTaskId != null && ids.Contains(t.ProviderTaskId)) || (t.Id != Guid.Empty && ids.Contains(t.Id.ToString()))) | ||
| .Select(t => new SyncItem { Id = t.Id }) |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The query logic does not match the real implementation. The real implementation in CrystaTaskService.cs (line 22) filters by WorkItemSyncInfo.SyncId, but this fake implementation filters by ProviderTaskId or Id. The input 'ids' parameter contains SyncId values (formatted as SyncInfo.SyncId), not ProviderTaskId values. This means the fake will fail to find matching tasks when they should exist, causing incorrect sync behavior in tests.
| var found = _updates | ||
| .Where(u => (u.Revision != null && ids.Contains(u.Revision)) || (u.ProviderTaskId != null && ids.Contains(u.ProviderTaskId)) || (u.Id != Guid.Empty && ids.Contains(u.Id.ToString()))) | ||
| .Select(u => new SyncItem { Id = u.Id }) |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The query logic does not match the real implementation. The real implementation in CrystaTaskService.cs (line 61) filters by SyncInfo.SyncId, but this fake implementation filters by Revision, ProviderTaskId, or Id. The input 'ids' parameter contains SyncId values from SyncInfo, not these other properties. This means the fake will fail to find matching updates when they should exist, causing incorrect sync behavior in tests.
| if (ids == null || ids.Count == 0) return Task.FromResult(new List<SyncItem>()); | ||
| var found = _comments | ||
| .Where(c => (c.Revision != null && ids.Contains(c.Revision)) || (c.ProviderTaskId != null && ids.Contains(c.ProviderTaskId)) || (c.Id != Guid.Empty && ids.Contains(c.Id.ToString()))) | ||
| .Select(c => new SyncItem { Id = c.Id }) |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The returned SyncItem objects are missing the SyncInfo property. Looking at the real implementation in CrystaTaskService.cs, GetCommentsSyncItemsAsync should populate SyncInfo from the comment's SyncInfo property. The current implementation only sets the Id field, but the calling code in AzureBoardSyncService expects SyncInfo.SyncId and SyncInfo.ContentHash to be populated for sync comparison logic (lines 263, 270 in AzureBoardSyncService.cs). This will cause sync operations to fail or behave incorrectly when using the fake.
| .Select(c => new SyncItem { Id = c.Id }) | |
| .Select(c => new SyncItem { Id = c.Id, SyncInfo = c.SyncInfo }) |
| if (ids == null || ids.Count == 0) return Task.FromResult(new List<SyncItem>()); | ||
| var found = _tasks | ||
| .Where(t => (t.ProviderTaskId != null && ids.Contains(t.ProviderTaskId)) || (t.Id != Guid.Empty && ids.Contains(t.Id.ToString()))) | ||
| .Select(t => new SyncItem { Id = t.Id }) |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The returned SyncItem objects are missing the SyncInfo property. Looking at the real implementation in CrystaTaskService.cs (line 26), GetWorkItemSyncItemsAsync should populate SyncInfo from the task's WorkItemSyncInfo property. The current implementation only sets the Id field, but the calling code in AzureBoardSyncService expects SyncInfo.SyncId and SyncInfo.ContentHash to be populated for sync comparison logic (lines 565, 572 in AzureBoardSyncService.cs). This will cause sync operations to fail or behave incorrectly when using the fake.
| .Select(t => new SyncItem { Id = t.Id }) | |
| .Select(t => new SyncItem | |
| { | |
| Id = t.Id, | |
| SyncInfo = t.WorkItemSyncInfo == null | |
| ? null | |
| : new SyncInfo | |
| { | |
| SyncId = t.WorkItemSyncInfo.SyncId, | |
| ContentHash = t.WorkItemSyncInfo.ContentHash | |
| } | |
| }) |
| if (!string.IsNullOrEmpty(project)) | ||
| { | ||
| ids = _tasks | ||
| .Where(t => t.CrystaProgram != null && string.Equals(t.CrystaProgram.ToString(), project, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(t.ProviderTaskId)) |
Copilot
AI
Dec 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default 'ToString()': CrystaProgram inherits 'ToString()' from 'Object', and so is not suitable for printing.
| .Where(t => t.CrystaProgram != null && string.Equals(t.CrystaProgram.ToString(), project, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(t.ProviderTaskId)) | |
| .Where(t => t.CrystaProgram != null && string.Equals(t.CrystaProgram.Name, project, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(t.ProviderTaskId)) |
|
@copilot open a new pull request to apply changes based on the comments in this thread |
|
@afshinalizadeh I've opened a new pull request, #110, to work on those changes. Once the pull request is ready, I'll request review from you. |
…e review Co-authored-by: afshinalizadeh <4254006+afshinalizadeh@users.noreply.github.com>
Co-authored-by: afshinalizadeh <4254006+afshinalizadeh@users.noreply.github.com>
[WIP] Refactor CrystaTask to service interface and add test fakes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 10 comments.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Replaced ICrystaTaskRepository with ICrystaTaskService across the codebase, updating all usages and DI registrations. Introduced CrystaTaskServiceFake for in-memory testing and updated AzureBoardSyncServiceTests to use fakes. Adjusted CrystaProgramSyncModuleServiceFake to accept configuration. Added src.sln for Visual Studio project structure.