- ProfileManagementDialog.xaml: height 750, new Row 4 with Register/Remove buttons - BooleanToVisibilityConverter added to Window.Resources - Fallback instructions panel bound to ShowFallbackInstructions - RegistrationStatus text block with StringToVisibilityConverter - Buttons row shifted to Row 5 - ProfileManagementViewModelRegistrationTests: 7 unit tests, all passing - ProfileManagementViewModelLogoTests: updated to 5-param constructor
158 lines
5.0 KiB
C#
158 lines
5.0 KiB
C#
using System.IO;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using Moq;
|
|
using SharepointToolbox.Core.Models;
|
|
using SharepointToolbox.Infrastructure.Auth;
|
|
using SharepointToolbox.Infrastructure.Persistence;
|
|
using SharepointToolbox.Services;
|
|
using SharepointToolbox.ViewModels;
|
|
|
|
namespace SharepointToolbox.Tests.ViewModels;
|
|
|
|
[Trait("Category", "Unit")]
|
|
public class ProfileManagementViewModelRegistrationTests : IDisposable
|
|
{
|
|
private readonly string _tempFile;
|
|
private readonly Mock<IBrandingService> _mockBranding;
|
|
private readonly Mock<IAppRegistrationService> _mockAppReg;
|
|
private readonly GraphClientFactory _graphClientFactory;
|
|
|
|
public ProfileManagementViewModelRegistrationTests()
|
|
{
|
|
_tempFile = Path.GetTempFileName();
|
|
File.Delete(_tempFile);
|
|
_mockBranding = new Mock<IBrandingService>();
|
|
_mockAppReg = new Mock<IAppRegistrationService>();
|
|
_graphClientFactory = new GraphClientFactory(new MsalClientFactory());
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (File.Exists(_tempFile)) File.Delete(_tempFile);
|
|
if (File.Exists(_tempFile + ".tmp")) File.Delete(_tempFile + ".tmp");
|
|
}
|
|
|
|
private ProfileManagementViewModel CreateViewModel()
|
|
{
|
|
var profileService = new ProfileService(new ProfileRepository(_tempFile));
|
|
return new ProfileManagementViewModel(
|
|
profileService,
|
|
_mockBranding.Object,
|
|
_graphClientFactory,
|
|
NullLogger<ProfileManagementViewModel>.Instance,
|
|
_mockAppReg.Object);
|
|
}
|
|
|
|
private static TenantProfile MakeProfile(string? appId = null) => new TenantProfile
|
|
{
|
|
Name = "TestTenant",
|
|
TenantUrl = "https://test.sharepoint.com",
|
|
ClientId = "00000000-0000-0000-0000-000000000001",
|
|
AppId = appId
|
|
};
|
|
|
|
[Fact]
|
|
public void RegisterAppCommand_CanExecute_WhenProfileSelected_AndNoAppId()
|
|
{
|
|
var vm = CreateViewModel();
|
|
vm.SelectedProfile = MakeProfile(appId: null);
|
|
|
|
Assert.True(vm.RegisterAppCommand.CanExecute(null));
|
|
}
|
|
|
|
[Fact]
|
|
public void RegisterAppCommand_CannotExecute_WhenNoProfile()
|
|
{
|
|
var vm = CreateViewModel();
|
|
|
|
Assert.False(vm.RegisterAppCommand.CanExecute(null));
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveAppCommand_CanExecute_WhenProfileHasAppId()
|
|
{
|
|
var vm = CreateViewModel();
|
|
vm.SelectedProfile = MakeProfile(appId: "some-app-id");
|
|
|
|
Assert.True(vm.RemoveAppCommand.CanExecute(null));
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveAppCommand_CannotExecute_WhenNoAppId()
|
|
{
|
|
var vm = CreateViewModel();
|
|
vm.SelectedProfile = MakeProfile(appId: null);
|
|
|
|
Assert.False(vm.RemoveAppCommand.CanExecute(null));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task RegisterApp_ShowsFallback_WhenNotAdmin()
|
|
{
|
|
_mockAppReg
|
|
.Setup(s => s.IsGlobalAdminAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
|
.ReturnsAsync(false);
|
|
|
|
var vm = CreateViewModel();
|
|
vm.SelectedProfile = MakeProfile(appId: null);
|
|
|
|
await vm.RegisterAppCommand.ExecuteAsync(null);
|
|
|
|
Assert.True(vm.ShowFallbackInstructions);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task RegisterApp_SetsAppId_OnSuccess()
|
|
{
|
|
_mockAppReg
|
|
.Setup(s => s.IsGlobalAdminAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
|
.ReturnsAsync(true);
|
|
_mockAppReg
|
|
.Setup(s => s.RegisterAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
|
.ReturnsAsync(AppRegistrationResult.Success("new-app-id-123"));
|
|
|
|
var profileService = new ProfileService(new ProfileRepository(_tempFile));
|
|
var profile = MakeProfile(appId: null);
|
|
await profileService.AddProfileAsync(profile);
|
|
|
|
var vm = new ProfileManagementViewModel(
|
|
profileService,
|
|
_mockBranding.Object,
|
|
_graphClientFactory,
|
|
NullLogger<ProfileManagementViewModel>.Instance,
|
|
_mockAppReg.Object);
|
|
vm.SelectedProfile = profile;
|
|
|
|
await vm.RegisterAppCommand.ExecuteAsync(null);
|
|
|
|
Assert.Equal("new-app-id-123", profile.AppId);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task RemoveApp_ClearsAppId()
|
|
{
|
|
_mockAppReg
|
|
.Setup(s => s.RemoveAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
|
.Returns(Task.CompletedTask);
|
|
_mockAppReg
|
|
.Setup(s => s.ClearMsalSessionAsync(It.IsAny<string>(), It.IsAny<string>()))
|
|
.Returns(Task.CompletedTask);
|
|
|
|
var profileService = new ProfileService(new ProfileRepository(_tempFile));
|
|
var profile = MakeProfile(appId: "existing-app-id");
|
|
await profileService.AddProfileAsync(profile);
|
|
|
|
var vm = new ProfileManagementViewModel(
|
|
profileService,
|
|
_mockBranding.Object,
|
|
_graphClientFactory,
|
|
NullLogger<ProfileManagementViewModel>.Instance,
|
|
_mockAppReg.Object);
|
|
vm.SelectedProfile = profile;
|
|
|
|
await vm.RemoveAppCommand.ExecuteAsync(null);
|
|
|
|
Assert.Null(profile.AppId);
|
|
}
|
|
}
|