Index: ios/chrome/browser/ui/util/label_link_controller_unittest.mm |
diff --git a/ios/chrome/browser/ui/util/label_link_controller_unittest.mm b/ios/chrome/browser/ui/util/label_link_controller_unittest.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..bf15fe8511424ab82e3e405cf3dc7c423b0836d3 |
--- /dev/null |
+++ b/ios/chrome/browser/ui/util/label_link_controller_unittest.mm |
@@ -0,0 +1,291 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#import "ios/chrome/browser/ui/util/label_link_controller.h" |
+ |
+#import "base/mac/scoped_nsobject.h" |
+#include "ios/chrome/browser/ui/util/text_region_mapper.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "testing/gtest_mac.h" |
+#include "testing/platform_test.h" |
+#include "url/gurl.h" |
+ |
+// A simple text region mapper that just returns the mapped bounds for |
+// any range. |
+@interface SimpleTextRegionMapper : NSObject<TextRegionMapper> |
+@end |
+ |
+@implementation SimpleTextRegionMapper { |
+ CGRect _bounds; |
+} |
+ |
+- (instancetype)initWithAttributedString:(NSAttributedString*)string |
+ bounds:(CGRect)bounds { |
+ if ((self = [super init])) { |
+ _bounds = bounds; |
+ } |
+ return self; |
+} |
+ |
+- (NSArray*)rectsForRange:(NSRange)range { |
+ return @[ [NSValue valueWithCGRect:_bounds] ]; |
+} |
+ |
+@end |
+ |
+#define EXPECT_UICOLOR_EQ(A, B) EXPECT_NSEQ([A description], [B description]) |
+ |
+namespace { |
+ |
+class LabelLinkControllerTest : public PlatformTest { |
+ protected: |
+ void SetUp() override { |
+ label_container_.reset([[UIView alloc] initWithFrame:CGRectZero]); |
+ label_.reset([[UILabel alloc] initWithFrame:CGRectZero]); |
+ [label_container_ addSubview:label_]; |
+ } |
+ |
+ void setLabelAttrString(NSString* str) { |
+ str_.reset([[NSAttributedString alloc] initWithString:str]); |
+ [label_ setAttributedText:str_]; |
+ } |
+ |
+ void setLabelAttrStringWithAttr(NSString* str, NSString* attr, id value) { |
+ str_.reset([[NSAttributedString alloc] initWithString:str |
+ attributes:@{attr : value}]); |
+ [label_ setAttributedText:str_]; |
+ } |
+ |
+ base::scoped_nsobject<UIView> label_container_; |
+ base::scoped_nsobject<UILabel> label_; |
+ base::scoped_nsobject<NSAttributedString> str_; |
+}; |
+ |
+TEST_F(LabelLinkControllerTest, TapTest) { |
+ setLabelAttrString(@"link tap test"); |
+ [label_ sizeToFit]; |
+ NSRange linkRange = NSMakeRange(5, 3); // "tap". |
+ |
+ base::scoped_nsobject<LabelLinkController> llc; |
+ GURL url = GURL("http://www.google.com"); |
+ __block NSInteger taps = 0; |
+ llc.reset([[LabelLinkController alloc] |
+ initWithLabel:label_ |
+ action:^(const GURL& tappedUrl) { |
+ EXPECT_EQ(tappedUrl, url); |
+ taps++; |
+ }]); |
+ [llc setTextMapperClass:[SimpleTextRegionMapper class]]; |
+ [llc addLinkWithRange:linkRange url:url]; |
+ NSArray* rects = [llc tapRectsForURL:url]; |
+ ASSERT_EQ(1UL, [rects count]); |
+ CGRect rect = [rects[0] CGRectValue]; |
+ |
+ CGPoint tapPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)); |
+ [llc tapLabelAtPoint:tapPoint]; |
+ EXPECT_EQ(1, taps); |
+} |
+ |
+TEST_F(LabelLinkControllerTest, LinkColorTest) { |
+ setLabelAttrStringWithAttr(@"link color test", NSForegroundColorAttributeName, |
+ [UIColor blueColor]); |
+ [label_ sizeToFit]; |
+ NSRange linkRange = NSMakeRange(5, 5); // "color". |
+ |
+ base::scoped_nsobject<LabelLinkController> llc; |
+ llc.reset([[LabelLinkController alloc] initWithLabel:label_ action:nullptr]); |
+ [llc setTextMapperClass:[SimpleTextRegionMapper class]]; |
+ [llc addLinkWithRange:linkRange url:GURL("http://www.google.com")]; |
+ |
+ // That shouldn't have changed the label's attributes. |
+ NSDictionary* attrs = |
+ [[label_ attributedText] attributesAtIndex:linkRange.location |
+ effectiveRange:nullptr]; |
+ EXPECT_UICOLOR_EQ(attrs[NSForegroundColorAttributeName], [UIColor blueColor]); |
+ |
+ [llc setLinkColor:[UIColor redColor]]; |
+ // That should only change the attributes at the link location |
+ attrs = [[label_ attributedText] attributesAtIndex:linkRange.location |
+ effectiveRange:nullptr]; |
+ EXPECT_UICOLOR_EQ(attrs[NSForegroundColorAttributeName], [UIColor redColor]); |
+ |
+ attrs = [[label_ attributedText] attributesAtIndex:0 effectiveRange:nullptr]; |
+ EXPECT_UICOLOR_EQ(attrs[NSForegroundColorAttributeName], [UIColor blueColor]); |
+ |
+ [llc setLinkColor:[UIColor yellowColor]]; |
+ // There shouldn't be a red foreground color attribute any more. |
+ attrs = [[label_ attributedText] attributesAtIndex:linkRange.location |
+ effectiveRange:nullptr]; |
+ EXPECT_UICOLOR_EQ(attrs[NSForegroundColorAttributeName], |
+ [UIColor yellowColor]); |
+} |
+ |
+TEST_F(LabelLinkControllerTest, LinkUnderlineTest) { |
+ setLabelAttrStringWithAttr(@"link underline test", |
+ NSUnderlineStyleAttributeName, |
+ @(NSUnderlineStyleSingle)); |
+ [label_ sizeToFit]; |
+ NSRange linkRange = NSMakeRange(5, 9); // "underline". |
+ |
+ base::scoped_nsobject<LabelLinkController> llc; |
+ llc.reset([[LabelLinkController alloc] initWithLabel:label_ action:nullptr]); |
+ [llc setTextMapperClass:[SimpleTextRegionMapper class]]; |
+ [llc addLinkWithRange:linkRange url:GURL("http://www.google.com")]; |
+ |
+ // That shouldn't have changed the label's attributes. |
+ NSDictionary* attrs = |
+ [[label_ attributedText] attributesAtIndex:linkRange.location |
+ effectiveRange:nullptr]; |
+ EXPECT_NSEQ(attrs[NSUnderlineStyleAttributeName], @(NSUnderlineStyleSingle)); |
+ |
+ [llc setLinkUnderlineStyle:NSUnderlineStyleDouble]; |
+ // That should only change the attributes at the link location |
+ attrs = [[label_ attributedText] attributesAtIndex:linkRange.location |
+ effectiveRange:nullptr]; |
+ EXPECT_NSEQ(attrs[NSUnderlineStyleAttributeName], @(NSUnderlineStyleDouble)); |
+ |
+ attrs = [[label_ attributedText] attributesAtIndex:0 effectiveRange:nullptr]; |
+ EXPECT_NSEQ(attrs[NSUnderlineStyleAttributeName], @(NSUnderlineStyleSingle)); |
+ |
+ [llc setLinkUnderlineStyle:NSUnderlineStyleThick]; |
+ // There shouldn't be a red foreground color attribute any more. |
+ attrs = [[label_ attributedText] attributesAtIndex:linkRange.location |
+ effectiveRange:nullptr]; |
+ EXPECT_NSEQ(attrs[NSUnderlineStyleAttributeName], @(NSUnderlineStyleThick)); |
+ |
+ [llc setLinkUnderlineStyle:NSUnderlineStyleNone]; |
+ // Should see the underlying underline style. |
+ attrs = [[label_ attributedText] attributesAtIndex:linkRange.location |
+ effectiveRange:nullptr]; |
+ EXPECT_NSEQ(attrs[NSUnderlineStyleAttributeName], @(NSUnderlineStyleSingle)); |
+} |
+ |
+TEST_F(LabelLinkControllerTest, BoundsChangeTest) { |
+ setLabelAttrString(@"bounds change test"); |
+ [label_ sizeToFit]; |
+ NSRange linkRange = NSMakeRange(7, 6); // "change". |
+ |
+ base::scoped_nsobject<LabelLinkController> llc; |
+ llc.reset([[LabelLinkController alloc] initWithLabel:label_ action:nullptr]); |
+ [llc setTextMapperClass:[SimpleTextRegionMapper class]]; |
+ GURL url = GURL("http://www.google.com"); |
+ [llc addLinkWithRange:linkRange url:url]; |
+ |
+ NSArray* rects = [llc tapRectsForURL:url]; |
+ ASSERT_EQ(1UL, [rects count]); |
+ NSValue* rect = rects[0]; |
+ EXPECT_TRUE(CGRectContainsRect([rect CGRectValue], [label_ bounds])); |
+ |
+ // Change the label bounds, expect the links to be recomputed. |
+ // (SimpleTextRegionMapper just maps all ranges to the label bounds). |
+ CGRect newFrame = CGRectMake(0, 0, 200, 200); |
+ [label_ setFrame:newFrame]; |
+ rects = [llc tapRectsForURL:url]; |
+ ASSERT_EQ(1UL, [rects count]); |
+ NSValue* newRect = rects[0]; |
+ EXPECT_NSNE(rect, newRect); |
+ EXPECT_TRUE(CGRectContainsRect([newRect CGRectValue], newFrame)); |
+} |
+ |
+TEST_F(LabelLinkControllerTest, AttributedTextChangeTest) { |
+ setLabelAttrString(@"attributed text change test"); |
+ [label_ sizeToFit]; |
+ NSRange linkRange = NSMakeRange(16, 6); // "change". |
+ |
+ base::scoped_nsobject<LabelLinkController> llc; |
+ llc.reset([[LabelLinkController alloc] initWithLabel:label_ action:nullptr]); |
+ [llc setTextMapperClass:[SimpleTextRegionMapper class]]; |
+ GURL url = GURL("http://www.google.com"); |
+ [llc addLinkWithRange:linkRange url:url]; |
+ |
+ NSArray* rects = [llc tapRectsForURL:url]; |
+ EXPECT_EQ(1UL, [rects count]); |
+ |
+ setLabelAttrString(@"crazy new attributed text"); |
+ // Expect all links to be gone. |
+ rects = [llc tapRectsForURL:url]; |
+ EXPECT_EQ(0UL, [rects count]); |
+} |
+ |
+TEST_F(LabelLinkControllerTest, TextChangeTest) { |
+ [label_ setText:@"text change test"]; |
+ [label_ sizeToFit]; |
+ NSRange linkRange = NSMakeRange(5, 6); // "change". |
+ |
+ base::scoped_nsobject<LabelLinkController> llc; |
+ llc.reset([[LabelLinkController alloc] initWithLabel:label_ action:nullptr]); |
+ [llc setTextMapperClass:[SimpleTextRegionMapper class]]; |
+ GURL url = GURL("http://www.google.com"); |
+ [llc addLinkWithRange:linkRange url:url]; |
+ |
+ NSArray* rects = [llc tapRectsForURL:url]; |
+ EXPECT_EQ(1UL, [rects count]); |
+ |
+ [label_ setText:@"crazy new text"]; |
+ // Expect all links to be gone. |
+ rects = [llc tapRectsForURL:url]; |
+ EXPECT_EQ(0UL, [rects count]); |
+} |
+ |
+TEST_F(LabelLinkControllerTest, LabelStyleInitTest) { |
+ [label_ setText:@"style init test"]; |
+ [label_ sizeToFit]; |
+ NSRange linkRange = NSMakeRange(6, 5); // "init". |
+ |
+ // Don't use an injected text mapper for this test. |
+ base::scoped_nsobject<LabelLinkController> llc; |
+ llc.reset([[LabelLinkController alloc] initWithLabel:label_ action:nullptr]); |
+ GURL url = GURL("http://www.google.com"); |
+ [llc addLinkWithRange:linkRange url:url]; |
+ |
+ NSArray* rects = [llc tapRectsForURL:url]; |
+ ASSERT_EQ(1UL, [rects count]); |
+ |
+ CGRect linkRect = [rects[0] CGRectValue]; |
+ |
+ // Make a new label and controller with a very large font size, and |
+ // compute the same tap rect. It should be different from the rect computed |
+ // above. |
+ llc.reset(); |
+ label_.reset([[UILabel alloc] initWithFrame:CGRectZero]); |
+ [label_ setText:@"style init test"]; |
+ [label_ setFont:[UIFont systemFontOfSize:40]]; |
+ [label_ sizeToFit]; |
+ llc.reset([[LabelLinkController alloc] initWithLabel:label_ action:nullptr]); |
+ url = GURL("http://www.google.com"); |
+ [llc addLinkWithRange:linkRange url:url]; |
+ rects = [llc tapRectsForURL:url]; |
+ ASSERT_EQ(1UL, [rects count]); |
+ CGRect newLinkRect = [rects[0] CGRectValue]; |
+ |
+ EXPECT_NSNE(NSStringFromCGRect(linkRect), NSStringFromCGRect(newLinkRect)); |
+} |
+ |
+TEST_F(LabelLinkControllerTest, LabelStylePropertyChangeTest) { |
+ [label_ setText:@"style change test"]; |
+ // Choose a size large enough so that the full text can be laid out with both |
+ // fonts in this test. |
+ CGSize labelSize = CGSizeMake(400, 50); |
+ [label_ setFrame:{CGPointZero, labelSize}]; |
+ |
+ NSRange linkRange = NSMakeRange(6, 6); // "change". |
+ |
+ // Don't use an injected text mapper for this test. |
+ base::scoped_nsobject<LabelLinkController> llc; |
+ llc.reset([[LabelLinkController alloc] initWithLabel:label_ action:nullptr]); |
+ GURL url = GURL("http://www.google.com"); |
+ [llc addLinkWithRange:linkRange url:url]; |
+ |
+ NSArray* rects = [llc tapRectsForURL:url]; |
+ ASSERT_EQ(1UL, [rects count]); |
+ NSValue* smallTextRect = rects[0]; |
+ |
+ [label_ setFont:[UIFont systemFontOfSize:40]]; |
+ // Expect all links to be changed. |
+ rects = [llc tapRectsForURL:url]; |
+ ASSERT_EQ(1UL, [rects count]); |
+ EXPECT_NSNE(smallTextRect, rects[0]); |
+} |
+ |
+} // namespace |