Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#endif

using ChilliCream.Nitro.CommandLine.Helpers;
using ChilliCream.Nitro.CommandLine.Services.Sessions;

namespace ChilliCream.Nitro.CommandLine.Commands.Launch;

Expand All @@ -27,10 +28,36 @@ private static Task<int> ExecuteAsync(
CancellationToken cancellationToken)
{
var console = services.GetRequiredService<INitroConsole>();
var sessionService = services.GetRequiredService<ISessionService>();
var browser = services.GetRequiredService<IBrowserLauncher>();

SystemBrowser.Open(Constants.NitroWebUrl);
console.OkLine($"[link={Constants.NitroWebUrl}]Nitro[/] is launched!");
var url = ResolveUrl(sessionService.Session);

browser.Open(url);
console.OkLine($"[link={url}]Nitro[/] is launched!");
Comment thread
tobias-tengler marked this conversation as resolved.
Outdated

return Task.FromResult(ExitCodes.Success);
}

private static string ResolveUrl(Session? session)
{
if (session is null)
{
return Constants.NitroWebUrl;
}

var defaultApiUrl = Constants.ApiUrl["https://".Length..];

if (session.ApiUrl == defaultApiUrl || session.ApiUrl == Constants.ApiUrl)
{
return Constants.NitroWebUrl;
}

var baseUrl = session.ApiUrl.StartsWith("https://", StringComparison.OrdinalIgnoreCase)
|| session.ApiUrl.StartsWith("http://", StringComparison.OrdinalIgnoreCase)
? session.ApiUrl
: $"https://{session.ApiUrl}";

return $"{baseUrl.TrimEnd('/')}/ui";
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using ChilliCream.Nitro.CommandLine.Helpers;
using ChilliCream.Nitro.CommandLine.Results;
using ChilliCream.Nitro.CommandLine.Services;
using ChilliCream.Nitro.CommandLine.Services.Configuration;
Expand All @@ -21,6 +22,8 @@ public static IServiceCollection AddNitroServices(this IServiceCollection servic
services.TryAddSingleton<IResultHolder, ResultHolder>();
services.TryAddSingleton<IResultFormatter, JsonResultFormatter>();

services.TryAddSingleton<IBrowserLauncher, SystemBrowserLauncher>();

return services;
}
}
3 changes: 0 additions & 3 deletions src/Nitro/CommandLine/src/CommandLine/Helpers/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ internal static class Constants
{
public const int DefaultPrintWidth = 1_000;

// 5 Minutes
public const int DefaultTimeoutSec = 60 * 5;

public const string NitroWebUrl = "https://nitro.chillicream.com";

public const string ApiUrl = "https://api.chillicream.com";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace ChilliCream.Nitro.CommandLine.Helpers;

internal interface IBrowserLauncher
{
void Open(string url);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace ChilliCream.Nitro.CommandLine.Helpers;

internal sealed class SystemBrowserLauncher : IBrowserLauncher
{
public void Open(string url) => SystemBrowser.Open(url);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public BaseSchemaFileOption() : base("--schema")
{
Description = "The path to the graphql file with the schema";
Required = true;
this.DefaultFileFromEnvironmentValue("SCHEMA_FILE");
this.DefaultFileFromEnvironmentValue(EnvironmentVariables.SchemaFile);
this.LegalFilePathsOnly();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,6 @@ internal static class EnvironmentVariables
public const string TreatDangerousAsBreaking = "TREAT_DANGEROUS_AS_BREAKING";
public const string AllowBreakingSchemaChanges = "ALLOW_BREAKING_SCHEMA_CHANGES";
public const string OperationsFile = "OPERATIONS_FILE";
public const string SchemaFile = "SCHEMA_FILE";
public const string SchemaExtensionFile = "SCHEMA_EXTENSION_FILE";
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public ExtensionFileOption() : base("--extension")
{
Description = "The path to the graphql file with the schema extension";
Required = true;
this.DefaultFileFromEnvironmentValue("SCHEMA_EXTENSION_FILE");
this.DefaultFileFromEnvironmentValue(EnvironmentVariables.SchemaExtensionFile);
this.LegalFilePathsOnly();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public SchemaFileOption() : base("--schema-file")
{
Description = "The path to the graphql file with the schema definition";
Required = true;
this.DefaultFileFromEnvironmentValue("SCHEMA_FILE");
this.DefaultFileFromEnvironmentValue(EnvironmentVariables.SchemaFile);
this.LegalFilePathsOnly();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public abstract class CommandTestBase
protected readonly Mock<IEnvironmentsClient> EnvironmentsClientMock = new(MockBehavior.Strict);
protected readonly Mock<IStagesClient> StagesClientMock = new(MockBehavior.Strict);
internal readonly Mock<Services.Sessions.ISessionService> _sessionServiceMock = new();
internal readonly Mock<IBrowserLauncher> BrowserLauncherMock = new();
protected readonly Mock<IWorkspacesClient> WorkspacesClientMock = new(MockBehavior.Strict);
private InteractionMode _interactionMode = InteractionMode.NonInteractive;
private bool _authenticated = true;
Expand Down Expand Up @@ -225,6 +226,7 @@ private ServiceProvider BuildServices(INitroConsole console)
services.Replace(ServiceDescriptor.Singleton(_fileSystemMock.Object));
services.Replace(ServiceDescriptor.Singleton(_environmentVariableProviderMock.Object));
services.Replace(ServiceDescriptor.Singleton(_sessionServiceMock.Object));
services.Replace(ServiceDescriptor.Singleton(BrowserLauncherMock.Object));
services.Replace(ServiceDescriptor.Singleton(WorkspacesClientMock.Object));
services.Replace(ServiceDescriptor.Singleton(SchemasClientMock.Object));
services.Replace(ServiceDescriptor.Singleton(FusionConfigurationClientMock.Object));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using ChilliCream.Nitro.CommandLine.Helpers;
using Moq;

namespace ChilliCream.Nitro.CommandLine.Tests.Commands.Session;

public sealed class LaunchCommandTests(NitroCommandFixture fixture) : SessionCommandTestBase(fixture)
{
[Fact]
public async Task Help_ReturnsSuccess()
{
// arrange & act
var result = await ExecuteCommandAsync(
"launch",
"--help");

// assert
result.AssertHelpOutput(
"""
Description:
Launch Nitro in your default browser.

Usage:
nitro launch [options]

Options:
-?, -h, --help Show help and usage information

Example:
nitro launch
""");
}

[Fact]
public async Task NoSession_OpensDefaultNitroWebUrl()
{
// arrange
SetupInteractionMode(InteractionMode.Interactive);

// act
var result = await ExecuteCommandAsync("launch");

// assert
Assert.Equal(0, result.ExitCode);
BrowserLauncherMock.Verify(x => x.Open(Constants.NitroWebUrl), Times.Once);
}

[Fact]
public async Task DefaultApiUrl_OpensDefaultNitroWebUrl()
{
// arrange
SetupInteractionMode(InteractionMode.Interactive);
SetupCustomSession();

// act
var result = await ExecuteCommandAsync("launch");

// assert
Assert.Equal(0, result.ExitCode);
BrowserLauncherMock.Verify(x => x.Open(Constants.NitroWebUrl), Times.Once);
}

[Fact]
public async Task CustomApiUrl_OpensBaseUrlSlashUi()
{
// arrange
SetupInteractionMode(InteractionMode.Interactive);
SetupCustomSession(
apiUrl: "api.custom.com",
identityUrl: "https://id.custom.com");

// act
var result = await ExecuteCommandAsync("launch");

// assert
Assert.Equal(0, result.ExitCode);
BrowserLauncherMock.Verify(x => x.Open("https://api.custom.com/ui"), Times.Once);
}

[Fact]
public async Task CustomApiUrlWithScheme_OpensBaseUrlSlashUi()
{
// arrange
SetupInteractionMode(InteractionMode.Interactive);
SetupCustomSession(
apiUrl: "https://api.custom.com",
identityUrl: "https://id.custom.com");

// act
var result = await ExecuteCommandAsync("launch");

// assert
Assert.Equal(0, result.ExitCode);
BrowserLauncherMock.Verify(x => x.Open("https://api.custom.com/ui"), Times.Once);
}
}
Loading
Loading