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
11 changes: 7 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
name: ci

# Trigger events as per Git Flow documentation
# Trigger events optimized to avoid duplicate runs
# - pull_request: Run checks on all PRs (primary validation)
# - push to main: Run checks after merge (final validation)
# - push tags: Trigger release workflow
# Note: Removed push trigger for develop to avoid duplicate runs with pull_request
on:
push:
branches:
- main
- develop
- main # Only run on main after PR merge
tags:
- 'v*'
- 'v*' # Trigger release on version tags
pull_request:
branches:
- main
Expand Down
19 changes: 13 additions & 6 deletions src/StarGate.Server/Handlers/ShippingProcessHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,19 @@ namespace StarGate.Server.Handlers;
public class ShippingProcessHandler : IProcessHandler
{
private readonly ILogger<ShippingProcessHandler> _logger;

public ShippingProcessHandler(ILogger<ShippingProcessHandler> logger)
private readonly Random _random;

/// <summary>
/// Initializes a new instance of the <see cref="ShippingProcessHandler"/> class.
/// </summary>
/// <param name="logger">Logger instance.</param>
/// <param name="randomSeed">Optional seed for Random. Use for deterministic testing. Default: null (time-based).</param>
public ShippingProcessHandler(
ILogger<ShippingProcessHandler> logger,
int? randomSeed = null)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_random = randomSeed.HasValue ? new Random(randomSeed.Value) : new Random();
}

public string ProcessType => "shipping";
Expand Down Expand Up @@ -166,8 +175,7 @@ private async Task<decimal> CalculateShippingCostAsync(
};

// Add random variation
var random = new Random();
var variation = (decimal)(random.NextDouble() * 5.0);
var variation = (decimal)(_random.NextDouble() * 5.0);

return baseCost + variation;
}
Expand All @@ -186,8 +194,7 @@ private async Task ReserveCarrierCapacityAsync(
shipmentId);

// Simulate capacity check (could fail with probability)
var random = new Random();
if (random.Next(100) < 2) // 2% failure rate
if (_random.Next(100) < 2) // 2% failure rate
{
throw new HttpRequestException($"Carrier {carrier} has no available capacity");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@ namespace StarGate.Server.Tests.Handlers;

public class ShippingProcessHandlerTests
{
// Use deterministic seed for consistent test results
// Production code uses time-based random (no seed)
private const int TestRandomSeed = 42;
private readonly ShippingProcessHandler _handler;

public ShippingProcessHandlerTests()
{
_handler = new ShippingProcessHandler(NullLogger<ShippingProcessHandler>.Instance);
_handler = new ShippingProcessHandler(
NullLogger<ShippingProcessHandler>.Instance,
randomSeed: TestRandomSeed);
}

[Fact]
Expand Down Expand Up @@ -179,9 +184,7 @@ public async Task ExecuteAsync_Should_AcceptValidCarriers(string carrier)
}
};

// Act & Assert
// Note: May occasionally fail due to simulated random failures
// In production tests, you'd mock external dependencies
// Act & Assert - Deterministic with seed=42
await _handler.ExecuteAsync(context);
}

Expand Down Expand Up @@ -261,12 +264,8 @@ public async Task ExecuteAsync_Should_CompleteSuccessfully_WithValidData()
}
};

// Act
// Note: May occasionally fail due to simulated random failures
// In production tests, you'd mock external dependencies
// Act & Assert - Deterministic with seed=42
await _handler.ExecuteAsync(context);

// Assert - no exception thrown
}

[Fact]
Expand All @@ -279,4 +278,29 @@ public void Constructor_Should_ThrowArgumentNullException_WhenLoggerIsNull()
act.Should().Throw<ArgumentNullException>()
.WithParameterName("logger");
}

[Fact]
public void Constructor_Should_AcceptRandomSeed()
{
// Act
var handler = new ShippingProcessHandler(
NullLogger<ShippingProcessHandler>.Instance,
randomSeed: 123);

// Assert
handler.Should().NotBeNull();
handler.ProcessType.Should().Be("shipping");
}

[Fact]
public void Constructor_Should_UseTimeBasedRandom_WhenSeedNotProvided()
{
// Act
var handler = new ShippingProcessHandler(
NullLogger<ShippingProcessHandler>.Instance);

// Assert
handler.Should().NotBeNull();
handler.ProcessType.Should().Be("shipping");
}
}
Loading