Cédric Luthi ffd24ec451 Fix intermittent test failure
When running on .NET Framework, the `Should_Report_Max_Remaining_Time_For_Extremely_Small_Progress` would intermittently fail with the following error:
```
task.RemainingTime
    should be
10675199.02:48:05.4775807
    but was
null
```

This is because it's possible that the two increment share the same timestamp thus making the `RemainingTime` null. To ensure the two increments don't share the same timestamp, we sleep for one millisecond.

Although I have only observed this issue on .NET Framework it would be possible that it occasionally also occur on .NET Core.
2021-08-30 11:08:24 +02:00

276 lines
8.2 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Threading;
using System.Threading.Tasks;
using Shouldly;
using Spectre.Console.Testing;
using Spectre.Verify.Extensions;
using VerifyXunit;
using Xunit;
namespace Spectre.Console.Tests.Unit
{
[UsesVerify]
[ExpectationPath("Live/Progress")]
public sealed class ProgressTests
{
[Fact]
public void Should_Render_Task_Correctly()
{
// Given
var console = new TestConsole()
.Width(10)
.Interactive()
.EmitAnsiSequences();
var progress = new Progress(console)
.Columns(new[] { new ProgressBarColumn() })
.AutoRefresh(false)
.AutoClear(true);
// When
progress.Start(ctx => ctx.AddTask("foo"));
// Then
console.Output
.NormalizeLineEndings()
.ShouldBe(
"[?25l" + // Hide cursor
" \n" + // Top padding
"━━━━━━━━━━\n" + // Task
" " + // Bottom padding
"[?25h"); // Clear + show cursor
}
[Fact]
public void Should_Not_Auto_Clear_If_Specified()
{
// Given
var console = new TestConsole()
.Width(10)
.Interactive()
.EmitAnsiSequences();
var progress = new Progress(console)
.Columns(new[] { new ProgressBarColumn() })
.AutoRefresh(false)
.AutoClear(false);
// When
progress.Start(ctx => ctx.AddTask("foo"));
// Then
console.Output
.NormalizeLineEndings()
.ShouldBe(
"[?25l" + // Hide cursor
" \n" + // Top padding
"━━━━━━━━━━\n" + // Task
" \n" + // Bottom padding
"[?25h"); // show cursor
}
[Fact]
[Expectation("Render_ReduceWidth")]
public Task Should_Reduce_Width_If_Needed()
{
// Given
var console = new TestConsole()
.Width(20)
.Interactive();
var progress = new Progress(console)
.Columns(new ProgressColumn[]
{
new TaskDescriptionColumn(),
new ProgressBarColumn(),
new PercentageColumn(),
new RemainingTimeColumn(),
new SpinnerColumn(),
})
.AutoRefresh(false)
.AutoClear(false);
// When
progress.Start(ctx =>
{
ctx.AddTask("foo");
ctx.AddTask("bar");
ctx.AddTask("baz");
});
// Then
return Verifier.Verify(console.Output);
}
[Fact]
public void Setting_Max_Value_Should_Set_The_MaxValue_And_Cap_Value()
{
// Given
var console = new TestConsole()
.Interactive();
var task = default(ProgressTask);
var progress = new Progress(console)
.Columns(new[] { new ProgressBarColumn() })
.AutoRefresh(false)
.AutoClear(false);
// When
progress.Start(ctx =>
{
task = ctx.AddTask("foo");
task.Increment(100);
task.MaxValue = 20;
});
// Then
task.MaxValue.ShouldBe(20);
task.Value.ShouldBe(20);
}
[Fact]
public void Setting_Value_Should_Override_Incremented_Value()
{
// Given
var console = new TestConsole()
.Interactive();
var task = default(ProgressTask);
var progress = new Progress(console)
.Columns(new[] { new ProgressBarColumn() })
.AutoRefresh(false)
.AutoClear(false);
// When
progress.Start(ctx =>
{
task = ctx.AddTask("foo");
task.Increment(50);
task.Value = 20;
});
// Then
task.MaxValue.ShouldBe(100);
task.Value.ShouldBe(20);
}
[Fact]
public void Setting_Value_To_MaxValue_Should_Finish_Task()
{
// Given
var console = new TestConsole()
.Interactive();
var task = default(ProgressTask);
var progress = new Progress(console)
.Columns(new[] { new ProgressBarColumn() })
.AutoRefresh(false)
.AutoClear(false);
// When
progress.Start(ctx =>
{
task = ctx.AddTask("foo");
task.Value = task.MaxValue;
});
// Then
task.IsFinished.ShouldBe(true);
}
[Fact]
public void Should_Increment_Manually_Set_Value()
{
// Given
var console = new TestConsole()
.Interactive();
var task = default(ProgressTask);
var progress = new Progress(console)
.Columns(new[] { new ProgressBarColumn() })
.AutoRefresh(false)
.AutoClear(false);
// When
progress.Start(ctx =>
{
task = ctx.AddTask("foo");
task.Value = 50;
task.Increment(10);
});
// Then
task.Value.ShouldBe(60);
}
[Fact]
public void Should_Hide_Completed_Tasks()
{
// Given
var console = new TestConsole()
.Width(10)
.Interactive()
.EmitAnsiSequences();
var taskFinished = default(ProgressTask);
var taskInProgress1 = default(ProgressTask);
var taskInProgress2 = default(ProgressTask);
var progress = new Progress(console)
.Columns(new[] { new ProgressBarColumn() })
.AutoRefresh(false)
.AutoClear(false)
.HideCompleted(true);
// When
progress.Start(ctx =>
{
taskInProgress1 = ctx.AddTask("foo");
taskFinished = ctx.AddTask("bar");
taskInProgress2 = ctx.AddTask("baz");
taskInProgress2.Increment(20);
taskFinished.Value = taskFinished.MaxValue;
});
// Then
console.Output
.NormalizeLineEndings()
.ShouldBe(
"[?25l" + // Hide cursor
" \n" + // top padding
"━━━━━━━━━━\n" + // taskInProgress1
"━━━━━━━━━━\n" + // taskInProgress2
" \n" + // bottom padding
"[?25h"); // show cursor
}
[Fact]
public void Should_Report_Max_Remaining_Time_For_Extremely_Small_Progress()
{
// Given
var console = new TestConsole()
.Interactive();
var task = default(ProgressTask);
var progress = new Progress(console)
.Columns(new[] { new RemainingTimeColumn() })
.AutoRefresh(false)
.AutoClear(false);
// When
progress.Start(ctx =>
{
task = ctx.AddTask("foo");
task.Increment(double.Epsilon);
// Make sure that at least one millisecond has elapsed between the increments else the RemainingTime is null
// when the last timestamp is equal to the first timestamp of the samples.
Thread.Sleep(1);
task.Increment(double.Epsilon);
});
// Then
task.RemainingTime.ShouldBe(TimeSpan.MaxValue);
}
}
}