fix(presentation): reuse counting views and gate native QA readiness

This commit is contained in:
NINI
2026-10-05 22:24:13 +09:00
parent 9aa9e3c709
commit 4081a1c1ed
4 changed files with 134 additions and 7 deletions
@@ -55,6 +55,34 @@ namespace MagnetismHeroes.Tests
yield return null;
}
[UnityTearDown] public IEnumerator TearDown() { Object.Destroy(_app.gameObject); yield return null; }
[UnityTest] public IEnumerator CountingRefreshPreservesViewsAndClearsMarkersInSameFreeBoard()
{
_app.StartStage(20); yield return null;
while (_app.Session.Board.Groups.Length > 1)
{
var groups=_app.Session.Board.Groups;
_app.CommitMove(groups[0].id,new Position3(.1f,0,0),groups[1].id);
}
var views=_app.Presenter.Balls.ToDictionary(pair=>pair.Key,pair=>pair.Value);
var badge=_app.Presenter.GetComponentInChildren<GroupBadge>();
var positions=views.ToDictionary(pair=>pair.Key,pair=>pair.Value.transform.position);
foreach (string id in views.Keys)
{
_app.CountBall(id);
foreach (var pair in views)
{
Assert.That(_app.Presenter.Balls[pair.Key], Is.SameAs(pair.Value), "Counting must retain each ball instance.");
Assert.That(pair.Value.transform.position, Is.EqualTo(positions[pair.Key]));
var marker=(GameObject)typeof(BallView).GetField("_countMarker",System.Reflection.BindingFlags.Instance|System.Reflection.BindingFlags.NonPublic).GetValue(pair.Value);
Assert.That(marker.activeSelf, Is.EqualTo(_app.Session.Board.CountedBallIds.Contains(pair.Key)));
}
Assert.That(_app.Presenter.GetComponentInChildren<GroupBadge>(), Is.SameAs(badge));
}
Assert.That(_app.Session.Screen, Is.EqualTo(SessionScreen.FreePlay));
Assert.That(_app.Voice.CurrentClipId, Is.EqualTo("count_01"));
Assert.That(_app.Voice.PendingCount, Is.EqualTo(10));
yield return null;
}
[UnityTest] public IEnumerator EveryCountingBallCanBeFoundPickedAndDirectlyDraggedAfterOrbit()
{
var proof=new List<string>();
@@ -25,7 +25,23 @@ namespace MagnetismHeroes.UnityRuntime.Presentation
&& board.Balls.All(ball => _balls.ContainsKey(ball.id));
var previous = _balls.Values.GroupBy(ball => ball.GroupId).ToDictionary(group => group.Key, group => group.Select(ball => ball.BallId).OrderBy(id => id).ToArray());
var contacts = _balls.Values.Where(ball => ball.ContactCandidate).Select(ball => ball.BallId).ToArray();
bool reuse = board != null && _balls.Count == board.BallCount && _badges.Count == board.Groups.Length
&& board.Groups.All(group => previous.TryGetValue(group.id, out var ids)
&& ids.SequenceEqual(group.ballIds.OrderBy(id => id)))
&& board.Balls.All(ball => _balls.TryGetValue(ball.id, out var view)
&& view.transform.position == ToVector(ball.position));
_board = board;
if (reuse)
{
CancelPreview();
foreach (var ball in _balls.Values)
{
ball.Selected = false; ball.Hinted = false;
ball.Bind(ball.BallId, ball.GroupId, board.CountedBallIds.Contains(ball.BallId));
}
PositionBadges();
return;
}
foreach (var view in _balls.Values) { view.gameObject.SetActive(false); Destroy(view.gameObject); }
foreach (var badge in _badges) { badge.gameObject.SetActive(false); Destroy(badge.gameObject); }
_balls.Clear(); _badges.Clear();