exchanger/tests/Exchanger.Tests/ProjectAssetSmokeTests.cs

533 lines
28 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using NUnit.Framework;
namespace Exchanger.Tests;
[TestFixture]
public sealed class ProjectAssetSmokeTests
{
private static readonly string[] ScenePaths =
[
"src/scenes/App/App.tscn",
"src/scenes/HomeScreen/HomeScreen.tscn",
"src/scenes/CashPaymentScreen/CashPaymentScreen.tscn",
"src/scenes/CardAmountScreen/CardAmountScreen.tscn",
"src/scenes/CardCustomAmountScreen/CardCustomAmountScreen.tscn",
"src/scenes/CardTerminalScreen/CardTerminalScreen.tscn",
"src/scenes/SuccessScreen/SuccessScreen.tscn",
"src/scenes/ErrorScreen/ErrorScreen.tscn",
"src/scenes/SettingsScreen/SettingsScreen.tscn",
"src/scenes/ServiceAccessScreen/ServiceAccessScreen.tscn",
"src/ui/ConnectionStatusIndicator/ConnectionStatusIndicator.tscn",
];
[TestCaseSource(nameof(ScenePaths))]
public void SceneFile_ExistsAndHasGodotHeader(string relativePath)
{
string path = Path.Combine(ProjectPaths.FindRoot(), relativePath);
Assert.That(File.Exists(path), Is.True, $"Не найдена сцена {relativePath}");
Assert.That(File.ReadLines(path).FirstOrDefault(), Does.StartWith("[gd_scene"));
}
[TestCase("src/scenes/HomeScreen/HomeScreen.tscn", "theme_type_variation = &\"PanelTitle\"")]
[TestCase("src/scenes/CashPaymentScreen/CashPaymentScreen.tscn", "theme_type_variation = &\"PrimaryButton\"")]
[TestCase("src/scenes/CardAmountScreen/CardAmountScreen.tscn", "theme_type_variation = &\"WhitePanel\"")]
[TestCase("src/scenes/CardCustomAmountScreen/CardCustomAmountScreen.tscn", "theme_type_variation = &\"CompactButton\"")]
[TestCase("src/scenes/CardTerminalScreen/CardTerminalScreen.tscn", "theme_type_variation = &\"PanelText\"")]
[TestCase("src/scenes/SuccessScreen/SuccessScreen.tscn", "theme_type_variation = &\"PanelTitle\"")]
[TestCase("src/scenes/ErrorScreen/ErrorScreen.tscn", "theme_type_variation = &\"ErrorText\"")]
[TestCase("src/scenes/ServiceAccessScreen/ServiceAccessScreen.tscn", "theme_type_variation = &\"SecondaryButton\"")]
public void UserAndServiceScene_DeclaresSemanticThemeContract(string relativePath, string marker)
{
string content = File.ReadAllText(Path.Combine(ProjectPaths.FindRoot(), relativePath));
Assert.That(content, Does.Contain(marker));
}
[Test]
public void SettingsScreen_AppliesSemanticThemeContractOnlyToFallbackVisuals()
{
string content = File.ReadAllText(Path.Combine(
ProjectPaths.FindRoot(),
"src/scenes/SettingsScreen/SettingsScreen.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(content, Does.Contain("if (!UsesSelfContainedThemeScene)"));
Assert.That(content, Does.Contain("ApplyFallbackThemeSemantics();"));
Assert.That(content, Does.Contain("ThemeSemanticTypes.SectionTabButton"));
Assert.That(content, Does.Contain("ThemeSemanticTypes.DangerButton"));
Assert.That(content, Does.Contain("case CheckButton:"));
Assert.That(content, Does.Contain("case OptionButton:"));
}
}
[Test]
public void SettingsScreen_HandlesSingleTouchAndHeldMouseDragScrolling()
{
string root = ProjectPaths.FindRoot();
string project = File.ReadAllText(Path.Combine(root, "project.godot"));
string settings = File.ReadAllText(Path.Combine(
root,
"src/scenes/SettingsScreen/SettingsScreen.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(project, Does.Contain("pointing/emulate_touch_from_mouse=true"));
Assert.That(settings, Does.Contain("case InputEventScreenTouch touch when touch.Index == 0:"));
Assert.That(settings, Does.Contain("case InputEventScreenDrag drag when drag.Index == _activeScrollTouchIndex:"));
Assert.That(settings, Does.Contain("case InputEventMouseButton { ButtonIndex: MouseButton.Left } mouseButton:"));
Assert.That(settings, Does.Contain("_scroll.ScrollVertical = _scrollDragStartOffset - Mathf.RoundToInt(dragDistance);"));
Assert.That(settings, Does.Contain("Mathf.Abs(dragDistance) < ScrollDragDeadzonePixels"));
}
}
[Test]
public void SettingsScreen_HasFixedSaveAndExitFooterOutsideScrollableContent()
{
string root = ProjectPaths.FindRoot();
string scene = File.ReadAllText(Path.Combine(
root,
"src/scenes/SettingsScreen/SettingsScreen.tscn"));
string settings = File.ReadAllText(Path.Combine(
root,
"src/scenes/SettingsScreen/SettingsScreen.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(scene, Does.Contain("[node name=\"Footer\" type=\"PanelContainer\" parent=\".\""));
Assert.That(scene, Does.Contain("[node name=\"SaveAndExitButton\" type=\"Button\" parent=\"Footer\""));
Assert.That(scene, Does.Not.Contain("parent=\"SafeMargin/Scroll/Content/Footer\""));
Assert.That(scene, Does.Contain("text = \"СОХРАНИТЬ И ВЫЙТИ\""));
Assert.That(scene, Does.Contain("custom_minimum_size = Vector2(0, 1100)"));
Assert.That(settings, Does.Contain("SaveAndExitRequested?.Invoke();"));
Assert.That(settings, Does.Contain("_footer.GetGlobalRect().HasPoint(pointerPosition)"));
Assert.That(settings, Does.Contain("_onScreenKeyboard.VisibilityChanged += OnScreenKeyboardVisibilityChanged;"));
Assert.That(settings, Does.Contain("_saveAndExitButton.Disabled = isVisible;"));
Assert.That(settings, Does.Contain("_saveAndExitButton.MouseFilter = isVisible"));
Assert.That(settings, Does.Contain("_footer.MouseFilter = isVisible"));
Assert.That(settings, Does.Contain("if (_onScreenKeyboard?.IsVisible ?? false)"));
}
}
[Test]
public void PhysicalServiceButton_BypassesOnlyTheOnScreenButtonGuard()
{
string root = ProjectPaths.FindRoot();
string app = File.ReadAllText(Path.Combine(root, "src/scenes/App/App.cs"));
string settings = File.ReadAllText(Path.Combine(
root,
"src/scenes/SettingsScreen/SettingsScreen.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(app, Does.Contain("_peripheryController.ServiceRequested += OnPhysicalServiceRequested;"));
Assert.That(app, Does.Contain("if (_settingsScreen.TryFinishEditing())"));
Assert.That(settings, Does.Contain("private void OnSaveAndExitPressed()"));
Assert.That(settings, Does.Contain("if (_onScreenKeyboard?.IsVisible ?? false)"));
Assert.That(settings, Does.Contain("_onScreenKeyboard?.Hide();"));
}
}
[Test]
public void ServiceManualAddition_OpensRegisteredNumericKeyboard()
{
string root = ProjectPaths.FindRoot();
string settings = File.ReadAllText(Path.Combine(
root,
"src/scenes/SettingsScreen/SettingsScreen.cs"));
string keyboard = File.ReadAllText(Path.Combine(
root,
"src/ui/OnScreenKeyboard/OnScreenKeyboardController.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(settings, Does.Contain("ShowServiceDialogNumericKeyboard();"));
Assert.That(settings, Does.Contain("_onScreenKeyboard?.ShowNumericField(_serviceDialogAmount);"));
Assert.That(keyboard, Does.Contain("public void ShowNumericField(SpinBox spinBox)"));
Assert.That(keyboard, Does.Contain("if (!_scroll.IsAncestorOf(field))"));
Assert.That(keyboard, Does.Contain("edit.EmitSignal(LineEdit.SignalName.TextChanged, edit.Text);"));
Assert.That(keyboard, Does.Contain("ApplyTextMutation(edit"));
}
}
[TestCase("src/scenes/SuccessScreen/SuccessScreen.cs")]
[TestCase("src/scenes/CardAmountScreen/CardAmountScreen.cs")]
[TestCase("src/scenes/CardTerminalScreen/CardTerminalScreen.cs")]
[TestCase("src/scenes/CashPaymentScreen/CashPaymentSummaryFormatter.cs")]
[TestCase("src/scenes/CardCustomAmountScreen/CardCustomAmountDisplayFormatter.cs")]
public void CustomerFacingTokenCounts_UseSharedRussianDeclension(string relativePath)
{
string content = File.ReadAllText(Path.Combine(ProjectPaths.FindRoot(), relativePath));
Assert.That(content, Does.Contain("TokenCountFormatter.Format"));
}
[Test]
public void SelfContainedThemeScreens_AreNotRestyledByHostControllers()
{
string root = ProjectPaths.FindRoot();
string themeManager = File.ReadAllText(Path.Combine(
root,
"src/core/ThemeManager/ThemeManager.cs"));
string bindableScreen = File.ReadAllText(Path.Combine(
root,
"src/core/ThemeManager/ThemeBindableScreen.cs"));
string settings = File.ReadAllText(Path.Combine(
root,
"src/scenes/SettingsScreen/SettingsScreen.cs"));
string cardKeypad = File.ReadAllText(Path.Combine(
root,
"src/scenes/CardCustomAmountScreen/CardCustomAmountScreen.cs"));
string serviceKeypad = File.ReadAllText(Path.Combine(
root,
"src/scenes/ServiceAccessScreen/ServiceAccessScreen.cs"));
string home = File.ReadAllText(Path.Combine(
root,
"src/scenes/HomeScreen/HomeScreen.cs"));
string cardAmount = File.ReadAllText(Path.Combine(
root,
"src/scenes/CardAmountScreen/CardAmountScreen.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(bindableScreen, Does.Contain("UsesSelfContainedThemeScene"));
Assert.That(bindableScreen, Does.Not.Contain("themeView.Name ="));
Assert.That(bindableScreen, Does.Not.Contain("themeView.SetAnchorsAndOffsetsPreset"));
Assert.That(themeManager, Does.Contain("UsesSelfContainedThemeScene: true"));
Assert.That(settings, Does.Not.Contain(".Modulate = show"));
Assert.That(home, Does.Not.Contain("MountRuntimeComponent"));
Assert.That(home, Does.Contain("home.scroll.content.stock_status.state"));
Assert.That(home, Does.Not.Contain("Branding.Subtitle"));
Assert.That(home, Does.Contain("SafeMargin/Scroll/Content/SpeechText"));
Assert.That(home, Does.Contain("_speechTextLabel.Text = _settings.Branding.ShortText;"));
Assert.That(home, Does.Contain("_speechTextLabel.Visible = _settings.MenuVisibility.ShowCustomText;"));
Assert.That(home, Does.Contain("home.decoration.custom_text_block"));
Assert.That(settings, Does.Contain("BrandingValidationField.ShortText"));
Assert.That(settings, Does.Not.Contain("BrandingValidationField.Subtitle"));
Assert.That(settings, Does.Contain("ПОКАЗЫВАТЬ ПОЛЬЗОВАТЕЛЬСКИЙ ТЕКСТ"));
Assert.That(cardAmount, Does.Contain("preset_grid.slot_{index:00}"));
Assert.That(settings, Does.Contain("bonus_panel.margin.content.rows"));
Assert.That(settings, Does.Contain("advertisement_playlist_panel.margin.content.rows"));
Assert.That(cardKeypad, Does.Contain("if (!UsesSelfContainedThemeScene)"));
Assert.That(serviceKeypad, Does.Contain("if (!UsesSelfContainedThemeScene)"));
}
}
[Test]
public void TrustedThemeRuntime_AllowsScriptsAndArbitraryRuntimeNodes()
{
string root = ProjectPaths.FindRoot();
string contract = File.ReadAllText(Path.Combine(
root,
"src/core/ThemeManager/ThemeSceneContract.cs"));
string staticBackground = File.ReadAllText(Path.Combine(
root,
"src/ui/StaticBackground/StaticBackground.cs"));
string visualSlot = File.ReadAllText(Path.Combine(
root,
"src/ui/ThemeVisualSlot/ThemeVisualSlot.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(contract, Does.Not.Contain("ScriptNotAllowed"));
Assert.That(contract, Does.Not.Contain("GetScript()"));
Assert.That(contract, Does.Not.Contain("ThemeDecorationBudget"));
Assert.That(staticBackground, Does.Not.Contain("ThemeDecorationBudget"));
Assert.That(visualSlot, Does.Not.Contain("ThemeDecorationBudget"));
}
}
[Test]
public void SettingsScreen_ExposesOnlyOwnerFacingSections()
{
string root = ProjectPaths.FindRoot();
string scene = File.ReadAllText(Path.Combine(
root,
"src/scenes/SettingsScreen/SettingsScreen.tscn"));
string code = File.ReadAllText(Path.Combine(
root,
"src/scenes/SettingsScreen/SettingsScreen.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(scene, Does.Not.Contain("НАСТРОЙКИ ВЛАДЕЛЬЦА АВТОМАТА"));
Assert.That(scene, Does.Not.Contain("Готовые суммы и ручной ввод используют общий диапазон и шаг."));
Assert.That(scene, Does.Not.Contain("Короткий сигнал не запускает оплату, промо или выдачу жетонов."));
Assert.That(scene, Does.Not.Contain("FALLBACK-ТЕКСТ"));
Assert.That(scene, Does.Not.Contain("text = \"ТАЙМАУТЫ\""));
Assert.That(scene, Does.Contain("text = \"ТЕКСТ НА ГЛАВНОМ ЭКРАНЕ\""));
Assert.That(scene, Does.Contain("text = \"СВОЙ ТЕКСТ • ДО 48 ЗНАКОВ\""));
Assert.That(scene, Does.Not.Contain("text = \"КОРОТКИЙ ТЕКСТ • ДО 48 ЗНАКОВ\""));
Assert.That(scene, Does.Contain("text = \"ТЕКСТ ВМЕСТО ПРОМО • ДО 120 ЗНАКОВ\""));
Assert.That(scene, Does.Contain("text = \"ВРЕМЯ ОЖИДАНИЯ\""));
Assert.That(scene, Does.Contain("text = \"ОБЩИЕ\""));
Assert.That(scene, Does.Contain("text = \"ЗВУК\""));
Assert.That(scene, Does.Contain("text = \"ПРОМО\""));
Assert.That(scene, Does.Contain("text = \"ТАРИФЫ\""));
Assert.That(scene, Does.Contain("text = \"ОПЛАТА\""));
Assert.That(scene, Does.Contain("text = \"СЕРВИС\""));
Assert.That(scene, Does.Contain("text = \"УЧЁТ ЖЕТОНОВ\""));
Assert.That(scene, Does.Contain("text = \"УЧИТЫВАТЬ ОСТАТОК ЖЕТОНОВ\""));
Assert.That(scene, Does.Contain("text = \"НЕ ПРОДАВАТЬ БОЛЬШЕ ОСТАТКА\""));
Assert.That(scene, Does.Contain("ServiceInventoryPanel/Margin/Content/Hopper1"));
Assert.That(scene, Does.Contain("ServiceInventoryPanel/Margin/Content/Hopper2"));
Assert.That(scene, Does.Contain("text = \"ХОППЕР 1 — ОСТАТОК: 0 ЖЕТОНОВ\""));
Assert.That(scene, Does.Contain("text = \"ХОППЕР 2 — ОСТАТОК: 0 ЖЕТОНОВ\""));
Assert.That(scene, Does.Contain("text = \"ПЕРЕСЧИТАТЬ\""));
Assert.That(scene, Does.Contain("text = \"ДОБАВИТЬ\""));
Assert.That(code, Does.Contain("SetTokenInventoryCounts(int hopper1Count, int hopper2Count)"));
Assert.That(code, Does.Contain("SetConfiguredHoppers(bool hopper1Configured, bool hopper2Configured)"));
Assert.That(code, Does.Contain("_serviceHopper1RecountButton.Visible = enabled && _hopper1Configured;"));
Assert.That(code, Does.Contain("_serviceHopper2RecountButton.Visible = enabled && _hopper2Configured;"));
Assert.That(code, Does.Contain("_serviceInventoryCount.Visible = enabled;"));
Assert.That(code, Does.Contain("_purchaseLimitEnabled.Visible = enabled;"));
Assert.That(code, Does.Contain("TokenInventoryPolicy.FormatHopperExactCount(1, hopper1)"));
Assert.That(code, Does.Contain("TokenInventoryPolicy.FormatHopperExactCount(2, hopper2)"));
Assert.That(code, Does.Contain("_appearanceSectionButton.Visible = false;"));
Assert.That(code, Does.Contain("_equipmentSectionButton.Visible = false;"));
Assert.That(code, Does.Contain("_diagnosticsSectionButton.Visible = false;"));
Assert.That(code, Does.Contain("_applicationName.Visible = false;"));
Assert.That(code, Does.Contain("_brandingPreviewPanel.Visible = false;"));
Assert.That(code, Does.Contain("BrandingValidationField.ShortText or BrandingValidationField.SupportPhone"));
Assert.That(code, Does.Contain("_advertisementPreviewPanel.Visible = false;"));
Assert.That(code, Does.Contain("_diagnosticsTestPanel.Visible = false;"));
}
}
[Test]
public void App_UpdatesExistingSupportLabelInsideExternalThemeFooter()
{
string root = ProjectPaths.FindRoot();
string code = File.ReadAllText(Path.Combine(root, "src/scenes/App/App.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(code, Does.Contain("footer.FindChild(\"Support\", recursive: true, owned: false) is Label supportLabel"));
Assert.That(code, Does.Contain("supportLabel.Text = $\"ТЕХПОДДЕРЖКА:\\n{_settings.Branding.SupportPhone}\""));
Assert.That(code, Does.Contain("не добавляя и не перестраивая её визуальные узлы"));
}
}
[Test]
public void SettingsScreen_ContainsThemeOwnedOnScreenKeyboards()
{
string root = ProjectPaths.FindRoot();
string scene = File.ReadAllText(Path.Combine(
root,
"src/scenes/SettingsScreen/SettingsScreen.tscn"));
string code = File.ReadAllText(Path.Combine(
root,
"src/scenes/SettingsScreen/SettingsScreen.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(scene, Does.Contain("parent=\"SafeMargin/KeyboardOverlay/TextKeyboard\""));
Assert.That(scene, Does.Contain("parent=\"SafeMargin/KeyboardOverlay/NumericKeyboard\""));
Assert.That(scene, Does.Contain("name=\"Key_00\""));
Assert.That(scene, Does.Contain("name=\"Key_32\""));
Assert.That(scene, Does.Contain("name=\"Digit0\""));
Assert.That(scene, Does.Contain("name=\"Digit9\""));
Assert.That(scene, Does.Contain("name=\"HideButton\""));
Assert.That(
System.Text.RegularExpressions.Regex.Matches(scene, "name=\\\"Key_[0-9]{2}\\\"").Count,
Is.EqualTo(33));
Assert.That(
System.Text.RegularExpressions.Regex.Matches(scene, "name=\\\"Digit[0-9]\\\"").Count,
Is.EqualTo(10));
Assert.That(code, Does.Contain("new OnScreenKeyboardController"));
Assert.That(code, Does.Contain("RegisterEditableDescendants(_scroll)"));
Assert.That(code, Does.Not.Contain("new Button { Text = \"й\""));
}
}
[Test]
public void CardCustomAmount_PrimaryEraseButtonDeletesOnlyLastDigit()
{
string root = ProjectPaths.FindRoot();
string scene = File.ReadAllText(Path.Combine(
root,
"src/scenes/CardCustomAmountScreen/CardCustomAmountScreen.tscn"));
string code = File.ReadAllText(Path.Combine(
root,
"src/scenes/CardCustomAmountScreen/CardCustomAmountScreen.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(scene, Does.Contain("text = \"СТЕРЕТЬ\""));
Assert.That(code, Does.Contain("_clearButton.Pressed += Backspace;"));
Assert.That(code, Does.Contain("_digits = _digits[..^1];"));
Assert.That(code, Does.Not.Contain("_clearButton.Pressed += Clear;"));
}
}
[Test]
public void SettingsScreen_BonusAmountHasNoSuffixThatHidesDigits()
{
string code = File.ReadAllText(Path.Combine(
ProjectPaths.FindRoot(),
"src/scenes/SettingsScreen/SettingsScreen.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(code, Does.Not.Contain("Suffix = \" жет."));
Assert.That(code, Does.Contain("slot.Bonus.Suffix = string.Empty;"));
}
}
[Test]
public void OnScreenKeyboardController_DoesNotConstructThemeVisualNodes()
{
string content = File.ReadAllText(Path.Combine(
ProjectPaths.FindRoot(),
"src/ui/OnScreenKeyboard/OnScreenKeyboardController.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(content, Does.Not.Contain("new Button"));
Assert.That(content, Does.Not.Contain("new PanelContainer"));
Assert.That(content, Does.Not.Contain("AddChild("));
Assert.That(content, Does.Not.Contain("SetAnchors"));
Assert.That(content, Does.Not.Contain("CustomMinimumSize"));
Assert.That(content, Does.Not.Contain("SizeFlagsHorizontal"));
Assert.That(content, Does.Not.Contain("SizeFlagsVertical"));
Assert.That(content, Does.Contain("VirtualKeyboardEnabled = false"));
Assert.That(content, Does.Contain("EnsureControlVisible"));
Assert.That(content, Does.Contain("_activeSpinBox!.Apply()"));
}
}
[Test]
public void ServiceAccessScreen_UsesOwnerFriendlyLanguage()
{
string root = ProjectPaths.FindRoot();
string scene = File.ReadAllText(Path.Combine(
root,
"src/scenes/ServiceAccessScreen/ServiceAccessScreen.tscn"));
string code = File.ReadAllText(Path.Combine(
root,
"src/scenes/ServiceAccessScreen/ServiceAccessScreen.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(scene, Does.Contain("text = \"ВХОД В НАСТРОЙКИ\""));
Assert.That(scene, Does.Not.Contain("СЕРВИСНЫЙ ВХОД"));
Assert.That(scene, Does.Not.Contain("СЕРВИСНЫЙ PIN"));
Assert.That(code, Does.Not.Contain("доступ к конфигурации"));
}
}
[Test]
public void BuiltInTheme_DisablesTextShadowAndButtonOutline()
{
string content = File.ReadAllText(Path.Combine(
ProjectPaths.FindRoot(),
"src/core/ThemeManager/BuiltInFallbackTheme.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(content, Does.Contain("SetColor(\"font_shadow_color\", \"Label\", Colors.Transparent)"));
Assert.That(content, Does.Contain("SetConstant(\"shadow_offset_x\", \"Label\", 0)"));
Assert.That(content, Does.Contain("SetConstant(\"shadow_offset_y\", \"Label\", 0)"));
Assert.That(content, Does.Contain("SetConstant(\"outline_size\", \"Button\", 0)"));
}
}
[Test]
public void WindowsExport_UsesSanitizedStagingWithoutTestsOrEditorAddons()
{
string root = ProjectPaths.FindRoot();
string preset = File.ReadAllText(Path.Combine(root, "export_presets.cfg"));
string script = File.ReadAllText(Path.Combine(root, "tools/export-windows.ps1"));
using (Assert.EnterMultipleScope())
{
Assert.That(preset, Does.Contain("name=\"Windows x64 Release\""));
Assert.That(preset, Does.Contain("name=\"Windows x64 Debug\""));
Assert.That(
preset,
Does.Contain("export_path=\"artifacts/windows/release/Exchanger.exe\"").IgnoreCase);
Assert.That(
preset,
Does.Contain("export_path=\"artifacts/windows/debug/Exchanger.Debug.exe\"").IgnoreCase);
Assert.That(preset, Does.Contain("include_filter=\"config/*.toml\""));
Assert.That(preset, Does.Contain("tests/**"));
Assert.That(preset, Does.Contain("references/**"));
Assert.That(preset, Does.Not.Contain("addons/**"));
Assert.That(preset, Does.Contain("addons/godot_ai/**"));
Assert.That(preset, Does.Contain("addons/log/**"));
Assert.That(preset, Does.Contain("addons/reload_current_scene/**"));
Assert.That(preset, Does.Not.Contain("addons/godotx_toast/**"));
Assert.That(preset, Does.Not.Contain("addons/native_video/**"));
Assert.That(script, Does.Contain("artifacts\\export-staging"));
Assert.That(script, Does.Contain("[ValidateSet(\"Release\", \"Debug\")]"));
Assert.That(script, Does.Contain("--export-release"));
Assert.That(script, Does.Contain("--export-debug"));
Assert.That(script, Does.Contain("^_mcp_game_helper="));
Assert.That(script, Does.Contain("^GodotxToast="));
}
}
[Test]
public void NativeVideo_UsesMobileRendererAndProvidesBothRuntimeLibraries()
{
string root = ProjectPaths.FindRoot();
string project = File.ReadAllText(Path.Combine(root, "project.godot"));
using (Assert.EnterMultipleScope())
{
Assert.That(project, Does.Contain("config/features=PackedStringArray(\"4.7\", \"C#\", \"Mobile\")"));
Assert.That(File.Exists(Path.Combine(root, "addons", "native_video", "native_video.gdextension")), Is.True);
Assert.That(File.Exists(Path.Combine(root, "addons", "native_video", "native_video.windows.debug.x86_64.dll")), Is.True);
Assert.That(File.Exists(Path.Combine(root, "addons", "native_video", "native_video.windows.release.x86_64.dll")), Is.True);
Assert.That(File.Exists(Path.Combine(root, "addons", "native_video", "libnative_video.linux.debug.x86_64.so")), Is.True);
Assert.That(File.Exists(Path.Combine(root, "addons", "native_video", "libnative_video.linux.release.x86_64.so")), Is.True);
}
}
[Test]
public void AdvertisementPlayers_UseNormalStopUnbindLifecycleWithoutRetentionCache()
{
string root = ProjectPaths.FindRoot();
string nodePlayer = File.ReadAllText(Path.Combine(
root,
"src/ui/AdvertisementPlayer/AdvertisementPlayer.cs"));
string presenter = File.ReadAllText(Path.Combine(
root,
"src/ui/AdvertisementPlayer/AdvertisementPresenter.cs"));
foreach (string source in new[] { nodePlayer, presenter })
{
using (Assert.EnterMultipleScope())
{
Assert.That(source, Does.Contain("_videoPlayer.Stop();"));
Assert.That(source, Does.Contain("_videoPlayer.Stream = null;"));
Assert.That(source, Does.Not.Contain("Dictionary<string, VideoStreamPlayer>"));
Assert.That(source, Does.Not.Contain("MaximumRetainedVideoPlayers"));
Assert.That(source, Does.Not.Contain("Native Video does not safely destroy"));
}
}
}
[Test]
public void BundledConfiguration_IsReadThroughGodotFileAccess()
{
string root = ProjectPaths.FindRoot();
string loader = File.ReadAllText(Path.Combine(
root,
"src/core/Configuration/AppSettingsLoader.cs"));
using (Assert.EnterMultipleScope())
{
Assert.That(loader, Does.Contain("MaterializeEmbeddedResource"));
Assert.That(loader, Does.Contain("Godot.FileAccess.Open"));
Assert.That(loader, Does.Contain("user://config/.embedded/default_settings.json"));
Assert.That(loader, Does.Contain("user://config/.embedded/technical_settings.toml"));
Assert.That(loader, Does.Not.Contain("ProjectSettings.GlobalizePath(DefaultSettingsPath)"));
Assert.That(loader, Does.Not.Contain("ProjectSettings.GlobalizePath(DefaultTechnicalSettingsPath)"));
}
}
}