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
12 changes: 8 additions & 4 deletions Assets/Tests/Editor/CliPathSetupFlowTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using UnityEngine;

using io.github.hatayama.UnityCliLoop.Application;
using io.github.hatayama.UnityCliLoop.Infrastructure;

namespace io.github.hatayama.UnityCliLoop.Tests.Editor
{
Expand All @@ -21,7 +22,7 @@ public async Task EnsureCliVisibleFromShellAsync_WhenAlreadyVisibleDoesNotApplyP
FakeNativeCliInstaller installer = new FakeNativeCliInstaller(
CreateSupportedPlan(),
CreateAppliedResult());
CliSetupApplicationService service = new(detector, installer);
CliSetupApplicationService service = new(detector, installer, new CliPinReaderService());

CliPathSetupFlowResult result = await service.EnsureCliVisibleFromShellAsync(
RuntimePlatform.OSXEditor,
Expand All @@ -39,7 +40,7 @@ public async Task EnsureCliVisibleFromShellAsync_WhenApplySucceedsRechecksShell(
FakeNativeCliInstaller installer = new FakeNativeCliInstaller(
CreateSupportedPlan(),
CreateAppliedResult());
CliSetupApplicationService service = new(detector, installer);
CliSetupApplicationService service = new(detector, installer, new CliPinReaderService());

CliPathSetupFlowResult result = await service.EnsureCliVisibleFromShellAsync(
RuntimePlatform.OSXEditor,
Expand All @@ -58,7 +59,7 @@ public async Task EnsureCliVisibleFromShellAsync_WhenUnsupportedShellReturnsManu
FakeNativeCliInstaller installer = new FakeNativeCliInstaller(
CreateUnsupportedPlan(),
CreateAppliedResult());
CliSetupApplicationService service = new(detector, installer);
CliSetupApplicationService service = new(detector, installer, new CliPinReaderService());

CliPathSetupFlowResult result = await service.EnsureCliVisibleFromShellAsync(
RuntimePlatform.OSXEditor,
Expand All @@ -78,7 +79,10 @@ public async Task EnsureCliVisibleFromShellAsync_WhenProfileApplyFailsReturnsFai
CliPathSetupApplyStatus.Failed,
"profile is read-only");
FakeNativeCliInstaller installer = new FakeNativeCliInstaller(CreateSupportedPlan(), applyResult);
CliSetupApplicationService service = new CliSetupApplicationService(detector, installer);
CliSetupApplicationService service = new CliSetupApplicationService(
detector,
installer,
new CliPinReaderService());

CliPathSetupFlowResult result = await service.EnsureCliVisibleFromShellAsync(
RuntimePlatform.OSXEditor,
Expand Down
187 changes: 187 additions & 0 deletions Assets/Tests/Editor/CliPinReaderServiceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
using System;
using System.IO;

using NUnit.Framework;

using io.github.hatayama.UnityCliLoop.Application;
using io.github.hatayama.UnityCliLoop.Infrastructure;

namespace io.github.hatayama.UnityCliLoop.Tests.Editor
{
/// <summary>
/// Test fixture that verifies CLI pin reader service file IO behavior.
/// </summary>
public sealed class CliPinReaderServiceTests
{
[Test]
public void LoadPinFromPath_WhenPinFileIsValid_ReturnsBothVersions()
{
// Tests that a well-formed pin file yields the project runner and dispatcher versions.
string root = CreateTestRoot();
string pinPath = Path.Combine(root, "project-runner-pin.json");

try
{
Directory.CreateDirectory(root);
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
File.WriteAllText(
pinPath,
"{\"projectRunnerVersion\":\"3.0.0\",\"minimumDispatcherVersion\":\"3.0.1\"}");

CliPinLoadResult result = CliPinReaderService.LoadPinFromPath(pinPath);

Assert.That(result.Success, Is.True);
Assert.That(result.Pin.ProjectRunnerVersion, Is.EqualTo("3.0.0"));
Assert.That(result.Pin.MinimumDispatcherVersion, Is.EqualTo("3.0.1"));
}
finally
{
// Why: guard so a failure before directory creation does not mask the original
// exception with a DirectoryNotFoundException from cleanup.
if (Directory.Exists(root))
{
Directory.Delete(root, recursive: true);
}
}
}

[Test]
public void LoadPinFromPath_WhenFileIsMissing_ReturnsFailureWithNotFoundMessage()
{
// Tests that a missing pin file fails with the exact "not found" message.
string root = CreateTestRoot();
string pinPath = Path.Combine(root, "project-runner-pin.json");

CliPinLoadResult result = CliPinReaderService.LoadPinFromPath(pinPath);

Assert.That(result.Success, Is.False);
Assert.That(result.ErrorMessage, Is.EqualTo($"Unity CLI Loop pin file not found at {pinPath}."));
}

[Test]
public void LoadPinFromPath_WhenFileIsEmpty_ReturnsFailureWithEmptyMessage()
{
// Tests that an empty pin file fails with the exact "is empty" message.
string root = CreateTestRoot();
string pinPath = Path.Combine(root, "project-runner-pin.json");

try
{
Directory.CreateDirectory(root);
File.WriteAllText(pinPath, "");

CliPinLoadResult result = CliPinReaderService.LoadPinFromPath(pinPath);

Assert.That(result.Success, Is.False);
Assert.That(result.ErrorMessage, Is.EqualTo($"Unity CLI Loop pin file at {pinPath} is empty."));
}
finally
{
// Why: guard so a failure before directory creation does not mask the original
// exception with a DirectoryNotFoundException from cleanup.
if (Directory.Exists(root))
{
Directory.Delete(root, recursive: true);
}
}
}

[Test]
public void LoadPinFromPath_WhenProjectRunnerVersionKeyIsMissing_ReturnsFailureWithMissingKeyMessage()
{
// Tests that a pin file without projectRunnerVersion fails with the exact missing-key message.
string root = CreateTestRoot();
string pinPath = Path.Combine(root, "project-runner-pin.json");

try
{
Directory.CreateDirectory(root);
File.WriteAllText(pinPath, "{\"minimumDispatcherVersion\":\"3.0.1\"}");

CliPinLoadResult result = CliPinReaderService.LoadPinFromPath(pinPath);

Assert.That(result.Success, Is.False);
Assert.That(
result.ErrorMessage,
Is.EqualTo($"Unity CLI Loop pin file at {pinPath} is missing projectRunnerVersion."));
}
finally
{
// Why: guard so a failure before directory creation does not mask the original
// exception with a DirectoryNotFoundException from cleanup.
if (Directory.Exists(root))
{
Directory.Delete(root, recursive: true);
}
}
}

[Test]
public void LoadPinFromPath_WhenMinimumDispatcherVersionKeyIsMissing_ReturnsFailureWithMissingKeyMessage()
{
// Tests that a pin file without minimumDispatcherVersion fails with the exact missing-key message.
string root = CreateTestRoot();
string pinPath = Path.Combine(root, "project-runner-pin.json");

try
{
Directory.CreateDirectory(root);
File.WriteAllText(pinPath, "{\"projectRunnerVersion\":\"3.0.0\"}");

CliPinLoadResult result = CliPinReaderService.LoadPinFromPath(pinPath);

Assert.That(result.Success, Is.False);
Assert.That(
result.ErrorMessage,
Is.EqualTo($"Unity CLI Loop pin file at {pinPath} is missing minimumDispatcherVersion."));
}
finally
{
// Why: guard so a failure before directory creation does not mask the original
// exception with a DirectoryNotFoundException from cleanup.
if (Directory.Exists(root))
{
Directory.Delete(root, recursive: true);
}
}
}

[Test]
public void LoadPinFromPath_WhenFileIsInvalidJson_ReturnsFailureWithInvalidJsonMessage()
{
// Tests that a pin file with malformed JSON fails with a message naming the pin path
// instead of letting the JsonReaderException escape.
string root = CreateTestRoot();
string pinPath = Path.Combine(root, "project-runner-pin.json");

try
{
Directory.CreateDirectory(root);
File.WriteAllText(pinPath, "{\"projectRunnerVersion\":");

CliPinLoadResult result = CliPinReaderService.LoadPinFromPath(pinPath);

Assert.That(result.Success, Is.False);
Assert.That(
result.ErrorMessage,
Does.StartWith($"Unity CLI Loop pin file at {pinPath} contains invalid JSON:"));
}
finally
{
// Why: guard so a failure before directory creation does not mask the original
// exception with a DirectoryNotFoundException from cleanup.
if (Directory.Exists(root))
{
Directory.Delete(root, recursive: true);
}
}
}

private static string CreateTestRoot()
{
return Path.Combine(
Path.GetTempPath(),
"unity-cli-loop-tests",
Guid.NewGuid().ToString("N"));
}
}
}
11 changes: 11 additions & 0 deletions Assets/Tests/Editor/CliPinReaderServiceTests.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 10 additions & 5 deletions Assets/Tests/Editor/CliSetupApplicationServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using UnityEngine;

using io.github.hatayama.UnityCliLoop.Application;
using io.github.hatayama.UnityCliLoop.Infrastructure;

namespace io.github.hatayama.UnityCliLoop.Tests.Editor
{
Expand All @@ -20,7 +21,8 @@ public async Task InstallGlobalCliAsync_UsesMinimumRequiredDispatcherReleaseTag(
FakeNativeCliInstaller nativeCliInstaller = new();
CliSetupApplicationService service = new(
new FakeCliInstallationDetector(new string[] { null }),
nativeCliInstaller);
nativeCliInstaller,
new CliPinReaderService());

await service.InstallGlobalCliAsync(RuntimePlatform.OSXEditor, CancellationToken.None);

Expand All @@ -35,7 +37,8 @@ public void GetMinimumRequiredCliVersion_UsesDispatcherVersion()
// Verifies setup reads the minimum dispatcher version from the package pin JSON.
CliSetupApplicationService service = new(
new FakeCliInstallationDetector(new string[] { null }),
new FakeNativeCliInstaller());
new FakeNativeCliInstaller(),
new CliPinReaderService());

Assert.That(service.GetMinimumRequiredCliVersion(), Is.EqualTo(ExpectedMinimumDispatcherVersion()));
}
Expand All @@ -46,7 +49,8 @@ public void GetMinimumRequiredCliReleaseTag_UsesDispatcherReleaseTag()
// Verifies setup derives the prefixed release tag from the package pin instead of a duplicated constant.
CliSetupApplicationService service = new(
new FakeCliInstallationDetector(new string[] { null }),
new FakeNativeCliInstaller());
new FakeNativeCliInstaller(),
new CliPinReaderService());

Assert.That(service.GetMinimumRequiredCliReleaseTag(), Is.EqualTo(ExpectedDispatcherReleaseTag()));
}
Expand All @@ -58,7 +62,8 @@ public void GetGlobalCliInstallCommand_UsesMinimumRequiredDispatcherReleaseTag()
FakeNativeCliInstaller nativeCliInstaller = new();
CliSetupApplicationService service = new(
new FakeCliInstallationDetector(new string[] { null }),
nativeCliInstaller);
nativeCliInstaller,
new CliPinReaderService());

NativeCliInstallCommand command = service.GetGlobalCliInstallCommand(
RuntimePlatform.OSXEditor,
Expand All @@ -71,7 +76,7 @@ public void GetGlobalCliInstallCommand_UsesMinimumRequiredDispatcherReleaseTag()

private static string ExpectedMinimumDispatcherVersion()
{
CliPinLoadResult result = CliPinReader.LoadPackagePin();
CliPinLoadResult result = new CliPinReaderService().LoadPackagePin();
Assert.That(result.Success, Is.True, result.ErrorMessage);
return result.Pin.MinimumDispatcherVersion;
}
Expand Down
Loading
Loading