blob: a03ed67a63dd447635267a3a4870acd9fb8b3988 [file] [log] [blame]
// Copyright 2022 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/util_swift.h"
#import <UIKit/UIKit.h>
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
// Calls a block when receiving a KVO notification.
@interface Observer : NSObject
@property(nonatomic, copy) void (^onChange)(id object, NSDictionary* change);
@end
@implementation Observer
- (void)observeValueForKeyPath:(NSString*)keyPath
ofObject:(id)object
change:(NSDictionary*)change
context:(void*)context {
if (self.onChange) {
self.onChange(object, change);
}
}
@end
// Sets up a window, a view, and an observer on the view's window property.
class UIViewWindowObservingTest : public PlatformTest {
protected:
UIViewWindowObservingTest()
: window_([[UIWindow alloc] init]),
view_([[UIView alloc] init]),
observer_([[Observer alloc] init]) {
[view_
addObserver:observer_
forKeyPath:@"window"
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
context:nullptr];
}
~UIViewWindowObservingTest() override {
[view_ removeObserver:observer_ forKeyPath:@"window"];
}
UIWindow* window_;
UIView* view_;
// Observes the view's `window` property.
Observer* observer_;
};
// Checks that the observer is not called when the view is added to the window
// and `cr_supportsWindowObserving` is set to `NO`.
TEST_F(UIViewWindowObservingTest, WindowObservingUnset) {
UIView.cr_supportsWindowObserving = NO;
EXPECT_FALSE(UIView.cr_supportsWindowObserving);
observer_.onChange = ^(id object, id change) {
FAIL() << "KVO should not have triggered before being enabled.";
};
[window_ addSubview:view_];
}
// Checks that the observer is called with the correct old and new windows when
// the view is added to the window and `cr_supportsWindowObserving` is set.
TEST_F(UIViewWindowObservingTest, WindowObservingSet) {
UIView.cr_supportsWindowObserving = YES;
EXPECT_TRUE(UIView.cr_supportsWindowObserving);
__block BOOL callback_called = NO;
observer_.onChange = ^(id object, id change) {
callback_called = YES;
EXPECT_EQ(change[NSKeyValueChangeOldKey], [NSNull null]);
EXPECT_EQ(change[NSKeyValueChangeNewKey], window_);
};
[window_ addSubview:view_];
EXPECT_TRUE(callback_called);
}
// Checks that the observer is not called when the view is added to the window
// and `cr_supportsWindowObserving` is reset to `NO`.
TEST_F(UIViewWindowObservingTest, WindowObservingReset) {
UIView.cr_supportsWindowObserving = YES;
UIView.cr_supportsWindowObserving = NO;
observer_.onChange = ^(id object, id change) {
FAIL() << "KVO should not have triggered after being disabled.";
};
[window_ addSubview:view_];
}