108 lines
4 KiB
C#
108 lines
4 KiB
C#
using FluentAssertions;
|
|
using TeamsISO.App.Services;
|
|
|
|
namespace TeamsISO.App.Tests.Services;
|
|
|
|
/// <summary>
|
|
/// Token-expansion + sanitization tests for <see cref="OutputNameTemplate"/>.
|
|
/// We don't touch <see cref="OutputNameTemplate.Get"/> / <see cref="OutputNameTemplate.Set"/>
|
|
/// here because those round-trip through %LOCALAPPDATA% file IO; the file-IO
|
|
/// path is exercised at integration test time. The token expander is pure and
|
|
/// easy to cover.
|
|
/// </summary>
|
|
public class OutputNameTemplateTests
|
|
{
|
|
private static readonly Guid TestId = new("11223344-5566-7788-99aa-bbccddeeff00");
|
|
|
|
[Fact]
|
|
public void Render_DefaultTemplate_ProducesGuidPrefix()
|
|
{
|
|
var name = OutputNameTemplate.Render(OutputNameTemplate.DefaultTemplate, TestId, "Jane");
|
|
// Default is "TEAMSISO_{guid}" → first 8 hex of TestId, uppercase.
|
|
name.Should().Be("TEAMSISO_11223344");
|
|
}
|
|
|
|
[Fact]
|
|
public void Render_NameToken_UsesSanitizedDisplayName()
|
|
{
|
|
var name = OutputNameTemplate.Render("TEAMSISO_{name}", TestId, "Jane Doe");
|
|
name.Should().Be("TEAMSISO_Jane_Doe", because: "spaces become underscores in the sanitizer");
|
|
}
|
|
|
|
[Fact]
|
|
public void Render_NameToken_StripsSpecialCharacters()
|
|
{
|
|
// NDI accepts more chars than we allow, but we keep it conservative
|
|
// (alphanumeric + underscore + hyphen + period). Anything else is dropped
|
|
// or converted to underscore (whitespace).
|
|
var name = OutputNameTemplate.Render("{name}", TestId, "Jane (PM) — Lead!");
|
|
// Expect: "Jane_PM__Lead" — parens dropped, em-dash dropped, exclamation dropped.
|
|
// Whitespace runs collapse into adjacent underscores.
|
|
name.Should().NotContain("(");
|
|
name.Should().NotContain(")");
|
|
name.Should().NotContain("—");
|
|
name.Should().NotContain("!");
|
|
name.Should().Contain("Jane");
|
|
name.Should().Contain("Lead");
|
|
}
|
|
|
|
[Fact]
|
|
public void Render_GuidToken_IsUppercaseFirst8()
|
|
{
|
|
var name = OutputNameTemplate.Render("{guid}", TestId, "Jane");
|
|
name.Should().Be("11223344");
|
|
}
|
|
|
|
[Fact]
|
|
public void Render_MachineToken_UsesEnvironmentMachineName()
|
|
{
|
|
var name = OutputNameTemplate.Render("{machine}", TestId, "Jane");
|
|
// Sanitization may transform spaces in machine names, so just assert non-empty
|
|
// and that it contains the machine name's alphanumeric-ish chars.
|
|
name.Should().NotBeNullOrEmpty();
|
|
// MachineName itself is sanitized in render — equality check would be brittle.
|
|
}
|
|
|
|
[Fact]
|
|
public void Render_TimestampToken_HasExpectedShape()
|
|
{
|
|
var name = OutputNameTemplate.Render("session_{timestamp}", TestId, "Jane");
|
|
// yyyyMMdd_HHmmss is 15 chars + underscore separator = 16.
|
|
// Combined with "session_" prefix → length should be at least 23.
|
|
name.Should().StartWith("session_");
|
|
name.Length.Should().BeGreaterThan("session_".Length + 14);
|
|
}
|
|
|
|
[Fact]
|
|
public void Render_MultipleTokens_AllExpand()
|
|
{
|
|
var name = OutputNameTemplate.Render("{name}_{guid}_{machine}", TestId, "Jane");
|
|
name.Should().StartWith("Jane_11223344_");
|
|
name.Should().NotContain("{");
|
|
name.Should().NotContain("}");
|
|
}
|
|
|
|
[Fact]
|
|
public void Render_TemplateWithNoTokens_PassesThrough()
|
|
{
|
|
var name = OutputNameTemplate.Render("STATIC_NAME", TestId, "Jane");
|
|
name.Should().Be("STATIC_NAME");
|
|
}
|
|
|
|
[Fact]
|
|
public void Render_EmptyDisplayName_DegradesToEmptyToken()
|
|
{
|
|
var name = OutputNameTemplate.Render("PFX_{name}", TestId, "");
|
|
name.Should().Be("PFX_");
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("Jane123")]
|
|
[InlineData("Jane-Doe")]
|
|
[InlineData("Jane.PM")]
|
|
public void Render_AllowedCharactersPreserved(string displayName)
|
|
{
|
|
var name = OutputNameTemplate.Render("{name}", TestId, displayName);
|
|
name.Should().Be(displayName, because: "alphanumeric, underscore, hyphen, period are all valid NDI chars");
|
|
}
|
|
}
|