From 1611f87990c9627f9becaef27109bb8ab7b07c05 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Antoine=20Th=C3=A9ate?=
<97221392+antoineatrhea@users.noreply.github.com>
Date: Mon, 8 Jan 2024 09:17:40 +0100
Subject: [PATCH] Fix #475: Added EngineeringModelId inside Template and
improvement (#492)
---
.dockerignore | 3 +-
.gitignore | 2 +
...ringModelApplicationTemplateTestFixture.cs | 203 ++++++++++++++++++
...IterationApplicationTemplateTestFixture.cs | 16 +-
COMET.Web.Common/COMET.Web.Common.csproj | 2 +-
...eEngineeringModelApplicationTemplate.razor | 2 +-
...gineeringModelApplicationTemplate.razor.cs | 66 +++++-
...ingleIterationApplicationTemplate.razor.cs | 21 +-
...leIterationApplicationTemplateViewModel.cs | 2 +-
.../ModelDashboardTestFixture.cs | 2 +-
.../ParameterEditorTestFixture.cs | 2 +-
.../Pages/Viewer/ViewerTestFixture.cs | 2 +-
COMETwebapp.sln.DotSettings | 5 +-
13 files changed, 303 insertions(+), 25 deletions(-)
create mode 100644 COMET.Web.Common.Tests/Components/Applications/SingleEngineeringModelApplicationTemplateTestFixture.cs
diff --git a/.dockerignore b/.dockerignore
index cf34eb6d..bac51aa4 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -14,4 +14,5 @@
**/docker-compose*
**/Dockerfile*
**/obj
-!nginx.conf
\ No newline at end of file
+!nginx.conf
+switcher.json
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index d93cc446..1c0c0a38 100644
--- a/.gitignore
+++ b/.gitignore
@@ -352,3 +352,5 @@ MigrationBackup/
# Jetbrains folders
.idea/
+
+switcher.json
\ No newline at end of file
diff --git a/COMET.Web.Common.Tests/Components/Applications/SingleEngineeringModelApplicationTemplateTestFixture.cs b/COMET.Web.Common.Tests/Components/Applications/SingleEngineeringModelApplicationTemplateTestFixture.cs
new file mode 100644
index 00000000..41191f2a
--- /dev/null
+++ b/COMET.Web.Common.Tests/Components/Applications/SingleEngineeringModelApplicationTemplateTestFixture.cs
@@ -0,0 +1,203 @@
+// --------------------------------------------------------------------------------------------------------------------
+//
+// Copyright (c) 2024 RHEA System S.A.
+//
+// Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine
+//
+// This file is part of COMET WEB Community Edition
+// The COMET WEB Community Edition is the RHEA Web Application implementation of ECSS-E-TM-10-25
+// Annex A and Annex C.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace COMET.Web.Common.Tests.Components.Applications
+{
+ using Bunit;
+
+ using CDP4Common.EngineeringModelData;
+ using CDP4Common.Extensions;
+
+ using CDP4Dal;
+
+ using COMET.Web.Common.Components;
+ using COMET.Web.Common.Components.Applications;
+ using COMET.Web.Common.Components.Selectors;
+ using COMET.Web.Common.Model.Configuration;
+ using COMET.Web.Common.Services.ConfigurationService;
+ using COMET.Web.Common.Services.SessionManagement;
+ using COMET.Web.Common.Services.StringTableService;
+ using COMET.Web.Common.Test.Helpers;
+ using COMET.Web.Common.ViewModels.Components;
+ using COMET.Web.Common.ViewModels.Components.Applications;
+ using COMET.Web.Common.ViewModels.Components.Selectors;
+
+ using DynamicData;
+
+ using Microsoft.AspNetCore.Components;
+ using Microsoft.Extensions.DependencyInjection;
+
+ using Moq;
+
+ using NUnit.Framework;
+
+ using TestContext = Bunit.TestContext;
+
+ [TestFixture]
+ public class SingleEngineeringModelApplicationTemplateTestFixture
+ {
+ private Mock viewModel;
+ private List openEngineeringModels;
+ private TestContext context;
+
+ [SetUp]
+ public void Setup()
+ {
+ this.context = new TestContext();
+ this.viewModel = new Mock();
+
+ this.openEngineeringModels = [];
+ var sessionService = new Mock();
+ sessionService.Setup(x => x.OpenEngineeringModels).Returns(this.openEngineeringModels);
+ sessionService.Setup(x => x.OpenIterations).Returns(new SourceList());
+ var session = new Mock();
+ session.Setup(x => x.DataSourceUri).Returns("http://localhost:5000");
+ sessionService.Setup(x => x.Session).Returns(session.Object);
+ this.viewModel.Setup(x => x.SessionService).Returns(sessionService.Object);
+ var mockConfigurationService = new Mock();
+ mockConfigurationService.Setup(x => x.ServerConfiguration).Returns(new ServerConfiguration());
+ this.context.Services.AddSingleton(this.viewModel.Object);
+ this.context.Services.AddSingleton();
+ this.context.Services.AddSingleton(mockConfigurationService.Object);
+ this.context.Services.AddSingleton(new Mock().Object);
+ this.context.Services.AddSingleton(sessionService.Object);
+ this.context.ConfigureDevExpressBlazor();
+ }
+
+ [TearDown]
+ public void Teardown()
+ {
+ this.context.CleanContext();
+ }
+
+ [Test]
+ public void VerifyWithEngineeringModelIdParameter()
+ {
+ this.openEngineeringModels.Add(new EngineeringModel
+ {
+ Iid = Guid.NewGuid()
+ });
+
+ this.viewModel.Setup(x => x.OnThingSelect(It.IsAny())).Callback((EngineeringModel engineeringModel) => this.viewModel.Setup(x => x.SelectedThing).Returns(engineeringModel));
+ var renderer = this.context.RenderComponent(parameters => { parameters.Add(p => p.EngineeringModelId, Guid.NewGuid()); });
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(renderer.Instance.EngineeringModelId, Is.EqualTo(this.openEngineeringModels[0].Iid));
+ this.viewModel.Verify(x => x.OnThingSelect(this.openEngineeringModels[0]), Times.Once);
+ });
+
+ this.viewModel.Setup(x => x.SelectedThing).Returns((EngineeringModel)null);
+ _ = this.context.RenderComponent(parameters => { parameters.Add(p => p.EngineeringModelId, this.openEngineeringModels[0].Iid); });
+
+ this.viewModel.Verify(x => x.OnThingSelect(this.openEngineeringModels[0]), Times.Exactly(2));
+
+ this.viewModel.Setup(x => x.SelectedThing).Returns(new EngineeringModel
+ {
+ Iid = Guid.NewGuid()
+ });
+
+ renderer = this.context.RenderComponent(parameters => { parameters.Add(p => p.EngineeringModelId, this.openEngineeringModels[0].Iid); });
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(renderer.Instance.EngineeringModelId, Is.EqualTo(this.viewModel.Object.SelectedThing.Iid));
+ this.viewModel.Verify(x => x.OnThingSelect(this.openEngineeringModels[0]), Times.Exactly(2));
+ });
+ }
+
+ [Test]
+ public void VerifyWithoutEngineeringModelIdParameter()
+ {
+ this.openEngineeringModels.Add(new EngineeringModel()
+ {
+ Iid = Guid.NewGuid()
+ });
+
+ var renderer = this.context.RenderComponent(parameters =>
+ {
+ parameters.Add(p => p.Body, builder =>
+ {
+ builder.OpenElement(0, "p");
+ builder.AddContent(1, "body");
+ builder.CloseComponent();
+ });
+ });
+
+ var navigationManager = this.context.Services.GetService();
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(navigationManager.Uri, Is.EqualTo("http://localhost/"));
+ this.viewModel.Verify(x => x.OnThingSelect(this.openEngineeringModels[0]), Times.Exactly(2));
+ });
+
+ this.viewModel.Setup(x => x.SelectedThing).Returns(this.openEngineeringModels[0]);
+ renderer.Instance.SetCorrectUrl();
+ var engineeringModel = this.viewModel.Object.SelectedThing;
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(navigationManager.Uri, Does.Contain("localhost%3A5000"));
+ Assert.That(navigationManager.Uri, Does.Contain(engineeringModel.Iid.ToShortGuid()));
+ });
+
+ renderer.Render();
+
+ var pElement = renderer.Find("p");
+ Assert.That(pElement.TextContent, Is.EqualTo("body"));
+
+ this.openEngineeringModels.Add(new EngineeringModel());
+
+ renderer = this.context.RenderComponent(parameters =>
+ {
+ parameters.Add(p => p.Body, builder =>
+ {
+ builder.OpenElement(0, "p");
+ builder.AddContent(1, "body");
+ builder.CloseComponent();
+ });
+ });
+
+ Assert.That(() => renderer.FindComponent(), Throws.Exception);
+ this.viewModel.Verify(x => x.AskToSelectThing(), Times.Once);
+ this.viewModel.Setup(x => x.IsOnSelectionMode).Returns(true);
+ this.viewModel.Setup(x => x.EngineeringModelSelectorViewModel).Returns(new EngineeringModelSelectorViewModel());
+ renderer.Render();
+ Assert.That(() => renderer.FindComponent(), Throws.Nothing);
+ this.openEngineeringModels.Clear();
+ this.viewModel.Setup(x => x.SelectedThing).Returns((EngineeringModel)null);
+ renderer.Instance.SetCorrectUrl();
+
+ renderer.Render();
+
+ Assert.Multiple(() =>
+ {
+ Assert.That(navigationManager.Uri, Is.EqualTo("http://localhost/"));
+ Assert.That(() => renderer.FindComponent(), Throws.Nothing);
+ });
+ }
+ }
+}
diff --git a/COMET.Web.Common.Tests/Components/Applications/SingleIterationApplicationTemplateTestFixture.cs b/COMET.Web.Common.Tests/Components/Applications/SingleIterationApplicationTemplateTestFixture.cs
index 0e50713c..3fde4584 100644
--- a/COMET.Web.Common.Tests/Components/Applications/SingleIterationApplicationTemplateTestFixture.cs
+++ b/COMET.Web.Common.Tests/Components/Applications/SingleIterationApplicationTemplateTestFixture.cs
@@ -108,13 +108,19 @@ public void VerifyWithIterationIdParameter()
}
});
+ this.viewModel.Setup(x => x.OnThingSelect(It.IsAny())).Callback((Iteration iteration) => this.viewModel.Setup(x => x.SelectedThing).Returns(iteration));
var renderer = this.context.RenderComponent(parameters => { parameters.Add(p => p.IterationId, Guid.NewGuid()); });
- Assert.That(renderer.Instance.IterationId, Is.EqualTo(Guid.Empty));
+ Assert.Multiple(() =>
+ {
+ Assert.That(renderer.Instance.IterationId, Is.EqualTo(this.openIterations.Items.First().Iid));
+ this.viewModel.Verify(x => x.OnThingSelect(this.openIterations.Items.First()), Times.Once);
+ });
+ this.viewModel.Setup(x => x.SelectedThing).Returns((Iteration)null);
_ = this.context.RenderComponent(parameters => { parameters.Add(p => p.IterationId, this.openIterations.Items.First().Iid); });
- this.viewModel.Verify(x => x.OnThingSelect(this.openIterations.Items.First()), Times.Once);
+ this.viewModel.Verify(x => x.OnThingSelect(this.openIterations.Items.First()), Times.Exactly(2));
this.viewModel.Setup(x => x.SelectedThing).Returns(new Iteration
{
@@ -132,8 +138,8 @@ public void VerifyWithIterationIdParameter()
Assert.Multiple(() =>
{
- Assert.That(renderer.Instance.IterationId, Is.EqualTo(this.openIterations.Items.First().Iid));
- this.viewModel.Verify(x => x.OnThingSelect(this.openIterations.Items.First()), Times.Once);
+ Assert.That(renderer.Instance.IterationId, Is.EqualTo(this.viewModel.Object.SelectedThing.Iid));
+ this.viewModel.Verify(x => x.OnThingSelect(this.openIterations.Items.First()), Times.Exactly(2));
});
}
@@ -167,7 +173,7 @@ public void VerifyWithoutIterationIdParameter()
Assert.Multiple(() =>
{
Assert.That(navigationManager.Uri, Is.EqualTo("http://localhost/"));
- this.viewModel.Verify(x => x.OnThingSelect(this.openIterations.Items.First()), Times.Once);
+ this.viewModel.Verify(x => x.OnThingSelect(this.openIterations.Items.First()), Times.Exactly(2));
});
this.viewModel.Setup(x => x.SelectedThing).Returns(this.openIterations.Items.First());
diff --git a/COMET.Web.Common/COMET.Web.Common.csproj b/COMET.Web.Common/COMET.Web.Common.csproj
index 38ce46af..a3294e2b 100644
--- a/COMET.Web.Common/COMET.Web.Common.csproj
+++ b/COMET.Web.Common/COMET.Web.Common.csproj
@@ -25,7 +25,7 @@
-
+
diff --git a/COMET.Web.Common/Components/Applications/SingleEngineeringModelApplicationTemplate.razor b/COMET.Web.Common/Components/Applications/SingleEngineeringModelApplicationTemplate.razor
index d9480a1b..8541adc3 100644
--- a/COMET.Web.Common/Components/Applications/SingleEngineeringModelApplicationTemplate.razor
+++ b/COMET.Web.Common/Components/Applications/SingleEngineeringModelApplicationTemplate.razor
@@ -27,7 +27,7 @@
-@if (this.ViewModel.SessionService.OpenIterations.Count == 0)
+@if (this.ViewModel.SessionService.OpenEngineeringModels.Count == 0)
{
diff --git a/COMET.Web.Common/Components/Applications/SingleEngineeringModelApplicationTemplate.razor.cs b/COMET.Web.Common/Components/Applications/SingleEngineeringModelApplicationTemplate.razor.cs
index 06a50c2b..8ed19b3c 100644
--- a/COMET.Web.Common/Components/Applications/SingleEngineeringModelApplicationTemplate.razor.cs
+++ b/COMET.Web.Common/Components/Applications/SingleEngineeringModelApplicationTemplate.razor.cs
@@ -27,12 +27,76 @@ namespace COMET.Web.Common.Components.Applications
{
using CDP4Common.EngineeringModelData;
- using COMET.Web.Common.ViewModels.Components.Applications;
+ using COMET.Web.Common.Extensions;
+ using COMET.Web.Common.Utilities;
+
+ using Microsoft.AspNetCore.Components;
///
/// Shared component that will englobe all applications where only one needs to be selected
///
public partial class SingleEngineeringModelApplicationTemplate
{
+ ///
+ /// The of selected
+ ///
+ [Parameter]
+ public Guid EngineeringModelId { get; set; }
+
+ ///
+ /// Method invoked when the component is ready to start, having received its
+ /// initial parameters from its parent in the render tree.
+ ///
+ protected override void OnInitialized()
+ {
+ this.UpdateProperties();
+ base.OnInitialized();
+ }
+
+ ///
+ /// Method invoked when the component has received parameters from its parent in
+ /// the render tree, and the incoming values have been assigned to properties.
+ ///
+ protected override void OnParametersSet()
+ {
+ base.OnParametersSet();
+ this.UpdateProperties();
+ }
+
+ ///
+ /// Update properties of the viewmodel based on provided parameters
+ ///
+ private void UpdateProperties()
+ {
+ if (this.EngineeringModelId == Guid.Empty)
+ {
+ switch (this.ViewModel.SessionService.OpenEngineeringModels.Count)
+ {
+ case 1:
+ this.ViewModel.OnThingSelect(this.ViewModel.SessionService.OpenEngineeringModels.First());
+ break;
+ case > 1:
+ this.ViewModel.AskToSelectThing();
+ break;
+ }
+ }
+ else if (this.EngineeringModelId != Guid.Empty && this.ViewModel.SelectedThing == null)
+ {
+ this.ViewModel.OnThingSelect(this.ViewModel.SessionService.OpenEngineeringModels.FirstOrDefault(x => x.Iid == this.EngineeringModelId));
+ }
+
+ this.EngineeringModelId = this.ViewModel.SelectedThing?.Iid ?? Guid.Empty;
+ }
+
+ ///
+ /// Set URL parameters based on the current context
+ ///
+ /// A of URL parameters
+ protected override void SetUrlParameters(Dictionary currentOptions)
+ {
+ base.SetUrlParameters(currentOptions);
+
+ currentOptions[QueryKeys.ModelKey] = this.ViewModel.SelectedThing.Iid.ToShortGuid();
+ }
}
}
diff --git a/COMET.Web.Common/Components/Applications/SingleIterationApplicationTemplate.razor.cs b/COMET.Web.Common/Components/Applications/SingleIterationApplicationTemplate.razor.cs
index a90bf3bc..c2fa561c 100644
--- a/COMET.Web.Common/Components/Applications/SingleIterationApplicationTemplate.razor.cs
+++ b/COMET.Web.Common/Components/Applications/SingleIterationApplicationTemplate.razor.cs
@@ -51,6 +51,7 @@ public partial class SingleIterationApplicationTemplate
///
protected override void OnInitialized()
{
+ this.UpdateProperties();
base.OnInitialized();
this.Disposables.Add(CDPMessageBus.Current.Listen()
@@ -64,7 +65,14 @@ protected override void OnInitialized()
protected override void OnParametersSet()
{
base.OnParametersSet();
+ this.UpdateProperties();
+ }
+ ///
+ /// Update properties of the viewmodel based on provided parameters
+ ///
+ private void UpdateProperties()
+ {
if (this.IterationId == Guid.Empty)
{
switch (this.ViewModel.SessionService.OpenIterations.Count)
@@ -79,17 +87,10 @@ protected override void OnParametersSet()
}
else if (this.IterationId != Guid.Empty && this.ViewModel.SelectedThing == null)
{
- var iteration = this.ViewModel.SessionService.OpenIterations.Items.FirstOrDefault(x => x.Iid == this.IterationId);
-
- if (iteration != null)
- {
- this.ViewModel.OnThingSelect(iteration);
- }
- else
- {
- this.IterationId = Guid.Empty;
- }
+ this.ViewModel.OnThingSelect(this.ViewModel.SessionService.OpenIterations.Items.FirstOrDefault(x => x.Iid == this.IterationId));
}
+
+ this.IterationId = this.ViewModel.SelectedThing?.Iid ?? Guid.Empty;
}
///
diff --git a/COMET.Web.Common/ViewModels/Components/Applications/SingleIterationApplicationTemplateViewModel.cs b/COMET.Web.Common/ViewModels/Components/Applications/SingleIterationApplicationTemplateViewModel.cs
index 9ed70210..6a9e4fe7 100644
--- a/COMET.Web.Common/ViewModels/Components/Applications/SingleIterationApplicationTemplateViewModel.cs
+++ b/COMET.Web.Common/ViewModels/Components/Applications/SingleIterationApplicationTemplateViewModel.cs
@@ -62,7 +62,7 @@ public SingleIterationApplicationTemplateViewModel(ISessionService sessionServic
public override void OnThingSelect(Iteration thing)
{
base.OnThingSelect(thing);
- this.SelectedIterationData = new IterationData(thing.IterationSetup, true);
+ this.SelectedIterationData = thing == null ? null : new IterationData(thing.IterationSetup, true);
}
///
diff --git a/COMETwebapp.Tests/Pages/ModelDashboard/ModelDashboardTestFixture.cs b/COMETwebapp.Tests/Pages/ModelDashboard/ModelDashboardTestFixture.cs
index 2e9c5b65..fd24b21a 100644
--- a/COMETwebapp.Tests/Pages/ModelDashboard/ModelDashboardTestFixture.cs
+++ b/COMETwebapp.Tests/Pages/ModelDashboard/ModelDashboardTestFixture.cs
@@ -192,7 +192,7 @@ public void VerifyIterationPreselection()
parameters.Add(p => p.IterationId, this.secondIteration.Iid.ToShortGuid());
});
- Assert.That(this.viewModel.SelectedThing, Is.Null);
+ Assert.That(this.viewModel.SelectedThing, Is.EqualTo(this.firstIteration));
}
}
}
diff --git a/COMETwebapp.Tests/Pages/ParameterEditor/ParameterEditorTestFixture.cs b/COMETwebapp.Tests/Pages/ParameterEditor/ParameterEditorTestFixture.cs
index 3e8a81fa..a4dc362c 100644
--- a/COMETwebapp.Tests/Pages/ParameterEditor/ParameterEditorTestFixture.cs
+++ b/COMETwebapp.Tests/Pages/ParameterEditor/ParameterEditorTestFixture.cs
@@ -201,7 +201,7 @@ public void VerifyIterationPreselection()
parameters.Add(p => p.IterationId, this.secondIteration.Iid.ToShortGuid());
});
- Assert.That(this.viewModel.SelectedThing, Is.Null);
+ Assert.That(this.viewModel.SelectedThing, Is.EqualTo(this.firstIteration));
}
}
}
diff --git a/COMETwebapp.Tests/Pages/Viewer/ViewerTestFixture.cs b/COMETwebapp.Tests/Pages/Viewer/ViewerTestFixture.cs
index bea12ed9..47730250 100644
--- a/COMETwebapp.Tests/Pages/Viewer/ViewerTestFixture.cs
+++ b/COMETwebapp.Tests/Pages/Viewer/ViewerTestFixture.cs
@@ -162,7 +162,7 @@ public void VerifyIterationPreselection()
this.context.RenderComponent(parameters => { parameters.Add(p => p.IterationId, this.secondIteration.Iid.ToShortGuid()); });
- Assert.That(this.viewModel.SelectedThing, Is.Null);
+ Assert.That(this.viewModel.SelectedThing, Is.EqualTo(this.firstIteration));
}
[Test]
diff --git a/COMETwebapp.sln.DotSettings b/COMETwebapp.sln.DotSettings
index 10dc2de5..d6f1c489 100644
--- a/COMETwebapp.sln.DotSettings
+++ b/COMETwebapp.sln.DotSettings
@@ -252,8 +252,8 @@
True
True
--------------------------------------------------------------------------------------------------------------------
- <copyright file="$FILENAME$" company="RHEA System S.A.">
- Copyright (c) $CURRENT_YEAR$ RHEA System S.A.
+ <copyright file="${File.FileName}" company="RHEA System S.A.">
+ Copyright (c) ${CurrentDate.Year} RHEA System S.A.
Authors: Sam Gerené, Alex Vorobiev, Alexander van Delft, Jaime Bernar, Théate Antoine
@@ -282,6 +282,7 @@
False
<Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
+ True
True
True
True