Files
yoga/csharp/tests/Facebook.YogaKit.Shared.Tests/YogaKitTest.cs
Rui Marinho 498a5980e8 Add YogaKit Shared and iOS version
Summary:
Using shared code for reuse in other platforms based on iOS native implementation.

Adds YogaKit sample.

Adds YogaKit tests (same as objc).

```
YogaKitTest : 80 ms
Facebook.YogaKit.iOS.Tests.exe : 81 ms
Tests run: 11 Passed: 8 Inconclusive: 0 Failed: 3 Ignored: 1
```

Since we don't have extension properties we need to go with a extension method to get access to the YogaLayout .

I m also not sure this is leak free yet, would love some help with testing and feedback about view/node lifecycle
Closes https://github.com/facebook/yoga/pull/336

Reviewed By: splhack

Differential Revision: D4415027

Pulled By: emilsjolander

fbshipit-source-id: c88328212426c3200e6f0c48cda594cd2c432065
2017-01-15 14:54:29 -08:00

370 lines
12 KiB
C#

using System.Drawing;
using Facebook.Yoga;
using NUnit.Framework;
using System;
#if __IOS__
using NativeView = UIKit.UIView;
using CoreGraphics;
#endif
namespace Facebook.YogaKit
{
[TestFixture]
public class YogaKitTest
{
[Test]
public void TestUsesYoga()
{
var view = new NativeView();
Assert.False(view.Yoga().IsEnabled);
view.Yoga().IsEnabled = true;
Assert.True(view.Yoga().IsEnabled);
view.Yoga().IsEnabled = false;
Assert.False(view.Yoga().IsEnabled);
}
[Test]
public void TestSizeThatFitsAsserts()
{
var view = new NativeView();
Assert.Ignore("Not implemented yet");
// dispatch_sync(dispatch_queue_create("com.facebook.Yoga.testing", DISPATCH_QUEUE_SERIAL), ^(void){
// XCTAssertThrows(view.yoga.intrinsicSize);
// });
}
[Test]
public void TestSizeThatFitsSmoke()
{
var container = new NativeView();
container.Yoga().IsEnabled = true;
container.Yoga().FlexDirection = YogaFlexDirection.Row;
container.Yoga().AlignItems = YogaAlign.FlexStart;
var longTextLabel = new UIKit.UILabel();
longTextLabel.Text = @"This is a very very very very very very very very long piece of text.";
longTextLabel.LineBreakMode = UIKit.UILineBreakMode.TailTruncation;
longTextLabel.Lines = 1;
longTextLabel.Yoga().IsEnabled = true;
longTextLabel.Yoga().FlexShrink = 1;
container.AddSubview(longTextLabel);
var textBadgeView = new NativeView();
textBadgeView.Yoga().IsEnabled = true;
textBadgeView.Yoga().MarginLeft = 3.0f;
textBadgeView.Yoga().Width = 10;
textBadgeView.Yoga().Height = 10;
container.AddSubview(textBadgeView);
var containerSize = container.Yoga().IntrinsicSize;
Assert.True(new SizeF(514, 21) == containerSize, $"Size is actually {containerSize})");
}
[Test]
public void TestThatMarkingLeafsAsDirtyWillTriggerASizeRecalculation()
{
var container = new NativeView(new CGRect(0, 0, 500, 500));
container.Yoga().IsEnabled = true;
container.Yoga().FlexDirection = YogaFlexDirection.Row;
container.Yoga().AlignItems = YogaAlign.FlexStart;
var label = new UIKit.UILabel();
label.Text = @"This is a short text.";
label.Lines = 1;
label.Yoga().IsEnabled = true;
container.AddSubview(label);
container.Yoga().ApplyLayout();
Assert.True(new SizeF(146, 21) == label.Bounds.Size, $"Size is actually {label.Bounds.Size})");
label.Text = @"This is a slightly longer text.";
label.Yoga().MarkDirty();
container.Yoga().ApplyLayout();
Assert.True(new SizeF(213, 21) == label.Bounds.Size, $"Size is actually {label.Bounds.Size})");
}
[Test]
public void TestFrameAndOriginPlacement()
{
var containerSize = new SizeF(320, 50);
var container = new NativeView(new CGRect(0, 0, containerSize.Width, containerSize.Height));
container.Yoga().IsEnabled = true;
container.Yoga().FlexDirection = YogaFlexDirection.Row;
for (int i = 0; i < 3; i++)
{
var subview = new NativeView();
subview.Yoga().IsEnabled = true;
subview.Yoga().FlexGrow = 1;
container.AddSubview(subview);
}
container.Yoga().ApplyLayout();
Assert.False(CGRect.Intersect(container.Subviews[0].Frame, container.Subviews[1].Frame) == CGRect.Empty);
Assert.False(CGRect.Intersect(container.Subviews[1].Frame, container.Subviews[2].Frame) == CGRect.Empty);
Assert.False(CGRect.Intersect(container.Subviews[0].Frame, container.Subviews[2].Frame) == CGRect.Empty);
float totalWidth = 0;
foreach (var view in container.Subviews)
totalWidth += (float)view.Bounds.Size.Width;
Assert.AreEqual(containerSize.Width, totalWidth, $"The container's width is {containerSize.Width}, the subviews take up {totalWidth}");
}
[Test]
public void TestThatLayoutIsCorrectWhenWeSwapViewOrder()
{
var containerSize = new SizeF(300, 50);
var container = new NativeView(new CGRect(0, 0, containerSize.Width, containerSize.Height));
container.Yoga().IsEnabled = true;
container.Yoga().FlexDirection = YogaFlexDirection.Row;
var subview1 = new NativeView();
subview1.Yoga().IsEnabled = true;
subview1.Yoga().FlexGrow = 1;
container.AddSubview(subview1);
var subview2 = new NativeView();
subview2.Yoga().IsEnabled = true;
subview2.Yoga().FlexGrow = 1;
container.AddSubview(subview2);
var subview3 = new NativeView();
subview3.Yoga().IsEnabled = true;
subview3.Yoga().FlexGrow = 1;
container.AddSubview(subview3);
container.Yoga().ApplyLayout();
Assert.True(subview1.Frame == new CGRect(0, 0, 100, 50));
Assert.True(subview2.Frame == new CGRect(100, 0, 100, 50), $"It's actually {subview2.Frame}");
Assert.True(subview3.Frame == new CGRect(200, 0, 100, 50));
container.ExchangeSubview(2, 0);
subview2.Yoga().IsIncludeInLayout = false;
container.Yoga().ApplyLayout();
Assert.True(subview3.Frame == new CGRect(0, 0, 150, 50));
Assert.True(subview1.Frame == new CGRect(150, 0, 150, 50));
//// this frame shouldn't have been modified since last time.
Assert.True(subview2.Frame == new CGRect(100, 0, 100, 50));
}
[Test]
public void TestThatWeRespectIncludeInLayoutFlag()
{
var containerSize = new SizeF(300, 50);
var container = new NativeView(new CGRect(0, 0, containerSize.Width, containerSize.Height));
container.Yoga().IsEnabled = true;
container.Yoga().FlexDirection = YogaFlexDirection.Row;
var subview1 = new NativeView();
subview1.Yoga().IsEnabled = true;
subview1.Yoga().FlexGrow = 1;
container.AddSubview(subview1);
var subview2 = new NativeView();
subview2.Yoga().IsEnabled = true;
subview2.Yoga().FlexGrow = 1;
container.AddSubview(subview2);
var subview3 = new NativeView();
subview3.Yoga().IsEnabled = true;
subview3.Yoga().FlexGrow = 1;
container.AddSubview(subview3);
container.Yoga().ApplyLayout();
foreach (var view in container.Subviews)
{
Assert.True(new CGSize(100, 50) == view.Bounds.Size, $"Actual size is {view.Bounds.Size}");
}
subview3.Yoga().IsIncludeInLayout = false;
container.Yoga().ApplyLayout();
Assert.True(subview1.Frame.Size == new CGSize(150, 50), $"Actual size is {subview1.Frame.Size}");
Assert.True(subview2.Frame.Size == new CGSize(150, 50), $"Actual size is {subview2.Frame.Size}");
//// We don't set the frame to zero, so, it should be set to what it was previously at.
Assert.True(subview3.Frame.Size == new CGSize(100, 50), $"Actual size is {subview3.Frame.Size}");
}
[Test]
public void TestThatNumberOfChildrenIsCorrectWhenWeIgnoreSubviews()
{
var container = new NativeView();
container.Yoga().IsEnabled = true;
container.Yoga().FlexDirection = YogaFlexDirection.Row;
var subview1 = new NativeView();
subview1.Yoga().IsEnabled = true;
subview1.Yoga().IsIncludeInLayout = false;
container.AddSubview(subview1);
var subview2 = new NativeView();
subview2.Yoga().IsEnabled = true;
subview2.Yoga().IsIncludeInLayout = false;
container.AddSubview(subview2);
var subview3 = new NativeView();
subview3.Yoga().IsEnabled = true;
subview3.Yoga().IsIncludeInLayout = true;
container.AddSubview(subview3);
container.Yoga().ApplyLayout();
Assert.AreEqual(1, container.Yoga().NumberOfChildren);
subview2.Yoga().IsIncludeInLayout = true;
container.Yoga().ApplyLayout();
Assert.AreEqual(2, container.Yoga().NumberOfChildren);
}
[Test]
public void TestThatViewNotIncludedInFirstLayoutPassAreIncludedInSecond()
{
var containerSize = new SizeF(300, 50);
var container = new NativeView(new CGRect(0, 0, containerSize.Width, containerSize.Height));
container.Yoga().IsEnabled = true;
container.Yoga().FlexDirection = YogaFlexDirection.Row;
var subview1 = new NativeView();
subview1.Yoga().IsEnabled = true;
subview1.Yoga().FlexGrow = 1;
container.AddSubview(subview1);
var subview2 = new NativeView();
subview2.Yoga().IsEnabled = true;
subview2.Yoga().FlexGrow = 1;
container.AddSubview(subview2);
var subview3 = new NativeView();
subview3.Yoga().IsEnabled = true;
subview3.Yoga().FlexGrow = 1;
subview3.Yoga().IsIncludeInLayout = false;
container.AddSubview(subview3);
container.Yoga().ApplyLayout();
Assert.True(subview1.Frame.Size == new CGSize(150, 50), $"Actual size is {subview1.Frame.Size}");
Assert.True(subview2.Frame.Size == new CGSize(150, 50), $"Actual size is {subview2.Frame.Size}");
Assert.True(subview3.Frame.Size == CGSize.Empty, $"Actual size is {subview3.Frame.Size}");
subview3.Yoga().IsIncludeInLayout = true;
container.Yoga().ApplyLayout();
foreach (var view in container.Subviews)
{
Assert.True(new CGSize(100, 50) == view.Bounds.Size, $"Actual size is {view.Bounds.Size}");
}
}
[Test]
public void TestYogaIsLeafFlag()
{
var view = new NativeView();
Assert.True(view.Yoga().IsLeaf);
for (int i = 0; i < 10; i++)
{
var subView = new NativeView();
view.AddSubview(subView);
}
Assert.True(view.Yoga().IsLeaf);
view.Yoga().IsEnabled = true;
view.Yoga().Width = 50.0f;
Assert.True(view.Yoga().IsLeaf);
var subView1 = view.Subviews[0];
subView1.Yoga().IsEnabled = true;
subView1.Yoga().Width = 50.0f;
Assert.False(view.Yoga().IsLeaf);
}
[Test]
public void TestThatWeCorrectlyAttachNestedViews()
{
var containerSize = new SizeF(300, 50);
var container = new NativeView(new CGRect(0, 0, containerSize.Width, containerSize.Height));
container.Yoga().IsEnabled = true;
container.Yoga().FlexDirection = YogaFlexDirection.Column;
var subview1 = new NativeView();
subview1.Yoga().IsEnabled = true;
subview1.Yoga().Width = 100;
subview1.Yoga().FlexGrow = 1;
subview1.Yoga().FlexDirection = YogaFlexDirection.Column;
container.AddSubview(subview1);
var subview2 = new NativeView();
subview2.Yoga().IsEnabled = true;
subview2.Yoga().Width = 150;
subview2.Yoga().FlexGrow = 1;
subview2.Yoga().FlexDirection = YogaFlexDirection.Column;
container.AddSubview(subview2);
foreach (var view in new NativeView[] { subview1, subview2 })
{
var someView = new NativeView();
someView.Yoga().IsEnabled = true;
someView.Yoga().FlexGrow = 1;
view.AddSubview(someView);
}
container.Yoga().ApplyLayout();
// Add the same amount of new views, reapply layout.
foreach (var view in new NativeView[] { subview1, subview2 })
{
var someView = new NativeView();
someView.Yoga().IsEnabled = true;
someView.Yoga().FlexGrow = 1;
view.AddSubview(someView);
}
container.Yoga().ApplyLayout();
Assert.True(new CGSize(100, 25) == subview1.Bounds.Size, $"Actual size is {subview1.Bounds.Size}");
foreach (var subview in subview1.Subviews)
{
var subviewSize = subview.Bounds.Size;
Assert.False(subviewSize.IsEmpty);
Assert.False(nfloat.IsNaN(subviewSize.Height));
Assert.False(nfloat.IsNaN(subviewSize.Width));
}
Assert.True(new CGSize(150, 25) == subview2.Bounds.Size, $"Actual size is {subview2.Bounds.Size}");
foreach (var subview in subview2.Subviews)
{
var subviewSize = subview.Bounds.Size;
Assert.False(subviewSize.IsEmpty);
Assert.False(nfloat.IsNaN(subviewSize.Height));
Assert.False(nfloat.IsNaN(subviewSize.Width));
}
}
[Test]
public void TestThatANonLeafNodeCanBecomeALeafNode()
{
var containerSize = new SizeF(300, 50);
var container = new NativeView(new CGRect(0, 0, containerSize.Width, containerSize.Height));
container.Yoga().IsEnabled = true;
var subview1 = new NativeView();
subview1.Yoga().IsEnabled = true;
container.AddSubview(subview1);
var subview2 = new NativeView();
subview2.Yoga().IsEnabled = true;
container.AddSubview(subview2);
container.Yoga().ApplyLayout();
subview2.RemoveFromSuperview();
container.Yoga().ApplyLayout();
}
}
}