Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 39 additions & 51 deletions Assets/Tests/Editor/MouseUiPointerTargetResolverTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,22 +53,20 @@ public void CreatePointerPressData_WithRightButton_MapsPressState()
/// Verifies an exact unique hierarchy path resolves to its active GameObject.
/// </summary>
[Test]
public void TryResolveGameObjectPath_WithUniquePath_ReturnsTarget()
public void ResolveGameObjectPath_WithUniquePath_ReturnsTarget()
{
GameObject root = CreateGameObject("MouseUiTargetResolverTests_UniqueRoot");
GameObject expectedTarget = CreateGameObject("Target", root.transform);
string targetPath = GameObjectPathUtility.GetFullPath(expectedTarget);
Vector2 inputPosition = new(10f, 20f);

bool resolved = MouseUiPointerTargetResolver.TryResolveGameObjectPath(
targetPath,
"TargetPath",
MouseAction.Click,
inputPosition,
out GameObject? target,
out SimulateMouseUiResponse? failureResponse);
(GameObject? target, SimulateMouseUiResponse? failureResponse) =
MouseUiPointerTargetResolver.ResolveGameObjectPath(
targetPath,
"TargetPath",
MouseAction.Click,
inputPosition);

Assert.That(resolved, Is.True);
Assert.That(target, Is.SameAs(expectedTarget));
Assert.That(failureResponse, Is.Null);
}
Expand All @@ -77,20 +75,18 @@ public void TryResolveGameObjectPath_WithUniquePath_ReturnsTarget()
/// Verifies a missing hierarchy path returns the exact wire-visible failure response.
/// </summary>
[Test]
public void TryResolveGameObjectPath_WithMissingPath_ReturnsNotFoundFailure()
public void ResolveGameObjectPath_WithMissingPath_ReturnsNotFoundFailure()
{
string targetPath = "MouseUiTargetResolverTests_MissingRoot/Target";
Vector2 inputPosition = new(10f, 20f);

bool resolved = MouseUiPointerTargetResolver.TryResolveGameObjectPath(
targetPath,
"TargetPath",
MouseAction.Click,
inputPosition,
out GameObject? target,
out SimulateMouseUiResponse? failureResponse);
(GameObject? target, SimulateMouseUiResponse? failureResponse) =
MouseUiPointerTargetResolver.ResolveGameObjectPath(
targetPath,
"TargetPath",
MouseAction.Click,
inputPosition);

Assert.That(resolved, Is.False);
Assert.That(target, Is.Null);
Assert.That(failureResponse, Is.Not.Null);
Assert.That(failureResponse!.Success, Is.False);
Expand All @@ -104,7 +100,7 @@ public void TryResolveGameObjectPath_WithMissingPath_ReturnsNotFoundFailure()
/// Verifies duplicate hierarchy paths return the exact ambiguity count and no target.
/// </summary>
[Test]
public void TryResolveGameObjectPath_WithDuplicatePath_ReturnsAmbiguousFailure()
public void ResolveGameObjectPath_WithDuplicatePath_ReturnsAmbiguousFailure()
{
GameObject firstRoot = CreateGameObject("MouseUiTargetResolverTests_DuplicateRoot");
GameObject firstTarget = CreateGameObject("Target", firstRoot.transform);
Expand All @@ -113,15 +109,13 @@ public void TryResolveGameObjectPath_WithDuplicatePath_ReturnsAmbiguousFailure()
string targetPath = GameObjectPathUtility.GetFullPath(firstTarget);
Vector2 inputPosition = new(10f, 20f);

bool resolved = MouseUiPointerTargetResolver.TryResolveGameObjectPath(
targetPath,
"TargetPath",
MouseAction.Click,
inputPosition,
out GameObject? target,
out SimulateMouseUiResponse? failureResponse);
(GameObject? target, SimulateMouseUiResponse? failureResponse) =
MouseUiPointerTargetResolver.ResolveGameObjectPath(
targetPath,
"TargetPath",
MouseAction.Click,
inputPosition);

Assert.That(resolved, Is.False);
Assert.That(target, Is.Null);
Assert.That(failureResponse, Is.Not.Null);
Assert.That(
Expand All @@ -134,22 +128,20 @@ public void TryResolveGameObjectPath_WithDuplicatePath_ReturnsAmbiguousFailure()
/// Verifies an empty drop path succeeds without resolving an explicit target.
/// </summary>
[Test]
public void TryResolveDropTargetPath_WithoutPath_ReturnsNoTarget()
public void ResolveDropTargetPath_WithoutPath_ReturnsNoTarget()
{
MouseUiSimulationCommand command = CreateCommand(new SimulateMouseUiSchema
{
Action = UnityCliLoopMouseUiAction.Drag,
DropTargetPath = " "
});

bool resolved = MouseUiPointerTargetResolver.TryResolveDropTargetPath(
command,
MouseAction.Drag,
new Vector2(10f, 20f),
out GameObject? dropTarget,
out SimulateMouseUiResponse? failureResponse);
(GameObject? dropTarget, SimulateMouseUiResponse? failureResponse) =
MouseUiPointerTargetResolver.ResolveDropTargetPath(
command,
MouseAction.Drag,
new Vector2(10f, 20f));

Assert.That(resolved, Is.True);
Assert.That(dropTarget, Is.Null);
Assert.That(failureResponse, Is.Null);
}
Expand All @@ -158,7 +150,7 @@ public void TryResolveDropTargetPath_WithoutPath_ReturnsNoTarget()
/// Verifies an explicit drop target without a handler returns the exact failure response.
/// </summary>
[Test]
public void TryResolveDropTargetPath_WithoutDropHandler_ReturnsFailure()
public void ResolveDropTargetPath_WithoutDropHandler_ReturnsFailure()
{
GameObject root = CreateGameObject("MouseUiTargetResolverTests_DropRoot");
GameObject target = CreateGameObject("DropTarget", root.transform);
Expand All @@ -170,14 +162,12 @@ public void TryResolveDropTargetPath_WithoutDropHandler_ReturnsFailure()
});
Vector2 inputPosition = new(10f, 20f);

bool resolved = MouseUiPointerTargetResolver.TryResolveDropTargetPath(
command,
MouseAction.Drag,
inputPosition,
out GameObject? dropTarget,
out SimulateMouseUiResponse? failureResponse);
(GameObject? dropTarget, SimulateMouseUiResponse? failureResponse) =
MouseUiPointerTargetResolver.ResolveDropTargetPath(
command,
MouseAction.Drag,
inputPosition);

Assert.That(resolved, Is.False);
Assert.That(dropTarget, Is.Null);
Assert.That(failureResponse, Is.Not.Null);
Assert.That(
Expand All @@ -192,7 +182,7 @@ public void TryResolveDropTargetPath_WithoutDropHandler_ReturnsFailure()
/// Verifies an explicit drop target with a hierarchy handler returns its raw target.
/// </summary>
[Test]
public void TryResolveDropTargetPath_WithDropHandler_ReturnsRawTarget()
public void ResolveDropTargetPath_WithDropHandler_ReturnsRawTarget()
{
GameObject root = CreateGameObject("MouseUiTargetResolverTests_DropHandlerRoot");
root.AddComponent<MouseUiPointerTargetResolverTestHandler>();
Expand All @@ -204,14 +194,12 @@ public void TryResolveDropTargetPath_WithDropHandler_ReturnsRawTarget()
DropTargetPath = targetPath
});

bool resolved = MouseUiPointerTargetResolver.TryResolveDropTargetPath(
command,
MouseAction.Drag,
new Vector2(10f, 20f),
out GameObject? dropTarget,
out SimulateMouseUiResponse? failureResponse);
(GameObject? dropTarget, SimulateMouseUiResponse? failureResponse) =
MouseUiPointerTargetResolver.ResolveDropTargetPath(
command,
MouseAction.Drag,
new Vector2(10f, 20f));

Assert.That(resolved, Is.True);
Assert.That(dropTarget, Is.SameAs(expectedTarget));
Assert.That(failureResponse, Is.Null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,18 @@ internal static (

if (parameters.BypassRaycast)
{
if (!MouseUiPointerTargetResolver.TryResolveGameObjectPath(
parameters.TargetPath,
"TargetPath",
action,
inputPosition,
out rawTarget,
out SimulateMouseUiResponse? failureResponse))
(GameObject? Target, SimulateMouseUiResponse? FailureResponse) resolution =
MouseUiPointerTargetResolver.ResolveGameObjectPath(
parameters.TargetPath,
"TargetPath",
action,
inputPosition);
if (resolution.FailureResponse != null)
{
return (startRaycast, null, failureResponse);
return (startRaycast, null, resolution.FailureResponse);
}

rawTarget = resolution.Target;
startRaycast = MouseUiPointerTargetResolver.CreateDirectRaycastResult(rawTarget!);
}
else if (hit != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,16 +219,14 @@ internal static async Task<SimulateMouseUiResponse> ExecuteDragEnd(
PointerEventData pointerData = MouseDragState.PointerData!;
GameObject target = MouseDragState.Target!;
string targetName = target.name;
GameObject? explicitDropTarget = null;

if (!MouseUiPointerTargetResolver.TryResolveDropTargetPath(
parameters,
MouseAction.DragEnd,
inputEnd,
out explicitDropTarget,
out SimulateMouseUiResponse? dropFailureResponse))
(GameObject? explicitDropTarget, SimulateMouseUiResponse? dropFailureResponse) =
MouseUiPointerTargetResolver.ResolveDropTargetPath(
parameters,
MouseAction.DragEnd,
inputEnd);
if (dropFailureResponse != null)
{
return dropFailureResponse!;
return dropFailureResponse;
}

SimulateMouseUiOverlayState.Update(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,14 @@ internal static async Task<SimulateMouseUiResponse> ExecuteDragOneShot(
return targetFailureResponse;
}

GameObject? explicitDropTarget = null;
if (!MouseUiPointerTargetResolver.TryResolveDropTargetPath(
parameters,
MouseAction.Drag,
inputEnd,
out explicitDropTarget,
out SimulateMouseUiResponse? dropFailureResponse))
(GameObject? explicitDropTarget, SimulateMouseUiResponse? dropFailureResponse) =
MouseUiPointerTargetResolver.ResolveDropTargetPath(
parameters,
MouseAction.Drag,
inputEnd);
if (dropFailureResponse != null)
{
return dropFailureResponse!;
return dropFailureResponse;
}

if (target == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ private static ResolvedPointerTargets ResolveBypassPressablePointerTargets(
PointerEventData pointerData,
MouseAction action)
{
if (!TryResolveGameObjectPath(
parameters.TargetPath,
"TargetPath",
action,
inputPos,
out GameObject? rawTarget,
out SimulateMouseUiResponse? failureResponse))
(GameObject? rawTarget, SimulateMouseUiResponse? failureResponse) =
ResolveGameObjectPath(
parameters.TargetPath,
"TargetPath",
action,
inputPos);
if (failureResponse != null)
{
return ResolvedPointerTargets.Failure(failureResponse);
}
Expand Down Expand Up @@ -112,61 +112,52 @@ private static ResolvedPointerTargets CreateResolvedPressablePointerTargets(
return ResolvedPointerTargets.Success(rawTarget, pressTarget, clickTarget, target);
}

internal static bool TryResolveGameObjectPath(
internal static (GameObject? Target, SimulateMouseUiResponse? FailureResponse) ResolveGameObjectPath(
string targetPath,
string parameterName,
MouseAction action,
Vector2 inputPosition,
out GameObject? target,
out SimulateMouseUiResponse? failureResponse)
Vector2 inputPosition)
{
TargetPathLookupResult lookupResult = FindActiveGameObjectByPath(targetPath);
target = lookupResult.Target;
if (target != null)
if (lookupResult.Target != null)
{
failureResponse = null;
return true;
return (lookupResult.Target, null);
}

string message = lookupResult.MatchCount == 0
? $"{parameterName} '{targetPath}' was not found."
: $"{parameterName} '{targetPath}' matched {lookupResult.MatchCount} active GameObjects. Use a unique hierarchy path.";

failureResponse = new SimulateMouseUiResponse
SimulateMouseUiResponse failureResponse = new()
{
Success = false,
Message = message,
Action = action.ToString(),
PositionX = inputPosition.x,
PositionY = inputPosition.y
};
return false;
return (null, failureResponse);
}

internal static bool TryResolveDropTargetPath(
internal static (GameObject? Target, SimulateMouseUiResponse? FailureResponse) ResolveDropTargetPath(
MouseUiSimulationCommand parameters,
MouseAction action,
Vector2 inputPosition,
out GameObject? dropTarget,
out SimulateMouseUiResponse? failureResponse)
Vector2 inputPosition)
{
dropTarget = null;
failureResponse = null;

if (string.IsNullOrWhiteSpace(parameters.DropTargetPath))
{
return true;
return (null, null);
}

if (!TryResolveGameObjectPath(
parameters.DropTargetPath,
"DropTargetPath",
action,
inputPosition,
out GameObject? rawDropTarget,
out failureResponse))
(GameObject? rawDropTarget, SimulateMouseUiResponse? failureResponse) =
ResolveGameObjectPath(
parameters.DropTargetPath,
"DropTargetPath",
action,
inputPosition);
if (failureResponse != null)
{
return false;
return (null, failureResponse);
}

GameObject? dropHandler = ExecuteEvents.GetEventHandler<IDropHandler>(rawDropTarget!);
Expand All @@ -180,11 +171,10 @@ internal static bool TryResolveDropTargetPath(
PositionX = inputPosition.x,
PositionY = inputPosition.y
};
return false;
return (null, failureResponse);
}

dropTarget = rawDropTarget;
return true;
return (rawDropTarget, null);
}

private static TargetPathLookupResult FindActiveGameObjectByPath(string targetPath)
Expand Down
Loading