Danro-Jump/Assets/Tests/EditMode/Editor/PrizeResultOverlayWindowTests.cs
Danil Iarosh 2289c48bab Add prize showcase cell grid visualization to PrizeResultOverlay
- В шаблон GameplayOverlays.uxml добавлен контейнер PrizeStandContainer с тестовыми ячейками для корректного отображения структуры витрины в UI Builder.

- Убрано принудительное скрытие display: none для QR-контейнера в GameplayHud.uss для видимости в редакторе; скрытие теперь происходит при старте в C# скрипте.

- В GameplayHud.uss добавлены стили для сетки ячеек витрины и их цветовых состояний (готова к выдаче, пустая, открывается, открыта, ошибка).

- В PrizeResultOverlayWindow.cs реализован метод SetPrizeStandStatus для динамической генерации сетки ячеек витрины на основе их реального статуса.

- В GameplayHudController.cs интегрирован опрос состояний ячеек при выдаче физического приза с витрины и обновление их статуса на экране.

- В PrizeResultOverlayWindowTests.cs добавлен юнит-тест SetPrizeStandStatus_RendersCellsWithCorrectStatuses для верификации логики отображения ячеек.
2026-06-23 15:47:36 +03:00

167 lines
7.0 KiB
C#

using System.Collections.Generic;
using System.Reflection;
using DanroJump.Prizes;
using DanroJump.Prizes.Qr;
using DanroJump.UI.Gameplay;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.UIElements;
namespace DanroJump.Tests.EditMode
{
public sealed class PrizeResultOverlayWindowTests
{
[Test]
public void SetResult_ShowsBigPrizeNamePhoneAndRunStats()
{
var root = CreateRoot();
var window = new PrizeResultOverlayWindow(root);
window.SetResult(
new PrizeFlowResult(PrizeRewardKind.Big, score: 125, coins: 8, height: 42.4f),
"Наушники",
"+79990000000");
Assert.That(root.Q<Label>("PrizeResultTitle").text, Is.EqualTo("Большой приз: Наушники"));
Assert.That(root.Q<Label>("PrizeResultSubtitle").text, Is.EqualTo("Обратитесь к оператору: +79990000000"));
Assert.That(root.Q<Label>("PrizeResultDetails").text, Is.EqualTo("Очки: 125. Монеты: 8. Высота: 42 м."));
Assert.That(root.Q<VisualElement>("PrizeQrContainer").style.display.value, Is.EqualTo(DisplayStyle.None));
}
[Test]
public void ReturnButton_RaisesReturnRequested()
{
var root = CreateRoot();
var window = new PrizeResultOverlayWindow(root);
var raised = false;
window.ReturnRequested += () => raised = true;
typeof(PrizeResultOverlayWindow)
.GetMethod("HandleReturnClicked", BindingFlags.Instance | BindingFlags.NonPublic)
?.Invoke(window, null);
Assert.That(raised, Is.True);
}
[TestCase(PrizeRewardKind.QRCode, "QR-приз!")]
[TestCase(PrizeRewardKind.Hopper, "Приз из хоппера!")]
[TestCase(PrizeRewardKind.PrizeStand, "Приз на витрине!")]
public void SetResult_ShowsLegacyPrizeTypeTitles(PrizeRewardKind rewardKind, string expectedTitle)
{
var root = CreateRoot();
var window = new PrizeResultOverlayWindow(root);
window.SetResult(new PrizeFlowResult(rewardKind, score: 10, coins: 0, height: 1f));
Assert.That(root.Q<Label>("PrizeResultTitle").text, Is.EqualTo(expectedTitle));
}
[Test]
public void SetResult_QrPrizeShowsQrBlock()
{
var root = CreateRoot();
var window = new PrizeResultOverlayWindow(root);
var texture = new Texture2D(4, 4);
var ticket = new PrizeQrTicket(
"https://t.me/+79999999999?text=QR",
"+7 (999) 999-99-99",
"79999999999",
"QR message",
texture,
QrPrizeTier.Bronze);
try
{
window.SetResult(
new PrizeFlowResult(PrizeRewardKind.QRCode, score: 10, coins: 1, height: 5f),
qrTicket: ticket);
Assert.That(root.Q<VisualElement>("PrizeQrContainer").style.display.value, Is.EqualTo(DisplayStyle.Flex));
Assert.That(root.Q<Image>("PrizeQrImage").image, Is.SameAs(texture));
Assert.That(root.Q<Label>("PrizeQrPhone").text, Is.EqualTo("+7 (999) 999-99-99"));
Assert.That(root.Q<Label>("PrizeQrMessage").text, Is.EqualTo("QR message"));
Assert.That(root.Q<Label>("PrizeResultSubtitle").text, Is.EqualTo("Отсканируйте QR-код для связи в Telegram."));
}
finally
{
UnityEngine.Object.DestroyImmediate(texture);
}
}
[Test]
public void Open_IgnoresImmediateReturnSubmitFromHeldArcadeButton()
{
var root = CreateRoot();
var window = new PrizeResultOverlayWindow(root);
var raised = false;
window.ReturnRequested += () => raised = true;
window.Open();
typeof(PrizeResultOverlayWindow)
.GetMethod("HandleReturnClicked", BindingFlags.Instance | BindingFlags.NonPublic)
?.Invoke(window, null);
Assert.That(raised, Is.False);
typeof(PrizeResultOverlayWindow)
.GetField("inputEnabledAtTime", BindingFlags.Instance | BindingFlags.NonPublic)
?.SetValue(window, float.NegativeInfinity);
typeof(PrizeResultOverlayWindow)
.GetMethod("HandleReturnClicked", BindingFlags.Instance | BindingFlags.NonPublic)
?.Invoke(window, null);
Assert.That(raised, Is.True);
}
[Test]
public void SetPrizeStandStatus_RendersCellsWithCorrectStatuses()
{
var root = CreateRoot();
var window = new PrizeResultOverlayWindow(root);
var statuses = new Dictionary<int, DanroJump.Hardware.Com.PrizeBoxStatus>
{
{ 1, DanroJump.Hardware.Com.PrizeBoxStatus.Ok },
{ 2, DanroJump.Hardware.Com.PrizeBoxStatus.Empty },
{ 3, DanroJump.Hardware.Com.PrizeBoxStatus.Error }
};
window.SetPrizeStandStatus(statuses, openingBox: 1);
var standContainer = root.Q<VisualElement>("PrizeStandContainer");
Assert.That(standContainer.style.display.value, Is.EqualTo(DisplayStyle.Flex));
var cells = standContainer.Query<VisualElement>(className: "prize-stand-cell").ToList();
Assert.That(cells.Count, Is.EqualTo(3));
Assert.That(cells[0].Q<Label>().text, Is.EqualTo("1"));
Assert.That(cells[0].ClassListContains("prize-stand-cell--opening"), Is.True);
Assert.That(cells[1].Q<Label>().text, Is.EqualTo("2"));
Assert.That(cells[1].ClassListContains("prize-stand-cell--empty"), Is.True);
Assert.That(cells[2].Q<Label>().text, Is.EqualTo("3"));
Assert.That(cells[2].ClassListContains("prize-stand-cell--error"), Is.True);
}
private static VisualElement CreateRoot()
{
var root = new VisualElement { name = "PrizeResultOverlay" };
root.Add(new Label { name = "PrizeResultTitle" });
root.Add(new Label { name = "PrizeResultSubtitle" });
root.Add(new Label { name = "PrizeResultDetails" });
var qrContainer = new VisualElement { name = "PrizeQrContainer" };
qrContainer.style.display = DisplayStyle.None;
qrContainer.Add(new Image { name = "PrizeQrImage" });
qrContainer.Add(new Label { name = "PrizeQrPhone" });
qrContainer.Add(new Label { name = "PrizeQrMessage" });
root.Add(qrContainer);
var standContainer = new VisualElement { name = "PrizeStandContainer" };
standContainer.style.display = DisplayStyle.None;
root.Add(standContainer);
root.Add(new Button { name = "PrizeResultReturnButton" });
return root;
}
}
}