/* * Copyright (c) 2025 ETH Zürich, IT Services * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ using System; using System.Collections.Generic; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using SafeExamBrowser.Client.Contracts; using SafeExamBrowser.Client.Responsibilities; using SafeExamBrowser.Communication.Contracts.Data; using SafeExamBrowser.Communication.Contracts.Events; using SafeExamBrowser.Communication.Contracts.Hosts; using SafeExamBrowser.Communication.Contracts.Proxies; using SafeExamBrowser.I18n.Contracts; using SafeExamBrowser.Logging.Contracts; using SafeExamBrowser.Server.Contracts.Data; using SafeExamBrowser.UserInterface.Contracts; using SafeExamBrowser.UserInterface.Contracts.MessageBox; using SafeExamBrowser.UserInterface.Contracts.Windows; using SafeExamBrowser.UserInterface.Contracts.Windows.Data; namespace SafeExamBrowser.Client.UnitTests.Responsibilities { [TestClass] public class CommunicationResponsibilityTests { private Mock clientHost; private ClientContext context; private Mock coordinator; private Mock messageBox; private Mock runtimeProxy; private Mock shutdown; private Mock splashScreen; private Mock text; private Mock uiFactory; private CommunicationResponsibility sut; [TestInitialize] public void Initialize() { var logger = new Mock(); clientHost = new Mock(); context = new ClientContext(); coordinator = new Mock(); messageBox = new Mock(); runtimeProxy = new Mock(); shutdown = new Mock(); splashScreen = new Mock(); text = new Mock(); uiFactory = new Mock(); context.ClientHost = clientHost.Object; sut = new CommunicationResponsibility( context, coordinator.Object, logger.Object, messageBox.Object, runtimeProxy.Object, shutdown.Object, splashScreen.Object, text.Object, uiFactory.Object); sut.Assume(ClientTask.RegisterEvents); } [TestMethod] public void Communication_MustCorrectlyHandleExamSelection() { var args = new ExamSelectionRequestEventArgs { Exams = new List<(string id, string lms, string name, string url)> { ("", "", "", "") }, RequestId = Guid.NewGuid() }; var dialog = new Mock(); dialog.Setup(d => d.Show(It.IsAny())).Returns(new ExamSelectionDialogResult { Success = true }); uiFactory.Setup(f => f.CreateExamSelectionDialog(It.IsAny>())).Returns(dialog.Object); clientHost.Raise(c => c.ExamSelectionRequested += null, args); runtimeProxy.Verify(p => p.SubmitExamSelectionResult(It.Is(g => g == args.RequestId), true, null), Times.Once); uiFactory.Verify(f => f.CreateExamSelectionDialog(It.IsAny>()), Times.Once); } [TestMethod] public void Communication_MustCorrectlyHandleMessageBoxRequest() { var args = new MessageBoxRequestEventArgs { Action = (int) MessageBoxAction.YesNo, Icon = (int) MessageBoxIcon.Question, Message = "Some question to be answered", RequestId = Guid.NewGuid(), Title = "A Title" }; messageBox.Setup(m => m.Show( It.Is(s => s == args.Message), It.Is(s => s == args.Title), It.Is(a => a == (MessageBoxAction) args.Action), It.Is(i => i == (MessageBoxIcon) args.Icon), It.IsAny())).Returns(MessageBoxResult.No); clientHost.Raise(c => c.MessageBoxRequested += null, args); runtimeProxy.Verify(p => p.SubmitMessageBoxResult( It.Is(g => g == args.RequestId), It.Is(r => r == (int) MessageBoxResult.No)), Times.Once); } [TestMethod] public void Communication_MustCorrectlyHandlePasswordRequest() { var args = new PasswordRequestEventArgs { Purpose = PasswordRequestPurpose.LocalSettings, RequestId = Guid.NewGuid() }; var dialog = new Mock(); var result = new PasswordDialogResult { Password = "blubb", Success = true }; dialog.Setup(d => d.Show(It.IsAny())).Returns(result); uiFactory.Setup(f => f.CreatePasswordDialog(It.IsAny(), It.IsAny())).Returns(dialog.Object); clientHost.Raise(c => c.PasswordRequested += null, args); runtimeProxy.Verify(p => p.SubmitPassword( It.Is(g => g == args.RequestId), It.Is(b => b == result.Success), It.Is(s => s == result.Password)), Times.Once); } [TestMethod] public void Communication_MustCorrectlyHandleAbortedReconfiguration() { clientHost.Raise(c => c.ReconfigurationAborted += null); splashScreen.Verify(s => s.Hide(), Times.AtLeastOnce); } [TestMethod] public void Communication_MustInformUserAboutDeniedReconfiguration() { var args = new ReconfigurationEventArgs { ConfigurationPath = @"C:\Some\File\Path.seb" }; clientHost.Raise(c => c.ReconfigurationDenied += null, args); messageBox.Verify(m => m.Show( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); } [TestMethod] public void Communication_MustCorrectlyHandleServerCommunicationFailure() { var args = new ServerFailureActionRequestEventArgs { RequestId = Guid.NewGuid() }; var dialog = new Mock(); dialog.Setup(d => d.Show(It.IsAny())).Returns(new ServerFailureDialogResult()); uiFactory.Setup(f => f.CreateServerFailureDialog(It.IsAny(), It.IsAny())).Returns(dialog.Object); clientHost.Raise(c => c.ServerFailureActionRequested += null, args); runtimeProxy.Verify(r => r.SubmitServerFailureActionResult(It.Is(g => g == args.RequestId), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); uiFactory.Verify(f => f.CreateServerFailureDialog(It.IsAny(), It.IsAny()), Times.Once); } [TestMethod] public void Communication_MustCorrectlyInitiateShutdown() { clientHost.Raise(c => c.Shutdown += null); shutdown.Verify(s => s(), Times.Once); } [TestMethod] public void Communication_MustShutdownOnLostConnection() { runtimeProxy.Raise(p => p.ConnectionLost += null); messageBox.Verify(m => m.Show( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); shutdown.Verify(s => s(), Times.Once); } [TestMethod] public void MustNotFailIfDependencyIsNull() { context.ClientHost = null; sut.Assume(ClientTask.DeregisterEvents); } } }