mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-04-21 02:02:31 -04:00
215 lines
7.2 KiB
C#
215 lines
7.2 KiB
C#
using Xunit;
|
|
using Moq;
|
|
using Microsoft.Extensions.Logging;
|
|
using allstarr.Services.Common;
|
|
using System.IO;
|
|
|
|
namespace allstarr.Tests;
|
|
|
|
public class EnvMigrationServiceTests
|
|
{
|
|
private readonly Mock<ILogger<EnvMigrationService>> _mockLogger;
|
|
private readonly string _testEnvPath;
|
|
|
|
public EnvMigrationServiceTests()
|
|
{
|
|
_mockLogger = new Mock<ILogger<EnvMigrationService>>();
|
|
_testEnvPath = Path.Combine(Path.GetTempPath(), $"test-{Guid.NewGuid()}.env");
|
|
}
|
|
|
|
[Fact]
|
|
public void MigrateEnvFile_RemovesQuotesFromPasswords()
|
|
{
|
|
// Arrange - passwords with quotes (old incorrect format)
|
|
var envContent = @"SCROBBLING_LASTFM_USERNAME=testuser
|
|
SCROBBLING_LASTFM_PASSWORD=""test!pass123""
|
|
MUSICBRAINZ_PASSWORD=""fake&Pass*Word$123""
|
|
SOME_OTHER_VAR=value";
|
|
|
|
File.WriteAllText(_testEnvPath, envContent);
|
|
|
|
var service = new TestEnvMigrationService(_mockLogger.Object, _testEnvPath);
|
|
|
|
// Act
|
|
service.MigrateEnvFile();
|
|
|
|
// Assert - quotes should be removed
|
|
var result = File.ReadAllText(_testEnvPath);
|
|
Assert.Contains("SCROBBLING_LASTFM_PASSWORD=test!pass123", result);
|
|
Assert.DoesNotContain("SCROBBLING_LASTFM_PASSWORD=\"test!pass123\"", result);
|
|
Assert.Contains("MUSICBRAINZ_PASSWORD=fake&Pass*Word$123", result);
|
|
Assert.DoesNotContain("MUSICBRAINZ_PASSWORD=\"fake&Pass*Word$123\"", result);
|
|
Assert.Contains("SCROBBLING_LASTFM_USERNAME=testuser", result);
|
|
Assert.Contains("SOME_OTHER_VAR=value", result);
|
|
|
|
// Cleanup
|
|
File.Delete(_testEnvPath);
|
|
}
|
|
|
|
[Fact]
|
|
public void MigrateEnvFile_LeavesUnquotedPasswordsAlone()
|
|
{
|
|
// Arrange - passwords without quotes (correct format)
|
|
var envContent = @"SCROBBLING_LASTFM_PASSWORD=already-unquoted!
|
|
MUSICBRAINZ_PASSWORD=also-unquoted&*$";
|
|
|
|
File.WriteAllText(_testEnvPath, envContent);
|
|
|
|
var service = new TestEnvMigrationService(_mockLogger.Object, _testEnvPath);
|
|
|
|
// Act
|
|
service.MigrateEnvFile();
|
|
|
|
// Assert - should remain unchanged
|
|
var result = File.ReadAllText(_testEnvPath);
|
|
Assert.Contains("SCROBBLING_LASTFM_PASSWORD=already-unquoted!", result);
|
|
Assert.Contains("MUSICBRAINZ_PASSWORD=also-unquoted&*$", result);
|
|
|
|
// Cleanup
|
|
File.Delete(_testEnvPath);
|
|
}
|
|
|
|
[Fact]
|
|
public void MigrateEnvFile_HandlesEmptyPasswords()
|
|
{
|
|
// Arrange
|
|
var envContent = @"SCROBBLING_LASTFM_PASSWORD=
|
|
MUSICBRAINZ_PASSWORD=";
|
|
|
|
File.WriteAllText(_testEnvPath, envContent);
|
|
|
|
var service = new TestEnvMigrationService(_mockLogger.Object, _testEnvPath);
|
|
|
|
// Act
|
|
service.MigrateEnvFile();
|
|
|
|
// Assert
|
|
var result = File.ReadAllText(_testEnvPath);
|
|
Assert.Contains("SCROBBLING_LASTFM_PASSWORD=", result);
|
|
Assert.DoesNotContain("SCROBBLING_LASTFM_PASSWORD=\"\"", result);
|
|
|
|
// Cleanup
|
|
File.Delete(_testEnvPath);
|
|
}
|
|
|
|
[Fact]
|
|
public void MigrateEnvFile_PreservesComments()
|
|
{
|
|
// Arrange
|
|
var envContent = @"# This is a comment
|
|
SCROBBLING_LASTFM_PASSWORD=fake!test123
|
|
# Another comment
|
|
MUSICBRAINZ_PASSWORD=test&pass*word";
|
|
|
|
File.WriteAllText(_testEnvPath, envContent);
|
|
|
|
var service = new TestEnvMigrationService(_mockLogger.Object, _testEnvPath);
|
|
|
|
// Act
|
|
service.MigrateEnvFile();
|
|
|
|
// Assert
|
|
var result = File.ReadAllText(_testEnvPath);
|
|
Assert.Contains("# This is a comment", result);
|
|
Assert.Contains("# Another comment", result);
|
|
|
|
// Cleanup
|
|
File.Delete(_testEnvPath);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("DEEZER_ARL", "\"abc123def456!@#\"")]
|
|
[InlineData("QOBUZ_USER_AUTH_TOKEN", "\"token&with*special$chars\"")]
|
|
[InlineData("SCROBBLING_LASTFM_SESSION_KEY", "\"session!key@here\"")]
|
|
[InlineData("SPOTIFY_API_SESSION_COOKIE", "\"cookie$value&here\"")]
|
|
public void MigrateEnvFile_RemovesQuotesFromAllSensitiveKeys(string key, string quotedValue)
|
|
{
|
|
// Arrange - value with quotes (old incorrect format)
|
|
var envContent = $"{key}={quotedValue}";
|
|
File.WriteAllText(_testEnvPath, envContent);
|
|
|
|
var service = new TestEnvMigrationService(_mockLogger.Object, _testEnvPath);
|
|
|
|
// Act
|
|
service.MigrateEnvFile();
|
|
|
|
// Assert - quotes should be removed
|
|
var result = File.ReadAllText(_testEnvPath);
|
|
var unquotedValue = quotedValue.Substring(1, quotedValue.Length - 2);
|
|
Assert.Contains($"{key}={unquotedValue}", result);
|
|
Assert.DoesNotContain(quotedValue, result);
|
|
|
|
// Cleanup
|
|
File.Delete(_testEnvPath);
|
|
}
|
|
|
|
[Fact]
|
|
public void MigrateEnvFile_HandlesMultipleQuotedPasswords()
|
|
{
|
|
// Arrange - all with quotes (old incorrect format)
|
|
var envContent = @"SCROBBLING_LASTFM_PASSWORD=""fakepass1!""
|
|
MUSICBRAINZ_PASSWORD=""testpass2&""
|
|
DEEZER_ARL=""fakearl3*""
|
|
QOBUZ_USER_AUTH_TOKEN=""testtoken4$""";
|
|
|
|
File.WriteAllText(_testEnvPath, envContent);
|
|
|
|
var service = new TestEnvMigrationService(_mockLogger.Object, _testEnvPath);
|
|
|
|
// Act
|
|
service.MigrateEnvFile();
|
|
|
|
// Assert - all quotes should be removed
|
|
var result = File.ReadAllText(_testEnvPath);
|
|
Assert.Contains("SCROBBLING_LASTFM_PASSWORD=fakepass1!", result);
|
|
Assert.DoesNotContain("SCROBBLING_LASTFM_PASSWORD=\"fakepass1!\"", result);
|
|
Assert.Contains("MUSICBRAINZ_PASSWORD=testpass2&", result);
|
|
Assert.DoesNotContain("MUSICBRAINZ_PASSWORD=\"testpass2&\"", result);
|
|
Assert.Contains("DEEZER_ARL=fakearl3*", result);
|
|
Assert.DoesNotContain("DEEZER_ARL=\"fakearl3*\"", result);
|
|
Assert.Contains("QOBUZ_USER_AUTH_TOKEN=testtoken4$", result);
|
|
Assert.DoesNotContain("QOBUZ_USER_AUTH_TOKEN=\"testtoken4$\"", result);
|
|
|
|
// Cleanup
|
|
File.Delete(_testEnvPath);
|
|
}
|
|
|
|
[Fact]
|
|
public void MigrateEnvFile_NoFileExists_LogsWarning()
|
|
{
|
|
// Arrange
|
|
var nonExistentPath = Path.Combine(Path.GetTempPath(), $"nonexistent-{Guid.NewGuid()}.env");
|
|
var service = new TestEnvMigrationService(_mockLogger.Object, nonExistentPath);
|
|
|
|
// Act
|
|
service.MigrateEnvFile();
|
|
|
|
// Assert - should not throw, just log warning
|
|
_mockLogger.Verify(
|
|
x => x.Log(
|
|
LogLevel.Warning,
|
|
It.IsAny<EventId>(),
|
|
It.Is<It.IsAnyType>((v, t) => v.ToString()!.Contains("No .env file found")),
|
|
It.IsAny<Exception>(),
|
|
It.IsAny<Func<It.IsAnyType, Exception?, string>>()),
|
|
Times.Once);
|
|
}
|
|
|
|
// Helper class to allow testing with custom path
|
|
private class TestEnvMigrationService : EnvMigrationService
|
|
{
|
|
private readonly string _customPath;
|
|
|
|
public TestEnvMigrationService(ILogger<EnvMigrationService> logger, string customPath)
|
|
: base(logger)
|
|
{
|
|
_customPath = customPath;
|
|
|
|
// Use reflection to set the private field
|
|
var field = typeof(EnvMigrationService).GetField("_envFilePath",
|
|
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
|
field?.SetValue(this, _customPath);
|
|
}
|
|
}
|
|
}
|