Skip to content

Commit 5e917de

Browse files
committed
Made SpinnerView more testable
1 parent 8dbd398 commit 5e917de

File tree

3 files changed

+130
-152
lines changed

3 files changed

+130
-152
lines changed

Terminal.Gui/Views/SpinnerView/SpinnerView.cs

+19-31
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
//------------------------------------------------------------------------------
1+
#nullable enable
2+
//------------------------------------------------------------------------------
23
// Windows Terminal supports Unicode and Emoji characters, but by default
34
// conhost shells (e.g., PowerShell and cmd.exe) do not. See
45
// <https://spectreconsole.net/best-practices>.
56
//------------------------------------------------------------------------------
67

7-
using System.Diagnostics;
8-
98
namespace Terminal.Gui;
109

1110
/// <summary>A <see cref="View"/> which displays (by default) a spinning line character.</summary>
1211
/// <remarks>
13-
/// By default animation only occurs when you call <see cref="SpinnerView.AdvanceAnimation(bool)"/>. Use
12+
/// By default, animation only occurs when you call <see cref="SpinnerView.AdvanceAnimation(bool)"/>. Use
1413
/// <see cref="AutoSpin"/> to make the automate calls to <see cref="SpinnerView.AdvanceAnimation(bool)"/>.
1514
/// </remarks>
1615
public class SpinnerView : View, IDesignable
@@ -25,7 +24,7 @@ public class SpinnerView : View, IDesignable
2524
private DateTime _lastRender = DateTime.MinValue;
2625
private string [] _sequence = DEFAULT_STYLE.Sequence;
2726
private SpinnerStyle _style = DEFAULT_STYLE;
28-
private object _timeout;
27+
private object? _timeout;
2928

3029
/// <summary>Creates a new instance of the <see cref="SpinnerView"/> class.</summary>
3130
public SpinnerView ()
@@ -134,14 +133,7 @@ public void AdvanceAnimation (bool setNeedsDraw = true)
134133
{
135134
if (SpinBounce)
136135
{
137-
if (SpinReverse)
138-
{
139-
_bounceReverse = false;
140-
}
141-
else
142-
{
143-
_bounceReverse = true;
144-
}
136+
_bounceReverse = !SpinReverse;
145137

146138
_currentIdx = Sequence.Length - 1;
147139
}
@@ -155,14 +147,7 @@ public void AdvanceAnimation (bool setNeedsDraw = true)
155147
{
156148
if (SpinBounce)
157149
{
158-
if (SpinReverse)
159-
{
160-
_bounceReverse = true;
161-
}
162-
else
163-
{
164-
_bounceReverse = false;
165-
}
150+
_bounceReverse = SpinReverse;
166151

167152
_currentIdx = 1;
168153
}
@@ -182,25 +167,26 @@ public void AdvanceAnimation (bool setNeedsDraw = true)
182167
}
183168
}
184169

185-
/// <inheritdoc />
170+
/// <inheritdoc/>
186171
protected override bool OnClearingViewport () { return true; }
187172

188-
/// <inheritdoc />
173+
/// <inheritdoc/>
189174
protected override bool OnDrawingContent ()
190175
{
191176
Render ();
177+
192178
return true;
193179
}
194180

195181
/// <summary>
196-
/// Renders the current frame of the spinner.
182+
/// Renders the current frame of the spinner.
197183
/// </summary>
198184
public void Render ()
199185
{
200186
if (Sequence is { Length: > 0 } && _currentIdx < Sequence.Length)
201187
{
202188
Move (Viewport.X, Viewport.Y);
203-
View.Driver?.AddStr (Sequence [_currentIdx]);
189+
Driver?.AddStr (Sequence [_currentIdx]);
204190
}
205191
}
206192

@@ -214,7 +200,8 @@ protected override void Dispose (bool disposing)
214200

215201
private void AddAutoSpinTimeout ()
216202
{
217-
if (_timeout is { })
203+
// Only add timeout if we are initialized and not already spinning
204+
if (_timeout is { } || !Application.Initialized)
218205
{
219206
return;
220207
}
@@ -223,7 +210,7 @@ private void AddAutoSpinTimeout ()
223210
TimeSpan.FromMilliseconds (SpinDelay),
224211
() =>
225212
{
226-
Application.Invoke (() => AdvanceAnimation());
213+
Application.Invoke (() => AdvanceAnimation ());
227214

228215
return true;
229216
}
@@ -237,7 +224,7 @@ private bool GetIsAsciiOnly ()
237224
return false;
238225
}
239226

