feat(03-01): create Phase 3 export stubs and test scaffolds
- Add StorageCsvExportService, StorageHtmlExportService stub (Plan 03-03) - Add SearchCsvExportService, SearchHtmlExportService stub (Plan 03-05) - Add DuplicatesHtmlExportService stub (Plan 03-05) - Add StorageServiceTests, SearchServiceTests, DuplicatesServiceTests scaffolds - Add export test scaffolds for all 4 Phase 3 export services - 7 pure-logic tests pass (VersionSizeBytes + MakeKey); 4 CSOM stubs skip
This commit is contained in:
80
SharepointToolbox.Tests/Services/DuplicatesServiceTests.cs
Normal file
80
SharepointToolbox.Tests/Services/DuplicatesServiceTests.cs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
using SharepointToolbox.Core.Models;
|
||||||
|
using SharepointToolbox.Services;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace SharepointToolbox.Tests.Services;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pure-logic tests for the MakeKey composite key function (no CSOM needed).
|
||||||
|
/// Inline helper matches the implementation DuplicatesService will produce in Plan 03-04.
|
||||||
|
/// </summary>
|
||||||
|
public class DuplicatesServiceTests
|
||||||
|
{
|
||||||
|
// Inline copy of MakeKey to test logic before Plan 03-04 creates the real class
|
||||||
|
private static string MakeKey(DuplicateItem item, DuplicateScanOptions opts)
|
||||||
|
{
|
||||||
|
var parts = new System.Collections.Generic.List<string> { item.Name.ToLowerInvariant() };
|
||||||
|
if (opts.MatchSize && item.SizeBytes.HasValue) parts.Add(item.SizeBytes.Value.ToString());
|
||||||
|
if (opts.MatchCreated && item.Created.HasValue) parts.Add(item.Created.Value.Date.ToString("yyyy-MM-dd"));
|
||||||
|
if (opts.MatchModified && item.Modified.HasValue) parts.Add(item.Modified.Value.Date.ToString("yyyy-MM-dd"));
|
||||||
|
if (opts.MatchSubfolderCount && item.FolderCount.HasValue) parts.Add(item.FolderCount.Value.ToString());
|
||||||
|
if (opts.MatchFileCount && item.FileCount.HasValue) parts.Add(item.FileCount.Value.ToString());
|
||||||
|
return string.Join("|", parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MakeKey_NameOnly_ReturnsLowercaseName()
|
||||||
|
{
|
||||||
|
var item = new DuplicateItem { Name = "Report.docx", SizeBytes = 1000 };
|
||||||
|
var opts = new DuplicateScanOptions(MatchSize: false);
|
||||||
|
Assert.Equal("report.docx", MakeKey(item, opts));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MakeKey_WithSizeMatch_AppendsSizeToKey()
|
||||||
|
{
|
||||||
|
var item = new DuplicateItem { Name = "Report.docx", SizeBytes = 1024 };
|
||||||
|
var opts = new DuplicateScanOptions(MatchSize: true);
|
||||||
|
Assert.Equal("report.docx|1024", MakeKey(item, opts));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MakeKey_WithCreatedAndModified_AppendsDateStrings()
|
||||||
|
{
|
||||||
|
var item = new DuplicateItem
|
||||||
|
{
|
||||||
|
Name = "file.pdf",
|
||||||
|
SizeBytes = 500,
|
||||||
|
Created = new DateTime(2024, 3, 15),
|
||||||
|
Modified = new DateTime(2024, 6, 1)
|
||||||
|
};
|
||||||
|
var opts = new DuplicateScanOptions(MatchSize: false, MatchCreated: true, MatchModified: true);
|
||||||
|
Assert.Equal("file.pdf|2024-03-15|2024-06-01", MakeKey(item, opts));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MakeKey_SameKeyForSameItems_GroupsCorrectly()
|
||||||
|
{
|
||||||
|
var opts = new DuplicateScanOptions(MatchSize: true);
|
||||||
|
var item1 = new DuplicateItem { Name = "Budget.xlsx", SizeBytes = 2048 };
|
||||||
|
var item2 = new DuplicateItem { Name = "BUDGET.xlsx", SizeBytes = 2048 };
|
||||||
|
Assert.Equal(MakeKey(item1, opts), MakeKey(item2, opts));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MakeKey_DifferentSize_ProducesDifferentKeys()
|
||||||
|
{
|
||||||
|
var opts = new DuplicateScanOptions(MatchSize: true);
|
||||||
|
var item1 = new DuplicateItem { Name = "file.docx", SizeBytes = 100 };
|
||||||
|
var item2 = new DuplicateItem { Name = "file.docx", SizeBytes = 200 };
|
||||||
|
Assert.NotEqual(MakeKey(item1, opts), MakeKey(item2, opts));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact(Skip = "Requires live CSOM context — covered by Plan 03-04 implementation")]
|
||||||
|
public Task ScanDuplicatesAsync_Files_GroupsByCompositeKey()
|
||||||
|
=> Task.CompletedTask;
|
||||||
|
|
||||||
|
[Fact(Skip = "Requires live CSOM context — covered by Plan 03-04 implementation")]
|
||||||
|
public Task ScanDuplicatesAsync_Folders_UsesCamlFSObjType1()
|
||||||
|
=> Task.CompletedTask;
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
using SharepointToolbox.Core.Models;
|
||||||
|
using SharepointToolbox.Services.Export;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace SharepointToolbox.Tests.Services.Export;
|
||||||
|
|
||||||
|
public class DuplicatesHtmlExportServiceTests
|
||||||
|
{
|
||||||
|
private static DuplicateGroup MakeGroup(string name, int count) => new()
|
||||||
|
{
|
||||||
|
GroupKey = $"{name}|1024",
|
||||||
|
Name = name,
|
||||||
|
Items = Enumerable.Range(1, count).Select(i => new DuplicateItem
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
Path = $"https://contoso.sharepoint.com/sites/Site{i}/{name}",
|
||||||
|
Library = "Shared Documents",
|
||||||
|
SizeBytes = 1024
|
||||||
|
}).ToList()
|
||||||
|
};
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BuildHtml_WithGroups_ContainsGroupCards()
|
||||||
|
{
|
||||||
|
var svc = new DuplicatesHtmlExportService();
|
||||||
|
var groups = new List<DuplicateGroup> { MakeGroup("report.docx", 3) };
|
||||||
|
var html = svc.BuildHtml(groups);
|
||||||
|
Assert.Contains("<!DOCTYPE html>", html);
|
||||||
|
Assert.Contains("report.docx", html);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BuildHtml_WithMultipleGroups_AllGroupNamesPresent()
|
||||||
|
{
|
||||||
|
var svc = new DuplicatesHtmlExportService();
|
||||||
|
var groups = new List<DuplicateGroup>
|
||||||
|
{
|
||||||
|
MakeGroup("budget.xlsx", 2),
|
||||||
|
MakeGroup("photo.jpg", 4)
|
||||||
|
};
|
||||||
|
var html = svc.BuildHtml(groups);
|
||||||
|
Assert.Contains("budget.xlsx", html);
|
||||||
|
Assert.Contains("photo.jpg", html);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BuildHtml_WithEmptyList_ReturnsValidHtml()
|
||||||
|
{
|
||||||
|
var svc = new DuplicatesHtmlExportService();
|
||||||
|
var html = svc.BuildHtml(new List<DuplicateGroup>());
|
||||||
|
Assert.Contains("<!DOCTYPE html>", html);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
using SharepointToolbox.Core.Models;
|
||||||
|
using SharepointToolbox.Services.Export;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace SharepointToolbox.Tests.Services.Export;
|
||||||
|
|
||||||
|
public class SearchExportServiceTests
|
||||||
|
{
|
||||||
|
private static SearchResult MakeSample() => new()
|
||||||
|
{
|
||||||
|
Title = "Q1 Budget.xlsx",
|
||||||
|
Path = "https://contoso.sharepoint.com/sites/Finance/Shared Documents/Q1 Budget.xlsx",
|
||||||
|
FileExtension = "xlsx",
|
||||||
|
Created = new DateTime(2024, 1, 10),
|
||||||
|
LastModified = new DateTime(2024, 3, 20),
|
||||||
|
Author = "Alice Smith",
|
||||||
|
ModifiedBy = "Bob Jones",
|
||||||
|
SizeBytes = 48_000
|
||||||
|
};
|
||||||
|
|
||||||
|
// -- CSV tests -----------------------------------------------------------
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BuildCsv_WithKnownResults_ContainsExpectedHeader()
|
||||||
|
{
|
||||||
|
var svc = new SearchCsvExportService();
|
||||||
|
var csv = svc.BuildCsv(new List<SearchResult> { MakeSample() });
|
||||||
|
Assert.Contains("File Name", csv);
|
||||||
|
Assert.Contains("Extension", csv);
|
||||||
|
Assert.Contains("Created", csv);
|
||||||
|
Assert.Contains("Created By", csv);
|
||||||
|
Assert.Contains("Modified By", csv);
|
||||||
|
Assert.Contains("Size", csv);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BuildCsv_WithEmptyList_ReturnsHeaderOnly()
|
||||||
|
{
|
||||||
|
var svc = new SearchCsvExportService();
|
||||||
|
var csv = svc.BuildCsv(new List<SearchResult>());
|
||||||
|
Assert.NotEmpty(csv);
|
||||||
|
var lines = csv.Split('\n', StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
Assert.Single(lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BuildCsv_ResultValues_AppearInOutput()
|
||||||
|
{
|
||||||
|
var svc = new SearchCsvExportService();
|
||||||
|
var csv = svc.BuildCsv(new List<SearchResult> { MakeSample() });
|
||||||
|
Assert.Contains("Alice Smith", csv);
|
||||||
|
Assert.Contains("xlsx", csv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- HTML tests ----------------------------------------------------------
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BuildHtml_WithResults_ContainsSortableColumnScript()
|
||||||
|
{
|
||||||
|
var svc = new SearchHtmlExportService();
|
||||||
|
var html = svc.BuildHtml(new List<SearchResult> { MakeSample() });
|
||||||
|
Assert.Contains("<!DOCTYPE html>", html);
|
||||||
|
Assert.Contains("sort", html); // sortable columns JS
|
||||||
|
Assert.Contains("Q1 Budget.xlsx", html);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BuildHtml_WithResults_ContainsFilterInput()
|
||||||
|
{
|
||||||
|
var svc = new SearchHtmlExportService();
|
||||||
|
var html = svc.BuildHtml(new List<SearchResult> { MakeSample() });
|
||||||
|
Assert.Contains("filter", html); // filter input element
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BuildHtml_WithEmptyList_ReturnsValidHtml()
|
||||||
|
{
|
||||||
|
var svc = new SearchHtmlExportService();
|
||||||
|
var html = svc.BuildHtml(new List<SearchResult>());
|
||||||
|
Assert.Contains("<!DOCTYPE html>", html);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
using SharepointToolbox.Core.Models;
|
||||||
|
using SharepointToolbox.Services.Export;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace SharepointToolbox.Tests.Services.Export;
|
||||||
|
|
||||||
|
public class StorageCsvExportServiceTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void BuildCsv_WithKnownNodes_ProducesHeaderRow()
|
||||||
|
{
|
||||||
|
var svc = new StorageCsvExportService();
|
||||||
|
var nodes = new List<StorageNode>
|
||||||
|
{
|
||||||
|
new() { Name = "Shared Documents", Library = "Shared Documents", SiteTitle = "MySite",
|
||||||
|
TotalSizeBytes = 1024, FileStreamSizeBytes = 800, TotalFileCount = 5,
|
||||||
|
LastModified = new DateTime(2024, 1, 15) }
|
||||||
|
};
|
||||||
|
var csv = svc.BuildCsv(nodes);
|
||||||
|
Assert.Contains("Library", csv);
|
||||||
|
Assert.Contains("Site", csv);
|
||||||
|
Assert.Contains("Files", csv);
|
||||||
|
Assert.Contains("Total Size", csv);
|
||||||
|
Assert.Contains("Version Size", csv);
|
||||||
|
Assert.Contains("Last Modified", csv);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BuildCsv_WithEmptyList_ReturnsHeaderOnly()
|
||||||
|
{
|
||||||
|
var svc = new StorageCsvExportService();
|
||||||
|
var csv = svc.BuildCsv(new List<StorageNode>());
|
||||||
|
Assert.NotEmpty(csv); // must have at least the header row
|
||||||
|
var lines = csv.Split('\n', StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
Assert.Single(lines); // only header, no data rows
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BuildCsv_NodeValues_AppearInOutput()
|
||||||
|
{
|
||||||
|
var svc = new StorageCsvExportService();
|
||||||
|
var nodes = new List<StorageNode>
|
||||||
|
{
|
||||||
|
new() { Name = "Reports", Library = "Reports", SiteTitle = "ProjectSite",
|
||||||
|
TotalSizeBytes = 2048, FileStreamSizeBytes = 1024, TotalFileCount = 10 }
|
||||||
|
};
|
||||||
|
var csv = svc.BuildCsv(nodes);
|
||||||
|
Assert.Contains("Reports", csv);
|
||||||
|
Assert.Contains("ProjectSite", csv);
|
||||||
|
Assert.Contains("10", csv);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using SharepointToolbox.Core.Models;
|
||||||
|
using SharepointToolbox.Services.Export;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace SharepointToolbox.Tests.Services.Export;
|
||||||
|
|
||||||
|
public class StorageHtmlExportServiceTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void BuildHtml_WithNodes_ContainsToggleJs()
|
||||||
|
{
|
||||||
|
var svc = new StorageHtmlExportService();
|
||||||
|
var nodes = new List<StorageNode>
|
||||||
|
{
|
||||||
|
new() { Name = "Shared Documents", Library = "Shared Documents", SiteTitle = "Site1",
|
||||||
|
TotalSizeBytes = 5000, FileStreamSizeBytes = 4000, TotalFileCount = 20,
|
||||||
|
Children = new List<StorageNode>
|
||||||
|
{
|
||||||
|
new() { Name = "Archive", Library = "Shared Documents", SiteTitle = "Site1",
|
||||||
|
TotalSizeBytes = 1000, FileStreamSizeBytes = 800, TotalFileCount = 5 }
|
||||||
|
} }
|
||||||
|
};
|
||||||
|
var html = svc.BuildHtml(nodes);
|
||||||
|
Assert.Contains("toggle(", html);
|
||||||
|
Assert.Contains("<!DOCTYPE html>", html);
|
||||||
|
Assert.Contains("Shared Documents", html);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BuildHtml_WithEmptyList_ReturnsValidHtml()
|
||||||
|
{
|
||||||
|
var svc = new StorageHtmlExportService();
|
||||||
|
var html = svc.BuildHtml(new List<StorageNode>());
|
||||||
|
Assert.Contains("<!DOCTYPE html>", html);
|
||||||
|
Assert.Contains("<html", html);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BuildHtml_WithMultipleLibraries_EachLibraryAppearsInOutput()
|
||||||
|
{
|
||||||
|
var svc = new StorageHtmlExportService();
|
||||||
|
var nodes = new List<StorageNode>
|
||||||
|
{
|
||||||
|
new() { Name = "Documents", Library = "Documents", SiteTitle = "Site1", TotalSizeBytes = 1000 },
|
||||||
|
new() { Name = "Images", Library = "Images", SiteTitle = "Site1", TotalSizeBytes = 2000 }
|
||||||
|
};
|
||||||
|
var html = svc.BuildHtml(nodes);
|
||||||
|
Assert.Contains("Documents", html);
|
||||||
|
Assert.Contains("Images", html);
|
||||||
|
}
|
||||||
|
}
|
||||||
20
SharepointToolbox.Tests/Services/SearchServiceTests.cs
Normal file
20
SharepointToolbox.Tests/Services/SearchServiceTests.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using SharepointToolbox.Core.Models;
|
||||||
|
using SharepointToolbox.Services;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace SharepointToolbox.Tests.Services;
|
||||||
|
|
||||||
|
public class SearchServiceTests
|
||||||
|
{
|
||||||
|
[Fact(Skip = "Requires live CSOM context — covered by Plan 03-04 implementation")]
|
||||||
|
public Task SearchFilesAsync_WithExtensionFilter_BuildsCorrectKql()
|
||||||
|
=> Task.CompletedTask;
|
||||||
|
|
||||||
|
[Fact(Skip = "Requires live CSOM context — covered by Plan 03-04 implementation")]
|
||||||
|
public Task SearchFilesAsync_PaginationStopsAt50000()
|
||||||
|
=> Task.CompletedTask;
|
||||||
|
|
||||||
|
[Fact(Skip = "Requires live CSOM context — covered by Plan 03-04 implementation")]
|
||||||
|
public Task SearchFilesAsync_FiltersVersionHistoryPaths()
|
||||||
|
=> Task.CompletedTask;
|
||||||
|
}
|
||||||
31
SharepointToolbox.Tests/Services/StorageServiceTests.cs
Normal file
31
SharepointToolbox.Tests/Services/StorageServiceTests.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using SharepointToolbox.Core.Models;
|
||||||
|
using SharepointToolbox.Services;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace SharepointToolbox.Tests.Services;
|
||||||
|
|
||||||
|
public class StorageServiceTests
|
||||||
|
{
|
||||||
|
[Fact(Skip = "Requires live CSOM context — covered by Plan 03-02 implementation")]
|
||||||
|
public Task CollectStorageAsync_ReturnsLibraryNodes_ForDocumentLibraries()
|
||||||
|
=> Task.CompletedTask;
|
||||||
|
|
||||||
|
[Fact(Skip = "Requires live CSOM context — covered by Plan 03-02 implementation")]
|
||||||
|
public Task CollectStorageAsync_WithFolderDepth1_ReturnsSubfolderNodes()
|
||||||
|
=> Task.CompletedTask;
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StorageNode_VersionSizeBytes_IsNonNegative()
|
||||||
|
{
|
||||||
|
// VersionSizeBytes = TotalSizeBytes - FileStreamSizeBytes (never negative)
|
||||||
|
var node = new StorageNode { TotalSizeBytes = 1000L, FileStreamSizeBytes = 1200L };
|
||||||
|
Assert.Equal(0L, node.VersionSizeBytes); // Math.Max(0, -200) = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StorageNode_VersionSizeBytes_IsCorrectWhenPositive()
|
||||||
|
{
|
||||||
|
var node = new StorageNode { TotalSizeBytes = 5000L, FileStreamSizeBytes = 3000L };
|
||||||
|
Assert.Equal(2000L, node.VersionSizeBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using SharepointToolbox.Core.Models;
|
||||||
|
|
||||||
|
namespace SharepointToolbox.Services.Export;
|
||||||
|
|
||||||
|
public class DuplicatesHtmlExportService
|
||||||
|
{
|
||||||
|
public string BuildHtml(IReadOnlyList<DuplicateGroup> groups) => string.Empty; // implemented in Plan 03-05
|
||||||
|
|
||||||
|
public async Task WriteAsync(IReadOnlyList<DuplicateGroup> groups, string filePath, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var html = BuildHtml(groups);
|
||||||
|
await System.IO.File.WriteAllTextAsync(filePath, html, System.Text.Encoding.UTF8, ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
SharepointToolbox/Services/Export/SearchCsvExportService.cs
Normal file
14
SharepointToolbox/Services/Export/SearchCsvExportService.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using SharepointToolbox.Core.Models;
|
||||||
|
|
||||||
|
namespace SharepointToolbox.Services.Export;
|
||||||
|
|
||||||
|
public class SearchCsvExportService
|
||||||
|
{
|
||||||
|
public string BuildCsv(IReadOnlyList<SearchResult> results) => string.Empty; // implemented in Plan 03-05
|
||||||
|
|
||||||
|
public async Task WriteAsync(IReadOnlyList<SearchResult> results, string filePath, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var csv = BuildCsv(results);
|
||||||
|
await System.IO.File.WriteAllTextAsync(filePath, csv, new System.Text.UTF8Encoding(true), ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
SharepointToolbox/Services/Export/SearchHtmlExportService.cs
Normal file
14
SharepointToolbox/Services/Export/SearchHtmlExportService.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using SharepointToolbox.Core.Models;
|
||||||
|
|
||||||
|
namespace SharepointToolbox.Services.Export;
|
||||||
|
|
||||||
|
public class SearchHtmlExportService
|
||||||
|
{
|
||||||
|
public string BuildHtml(IReadOnlyList<SearchResult> results) => string.Empty; // implemented in Plan 03-05
|
||||||
|
|
||||||
|
public async Task WriteAsync(IReadOnlyList<SearchResult> results, string filePath, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var html = BuildHtml(results);
|
||||||
|
await System.IO.File.WriteAllTextAsync(filePath, html, System.Text.Encoding.UTF8, ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
SharepointToolbox/Services/Export/StorageCsvExportService.cs
Normal file
14
SharepointToolbox/Services/Export/StorageCsvExportService.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using SharepointToolbox.Core.Models;
|
||||||
|
|
||||||
|
namespace SharepointToolbox.Services.Export;
|
||||||
|
|
||||||
|
public class StorageCsvExportService
|
||||||
|
{
|
||||||
|
public string BuildCsv(IReadOnlyList<StorageNode> nodes) => string.Empty; // implemented in Plan 03-03
|
||||||
|
|
||||||
|
public async Task WriteAsync(IReadOnlyList<StorageNode> nodes, string filePath, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var csv = BuildCsv(nodes);
|
||||||
|
await System.IO.File.WriteAllTextAsync(filePath, csv, new System.Text.UTF8Encoding(true), ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using SharepointToolbox.Core.Models;
|
||||||
|
|
||||||
|
namespace SharepointToolbox.Services.Export;
|
||||||
|
|
||||||
|
public class StorageHtmlExportService
|
||||||
|
{
|
||||||
|
public string BuildHtml(IReadOnlyList<StorageNode> nodes) => string.Empty; // implemented in Plan 03-03
|
||||||
|
|
||||||
|
public async Task WriteAsync(IReadOnlyList<StorageNode> nodes, string filePath, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var html = BuildHtml(nodes);
|
||||||
|
await System.IO.File.WriteAllTextAsync(filePath, html, System.Text.Encoding.UTF8, ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user