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