forked from derkork/godot-test-driver
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNodeDriver.cs
136 lines (119 loc) · 4.24 KB
/
NodeDriver.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using System;
using System.Collections.Generic;
using System.Linq;
using Godot;
using JetBrains.Annotations;
using Object = Godot.GodotObject;
namespace GodotTestDriver.Drivers
{
/// <summary>
/// Base class for test drivers that work on nodes. This is the non-generic variant, which will make it easier to
/// create some fluent APIs.
/// </summary>
public abstract class NodeDriver
{
}
/// <summary>
/// Base class for test drivers that work on nodes.
/// </summary>
[PublicAPI]
public abstract class NodeDriver<T> : NodeDriver where T : Node
{
private readonly Func<T> _producer;
/// <summary>
/// The description given to the test driver.
/// </summary>
public string Description { get; }
protected NodeDriver(Func<T> producer, string description = "")
{
_producer = producer;
Description = description;
}
/// <summary>
/// Is the node currently present in the tree?
/// </summary>
public bool IsPresent => Root != null;
/// <summary>
/// Builds drivers for a set of children of the current driver's root node. The first function needs to return
/// the currently applicable child nodes, the second function will produce a driver for each child.
/// </summary>
protected IEnumerable<TDriver> BuildDrivers<TDriver, TNode>(Func<T, IEnumerable<TNode>> childSelector,
Func<Func<TNode>, TDriver> driverFactory)
where TDriver : NodeDriver where TNode:Node
{
var root = Root;
if (root == null)
{
yield return null;
}
var children = childSelector(root).ToList();
foreach (var child in children)
{
yield return driverFactory(() => Root?.GetNode<TNode>(child.GetPath()));
}
}
/// <summary>
/// Helper function to build an error message. Prefixes the message with a human readable description of this
/// driver.
/// </summary>
protected string ErrorMessage(string message)
{
// if description is blank or empty, use the type name as description
var typeName = GetType().Name;
if (string.IsNullOrEmpty(Description))
{
return $"{typeName}: {message}";
}
return $"{typeName} [{Description}] {message}";
}
/// <summary>
/// Returns the root node. Can be null in case the root
/// node is not currently present in the scene tree or if the root node is not a valid instance anymore.
/// </summary>
[CanBeNull]
public T Root
{
get
{
var node = _producer();
return Object.IsInstanceValid(node) && node.IsInsideTree() ? node : null;
}
}
/// <summary>
/// Returns the root node and ensures it is present.
/// </summary>
public T PresentRoot
{
get
{
var result = Root;
if (result == null)
{
throw new InvalidOperationException(ErrorMessage("Node is not present in the scene tree."));
}
return result;
}
}
/// <summary>
/// Returns whether this node has the given signal connected to the given target.
/// </summary>
public bool IsSignalConnected(string signal, Object target, string method)
{
return PresentRoot.IsConnected(signal,new Callable(target,method));
}
/// <summary>
/// Returns whether the given signal of this node is connected to any other node.
/// </summary>
public bool IsSignalConnectedToAnywhere(string signal)
{
return PresentRoot.GetSignalConnectionList(signal).Count > 0;
}
/// <summary>
/// Returns a signal awaiter that can be used to wait for the given signal.
/// </summary>
public SignalAwaiter GetSignalAwaiter(StringName signal)
{
return PresentRoot.ToSignal(PresentRoot,signal);
}
}
}