elsa-core/test/unit/Elsa.Scheduling.UnitTests/Services/CronosCronParserTests.cs
Sipke Schoorstra f51f1e918e
Add extensive unit and component tests for scheduling activities (#7036)
* Add DispatchWorkflow tests with new workflow definitions

- Introduced multiple workflow definitions with varied scenarios including input handling, correlation IDs, and fault handling.
- Enhanced `DispatchWorkflowsTests` with comprehensive test cases to validate `DispatchWorkflow` behavior under different configurations.
- Updated existing workflows and tests for improved structure, readability, and accuracy.
- Refactored and renamed related workflows for consistency across test suites.

* Update test/component/Elsa.Workflows.ComponentTests/Scenarios/Activities/DispatchWorkflows/DispatchWorkflowsTests.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Refactor DispatchWorkflowsTests for readability and maintainability

- Replaced hardcoded constants with named variables for improved clarity.
- Enhanced assertions using utility methods like `Assert.Single` for cleaner code.
- Updated WriteLine activity tests to handle null values reliably.
- Introduced timeout handling for child workflow execution.

* Update GUID length validation in JintJavaScriptFunctionBehaviorTests

- Adjusted `shortGuid` length assertion to accommodate a range of 19-22 characters instead of 20-22.

* Add extensive unit and component tests for scheduling activities

- Introduced unit tests for `Cron`, `Delay`, `Timer`, and `StartAt` scheduling activities, covering general usage and corner cases.
- Added component tests validating `Cron`, `Delay`, `Timer`, and `StartAt` workflows within broader scenarios, focusing on workflow execution, blocking, and resumption of activities.
- Enhanced test project structures with new folder setups aligning to activity categories.
- Updated namespaces and project files to match the new structure and added validation for scheduling logic.

* Refactor Timer activity tests for consistency and reusability

- Extracted shared logic for timer activity tests into `TimerActivityTestBase`.
- Refactored `DelayTests`, `TimerTests`, `CronTests`, and `StartAtTests` to inherit from `TimerActivityTestBase`.
- Removed redundant code and improved test consistency across all timer activity test cases.
- Cleaned up unused imports and optimized namespaces.

* Remove unused folder references from test project files

* [WIP] Update unit and component tests for scheduling activities (#7037)

* Initial plan

* Replace ContainsKey + indexer with TryGetValue in CronTests

Co-authored-by: sfmskywalker <938393+sfmskywalker@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sfmskywalker <938393+sfmskywalker@users.noreply.github.com>

* Fixing build after merge

* Remove DispatchWorkflowsTests and related references from the test suite

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: sfmskywalker <938393+sfmskywalker@users.noreply.github.com>
Co-authored-by: lucas.hipolito <lukhipolito@yahoo.com.br>
2025-11-07 21:54:50 +01:00

112 lines
3.2 KiB
C#

using Elsa.Common;
using Elsa.Scheduling.Services;
using NSubstitute;
namespace Elsa.Scheduling.UnitTests.Services;
public class CronosCronParserTests
{
[Theory]
[InlineData("0 0 0 * * *")] // Daily at midnight
[InlineData("0 0 */6 * * *")] // Every 6 hours
[InlineData("0 0 0 * * MON")] // Every Monday
[InlineData("0 0 9 * * MON-FRI")] // Weekdays at 9 AM
[InlineData("0 0 0 1 */3 *")] // First day of every 3 months
[InlineData("0 0 0 L * *")] // Last day of month
public void GetNextOccurrence_WithValidExpression_ReturnsTimeInFuture(string cronExpression)
{
// Arrange
var parser = CreateParser(out var now);
// Act
var nextOccurrence = parser.GetNextOccurrence(cronExpression);
// Assert
Assert.True(nextOccurrence > now);
}
[Fact]
public void GetNextOccurrence_WithSecondsPrecision_ReturnsCorrectSecond()
{
// Arrange
var parser = CreateParser(out _);
// Act
var nextOccurrence = parser.GetNextOccurrence("30 * * * * *");
// Assert
Assert.Equal(30, nextOccurrence.Second);
}
[Fact]
public void GetNextOccurrence_AtMidnight_ReturnsNextDay()
{
// Arrange
var now = new DateTimeOffset(2025, 1, 6, 0, 0, 0, TimeSpan.Zero);
var parser = CreateParser(now);
// Act
var nextOccurrence = parser.GetNextOccurrence("0 0 0 * * *");
// Assert
Assert.Equal(7, nextOccurrence.Day);
}
[Fact]
public void GetNextOccurrence_EverySecond_ReturnsNextSecond()
{
// Arrange
var now = new DateTimeOffset(2025, 1, 6, 12, 30, 45, TimeSpan.Zero);
var parser = CreateParser(now);
// Act
var nextOccurrence = parser.GetNextOccurrence("* * * * * *");
// Assert
Assert.Equal(46, nextOccurrence.Second);
Assert.True((nextOccurrence - now).TotalSeconds < 2);
}
[Fact]
public void GetNextOccurrence_WithSpecificDayOfMonth_ReturnsCorrectDay()
{
// Arrange
var parser = CreateParser(out _);
// Act
var nextOccurrence = parser.GetNextOccurrence("0 0 0 15 * *");
// Assert
Assert.Equal(15, nextOccurrence.Day);
Assert.Equal(0, nextOccurrence.Hour);
}
[Theory]
[InlineData("invalid")]
[InlineData("* * * *")] // Too few fields
[InlineData("60 * * * * *")] // Invalid second (>59)
[InlineData("* 60 * * * *")] // Invalid minute (>59)
[InlineData("* * 25 * * *")] // Invalid hour (>23)
public void GetNextOccurrence_WithInvalidExpression_ThrowsException(string cronExpression)
{
// Arrange
var parser = CreateParser(out _);
// Act & Assert
Assert.ThrowsAny<Exception>(() => parser.GetNextOccurrence(cronExpression));
}
private static CronosCronParser CreateParser(out DateTimeOffset now)
{
now = new DateTimeOffset(2025, 1, 6, 12, 0, 0, TimeSpan.Zero);
return CreateParser(now);
}
private static CronosCronParser CreateParser(DateTimeOffset now)
{
var clock = Substitute.For<ISystemClock>();
clock.UtcNow.Returns(now);
return new CronosCronParser(clock);
}
}