Skip to content

Commit

Permalink
Feat #701 Allow tabs to be reordered and move between split screens + #…
Browse files Browse the repository at this point in the history
…700 Limit split screen to 2 views max (#708)
  • Loading branch information
joao4all authored Jul 23, 2024
1 parent 77023f0 commit 0b80461
Show file tree
Hide file tree
Showing 19 changed files with 610 additions and 292 deletions.
77 changes: 71 additions & 6 deletions COMETwebapp.Tests/Components/Tabs/TabsPanelComponentTestFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace COMETwebapp.Tests.Components.Tabs
using COMET.Web.Common.Test.Helpers;

using COMETwebapp.Components.EngineeringModel;
using COMETwebapp.Components.Shared;
using COMETwebapp.Components.Tabs;
using COMETwebapp.Model;
using COMETwebapp.Utilities;
Expand Down Expand Up @@ -63,6 +64,8 @@ public class TabsPanelComponentTestFixture
private Mock<ITabsViewModel> viewModel;
private Mock<IEngineeringModelBodyViewModel> engineeringModelBodyViewModel;
private Iteration iteration;
private TabPanelInformation mainPanel;
private TabPanelInformation sidePanel;

[SetUp]
public void SetUp()
Expand Down Expand Up @@ -98,10 +101,17 @@ public void SetUp()
this.viewModel = new Mock<ITabsViewModel>();
var openTabs = new SourceList<TabbedApplicationInformation>();
openTabs.Add(new TabbedApplicationInformation(this.engineeringModelBodyViewModel.Object, typeof(EngineeringModelBody), this.iteration));
this.viewModel.Setup(x => x.OpenTabs).Returns(openTabs);
this.viewModel.Setup(x => x.CurrentTab).Returns(openTabs.Items.First());
this.sidePanel = new TabPanelInformation();

this.mainPanel = new TabPanelInformation
{
OpenTabs = openTabs,
CurrentTab = openTabs.Items.First()
};

this.viewModel.Setup(x => x.MainPanel).Returns(this.mainPanel);
this.viewModel.Setup(x => x.SidePanel).Returns(this.sidePanel);
this.viewModel.Setup(x => x.SelectedApplication).Returns(engineeringModelBodyApplication);
this.viewModel.Setup(x => x.SidePanels).Returns(new SourceList<TabPanelInformation>());

var sessionService = new Mock<ISessionService>();
sessionService.Setup(x => x.GetDomainOfExpertise(It.IsAny<Iteration>())).Returns(new DomainOfExpertise());
Expand All @@ -114,10 +124,9 @@ public void SetUp()
this.renderer = this.context.RenderComponent<TabsPanelComponent>(parameters =>
{
parameters.Add(p => p.ViewModel, this.viewModel.Object);
parameters.Add(p => p.Handler, this.viewModel.Object);
parameters.Add(p => p.Panel, this.mainPanel);
parameters.Add(p => p.CssClass, "css-test-class");
parameters.Add(p => p.IsSidePanelAvailable, true);
parameters.Add(p => p.Tabs, this.viewModel.Object.OpenTabs.Items.ToList());
});
}

Expand All @@ -134,7 +143,12 @@ public async Task VerifyAddSidePanel()
var sidePanelButton = this.renderer.FindComponents<DxButton>().First(x => x.Instance.Id == "new-side-panel-button");
await this.renderer.InvokeAsync(sidePanelButton.Instance.Click.InvokeAsync);

this.viewModel.VerifySet(x => x.CurrentTab = null, Times.Once);
Assert.Multiple(() =>
{
Assert.That(this.viewModel.Object.SidePanel.OpenTabs, Has.Count.GreaterThan(0));
Assert.That(this.viewModel.Object.SidePanel.CurrentTab, Is.Not.Null);
Assert.That(this.viewModel.Object.MainPanel.OpenTabs, Has.Count.EqualTo(0));
});
}

[Test]
Expand All @@ -147,5 +161,56 @@ public void VerifyComponent()
Assert.That(this.renderer.Markup, Does.Contain("css-test-class"));
});
}

