Files
Sharepoint-Toolbox/SharepointToolbox.Tests/Services/Export/UserAccessHtmlExportServiceTests.cs
Dev d8b66169e6 feat(11-02): extend export tests to verify branding injection across all 5 services
- HtmlExportServiceTests: 3 new tests (MSP logo only, null branding no img, both logos)
- SearchExportServiceTests: 1 new branding test (img tag present when branding provided)
- StorageHtmlExportServiceTests: 1 new branding test (img tag present)
- DuplicatesHtmlExportServiceTests: 1 new branding test (img tag present)
- UserAccessHtmlExportServiceTests: 1 new branding test (img tag present)
- MakeBranding helper added to each test class
- All 45 export tests pass; full suite 247/247 with 0 failures
2026-04-08 14:45:55 +02:00

145 lines
5.6 KiB
C#

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 ReportBranding MakeBranding(bool msp = true, bool client = false)
{
var mspLogo = msp ? new LogoData { Base64 = "bXNw", MimeType = "image/png" } : null;
var clientLogo = client ? new LogoData { Base64 = "Y2xpZW50", MimeType = "image/jpeg" } : null;
return new ReportBranding(mspLogo, clientLogo);
}
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("&lt;script&gt;", html);
}
// ── Branding tests ────────────────────────────────────────────────────────
[Fact]
public void BuildHtml_WithBranding_ContainsLogoImg()
{
var svc = new UserAccessHtmlExportService();
var html = svc.BuildHtml(new[] { DefaultEntry }, MakeBranding(msp: true));
Assert.Contains("data:image/png;base64,bXNw", html);
}
}