using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Terminal.Gui;
using Xunit;
namespace UnitTests {
public class TreeViewTests
{
#region Test Setup Methods
class Factory
{
public Car[] Cars {get;set;}
};
class Car {
};
private TreeView CreateTree()
{
return CreateTree(out _, out _, out _);
}
private TreeView CreateTree(out Factory factory1, out Car car1, out Car car2)
{
car1 = new Car();
car2 = new Car();
factory1 = new Factory()
{
Cars = new []{car1 ,car2}
};
var tree = new TreeView();
tree.ChildrenGetter = (s)=> s is Factory f ? f.Cars: null;
tree.AddObject(factory1);
return tree;
}
#endregion
///
/// Tests that and are consistent
///
[Fact]
public void IsExpanded_TrueAfterExpand()
{
var tree = CreateTree(out Factory f, out _, out _);
Assert.False(tree.IsExpanded(f));
tree.Expand(f);
Assert.True(tree.IsExpanded(f));
tree.Collapse(f);
Assert.False(tree.IsExpanded(f));
}
///
/// Tests that and behaves correctly when an object cannot be expanded (because it has no children)
///
[Fact]
public void IsExpanded_FalseIfCannotExpand()
{
var tree = CreateTree(out Factory f, out Car c, out _);
// expose the car by expanding the factory
tree.Expand(f);
// car is not expanded
Assert.False(tree.IsExpanded(c));
//try to expand the car (should have no effect because cars have no children)
tree.Expand(c);
Assert.False(tree.IsExpanded(c));
// should also be ignored
tree.Collapse(c);
Assert.False(tree.IsExpanded(c));
}
///
/// Tests illegal ranges for
///
[Fact]
public void ScrollOffset_CannotBeNegative()
{
var tree = CreateTree();
Assert.Equal(0,tree.ScrollOffset);
tree.ScrollOffset = -100;
Assert.Equal(0,tree.ScrollOffset);
tree.ScrollOffset = 10;
Assert.Equal(10,tree.ScrollOffset);
}
///
/// Tests for objects that are as yet undiscovered by the tree
///
[Fact]
public void GetScrollOffsetOf_MinusOneForUnRevealed()
{
var tree = CreateTree(out Factory f, out Car c1, out Car c2);
// to start with the tree is collapsed and only knows about the root object
Assert.Equal(0,tree.GetScrollOffsetOf(f));
Assert.Equal(-1,tree.GetScrollOffsetOf(c1));
Assert.Equal(-1,tree.GetScrollOffsetOf(c2));
// reveal it by expanding the root object
tree.Expand(f);
// tree now knows about children
Assert.Equal(0,tree.GetScrollOffsetOf(f));
Assert.Equal(1,tree.GetScrollOffsetOf(c1));
Assert.Equal(2,tree.GetScrollOffsetOf(c2));
// after collapsing the root node again
tree.Collapse(f);
// tree no longer knows about the locations of these objects
Assert.Equal(0,tree.GetScrollOffsetOf(f));
Assert.Equal(-1,tree.GetScrollOffsetOf(c1));
Assert.Equal(-1,tree.GetScrollOffsetOf(c2));
}
///
/// Simulates behind the scenes changes to an object (which children it has) and how to sync that into the tree using
///
[Fact]
public void RefreshObject_ChildRemoved()
{
var tree = CreateTree(out Factory f, out Car c1, out Car c2);
//reveal it by expanding the root object
tree.Expand(f);
Assert.Equal(0,tree.GetScrollOffsetOf(f));
Assert.Equal(1,tree.GetScrollOffsetOf(c1));
Assert.Equal(2,tree.GetScrollOffsetOf(c2));
// Factory now no longer makes Car c1 (only c2)
f.Cars = new Car[]{c2};
// Tree does not know this yet
Assert.Equal(0,tree.GetScrollOffsetOf(f));
Assert.Equal(1,tree.GetScrollOffsetOf(c1));
Assert.Equal(2,tree.GetScrollOffsetOf(c2));
// If the user has selected the node c1
tree.SelectedObject = c1;
// When we refresh the tree
tree.RefreshObject(f);
// Now tree knows that factory has only one child node c2
Assert.Equal(0,tree.GetScrollOffsetOf(f));
Assert.Equal(-1,tree.GetScrollOffsetOf(c1));
Assert.Equal(1,tree.GetScrollOffsetOf(c2));
// The old selection was c1 which is now gone so selection should default to the parent of that branch (the factory)
Assert.Equal(f,tree.SelectedObject);
}
}
}