[Test]
public async Task VerifyTabsOrdering()
{
var newTab = new TabbedApplicationInformation(this.engineeringModelBodyViewModel.Object, typeof(EngineeringModelBody), this.iteration);
this.mainPanel.OpenTabs.Add(newTab);

Assert.Multiple(() =>
{
Assert.That(this.mainPanel.OpenTabs, Has.Count.EqualTo(2));
Assert.That(this.sidePanel.OpenTabs, Has.Count.EqualTo(0));
Assert.That(this.mainPanel.OpenTabs.Items.First(), Is.Not.EqualTo(newTab));
Assert.That(this.mainPanel.OpenTabs.Items.ElementAt(1), Is.EqualTo(newTab));
});

var sortableList = this.renderer.FindComponent<SortableList<TabbedApplicationInformation>>();
await this.renderer.InvokeAsync(() => sortableList.Instance.OnUpdate.InvokeAsync((0, 1)));

Assert.Multiple(() =>
{
Assert.That(this.mainPanel.OpenTabs, Has.Count.EqualTo(2));
Assert.That(this.mainPanel.OpenTabs.Items.First(), Is.EqualTo(newTab));
Assert.That(this.mainPanel.OpenTabs.Items.ElementAt(1), Is.Not.EqualTo(newTab));
});

await this.renderer.InvokeAsync(() => sortableList.Instance.OnRemove.InvokeAsync((0, 0)));
this.sidePanel.CurrentTab = this.sidePanel.OpenTabs.Items.First();

Assert.Multiple(() =>
{
Assert.That(this.mainPanel.OpenTabs, Has.Count.EqualTo(1));
Assert.That(this.sidePanel.OpenTabs, Has.Count.EqualTo(1));
Assert.That(this.mainPanel.OpenTabs.Items.First(), Is.Not.EqualTo(newTab));
Assert.That(this.sidePanel.OpenTabs.Items.First(), Is.EqualTo(newTab));
});

this.renderer.SetParametersAndRender(parameters =>
{
parameters.Add(p => p.Panel, this.sidePanel);
});

sortableList = this.renderer.FindComponent<SortableList<TabbedApplicationInformation>>();
await this.renderer.InvokeAsync(() => sortableList.Instance.OnRemove.InvokeAsync((0, 0)));

Assert.Multiple(() =>
{
Assert.That(this.mainPanel.OpenTabs, Has.Count.EqualTo(2));
Assert.That(this.sidePanel.OpenTabs, Has.Count.EqualTo(0));
Assert.That(this.mainPanel.OpenTabs.Items.First(), Is.EqualTo(newTab));
});
}
}
}
63 changes: 28 additions & 35 deletions COMETwebapp.Tests/Pages/TabsTestFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,27 +67,14 @@ public class TabsTestFixture
private Mock<IEngineeringModelBodyViewModel> engineeringModelBodyViewModel;
private IRenderedComponent<Tabs> renderer;
private Iteration iteration;
private TabPanelInformation mainPanel;

[SetUp]
public void Setup()
{
this.context = new TestContext();

var engineeringModelBodyApplication = Applications.ExistingApplications.OfType<TabbedApplication>().First(x => x.Url == WebAppConstantValues.EngineeringModelPage);
this.viewModel = new Mock<ITabsViewModel>();

var sidePanels = new SourceList<TabPanelInformation>();
sidePanels.Add(new TabPanelInformation());
this.viewModel.Setup(x => x.OpenTabs).Returns(new SourceList<TabbedApplicationInformation>());
this.viewModel.Setup(x => x.SelectedApplication).Returns(engineeringModelBodyApplication);
this.viewModel.Setup(x => x.SidePanels).Returns(sidePanels);

var optionsTableViewModel = new Mock<IOptionsTableViewModel>();
optionsTableViewModel.Setup(x => x.Rows).Returns(new SourceList<OptionRowViewModel>());
optionsTableViewModel.Setup(x => x.CurrentThing).Returns(new Option());
this.engineeringModelBodyViewModel = new Mock<IEngineeringModelBodyViewModel>();
this.engineeringModelBodyViewModel.Setup(x => x.OptionsTableViewModel).Returns(optionsTableViewModel.Object);

var engineeringSetupModel = new EngineeringModelSetup();

this.iteration = new Iteration
Expand All @@ -102,6 +89,26 @@ public void Setup()
}
};

