Turned getter-like extension methods into extension properties (#1157)

This commit is contained in:
Thorsten Sommer authored and GitHub committed 2026-11-04 13:00:56 +01:00
1 parent 0375318b1b
commit f649febf88
286 files changed
+1379 -1109

No files matched your search

@@ -24,7 +24,7 @@ public sealed class WebRootFilesTests
{
private static IEnumerable<string> ChangelogFiles() => Changelog.LOGS.Select(log => log.Filename);
private static IEnumerable<ERIVersion> SpecificationVersions() => Enum.GetValues<ERIVersion>().Where(version => version.WasSpecificationSelected());
private static IEnumerable<ERIVersion> SpecificationVersions() => Enum.GetValues<ERIVersion>().Where(version => version.WasSpecificationSelected);
private static string ReadAppPageSource([CallerFilePath] string sourceFilePath = "") => File.ReadAllText(Path.Combine(Path.GetDirectoryName(sourceFilePath)!, "..", "..", "..", "MindWork AI Studio", "App.razor"));
@@ -78,7 +78,7 @@ public sealed class WebRootFilesTests
var destinationPath = Path.Combine(Path.GetTempPath(), $"eri-specification-{Guid.NewGuid():N}.json");
try
{
Assert.That(await webRootFiles.CopyToAsync(version.SpecificationURL(), destinationPath), Is.True);
Assert.That(await webRootFiles.CopyToAsync(version.SpecificationURL, destinationPath), Is.True);
Assert.That(await File.ReadAllTextAsync(destinationPath), Is.EqualTo(await version.ReadSpecification(webRootFiles)));
}
finally
@@ -42,7 +42,7 @@ public sealed class AssistantLaunchServiceTests
using (Assert.EnterMultipleScope())
{
Assert.That(destinations, Is.Not.Empty);
Assert.That(destinations.All(destination => destination.AllowSendTo()), Is.True);
Assert.That(destinations.All(destination => destination.AllowSendTo), Is.True);
Assert.That(destinations, Does.Not.Contain(AIStudio.Tools.Components.DYNAMIC_ASSISTANT), "Assistant plugins cannot take content yet.");
Assert.That(destinations, Does.Not.Contain(AIStudio.Tools.Components.NONE));
}
@@ -58,7 +58,7 @@ public sealed class AssistantLaunchServiceTests
[Test]
public void ShorterNamesComeFirst()
{
var lengths = AssistantLaunchService.SelectDestinations(AIStudio.Tools.Components.CHAT, _ => true).Select(destination => destination.Name().Length).ToList();
var lengths = AssistantLaunchService.SelectDestinations(AIStudio.Tools.Components.CHAT, _ => true).Select(destination => destination.Name.Length).ToList();
Assert.That(lengths, Is.Ordered);
}
}
@@ -77,7 +77,7 @@ public sealed class CodeLanguageDetectorTests
{
using (Assert.EnterMultipleScope())
{
var isFormat = FileExportFormatExtensions.TryFromCodeFenceLanguage(fenceLanguage, out _);
var isFormat = FileExportFormat.TryFromCodeFenceLanguage(fenceLanguage, out _);
Assert.That(isFormat || SourceCodeLanguages.Aliases.Contains(fenceLanguage, StringComparer.OrdinalIgnoreCase), Is.True, "The export would save it as a text file.");
Assert.That(CodeHighlighters.TryGetRules(fenceLanguage, out _) || LIBRARY_LANGUAGES.Contains(fenceLanguage), Is.True, "Nobody highlights it.");
}
@@ -14,7 +14,7 @@ public sealed class CodeTokenKindExtensionsTests
public async Task EveryKindHasAClassWhichTheStyleSheetColors([Values] CodeTokenKind kind)
{
var styleSheet = await new WebRootFiles().ReadTextAsync("system/MudBlazor.Markdown/MudBlazor.Markdown.min.css");
var cssClass = kind.ToCssClass().Split(' ')[0];
var cssClass = kind.CssClass.Split(' ')[0];
Assert.That(styleSheet, Does.Contain($".{cssClass}"), "A library which renames its classes would leave this kind without color.");
}
+26 -26
View File
@@ -13,11 +13,11 @@ public sealed class FileExportFormatTests
{
using (Assert.EnterMultipleScope())
{
Assert.That(FileExportFormat.MICROSOFT_WORD.FollowsPageAnchors(), Is.False, "Word looks for a file whose name ends in the fragment, finds none, and refuses the link.");
Assert.That(FileExportFormat.OPEN_DOCUMENT_TEXT.FollowsPageAnchors(), Is.False, "LibreOffice does the same, verified on 2026-09-15 with an exported .odt.");
Assert.That(FileExportFormat.HTML.FollowsPageAnchors(), Is.True, "A browser opens the document on the page the fragment names.");
Assert.That(FileExportFormat.MARKDOWN.FollowsPageAnchors(), Is.True);
Assert.That(FileExportFormat.LATEX.FollowsPageAnchors(), Is.True);
Assert.That(FileExportFormat.MICROSOFT_WORD.FollowsPageAnchors, Is.False, "Word looks for a file whose name ends in the fragment, finds none, and refuses the link.");
Assert.That(FileExportFormat.OPEN_DOCUMENT_TEXT.FollowsPageAnchors, Is.False, "LibreOffice does the same, verified on 2026-09-15 with an exported .odt.");
Assert.That(FileExportFormat.HTML.FollowsPageAnchors, Is.True, "A browser opens the document on the page the fragment names.");
Assert.That(FileExportFormat.MARKDOWN.FollowsPageAnchors, Is.True);
Assert.That(FileExportFormat.LATEX.FollowsPageAnchors, Is.True);
}
}
@@ -27,7 +27,7 @@ public sealed class FileExportFormatTests
// Whoever adds a format decides what its reader can follow, rather than inheriting an
// assumption. This fails for a format which nobody thought about, because the list below
// has to name it:
Assert.That(FileExportFormatExtensions.ANSWER_FORMATS, Is.EquivalentTo(new[]
Assert.That(FileExportFormat.AnswerFormats, Is.EquivalentTo(new[]
{
FileExportFormat.MICROSOFT_WORD,
FileExportFormat.OPEN_DOCUMENT_TEXT,
@@ -59,10 +59,10 @@ public sealed class FileExportFormatTests
{
using (Assert.EnterMultipleScope())
{
Assert.That(FileExportFormat.HTML.NeedsPageTitle(), Is.True, "Without one, the browser tab shows the random name of the temporary file Pandoc read.");
Assert.That(FileExportFormat.MICROSOFT_WORD.NeedsPageTitle(), Is.False, "Word would keep it as a document property nobody asked for.");
Assert.That(FileExportFormat.OPEN_DOCUMENT_TEXT.NeedsPageTitle(), Is.False, "The same goes for an OpenDocument file.");
Assert.That(FileExportFormat.LATEX.NeedsPageTitle(), Is.False);
Assert.That(FileExportFormat.HTML.NeedsPageTitle, Is.True, "Without one, the browser tab shows the random name of the temporary file Pandoc read.");
Assert.That(FileExportFormat.MICROSOFT_WORD.NeedsPageTitle, Is.False, "Word would keep it as a document property nobody asked for.");
Assert.That(FileExportFormat.OPEN_DOCUMENT_TEXT.NeedsPageTitle, Is.False, "The same goes for an OpenDocument file.");
Assert.That(FileExportFormat.LATEX.NeedsPageTitle, Is.False);
}
}
@@ -81,9 +81,9 @@ public sealed class FileExportFormatTests
{
using (Assert.EnterMultipleScope())
{
Assert.That(FileExportFormatExtensions.TryFromCodeFenceLanguage(language, out var format), Is.True);
Assert.That(FileExportFormat.TryFromCodeFenceLanguage(language, out var format), Is.True);
Assert.That(format, Is.EqualTo(expectedFormat));
Assert.That(format.IsPlainText(), Is.True, "A code block holds text, so the export writes it as it is.");
Assert.That(format.IsPlainText, Is.True, "A code block holds text, so the export writes it as it is.");
}
}
@@ -92,16 +92,16 @@ public sealed class FileExportFormatTests
{
using (Assert.EnterMultipleScope())
{
Assert.That(FileExportFormat.MICROSOFT_WORD.IsPlainText(), Is.False, "A Word file is an archive, and writing text into one breaks it.");
Assert.That(FileExportFormat.OPEN_DOCUMENT_TEXT.IsPlainText(), Is.False);
Assert.That(FileExportFormat.NONE.IsPlainText(), Is.False, "No format means no file.");
Assert.That(FileExportFormat.UNKNOWN.IsPlainText(), Is.False);
Assert.That(FileExportFormat.HTML.IsPlainText(), Is.True, "A page the model wrote is a finished file, even though an entire answer needs Pandoc to become one.");
Assert.That(FileExportFormat.LATEX.IsPlainText(), Is.True);
Assert.That(FileExportFormat.MARKDOWN.IsPlainText(), Is.True);
Assert.That(FileExportFormat.CSV.IsPlainText(), Is.True);
Assert.That(FileExportFormat.TSV.IsPlainText(), Is.True);
Assert.That(FileExportFormat.SOURCE_CODE.IsPlainText(), Is.True, "Code is text, whatever its language.");
Assert.That(FileExportFormat.MICROSOFT_WORD.IsPlainText, Is.False, "A Word file is an archive, and writing text into one breaks it.");
Assert.That(FileExportFormat.OPEN_DOCUMENT_TEXT.IsPlainText, Is.False);
Assert.That(FileExportFormat.NONE.IsPlainText, Is.False, "No format means no file.");
Assert.That(FileExportFormat.UNKNOWN.IsPlainText, Is.False);
Assert.That(FileExportFormat.HTML.IsPlainText, Is.True, "A page the model wrote is a finished file, even though an entire answer needs Pandoc to become one.");
Assert.That(FileExportFormat.LATEX.IsPlainText, Is.True);
Assert.That(FileExportFormat.MARKDOWN.IsPlainText, Is.True);
Assert.That(FileExportFormat.CSV.IsPlainText, Is.True);
Assert.That(FileExportFormat.TSV.IsPlainText, Is.True);
Assert.That(FileExportFormat.SOURCE_CODE.IsPlainText, Is.True, "Code is text, whatever its language.");
}
}
@@ -110,9 +110,9 @@ public sealed class FileExportFormatTests
{
using (Assert.EnterMultipleScope())
{
Assert.That(FileExportFormat.SOURCE_CODE.ToFileExtension(), Is.Empty, "Python and Rust share the format, but not the extension.");
Assert.That(FileExportFormat.SOURCE_CODE.ToFileTypeFilter(), Is.Null, "Without the language, the save dialog would offer the wrong files.");
Assert.That(FileExportFormatExtensions.ANSWER_FORMATS, Does.Not.Contain(FileExportFormat.SOURCE_CODE), "Code is one block out of an answer, never the answer itself.");
Assert.That(FileExportFormat.SOURCE_CODE.FileExtension, Is.Empty, "Python and Rust share the format, but not the extension.");
Assert.That(FileExportFormat.SOURCE_CODE.FileTypeFilter, Is.Null, "Without the language, the save dialog would offer the wrong files.");
Assert.That(FileExportFormat.AnswerFormats, Does.Not.Contain(FileExportFormat.SOURCE_CODE), "Code is one block out of an answer, never the answer itself.");
}
}
@@ -124,7 +124,7 @@ public sealed class FileExportFormatTests
{
using (Assert.EnterMultipleScope())
{
Assert.That(FileExportFormatExtensions.TryFromCodeFenceLanguage(language, out var format), Is.False);
Assert.That(FileExportFormat.TryFromCodeFenceLanguage(language, out var format), Is.False);
Assert.That(format, Is.EqualTo(FileExportFormat.NONE));
}
}
@@ -63,8 +63,8 @@ public sealed class MailboxProviderTemplatesTests
[Test]
public void EveryUsernameFormatHasItsOwnDescription()
{
var descriptions = Enum.GetValues<MailboxUsernameFormat>().Select(format => format.GetDescription()).ToList();
var fallback = ((MailboxUsernameFormat)int.MaxValue).GetDescription();
var descriptions = Enum.GetValues<MailboxUsernameFormat>().Select(format => format.Description).ToList();
var fallback = ((MailboxUsernameFormat)int.MaxValue).Description;
using (Assert.EnterMultipleScope())
{
+4 -4
View File
@@ -162,10 +162,10 @@ public sealed class PassageProvenanceTests
{
using (Assert.EnterMultipleScope())
{
Assert.That(Passage(HANDBOOK_URL, "text").GetProvenanceKind(), Is.EqualTo(ProvenanceKind.DATA_SOURCE_PASSAGE));
Assert.That((Passage(HANDBOOK_URL, "text") with { Type = RetrievalContentType.TEXT_TRANSCRIPT }).GetProvenanceKind(), Is.EqualTo(ProvenanceKind.DATA_SOURCE_PASSAGE));
Assert.That((Passage(HANDBOOK_URL, "text") with { Type = RetrievalContentType.TEXT_EMAIL }).GetProvenanceKind(), Is.EqualTo(ProvenanceKind.MAIL), "A mail is a mail, whether a mailbox data source or a tool handed it over.");
Assert.That((Passage(HANDBOOK_URL, "text") with { Type = RetrievalContentType.TEXT_WEBSITE }).GetProvenanceKind(), Is.EqualTo(ProvenanceKind.WEB_PAGE));
Assert.That(Passage(HANDBOOK_URL, "text").ProvenanceKind, Is.EqualTo(ProvenanceKind.DATA_SOURCE_PASSAGE));
Assert.That((Passage(HANDBOOK_URL, "text") with { Type = RetrievalContentType.TEXT_TRANSCRIPT }).ProvenanceKind, Is.EqualTo(ProvenanceKind.DATA_SOURCE_PASSAGE));
Assert.That((Passage(HANDBOOK_URL, "text") with { Type = RetrievalContentType.TEXT_EMAIL }).ProvenanceKind, Is.EqualTo(ProvenanceKind.MAIL), "A mail is a mail, whether a mailbox data source or a tool handed it over.");
Assert.That((Passage(HANDBOOK_URL, "text") with { Type = RetrievalContentType.TEXT_WEBSITE }).ProvenanceKind, Is.EqualTo(ProvenanceKind.WEB_PAGE));
}
}
@@ -15,9 +15,9 @@ public sealed class LayoutPurposeTests
{
foreach (var purpose in Enum.GetValues<LayoutPurpose>())
{
Assert.That(purpose.Label(), Is.Not.Empty, $"The kind of slide {purpose} has no label.");
Assert.That(purpose.Question(), Does.EndWith("?"), $"The kind of slide {purpose} has no question.");
Assert.That(purpose.PromptDescription(), Is.Not.Empty.And.Not.EndWith("."), $"The kind of slide {purpose} has no description, or one which ends where the rule for the model goes on.");
Assert.That(purpose.Label, Is.Not.Empty, $"The kind of slide {purpose} has no label.");
Assert.That(purpose.Question, Does.EndWith("?"), $"The kind of slide {purpose} has no question.");
Assert.That(purpose.PromptDescription, Is.Not.Empty.And.Not.EndWith("."), $"The kind of slide {purpose} has no description, or one which ends where the rule for the model goes on.");
}
}
}
@@ -28,7 +28,7 @@ public sealed class LayoutPurposeTests
[Test]
public void EveryKindOfSlideHasALabelOfItsOwn()
{
var labels = Enum.GetValues<LayoutPurpose>().Select(purpose => purpose.Label()).ToList();
var labels = Enum.GetValues<LayoutPurpose>().Select(purpose => purpose.Label).ToList();
Assert.That(labels, Is.Unique);
}
@@ -42,7 +42,7 @@ public sealed class LayoutPurposeTests
[Test]
public void TheKindsOfSlidesFollowTheOrderOfTheAreas()
{
var areas = Enum.GetValues<LayoutPurpose>().Select(purpose => purpose.Area()).ToList();
var areas = Enum.GetValues<LayoutPurpose>().Select(purpose => purpose.Area).ToList();
using (Assert.EnterMultipleScope())
{
Assert.That(areas, Is.Ordered, "The kinds of an area stand together, and the areas follow their own order.");
@@ -433,7 +433,7 @@ public sealed class PresentationTemplateTests
(PlaceholderRole.TEXT, 3, StackedHeadings.THIRD_TEXT, 8U),
}), "The copies are numbered after the slots of the layout, in reading order.");
Assert.That(slide.SlotCopies.Select(copy => copy.Slot.Capacity), Is.EqualTo(new TextCapacity?[] { new TextCapacity(1, 14), new TextCapacity(3, 25), new TextCapacity(1, 18), new TextCapacity(3, 25) }), "A copy holds what its size allows, as a moved slot does.");
Assert.That(slide.Slots.Select(slot => $"{slot.Role.CatalogName()} {slot.Ordinal}"), Is.EqualTo(new[] { "title 1", "label 1", "text 1", "label 2", "text 2", "label 3", "text 3" }));
Assert.That(slide.Slots.Select(slot => $"{slot.Role.CatalogName} {slot.Ordinal}"), Is.EqualTo(new[] { "title 1", "label 1", "text 1", "label 2", "text 2", "label 3", "text 3" }));
Assert.That(slide.Contents.Select(content => (content.Slot.Role, content.Text)), Is.EqualTo(new[]
{
(PlaceholderRole.TITLE, "Missions"),
@@ -500,7 +500,7 @@ public sealed class PresentationTemplateTests
using (Assert.EnterMultipleScope())
{
Assert.That(slide.SlotCopies.Select(copy => (copy.Slot.Ordinal, copy.Slot.Bounds)), Is.EqualTo(new[] { (2, upperRight), (3, lowerRight) }));
Assert.That(slide.Slots.Select(slot => $"{slot.Role.CatalogName()} {slot.Ordinal}"), Is.EqualTo(new[] { "title 1", "label 1", "text 2", "text 1", "text 3" }), "The slots of the layout keep their numbers; a copy goes where a reader comes across it.");
Assert.That(slide.Slots.Select(slot => $"{slot.Role.CatalogName} {slot.Ordinal}"), Is.EqualTo(new[] { "title 1", "label 1", "text 2", "text 1", "text 3" }), "The slots of the layout keep their numbers; a copy goes where a reader comes across it.");
}
}
+2 -2
View File
@@ -121,7 +121,7 @@ public sealed class SourceCodeLanguagesTests
[Test]
public void NoAliasNamesAFormatOfItsOwn()
{
// FileExportFormatExtensions.TryFromCodeFenceLanguage is asked first, so such an entry would never be found:
Assert.That(SourceCodeLanguages.Aliases.Where(alias => FileExportFormatExtensions.TryFromCodeFenceLanguage(alias, out _)), Is.Empty);
// FileExportFormat.TryFromCodeFenceLanguage is asked first, so such an entry would never be found:
Assert.That(SourceCodeLanguages.Aliases.Where(alias => FileExportFormat.TryFromCodeFenceLanguage(alias, out _)), Is.Empty);
}
}
+2 -2
View File
@@ -279,8 +279,8 @@ public sealed class SourcePassageTests
{
using (Assert.EnterMultipleScope())
{
Assert.That((Passage(HANDBOOK_URL, "Welcome.") with { Type = RetrievalContentType.TEXT_TRANSCRIPT }).IsTranscript(), Is.True);
Assert.That(Passage(HANDBOOK_URL, "Welcome.").IsTranscript(), Is.False);
Assert.That((Passage(HANDBOOK_URL, "Welcome.") with { Type = RetrievalContentType.TEXT_TRANSCRIPT }).IsTranscript, Is.True);
Assert.That(Passage(HANDBOOK_URL, "Welcome.").IsTranscript, Is.False);
}
}
@@ -65,7 +65,7 @@ public sealed class MailPassageTests
Assert.That(new[] { passage }.GetPassagesOf(MAIL_SOURCE), Is.EqualTo(new[] { passage }), "Only a passage under its source gets the eye next to it.");
Assert.That(passage.Path, Is.Empty, "The address of a mail names it for AI Studio only, so there is nothing to copy or open.");
Assert.That(passage.DataSourceName, Is.EqualTo(MAIL_SOURCE.Title));
Assert.That(passage.GetProvenanceKind(), Is.EqualTo(ProvenanceKind.MAIL));
Assert.That(passage.ProvenanceKind, Is.EqualTo(ProvenanceKind.MAIL));
}
}
}
@@ -140,7 +140,7 @@ public sealed class ToolOutboundDataTests : ToolRegistryTestBase
Assert.That(hasRun, Is.False, "The mail would already have left AI Studio.");
Assert.That(outcome.Trace.Status, Is.EqualTo(ToolInvocationTraceStatus.BLOCKED));
Assert.That(outcome.Content, Does.Contain("Work mailbox"), "The user learns which mailbox stands in the way.");
Assert.That(outcome.Content, Does.Contain(OutboundDataRestriction.ONLY_LINKS_FROM_CHAT.GetName()));
Assert.That(outcome.Content, Does.Contain(OutboundDataRestriction.ONLY_LINKS_FROM_CHAT.Name));
}
}
@@ -154,7 +154,7 @@ public sealed class ToolOutboundDataTests : ToolRegistryTestBase
{
Assert.That(message, Does.Contain("removed since"));
Assert.That(message, Does.Not.Contain("Private mailbox"), "Another mailbox did not restrict the chat.");
Assert.That(message, Does.Contain(OutboundDataRestriction.ONLY_CONFIGURED_SERVICES.GetName()), "The restriction stays, so the user still learns why.");
Assert.That(message, Does.Contain(OutboundDataRestriction.ONLY_CONFIGURED_SERVICES.Name), "The restriction stays, so the user still learns why.");
}
}
@@ -168,7 +168,7 @@ public sealed class ToolOutboundDataTests : ToolRegistryTestBase
{
Assert.That(message, Does.Contain("Confluence wiki"), "The user learns that the wiki stands in the way.");
Assert.That(message, Does.Not.Contain("mailbox"), "No mailbox restricted the chat.");
Assert.That(message, Does.Contain(OutboundDataRestriction.ONLY_LINKS_FROM_CHAT.GetName()));
Assert.That(message, Does.Contain(OutboundDataRestriction.ONLY_LINKS_FROM_CHAT.Name));
}
}
@@ -182,7 +182,7 @@ public sealed class ToolOutboundDataTests : ToolRegistryTestBase
{
Assert.That(message, Does.Contain("intranet.example.org"), "The user learns which page stands in the way.");
Assert.That(message, Does.Not.Contain("mailbox"), "No mailbox restricted the chat.");
Assert.That(message, Does.Contain(OutboundDataRestriction.ONLY_CONFIGURED_SERVICES.GetName()));
Assert.That(message, Does.Contain(OutboundDataRestriction.ONLY_CONFIGURED_SERVICES.Name));
}
}
@@ -196,7 +196,7 @@ public sealed class ToolOutboundDataTests : ToolRegistryTestBase
{
Assert.That(message, Does.Contain("Project files"), "The user learns which data source stands in the way.");
Assert.That(message, Does.Not.Contain("mailbox"), "No mailbox restricted the chat.");
Assert.That(message, Does.Contain(OutboundDataRestriction.ONLY_LINKS_FROM_CHAT.GetName()));
Assert.That(message, Does.Contain(OutboundDataRestriction.ONLY_LINKS_FROM_CHAT.Name));
}
}
@@ -210,7 +210,7 @@ public sealed class ToolOutboundDataTests : ToolRegistryTestBase
{
Assert.That(message, Does.Contain("removed since"));
Assert.That(message, Does.Not.Contain("Minutes"), "Another data source did not restrict the chat.");
Assert.That(message, Does.Contain(OutboundDataRestriction.ONLY_CONFIGURED_SERVICES.GetName()), "The restriction stays, so the user still learns why.");
Assert.That(message, Does.Contain(OutboundDataRestriction.ONLY_CONFIGURED_SERVICES.Name), "The restriction stays, so the user still learns why.");
}
}
@@ -37,7 +37,7 @@ public sealed class MailboxValidationTests
[TestCase(MailboxTransportSecurity.SSL_ON_CONNECT, ExpectedResult = 993)]
[TestCase(MailboxTransportSecurity.STARTTLS, ExpectedResult = 143)]
[TestCase(MailboxTransportSecurity.UNKNOWN, ExpectedResult = null)]
public int? EachEncryptionComesWithItsUsualPort(MailboxTransportSecurity transportSecurity) => transportSecurity.GetUsualPort();
public int? EachEncryptionComesWithItsUsualPort(MailboxTransportSecurity transportSecurity) => transportSecurity.UsualPort;
[TestCase(0, ExpectedResult = false)]
[TestCase(DataSourceValidation.MIN_ATTACHMENT_SIZE_MEGABYTES, ExpectedResult = true)]