test(07-08): add export and ViewModel unit tests
- UserAccessCsvExportServiceTests (5): summary section, data header, RFC 4180 quote escaping, 7-column count, WriteSingleFileAsync multi-user output - UserAccessHtmlExportServiceTests (7): DOCTYPE, stats cards, dual-view sections, access type badges, filterTable JS, toggleView JS, HTML entity encoding - UserAccessAuditViewModelTests (8): AuditUsersAsync invocation, results population, summary properties computation, tenant switch reset, GlobalSitesChanged update, override guard, CanExport false/true states
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
using System.Collections.Generic;
|
||||
using SharepointToolbox.Core.Models;
|
||||
using SharepointToolbox.Services.Export;
|
||||
|
||||
namespace SharepointToolbox.Tests.Services.Export;
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for UserAccessHtmlExportService (Phase 7 Plan 08).
|
||||
/// Verifies: DOCTYPE, stats cards, dual-view sections, access type badges,
|
||||
/// filter script, toggle script, HTML entity encoding.
|
||||
/// </summary>
|
||||
public class UserAccessHtmlExportServiceTests
|
||||
{
|
||||
// ── Helper factory ────────────────────────────────────────────────────────
|
||||
|
||||
private static UserAccessEntry MakeEntry(
|
||||
string userDisplay = "Alice Smith",
|
||||
string userLogin = "alice@contoso.com",
|
||||
string siteUrl = "https://contoso.sharepoint.com",
|
||||
string siteTitle = "Contoso",
|
||||
string objectType = "List",
|
||||
string objectTitle = "Docs",
|
||||
string objectUrl = "https://contoso.sharepoint.com/Docs",
|
||||
string permLevel = "Read",
|
||||
AccessType accessType = AccessType.Direct,
|
||||
string grantedThrough = "Direct Permissions",
|
||||
bool isHighPrivilege = false,
|
||||
bool isExternal = false) =>
|
||||
new(userDisplay, userLogin, siteUrl, siteTitle, objectType, objectTitle, objectUrl,
|
||||
permLevel, accessType, grantedThrough, isHighPrivilege, isExternal);
|
||||
|
||||
private static readonly UserAccessEntry DefaultEntry = MakeEntry();
|
||||
|
||||
// ── Test 1: BuildHtml contains DOCTYPE ───────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void BuildHtml_contains_doctype()
|
||||
{
|
||||
var svc = new UserAccessHtmlExportService();
|
||||
var html = svc.BuildHtml(new[] { DefaultEntry });
|
||||
|
||||
Assert.StartsWith("<!DOCTYPE html>", html.TrimStart());
|
||||
}
|
||||
|
||||
// ── Test 2: BuildHtml has stats cards ─────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void BuildHtml_has_stats_cards()
|
||||
{
|
||||
var svc = new UserAccessHtmlExportService();
|
||||
var html = svc.BuildHtml(new[] { DefaultEntry });
|
||||
|
||||
Assert.Contains("Total Accesses", html);
|
||||
Assert.Contains("stat-card", html);
|
||||
}
|
||||
|
||||
// ── Test 3: BuildHtml has both view sections ──────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void BuildHtml_has_both_views()
|
||||
{
|
||||
var svc = new UserAccessHtmlExportService();
|
||||
var html = svc.BuildHtml(new[] { DefaultEntry });
|
||||
|
||||
// By-user view
|
||||
Assert.Contains("view-user", html);
|
||||
// By-site view
|
||||
Assert.Contains("view-site", html);
|
||||
}
|
||||
|
||||
// ── Test 4: BuildHtml has access type badge CSS classes ───────────────────
|
||||
|
||||
[Fact]
|
||||
public void BuildHtml_has_access_type_badges()
|
||||
{
|
||||
var entries = new List<UserAccessEntry>
|
||||
{
|
||||
MakeEntry(accessType: AccessType.Direct),
|
||||
MakeEntry(userLogin: "bob@contoso.com", accessType: AccessType.Group),
|
||||
MakeEntry(userLogin: "carol@contoso.com", accessType: AccessType.Inherited)
|
||||
};
|
||||
|
||||
var svc = new UserAccessHtmlExportService();
|
||||
var html = svc.BuildHtml(entries);
|
||||
|
||||
Assert.Contains("access-direct", html);
|
||||
Assert.Contains("access-group", html);
|
||||
Assert.Contains("access-inherited", html);
|
||||
}
|
||||
|
||||
// ── Test 5: BuildHtml has filterTable JS function ─────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void BuildHtml_has_filter_script()
|
||||
{
|
||||
var svc = new UserAccessHtmlExportService();
|
||||
var html = svc.BuildHtml(new[] { DefaultEntry });
|
||||
|
||||
Assert.Contains("filterTable", html);
|
||||
}
|
||||
|
||||
// ── Test 6: BuildHtml has toggleView JS function ──────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void BuildHtml_has_toggle_script()
|
||||
{
|
||||
var svc = new UserAccessHtmlExportService();
|
||||
var html = svc.BuildHtml(new[] { DefaultEntry });
|
||||
|
||||
Assert.Contains("toggleView", html);
|
||||
}
|
||||
|
||||
// ── Test 7: BuildHtml encodes HTML entities ───────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void BuildHtml_encodes_html_entities()
|
||||
{
|
||||
var entryWithScript = MakeEntry(objectTitle: "<script>alert('xss')</script>");
|
||||
var svc = new UserAccessHtmlExportService();
|
||||
var html = svc.BuildHtml(new[] { entryWithScript });
|
||||
|
||||
// Raw script tag must not appear verbatim
|
||||
Assert.DoesNotContain("<script>alert", html);
|
||||
// Encoded form must be present
|
||||
Assert.Contains("<script>", html);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user