var optionsTableViewModel = new Mock<IOptionsTableViewModel>();
optionsTableViewModel.Setup(x => x.Rows).Returns(new SourceList<OptionRowViewModel>());
optionsTableViewModel.Setup(x => x.CurrentThing).Returns(new Option());
this.engineeringModelBodyViewModel = new Mock<IEngineeringModelBodyViewModel>();
this.engineeringModelBodyViewModel.Setup(x => x.OptionsTableViewModel).Returns(optionsTableViewModel.Object);

var openTabs = new SourceList<TabbedApplicationInformation>();
openTabs.Add(new TabbedApplicationInformation(this.engineeringModelBodyViewModel.Object, typeof(EngineeringModelBody), this.iteration));

this.mainPanel = new TabPanelInformation
{
OpenTabs = openTabs,
CurrentTab = openTabs.Items.First()
};

this.viewModel = new Mock<ITabsViewModel>();
this.viewModel.Setup(x => x.MainPanel).Returns(this.mainPanel);
this.viewModel.Setup(x => x.SidePanel).Returns(new TabPanelInformation());
this.viewModel.Setup(x => x.SelectedApplication).Returns(engineeringModelBodyApplication);

var configuration = new Mock<IConfigurationService>();
configuration.Setup(x => x.ServerConfiguration).Returns(new ServerConfiguration());