240-
if (_sequence is { } && _sequence.Length > 0)
227+
if (_sequence is { Length: > 0 })
241228
{
242229
foreach (string frame in _sequence)
243230
{
@@ -260,7 +247,7 @@ private int GetSpinnerWidth ()
260247
{
261248
var max = 0;
262249

263-
if (_sequence is { } && _sequence.Length > 0)
250+
if (_sequence is { Length: > 0 })
264251
{
265252
foreach (string frame in _sequence)
266253
{
@@ -295,15 +282,15 @@ private void SetDelay (int delay)
295282

296283
private void SetSequence (string [] frames)
297284
{
298-
if (frames is { } && frames.Length > 0)
285+
if (frames is { Length: > 0 })
299286
{
300287
_style = new SpinnerStyle.Custom ();
301288
_sequence = frames;
302289
Width = GetSpinnerWidth ();
303290
}
304291
}
305292

306-
private void SetStyle (SpinnerStyle style)
293+
private void SetStyle (SpinnerStyle? style)
307294
{
308295
if (style is { })
309296
{
@@ -320,6 +307,7 @@ bool IDesignable.EnableForDesign ()
320307
Style = new SpinnerStyle.Points ();
321308
SpinReverse = true;
322309
AutoSpin = true;
310+
323311
return true;
324312
}
325313
}

Tests/UnitTests/Views/AllViewsTests.cs

-120
Original file line numberDiff line numberDiff line change
@@ -62,124 +62,4 @@ public void AllViews_Center_Properly (Type viewType)
6262
Application.Shutdown ();
6363
}
6464

65-
//[Fact]
66-
//public void AllViews_HotKey_Works ()
67-
//{
68-
// foreach (var type in GetAllViewClasses ()) {
69-
// _output.WriteLine ($"Testing {type.Name}");
70-
// var view = GetTypeInitializer (type, type.GetConstructor (Array.Empty<Type> ()));
71-
// view.HotKeySpecifier = (Rune)'^';
72-
// view.Text = "^text";
73-
// Assert.Equal(Key.T, view.HotKey);
74-
// }
75-
//}
76-
77-
[Theory]
78-
[MemberData (nameof (AllViewTypes))]
79-
[SetupFakeDriver] // Required for spinner view that wants to register timeouts
80-
public void AllViews_Command_Select_Raises_Selecting (Type viewType)
81-
{
82-
// Required for spinner view that wants to register timeouts
83-
Application.MainLoop = new (new FakeMainLoop (Application.Driver));
84-
85-
var view = CreateInstanceIfNotGeneric (viewType);
86-
87-
if (view == null)
88-
{
89-
output.WriteLine ($"Ignoring {viewType} - It's a Generic");
90-
91-
return;
92-
}
93-
94-
if (view is IDesignable designable)
95-
{
96-
designable.EnableForDesign ();
97-
}
98-
99-
var selectingCount = 0;
100-
view.Selecting += (s, e) => selectingCount++;
101-
102-
var acceptedCount = 0;
103-
view.Accepting += (s, e) => { acceptedCount++; };
104-
105-
if (view.InvokeCommand (Command.Select) == true)
106-
{
107-
Assert.Equal (1, selectingCount);
108-
Assert.Equal (0, acceptedCount);
109-
}
110-
}
111-
112-
[Theory]
113-
[SetupFakeDriver] // Required for spinner view that wants to register timeouts
114-
[MemberData (nameof (AllViewTypes))]
115-
public void AllViews_Command_Accept_Raises_Accepted (Type viewType)
116-
{
117-
// Required for spinner view that wants to register timeouts
118-
Application.MainLoop = new (new FakeMainLoop (Application.Driver));
119-
120-
var view = CreateInstanceIfNotGeneric (viewType);
121-
122-
if (view == null)
123-
{
124-
output.WriteLine ($"Ignoring {viewType} - It's a Generic");
125-
126-
return;
127-
}
128-
129-
if (view is IDesignable designable)
130-
{
131-
designable.EnableForDesign ();
132-
}
133-
134-
var selectingCount = 0;
135-
view.Selecting += (s, e) => selectingCount++;
136-
137-
var acceptedCount = 0;
138-
view.Accepting += (s, e) => { acceptedCount++; };
139-
140-
if (view.InvokeCommand (Command.Accept) == true)
141-
{
142-
Assert.Equal (0, selectingCount);
143-
Assert.Equal (1, acceptedCount);
144-
}
145-
}
146-
147-
[Theory]
148-
[MemberData (nameof (AllViewTypes))]
149-
[SetupFakeDriver] // Required for spinner view that wants to register timeouts
150-
public void AllViews_Command_HotKey_Raises_HandlingHotKey (Type viewType)
151-
{
152-
// Required for spinner view that wants to register timeouts
153-
Application.MainLoop = new (new FakeMainLoop (Application.Driver));
154-
155-
var view = CreateInstanceIfNotGeneric (viewType);
156-
157-
if (view == null)
158-
{
159-
output.WriteLine ($"Ignoring {viewType} - It's a Generic");
160-
161-
return;
162-
}
163-
164-
if (view is IDesignable designable)
165-
{
166-
designable.EnableForDesign ();
167-
}
168-
else
169-
{
170-
view.HotKey = Key.T;
171-
}
172-
173-
var acceptedCount = 0;
174-
view.Accepting += (s, e) => { acceptedCount++; };
175-
176-
var handlingHotKeyCount = 0;
177-
view.HandlingHotKey += (s, e) => { handlingHotKeyCount++; };
178-
179-
if (view.InvokeCommand (Command.HotKey) == true)
180-
{
181-
Assert.Equal (1, handlingHotKeyCount);
182-
Assert.Equal (0, acceptedCount);
183-
}
184-
}
18565
}

0 commit comments

Comments
 (0)