Summary: Compared to what was planned, I added the `overflow` value which seemed missing. I had to modify the implementation a bit for all values which are backed by a `YGValue`, but we should probably enable the pixel dimensions in Objective-C and Swift somehow later. Closes https://github.com/facebook/yoga/pull/322 Reviewed By: dshahidehpour Differential Revision: D4386906 Pulled By: emilsjolander fbshipit-source-id: 05ac0e571ef3a8ff0be31469e449a7b23f102218
388 lines
14 KiB
Objective-C
388 lines
14 KiB
Objective-C
/**
|
|
* Copyright (c) 2014-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*/
|
|
|
|
#import <XCTest/XCTest.h>
|
|
|
|
#import <YogaKit/UIView+Yoga.h>
|
|
|
|
@interface YogaKitTests : XCTestCase
|
|
@end
|
|
|
|
@implementation YogaKitTests
|
|
|
|
#ifndef TRAVIS_CI
|
|
|
|
- (void)testNodesAreDeallocedWithSingleView
|
|
{
|
|
XCTAssertEqual(0, YGNodeGetInstanceCount());
|
|
|
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
|
view.yoga.flexBasis = 1;
|
|
XCTAssertEqual(1, YGNodeGetInstanceCount());
|
|
view = nil;
|
|
|
|
XCTAssertEqual(0, YGNodeGetInstanceCount());
|
|
}
|
|
|
|
- (void)testNodesAreDeallocedCascade
|
|
{
|
|
XCTAssertEqual(0, YGNodeGetInstanceCount());
|
|
|
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
|
view.yoga.flexBasis = 1;
|
|
|
|
for (int i=0; i<10; i++) {
|
|
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview.yoga.flexBasis = 1;
|
|
[view addSubview:subview];
|
|
}
|
|
XCTAssertEqual(11, YGNodeGetInstanceCount());
|
|
view = nil;
|
|
|
|
XCTAssertEqual(0, YGNodeGetInstanceCount());
|
|
}
|
|
|
|
#endif
|
|
|
|
- (void)testUsesYoga
|
|
{
|
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
|
XCTAssertFalse(view.yoga.isEnabled);
|
|
|
|
view.yoga.isEnabled = YES;
|
|
XCTAssertTrue(view.yoga.isEnabled);
|
|
|
|
view.yoga.isEnabled = NO;
|
|
XCTAssertFalse(view.yoga.isEnabled);
|
|
}
|
|
|
|
- (void)testSizeThatFitsAsserts
|
|
{
|
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
|
dispatch_sync(dispatch_queue_create("com.facebook.Yoga.testing", DISPATCH_QUEUE_SERIAL), ^(void){
|
|
XCTAssertThrows(view.yoga.intrinsicSize);
|
|
});
|
|
}
|
|
|
|
- (void)testSizeThatFitsSmoke
|
|
{
|
|
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
|
|
container.yoga.isEnabled = YES;
|
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
|
container.yoga.alignItems = YGAlignFlexStart;
|
|
|
|
UILabel *longTextLabel = [[UILabel alloc] initWithFrame:CGRectZero];
|
|
longTextLabel.text = @"This is a very very very very very very very very long piece of text.";
|
|
longTextLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
|
longTextLabel.numberOfLines = 1;
|
|
longTextLabel.yoga.isEnabled = YES;
|
|
longTextLabel.yoga.flexShrink = 1;
|
|
[container addSubview:longTextLabel];
|
|
|
|
UIView *textBadgeView = [[UIView alloc] initWithFrame:CGRectZero];
|
|
textBadgeView.yoga.isEnabled = YES;
|
|
textBadgeView.yoga.marginLeft = 3.0;
|
|
textBadgeView.yoga.width = 10;
|
|
textBadgeView.yoga.height = 10;
|
|
[container addSubview:textBadgeView];
|
|
|
|
const CGSize containerSize = container.yoga.intrinsicSize;
|
|
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(514,21), containerSize), @"Size is actually %@", NSStringFromCGSize(containerSize));
|
|
}
|
|
|
|
- (void)testThatMarkingLeafsAsDirtyWillTriggerASizeRecalculation
|
|
{
|
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 50)];
|
|
container.yoga.isEnabled = YES;
|
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
|
container.yoga.alignItems = YGAlignFlexStart;
|
|
|
|
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
|
|
label.text = @"This is a short text.";
|
|
label.numberOfLines = 1;
|
|
label.yoga.isEnabled = YES;
|
|
[container addSubview:label];
|
|
|
|
[container.yoga applyLayout];
|
|
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(146,21), label.bounds.size), @"Size is actually %@", NSStringFromCGSize(label.bounds.size));
|
|
|
|
label.text = @"This is a slightly longer text.";
|
|
[label.yoga markDirty];
|
|
|
|
[container.yoga applyLayout];
|
|
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(213,21), label.bounds.size), @"Size is actually %@", NSStringFromCGSize(label.bounds.size));
|
|
}
|
|
|
|
- (void)testFrameAndOriginPlacement
|
|
{
|
|
const CGSize containerSize = CGSizeMake(320, 50);
|
|
|
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];
|
|
container.yoga.isEnabled = YES;
|
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview.yoga.isEnabled = YES;
|
|
subview.yoga.flexGrow = 1;
|
|
|
|
[container addSubview:subview];
|
|
}
|
|
[container.yoga applyLayout];
|
|
|
|
XCTAssertFalse(CGRectIntersectsRect([container.subviews objectAtIndex:0].frame, [container.subviews objectAtIndex:1].frame));
|
|
XCTAssertFalse(CGRectIntersectsRect([container.subviews objectAtIndex:1].frame, [container.subviews objectAtIndex:2].frame));
|
|
XCTAssertFalse(CGRectIntersectsRect([container.subviews objectAtIndex:0].frame, [container.subviews objectAtIndex:2].frame));
|
|
|
|
CGFloat totalWidth = 0;
|
|
for (UIView *view in container.subviews) {
|
|
totalWidth += view.bounds.size.width;
|
|
}
|
|
|
|
XCTAssertEqual(containerSize.width, totalWidth, @"The container's width is %.6f, the subviews take up %.6f", containerSize.width, totalWidth);
|
|
}
|
|
|
|
- (void)testThatLayoutIsCorrectWhenWeSwapViewOrder
|
|
{
|
|
const CGSize containerSize = CGSizeMake(300, 50);
|
|
|
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];
|
|
container.yoga.isEnabled = YES;
|
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
|
|
|
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview1.yoga.isEnabled = YES;
|
|
subview1.yoga.flexGrow = 1;
|
|
[container addSubview:subview1];
|
|
|
|
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview2.yoga.isEnabled = YES;
|
|
subview2.yoga.flexGrow = 1;
|
|
[container addSubview:subview2];
|
|
|
|
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview3.yoga.isEnabled = YES;
|
|
subview3.yoga.flexGrow = 1;
|
|
[container addSubview:subview3];
|
|
|
|
[container.yoga applyLayout];
|
|
|
|
XCTAssertTrue(CGRectEqualToRect(subview1.frame, CGRectMake(0, 0, 100, 50)));
|
|
XCTAssertTrue(CGRectEqualToRect(subview2.frame, CGRectMake(100, 0, 100, 50)), @"It's actually %@", NSStringFromCGRect(subview2.frame));
|
|
XCTAssertTrue(CGRectEqualToRect(subview3.frame, CGRectMake(200, 0, 100, 50)));
|
|
|
|
[container exchangeSubviewAtIndex:2 withSubviewAtIndex:0];
|
|
subview2.yoga.isIncludedInLayout = NO;
|
|
[container.yoga applyLayout];
|
|
|
|
XCTAssertTrue(CGRectEqualToRect(subview3.frame, CGRectMake(0, 0, 150, 50)));
|
|
XCTAssertTrue(CGRectEqualToRect(subview1.frame, CGRectMake(150, 0, 150, 50)));
|
|
|
|
// this frame shouldn't have been modified since last time.
|
|
XCTAssertTrue(CGRectEqualToRect(subview2.frame, CGRectMake(100, 0, 100, 50)));
|
|
}
|
|
|
|
- (void)testThatWeRespectIncludeInLayoutFlag
|
|
{
|
|
const CGSize containerSize = CGSizeMake(300, 50);
|
|
|
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, containerSize.width, containerSize.height)];
|
|
container.yoga.isEnabled = YES;
|
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
|
|
|
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview1.yoga.isEnabled = YES;
|
|
subview1.yoga.flexGrow = 1;
|
|
[container addSubview:subview1];
|
|
|
|
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview2.yoga.isEnabled = YES;
|
|
subview2.yoga.flexGrow = 1;
|
|
[container addSubview:subview2];
|
|
|
|
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview3.yoga.isEnabled = YES;
|
|
subview3.yoga.flexGrow = 1;
|
|
[container addSubview:subview3];
|
|
|
|
[container.yoga applyLayout];
|
|
|
|
for (UIView *view in container.subviews) {
|
|
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 50), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(view.bounds.size));
|
|
}
|
|
|
|
subview3.yoga.isIncludedInLayout = NO;
|
|
[container.yoga applyLayout];
|
|
|
|
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 50), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview1.bounds.size));
|
|
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 50), subview2.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview2.bounds.size));
|
|
|
|
// We don't set the frame to zero, so, it should be set to what it was previously at.
|
|
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 50), subview3.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview3.bounds.size));
|
|
}
|
|
|
|
- (void)testThatNumberOfChildrenIsCorrectWhenWeIgnoreSubviews
|
|
{
|
|
UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
|
|
container.yoga.isEnabled = YES;
|
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
|
|
|
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview1.yoga.isEnabled = YES;
|
|
subview1.yoga.isIncludedInLayout = NO;
|
|
[container addSubview:subview1];
|
|
|
|
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview2.yoga.isEnabled = YES;
|
|
subview2.yoga.isIncludedInLayout = NO;
|
|
[container addSubview:subview2];
|
|
|
|
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview3.yoga.isEnabled = YES;
|
|
subview3.yoga.isIncludedInLayout = YES;
|
|
[container addSubview:subview3];
|
|
|
|
[container.yoga applyLayout];
|
|
XCTAssertEqual(1, container.yoga.numberOfChildren);
|
|
|
|
subview2.yoga.isIncludedInLayout = YES;
|
|
[container.yoga applyLayout];
|
|
XCTAssertEqual(2, container.yoga.numberOfChildren);
|
|
}
|
|
|
|
- (void)testThatViewNotIncludedInFirstLayoutPassAreIncludedInSecond
|
|
{
|
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
|
|
container.yoga.isEnabled = YES;
|
|
container.yoga.flexDirection = YGFlexDirectionRow;
|
|
|
|
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview1.yoga.isEnabled = YES;
|
|
subview1.yoga.flexGrow = 1;
|
|
[container addSubview:subview1];
|
|
|
|
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview2.yoga.isEnabled = YES;
|
|
subview2.yoga.flexGrow = 1;
|
|
[container addSubview:subview2];
|
|
|
|
UIView *subview3 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview3.yoga.isEnabled = YES;
|
|
subview3.yoga.flexGrow = 1;
|
|
subview3.yoga.isIncludedInLayout = NO;
|
|
[container addSubview:subview3];
|
|
|
|
[container.yoga applyLayout];
|
|
|
|
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 50), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview1.bounds.size));
|
|
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 50), subview2.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview2.bounds.size));
|
|
XCTAssertTrue(CGSizeEqualToSize(CGSizeZero, subview3.bounds.size), @"Actual size %@", NSStringFromCGSize(subview3.bounds.size));
|
|
|
|
subview3.yoga.isIncludedInLayout = YES;
|
|
[container.yoga applyLayout];
|
|
for (UIView *view in container.subviews) {
|
|
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 50), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(view.bounds.size));
|
|
}
|
|
}
|
|
|
|
- (void)testyg_isLeafFlag
|
|
{
|
|
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
|
|
XCTAssertTrue(view.yoga.isLeaf);
|
|
|
|
for (int i=0; i<10; i++) {
|
|
UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
|
|
[view addSubview:subview];
|
|
}
|
|
XCTAssertTrue(view.yoga.isLeaf);
|
|
|
|
view.yoga.isEnabled = YES;
|
|
view.yoga.width = 50.0;
|
|
XCTAssertTrue(view.yoga.isLeaf);
|
|
|
|
UIView *const subview = view.subviews[0];
|
|
subview.yoga.isEnabled = YES;
|
|
subview.yoga.width = 50.0;
|
|
XCTAssertFalse(view.yoga.isLeaf);
|
|
}
|
|
|
|
- (void)testThatWeCorrectlyAttachNestedViews
|
|
{
|
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
|
|
container.yoga.isEnabled = YES;
|
|
container.yoga.flexDirection = YGFlexDirectionColumn;
|
|
|
|
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview1.yoga.isEnabled = YES;
|
|
subview1.yoga.width = 100;
|
|
subview1.yoga.flexGrow = 1;
|
|
subview1.yoga.flexDirection = YGFlexDirectionColumn;
|
|
[container addSubview:subview1];
|
|
|
|
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview2.yoga.isEnabled = YES;
|
|
subview2.yoga.width = 150;
|
|
subview2.yoga.flexGrow = 1;
|
|
subview2.yoga.flexDirection = YGFlexDirectionColumn;
|
|
[container addSubview:subview2];
|
|
|
|
for (UIView *view in @[subview1, subview2]) {
|
|
UIView *someView = [[UIView alloc] initWithFrame:CGRectZero];
|
|
someView.yoga.isEnabled = YES;
|
|
someView.yoga.flexGrow = 1;
|
|
[view addSubview:someView];
|
|
}
|
|
[container.yoga applyLayout];
|
|
|
|
// Add the same amount of new views, reapply layout.
|
|
for (UIView *view in @[subview1, subview2]) {
|
|
UIView *someView = [[UIView alloc] initWithFrame:CGRectZero];
|
|
someView.yoga.isEnabled = YES;
|
|
someView.yoga.flexGrow = 1;
|
|
[view addSubview:someView];
|
|
}
|
|
[container.yoga applyLayout];
|
|
|
|
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(100, 25), subview1.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview1.bounds.size));
|
|
for (UIView *subview in subview1.subviews) {
|
|
const CGSize subviewSize = subview.bounds.size;
|
|
XCTAssertFalse(CGSizeEqualToSize(CGSizeZero, subviewSize));
|
|
XCTAssertFalse(isnan(subviewSize.height));
|
|
XCTAssertFalse(isnan(subviewSize.width));
|
|
}
|
|
|
|
XCTAssertTrue(CGSizeEqualToSize(CGSizeMake(150, 25), subview2.bounds.size), @"Actual size is %@", NSStringFromCGSize(subview2.bounds.size));
|
|
for (UIView *subview in subview2.subviews) {
|
|
const CGSize subviewSize = subview.bounds.size;
|
|
XCTAssertFalse(CGSizeEqualToSize(CGSizeZero, subview.bounds.size));
|
|
XCTAssertFalse(isnan(subviewSize.height));
|
|
XCTAssertFalse(isnan(subviewSize.width));
|
|
}
|
|
}
|
|
|
|
- (void)testThatANonLeafNodeCanBecomeALeafNode
|
|
{
|
|
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
|
|
container.yoga.isEnabled = YES;
|
|
|
|
UIView *subview1 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview1.yoga.isEnabled = YES;
|
|
[container addSubview:subview1];
|
|
|
|
UIView *subview2 = [[UIView alloc] initWithFrame:CGRectZero];
|
|
subview2.yoga.isEnabled = YES;
|
|
[subview1 addSubview:subview2];
|
|
|
|
[container.yoga applyLayout];
|
|
[subview2 removeFromSuperview];
|
|
[container.yoga applyLayout];
|
|
}
|
|
|
|
@end
|