Expand Down Expand Up @@ -129,22 +136,16 @@ public void Teardown()
[Test]
public async Task VerifyTabComponents()
{
var openTabs = new SourceList<TabbedApplicationInformation>();
openTabs.Add(new TabbedApplicationInformation(this.engineeringModelBodyViewModel.Object, typeof(EngineeringModelBody), this.iteration));
this.viewModel.Setup(x => x.OpenTabs).Returns(openTabs);
this.viewModel.Setup(x => x.CurrentTab).Returns(openTabs.Items.First());
this.renderer.Render();

var tabComponents = this.renderer.FindComponents<TabComponent>();
var firstTab = tabComponents[0];

await this.renderer.InvokeAsync(firstTab.Instance.OnClick.Invoke);
this.viewModel.VerifySet(x => x.CurrentTab = openTabs.Items.First(), Times.Once);
Assert.That(this.viewModel.Object.MainPanel.CurrentTab, Is.EqualTo(this.mainPanel.OpenTabs.Items.First()));
await this.renderer.InvokeAsync(firstTab.Instance.OnIconClick.Invoke);

Assert.Multiple(() =>
{
this.viewModel.Verify(x => x.OpenTabs, Times.AtLeastOnce);
Assert.That(this.viewModel.Object.MainPanel.OpenTabs, Has.Count.EqualTo(0));
Assert.That(this.renderer.Instance.IsOpenTabVisible, Is.False);
});

Expand All @@ -156,13 +157,6 @@ public async Task VerifyTabComponents()
[Test]
public async Task VerifyTabCustomButton()
{
var openTabs = new SourceList<TabbedApplicationInformation>();
var tabToOpen = new TabbedApplicationInformation(this.engineeringModelBodyViewModel.Object, typeof(EngineeringModelBody), this.iteration);
openTabs.Add(tabToOpen);
this.viewModel.Setup(x => x.OpenTabs).Returns(openTabs);
this.viewModel.Setup(x => x.CurrentTab).Returns(tabToOpen);
this.renderer.Render();

var tabCustomButton = this.renderer.FindComponents<DxButton>().First(x => x.Instance.Id == "tab-custom-option-button");
await this.renderer.InvokeAsync(tabCustomButton.Instance.Click.InvokeAsync);
Assert.That(this.renderer.Instance.IsOpenTabVisible, Is.True);
Expand All @@ -171,8 +165,7 @@ public async Task VerifyTabCustomButton()
await this.renderer.InvokeAsync(openTabComponent.Instance.OnCancel.Invoke);
Assert.That(this.renderer.Instance.IsOpenTabVisible, Is.False);

tabToOpen = new TabbedApplicationInformation(this.engineeringModelBodyViewModel.Object, typeof(EngineeringModelBody), null);
openTabs.ReplaceAt(0, tabToOpen);
this.mainPanel.OpenTabs.ReplaceAt(0, new TabbedApplicationInformation(this.engineeringModelBodyViewModel.Object, typeof(EngineeringModelBody), null));
this.renderer.Render();
var hasCustomOption = this.renderer.FindComponents<DxButton>().Any(x => x.Instance.Id == "tab-custom-option-button");
Assert.That(hasCustomOption, Is.False);
Expand All @@ -181,6 +174,9 @@ public async Task VerifyTabCustomButton()
[Test]
public void VerifyTabsPage()
{
this.viewModel.Setup(x => x.MainPanel).Returns(new TabPanelInformation());
this.renderer.Render();

var tabComponents = this.renderer.FindComponents<TabComponent>();
var openTab = this.renderer.FindComponents<OpenTab>();

Expand All @@ -190,10 +186,7 @@ public void VerifyTabsPage()
Assert.That(openTab, Has.Count.EqualTo(1));
});

var openTabs = new SourceList<TabbedApplicationInformation>();
openTabs.Add(new TabbedApplicationInformation(this.engineeringModelBodyViewModel.Object, typeof(EngineeringModelBody), this.iteration));
this.viewModel.Setup(x => x.OpenTabs).Returns(openTabs);
this.viewModel.Setup(x => x.CurrentTab).Returns(openTabs.Items.First());
this.viewModel.Setup(x => x.MainPanel).Returns(this.mainPanel);
this.renderer.Render();

tabComponents = this.renderer.FindComponents<TabComponent>();
Expand Down
55 changes: 27 additions & 28 deletions COMETwebapp.Tests/ViewModels/Pages/TabsViewModelTestFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,35 +68,35 @@ public void Setup()
[Test]
public void VerifyOnSelectedApplication()
{
Assert.That(this.viewModel.CurrentTab, Is.Null);
Assert.That(this.viewModel.MainPanel.CurrentTab, Is.Null);

this.viewModel.OpenTabs.Add(new TabbedApplicationInformation(new Mock<IEngineeringModelBodyViewModel>().Object, typeof(EngineeringModelBody), new Iteration()));
this.viewModel.MainPanel.OpenTabs.Add(new TabbedApplicationInformation(new Mock<IEngineeringModelBodyViewModel>().Object, typeof(EngineeringModelBody), new Iteration()));
this.viewModel.SelectedApplication = this.viewModel.AvailableApplications.FirstOrDefault(x => x.Url == WebAppConstantValues.EngineeringModelPage);

Assert.That(this.viewModel.CurrentTab, Is.Not.Null);
Assert.That(this.viewModel.MainPanel.CurrentTab, Is.Not.Null);
}

[Test]
public void VerifyTabCreation()
{
var engineeringModelApplication = this.viewModel.AvailableApplications.First(x => x.Url == WebAppConstantValues.EngineeringModelPage);
this.viewModel.CreateNewTab(engineeringModelApplication, Guid.Empty);
this.viewModel.CreateNewTab(engineeringModelApplication, Guid.Empty, this.viewModel.MainPanel);

Assert.Multiple(() =>
{
Assert.That(this.viewModel.CurrentTab, Is.Not.Null);
Assert.That(this.viewModel.CurrentTab.ObjectOfInterest, Is.TypeOf<Iteration>());
Assert.That(this.viewModel.MainPanel.CurrentTab, Is.Not.Null);
Assert.That(this.viewModel.MainPanel.CurrentTab.ObjectOfInterest, Is.TypeOf<Iteration>());
Assert.That(this.viewModel.SelectedApplication, Is.Not.Null);
Assert.That(this.viewModel.OpenTabs, Has.Count.EqualTo(1));
Assert.That(this.viewModel.MainPanel.OpenTabs, Has.Count.EqualTo(1));
});

var bookEditorApplication = this.viewModel.AvailableApplications.First(x => x.Url == WebAppConstantValues.BookEditorPage);
this.viewModel.CreateNewTab(bookEditorApplication, Guid.Empty);
this.viewModel.CreateNewTab(bookEditorApplication, Guid.Empty, this.viewModel.MainPanel);

Assert.Multiple(() =>
{
Assert.That(this.viewModel.CurrentTab.ObjectOfInterest, Is.TypeOf<EngineeringModel>());
Assert.That(this.viewModel.OpenTabs, Has.Count.EqualTo(2));
Assert.That(this.viewModel.MainPanel.CurrentTab.ObjectOfInterest, Is.TypeOf<EngineeringModel>());
Assert.That(this.viewModel.MainPanel.OpenTabs, Has.Count.EqualTo(2));
});
}

Expand All @@ -105,27 +105,26 @@ public void VerifyTabRemoval()
{
var engineeringModelApplication1 = this.viewModel.AvailableApplications.First(x => x.Url == WebAppConstantValues.EngineeringModelPage);
var engineeringModelApplication2 = this.viewModel.AvailableApplications.First(x => x.Url == WebAppConstantValues.EngineeringModelPage);
this.viewModel.CreateNewTab(engineeringModelApplication1, Guid.Empty);
this.viewModel.CreateNewTab(engineeringModelApplication2, Guid.Empty);
this.viewModel.SidePanels.Add(new TabPanelInformation());
this.viewModel.CreateNewTab(engineeringModelApplication1, Guid.Empty, this.viewModel.MainPanel);
this.viewModel.CreateNewTab(engineeringModelApplication2, Guid.Empty, this.viewModel.MainPanel);

var removedTab = this.viewModel.OpenTabs.Items.ElementAt(1);
var removedTab = this.viewModel.MainPanel.OpenTabs.Items.ElementAt(1);

Assert.That(this.viewModel.CurrentTab, Is.EqualTo(removedTab));
this.viewModel.OpenTabs.Remove(removedTab);
Assert.That(this.viewModel.MainPanel.CurrentTab, Is.EqualTo(removedTab));
this.viewModel.MainPanel.OpenTabs.Remove(removedTab);

Assert.Multiple(() =>
{
Assert.That(this.viewModel.CurrentTab, Is.Not.EqualTo(removedTab));
Assert.That(this.viewModel.CurrentTab, Is.Not.Null);
Assert.That(this.viewModel.MainPanel.CurrentTab, Is.Not.EqualTo(removedTab));
Assert.That(this.viewModel.MainPanel.CurrentTab, Is.Not.Null);
});

this.viewModel.CreateNewTab(engineeringModelApplication2, Guid.Empty);
this.viewModel.CreateNewTab(engineeringModelApplication2, Guid.Empty);
Assert.That(this.viewModel.OpenTabs, Has.Count.EqualTo(3));
this.viewModel.CreateNewTab(engineeringModelApplication2, Guid.Empty, this.viewModel.MainPanel);
this.viewModel.CreateNewTab(engineeringModelApplication2, Guid.Empty, this.viewModel.MainPanel);
Assert.That(this.viewModel.MainPanel.OpenTabs, Has.Count.EqualTo(3));

this.viewModel.OpenTabs.RemoveRange(1, 2);
Assert.That(this.viewModel.OpenTabs, Has.Count.EqualTo(1));
this.viewModel.MainPanel.OpenTabs.RemoveRange(1, 2);
Assert.That(this.viewModel.MainPanel.OpenTabs, Has.Count.EqualTo(1));
}

[Test]
Expand All @@ -134,17 +133,17 @@ public void VerifyTabsOnSessionChanges()
var engineeringModelApplication = this.viewModel.AvailableApplications.First(x => x.Url == WebAppConstantValues.EngineeringModelPage);
var iteration = new Iteration();

this.viewModel.CreateNewTab(engineeringModelApplication, iteration.Iid);
this.viewModel.CreateNewTab(engineeringModelApplication, iteration.Iid, this.viewModel.MainPanel);
this.openIterations.Add(iteration);

Assert.Multiple(() =>
{
Assert.That(this.viewModel.OpenTabs, Has.Count.EqualTo(1));
Assert.That(this.viewModel.CurrentTab, Is.Not.Null);
Assert.That(this.viewModel.MainPanel.OpenTabs, Has.Count.EqualTo(1));
Assert.That(this.viewModel.MainPanel.CurrentTab, Is.Not.Null);
});

this.openIterations.Clear();
Assert.That(this.viewModel.CurrentTab, Is.Null);
Assert.That(this.viewModel.MainPanel.CurrentTab, Is.Null);
}

[Test]
Expand All @@ -154,7 +153,7 @@ public void VerifyViewModelProperties()
{
Assert.That(this.viewModel.AvailableApplications, Is.Not.Empty);
Assert.That(this.viewModel.SelectedApplication, Is.Null);
Assert.That(this.viewModel.OpenTabs, Has.Count.EqualTo(0));
Assert.That(this.viewModel.MainPanel.OpenTabs, Has.Count.EqualTo(0));
});
}
}
Expand Down
Loading

0 comments on commit 0b80461

Please sign in to comment.