feat(04-03): implement FileTransferService with MoveCopyUtil and conflict policies
- FileTransferService.cs: CSOM copy/move via MoveCopyUtil.CopyFileByPath/MoveFileByPath - Conflict policies: Skip (catch ServerException), Overwrite (overwrite=true), Rename (KeepBoth=true) - ResourcePath.FromDecodedUrl for special character support - Recursive folder enumeration with system folder filtering - EnsureFolderAsync creates intermediate destination folders - Best-effort metadata preservation (ResetAuthorAndCreatedOnCopy=false) - FileTransferServiceTests.cs: 4 passing tests, 3 skipped (integration)
This commit is contained in:
56
SharepointToolbox.Tests/Services/BulkMemberServiceTests.cs
Normal file
56
SharepointToolbox.Tests/Services/BulkMemberServiceTests.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using SharepointToolbox.Core.Models;
|
||||
using SharepointToolbox.Services;
|
||||
|
||||
namespace SharepointToolbox.Tests.Services;
|
||||
|
||||
public class BulkMemberServiceTests
|
||||
{
|
||||
[Fact]
|
||||
public void BulkMemberService_Implements_IBulkMemberService()
|
||||
{
|
||||
// GraphClientFactory requires MsalClientFactory which requires real MSAL setup
|
||||
// Verify the type hierarchy at minimum
|
||||
Assert.True(typeof(IBulkMemberService).IsAssignableFrom(typeof(BulkMemberService)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BulkMemberRow_DefaultValues()
|
||||
{
|
||||
var row = new BulkMemberRow();
|
||||
Assert.Equal(string.Empty, row.Email);
|
||||
Assert.Equal(string.Empty, row.GroupName);
|
||||
Assert.Equal(string.Empty, row.GroupUrl);
|
||||
Assert.Equal(string.Empty, row.Role);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BulkMemberRow_PropertiesSettable()
|
||||
{
|
||||
var row = new BulkMemberRow
|
||||
{
|
||||
Email = "user@test.com",
|
||||
GroupName = "Marketing",
|
||||
GroupUrl = "https://contoso.sharepoint.com/sites/Marketing",
|
||||
Role = "Owner"
|
||||
};
|
||||
|
||||
Assert.Equal("user@test.com", row.Email);
|
||||
Assert.Equal("Marketing", row.GroupName);
|
||||
Assert.Equal("Owner", row.Role);
|
||||
}
|
||||
|
||||
[Fact(Skip = "Requires live SharePoint tenant and Graph permissions")]
|
||||
public async Task AddMembersAsync_ValidRows_AddsToGroups()
|
||||
{
|
||||
}
|
||||
|
||||
[Fact(Skip = "Requires live SharePoint tenant")]
|
||||
public async Task AddMembersAsync_InvalidEmail_ReportsPerItemError()
|
||||
{
|
||||
}
|
||||
|
||||
[Fact(Skip = "Requires Graph permissions - Group.ReadWrite.All")]
|
||||
public async Task AddMembersAsync_M365Group_UsesGraphApi()
|
||||
{
|
||||
}
|
||||
}
|
||||
57
SharepointToolbox.Tests/Services/FileTransferServiceTests.cs
Normal file
57
SharepointToolbox.Tests/Services/FileTransferServiceTests.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using SharepointToolbox.Core.Models;
|
||||
using SharepointToolbox.Services;
|
||||
|
||||
namespace SharepointToolbox.Tests.Services;
|
||||
|
||||
public class FileTransferServiceTests
|
||||
{
|
||||
[Fact]
|
||||
public void FileTransferService_Implements_IFileTransferService()
|
||||
{
|
||||
var service = new FileTransferService();
|
||||
Assert.IsAssignableFrom<IFileTransferService>(service);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TransferJob_DefaultValues_AreCorrect()
|
||||
{
|
||||
var job = new TransferJob();
|
||||
Assert.Equal(TransferMode.Copy, job.Mode);
|
||||
Assert.Equal(ConflictPolicy.Skip, job.ConflictPolicy);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConflictPolicy_HasAllValues()
|
||||
{
|
||||
Assert.Equal(3, Enum.GetValues<ConflictPolicy>().Length);
|
||||
Assert.Contains(ConflictPolicy.Skip, Enum.GetValues<ConflictPolicy>());
|
||||
Assert.Contains(ConflictPolicy.Overwrite, Enum.GetValues<ConflictPolicy>());
|
||||
Assert.Contains(ConflictPolicy.Rename, Enum.GetValues<ConflictPolicy>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TransferMode_HasAllValues()
|
||||
{
|
||||
Assert.Equal(2, Enum.GetValues<TransferMode>().Length);
|
||||
Assert.Contains(TransferMode.Copy, Enum.GetValues<TransferMode>());
|
||||
Assert.Contains(TransferMode.Move, Enum.GetValues<TransferMode>());
|
||||
}
|
||||
|
||||
[Fact(Skip = "Requires live SharePoint tenant")]
|
||||
public async Task TransferAsync_CopyMode_CopiesFiles()
|
||||
{
|
||||
// Integration test — needs real ClientContext
|
||||
}
|
||||
|
||||
[Fact(Skip = "Requires live SharePoint tenant")]
|
||||
public async Task TransferAsync_MoveMode_DeletesSourceAfterCopy()
|
||||
{
|
||||
// Integration test — needs real ClientContext
|
||||
}
|
||||
|
||||
[Fact(Skip = "Requires live SharePoint tenant")]
|
||||
public async Task TransferAsync_SkipConflict_DoesNotOverwrite()
|
||||
{
|
||||
// Integration test — needs real ClientContext
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user