From 6d1ece1fbcc9d919664165c513dae876f9b45a40 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Sun, 1 Nov 2026 13:41:23 +0100 Subject: [PATCH] Embedded Blazor's script into the app, since .NET 10 moved it out of the framework --- .../MindWork AI Studio.csproj | 31 +++++++++++++++++ .../Tools/AppAccess/WebRootFilesTests.cs | 34 +++++++++++++++++-- .../InternalPluginResourcesTests.cs | 29 ++++++++++++++++ 3 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 app/Tests/Tools/PluginSystem/InternalPluginResourcesTests.cs diff --git a/app/MindWork AI Studio/MindWork AI Studio.csproj b/app/MindWork AI Studio/MindWork AI Studio.csproj index fee90113d..87449d584 100644 --- a/app/MindWork AI Studio/MindWork AI Studio.csproj +++ b/app/MindWork AI Studio/MindWork AI Studio.csproj @@ -45,6 +45,13 @@ --> IL2026, CS8974 latest + + + true @@ -207,4 +214,28 @@ + + + + $(BlazorFrameworkStaticWebAssetRoot)\blazor.web.js + + + + + + + + + + diff --git a/app/Tests/Tools/AppAccess/WebRootFilesTests.cs b/app/Tests/Tools/AppAccess/WebRootFilesTests.cs index 8ddef6e70..78084c529 100644 --- a/app/Tests/Tools/AppAccess/WebRootFilesTests.cs +++ b/app/Tests/Tools/AppAccess/WebRootFilesTests.cs @@ -1,3 +1,6 @@ +using System.Runtime.CompilerServices; +using System.Text.RegularExpressions; + using AIStudio.Assistants.ERI; using AIStudio.Tools; @@ -6,12 +9,15 @@ using Changelog = AIStudio.Components.Changelog; namespace AIStudio.Tests.Tools.AppAccess; /// -/// Checks that the app reads the files below wwwroot which it shows itself. +/// Checks that the app reads the files below wwwroot which it shows itself, and that the release +/// can serve every file which the page of the app loads. /// /// /// The changelogs and the ERI specifications come from the files embedded into the app, not from a /// request to its own server. A file which is missing there would leave the changelog or the ERI -/// assistant empty without any error. +/// assistant empty without any error. The release serves its static files from the same embedded +/// files; one which is missing there leaves the window without styles, or without any interaction +/// at all, while a debug build keeps working. /// [TestFixture] public sealed class WebRootFilesTests @@ -20,6 +26,30 @@ public sealed class WebRootFilesTests private static IEnumerable SpecificationVersions() => Enum.GetValues().Where(version => version.WasSpecificationSelected()); + private static string ReadAppPageSource([CallerFilePath] string sourceFilePath = "") => File.ReadAllText(Path.Combine(Path.GetDirectoryName(sourceFilePath)!, "..", "..", "..", "MindWork AI Studio", "App.razor")); + + /// + /// Reads the scripts and style sheets which App.razor loads from the app itself, so that a new one + /// is checked without anybody having to add it to a test. + /// + private static IEnumerable FilesOfTheAppPage() => Regex.Matches(ReadAppPageSource(), @"<(?:script|link)\b[^>]*\b(?:src|href)=""(?[^""]+)""") + .Select(match => match.Groups["path"].Value) + .Where(path => !path.Contains("//", StringComparison.Ordinal)); + + [Test] + public void TheAppPageLoadsFilesOfTheApp() + { + Assert.That(FilesOfTheAppPage(), Does.Contain("_framework/blazor.web.js").And.Contain("app.css"), "The test no longer finds the scripts and style sheets in App.razor."); + } + + [TestCaseSource(nameof(FilesOfTheAppPage))] + public void EveryFileOfTheAppPageIsEmbedded(string path) + { + var file = new WebRootFiles().FileProvider.GetFileInfo(path); + Assert.That(file.Exists, Is.True, $"The release would not serve '{path}', since it is not among the embedded files."); + Assert.That(file.Length, Is.GreaterThan(0), $"The release would serve '{path}' as an empty file."); + } + [TestCaseSource(nameof(ChangelogFiles))] public async Task EveryChangelogCanBeRead(string filename) { diff --git a/app/Tests/Tools/PluginSystem/InternalPluginResourcesTests.cs b/app/Tests/Tools/PluginSystem/InternalPluginResourcesTests.cs new file mode 100644 index 000000000..c06806c25 --- /dev/null +++ b/app/Tests/Tools/PluginSystem/InternalPluginResourcesTests.cs @@ -0,0 +1,29 @@ +using System.Reflection; + +using AIStudio.Tools.PluginSystem; + +using Microsoft.Extensions.FileProviders; + +namespace AIStudio.Tests.Tools.PluginSystem; + +/// +/// Checks that the release finds the plugins which ship with AI Studio, such as the language plugins. +/// +/// +/// A debug build reads these plugins from the source tree, while the release copies them out of the +/// files embedded into the app. A plugin which is missing there would leave the release without its +/// language, and only an error in the log would tell. +/// +[TestFixture] +public sealed class InternalPluginResourcesTests +{ + [Test] + public void EveryInternalPluginIsEmbedded([Values] InternalPlugin plugin) + { + var embeddedPlugins = new ManifestEmbeddedFileProvider(Assembly.GetAssembly(type: typeof(Program))!, "Plugins"); + var mainFile = embeddedPlugins.GetFileInfo($"{plugin.MetaData().ResourcePath}/plugin.lua"); + + Assert.That(mainFile.Exists, Is.True, $"The release would not find the plugin {plugin}, since it is not among the embedded files."); + Assert.That(mainFile.Length, Is.GreaterThan(0), $"The release would find the plugin {plugin} empty."); + } +} \ No newline at end of file