Skip to content

Commit 64d9add

Browse files
authored
Add a golden scenario test for fallback font rendering on iOS take 3 (flutter#22736)
1 parent 6625308 commit 64d9add

24 files changed

+230
-139
lines changed

testing/scenario_app/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ pubspec.lock # This only has local dependencies in it.
33
build/
44

55
ios/Scenarios/*.framework/
6+
ios/Scenarios/*.xcframework/
67
android/app/libs/flutter.jar
78
android/app/src/main/jniLibs/arm64-v8a/libapp.so
89
android/gradle-home/.cache

testing/scenario_app/ios/Scenarios/Scenarios.xcodeproj/project.pbxproj

Lines changed: 14 additions & 34 deletions
Large diffs are not rendered by default.

testing/scenario_app/ios/Scenarios/Scenarios.xcodeproj/xcshareddata/xcschemes/Scenarios.xcscheme

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,6 @@
2828
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
2929
shouldUseLaunchSchemeArgsEnv = "YES"
3030
systemAttachmentLifetime = "keepNever">
31-
<MacroExpansion>
32-
<BuildableReference
33-
BuildableIdentifier = "primary"
34-
BlueprintIdentifier = "248D76C622E388370012F0C1"
35-
BuildableName = "Scenarios.app"
36-
BlueprintName = "Scenarios"
37-
ReferencedContainer = "container:Scenarios.xcodeproj">
38-
</BuildableReference>
39-
</MacroExpansion>
4031
<Testables>
4132
<TestableReference
4233
skipped = "NO"
@@ -87,6 +78,10 @@
8778
argument = "--screen-before-flutter"
8879
isEnabled = "NO">
8980
</CommandLineArgument>
81+
<CommandLineArgument
82+
argument = "--bogus-font-text"
83+
isEnabled = "NO">
84+
</CommandLineArgument>
9085
<CommandLineArgument
9186
argument = "--text-semantics-focus"
9287
isEnabled = "NO">

testing/scenario_app/ios/Scenarios/Scenarios/AppDelegate.m

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ - (BOOL)application:(UIApplication*)application
2828
self.window.tintColor = UIColor.systemPinkColor;
2929
}
3030
NSDictionary<NSString*, NSString*>* launchArgsMap = @{
31-
// The Platform view golden test args should match `PlatformViewGoldenTestManager`.
31+
// The golden test args should match `GoldenTestManager`.
3232
@"--locale-initialization" : @"locale_initialization",
3333
@"--platform-view" : @"platform_view",
3434
@"--platform-view-no-overlay-intersection" : @"platform_view_no_overlay_intersection",
@@ -53,7 +53,8 @@ - (BOOL)application:(UIApplication*)application
5353
@"--tap-status-bar" : @"tap_status_bar",
5454
@"--text-semantics-focus" : @"text_semantics_focus",
5555
@"--animated-color-square" : @"animated_color_square",
56-
@"--platform-view-with-continuous-texture" : @"platform_view_with_continuous_texture"
56+
@"--platform-view-with-continuous-texture" : @"platform_view_with_continuous_texture",
57+
@"--bogus-font-text" : @"bogus_font_text"
5758
};
5859
__block NSString* flutterViewControllerTestName = nil;
5960
[launchArgsMap
@@ -104,16 +105,18 @@ - (void)setupFlutterViewControllerTest:(NSString*)scenarioIdentifier {
104105
codec:[FlutterJSONMethodCodec sharedInstance]];
105106
[channel invokeMethod:@"set_scenario" arguments:@{@"name" : scenarioIdentifier}];
106107
}];
108+
// Can be used to synchronize timing in the test for a signal from Dart.
107109
[engine.binaryMessenger
108-
setMessageHandlerOnChannel:@"touches_scenario"
110+
setMessageHandlerOnChannel:@"display_data"
109111
binaryMessageHandler:^(NSData* _Nullable message, FlutterBinaryReply _Nonnull reply) {
110112
NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:message
111113
options:0
112114
error:nil];
113-
UITextField* text = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 300, 100)];
114-
text.text = dict[@"change"];
115+
UITextField* text = [[UITextField alloc] initWithFrame:CGRectMake(0, 400, 300, 100)];
116+
text.text = dict[@"data"];
115117
[flutterViewController.view addSubview:text];
116118
}];
119+
117120
TextPlatformViewFactory* textPlatformViewFactory =
118121
[[TextPlatformViewFactory alloc] initWithMessenger:engine.binaryMessenger];
119122
NSObject<FlutterPluginRegistrar>* registrar =
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#import <Flutter/Flutter.h>
6+
#import <XCTest/XCTest.h>
7+
#import "GoldenTestManager.h"
8+
9+
FLUTTER_ASSERT_ARC
10+
11+
@interface BogusFontTextTest : XCTestCase
12+
13+
@end
14+
15+
@implementation BogusFontTextTest
16+
17+
- (void)testFontRenderingWhenSuppliedWithBogusFont {
18+
self.continueAfterFailure = NO;
19+
20+
XCUIApplication* application = [[XCUIApplication alloc] init];
21+
application.launchArguments = @[ @"--bogus-font-text" ];
22+
[application launch];
23+
24+
XCUIElement* addTextField = application.textFields[@"ready"];
25+
XCTAssertTrue([addTextField waitForExistenceWithTimeout:30]);
26+
27+
GoldenTestManager* manager = [[GoldenTestManager alloc] initWithLaunchArg:@"--bogus-font-text"];
28+
[manager checkGoldenForTest:self];
29+
}
30+
31+
@end

testing/scenario_app/ios/Scenarios/ScenariosUITests/GoldenPlatformViewTests.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// found in the LICENSE file.
44

55
#import <XCTest/XCTest.h>
6-
#import "PlatformViewGoldenTestManager.h"
6+
#import "GoldenTestManager.h"
77

88
NS_ASSUME_NONNULL_BEGIN
99

@@ -12,20 +12,19 @@ NS_ASSUME_NONNULL_BEGIN
1212
// A new PlatformView golden tests can subclass this and override the `-initiWithInvocation:`
1313
// method, which then retun the `-initWithManager:invocation:`
1414
//
15-
// Then in any test method, call `checkGolden` to perform the golden test.
15+
// Then in any test method, call `checkPlatformViewGolden` to perform the golden test.
1616
//
1717
// This base class doesn't run any test case on its own.
1818
@interface GoldenPlatformViewTests : XCTestCase
1919

2020
@property(nonatomic, strong) XCUIApplication* application;
2121

22-
// Initialize with a `PlatformViewGoldenTestManager`.
23-
- (instancetype)initWithManager:(PlatformViewGoldenTestManager*)manager
24-
invocation:(NSInvocation*)invocation;
22+
// Initialize with a `GoldenTestManager`.
23+
- (instancetype)initWithManager:(GoldenTestManager*)manager invocation:(NSInvocation*)invocation;
2524

2625
// Take a sceenshot of the test app and check it has the same pixels with goldenImage inside the
27-
// `PlatformViewGoldenTestManager`.
28-
- (void)checkGolden;
26+
// `GoldenTestManager`.
27+
- (void)checkPlatformViewGolden;
2928

3029
@end
3130

testing/scenario_app/ios/Scenarios/ScenariosUITests/GoldenPlatformViewTests.m

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,21 @@
55
#import "GoldenPlatformViewTests.h"
66

77
#include <sys/sysctl.h>
8-
9-
#import "PlatformViewGoldenTestManager.h"
8+
#import "GoldenTestManager.h"
109

1110
static const NSInteger kSecondsToWaitForPlatformView = 30;
1211

1312
@interface GoldenPlatformViewTests ()
1413

1514
@property(nonatomic, copy) NSString* goldenName;
1615

17-
@property(nonatomic, strong) PlatformViewGoldenTestManager* manager;
16+
@property(nonatomic, strong) GoldenTestManager* manager;
1817

1918
@end
2019

2120
@implementation GoldenPlatformViewTests
2221

23-
- (instancetype)initWithManager:(PlatformViewGoldenTestManager*)manager
24-
invocation:(NSInvocation*)invocation {
22+
- (instancetype)initWithManager:(GoldenTestManager*)manager invocation:(NSInvocation*)invocation {
2523
self = [super initWithInvocation:invocation];
2624
_manager = manager;
2725
return self;
@@ -37,7 +35,7 @@ - (void)setUp {
3735
}
3836

3937
// Note: don't prefix with "test" or GoldenPlatformViewTests will run instead of the subclasses.
40-
- (void)checkGolden {
38+
- (void)checkPlatformViewGolden {
4139
XCUIElement* element = self.application.textViews.firstMatch;
4240
BOOL exists = [element waitForExistenceWithTimeout:kSecondsToWaitForPlatformView];
4341
if (!exists) {
@@ -47,29 +45,6 @@ - (void)checkGolden {
4745
@(kSecondsToWaitForPlatformView));
4846
}
4947

50-
GoldenImage* golden = self.manager.goldenImage;
51-
52-
XCUIScreenshot* screenshot = [[XCUIScreen mainScreen] screenshot];
53-
if (!golden.image) {
54-
XCTAttachment* attachment = [XCTAttachment attachmentWithScreenshot:screenshot];
55-
attachment.name = @"new_golden";
56-
attachment.lifetime = XCTAttachmentLifetimeKeepAlways;
57-
[self addAttachment:attachment];
58-
XCTFail(@"This test will fail - no golden named %@ found. Follow the steps in the "
59-
@"README to add a new golden.",
60-
golden.goldenName);
61-
}
62-
63-
if (![golden compareGoldenToImage:screenshot.image]) {
64-
XCTAttachment* screenshotAttachment;
65-
screenshotAttachment = [XCTAttachment attachmentWithImage:screenshot.image];
66-
screenshotAttachment.name = golden.goldenName;
67-
screenshotAttachment.lifetime = XCTAttachmentLifetimeKeepAlways;
68-
[self addAttachment:screenshotAttachment];
69-
70-
XCTFail(@"Goldens to not match. Follow the steps in the "
71-
@"README to update golden named %@ if needed.",
72-
golden.goldenName);
73-
}
48+
[self.manager checkGoldenForTest:self];
7449
}
7550
@end
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// found in the LICENSE file.
44

55
#import <Foundation/Foundation.h>
6-
6+
#import <XCTest/XCTest.h>
77
#import "GoldenImage.h"
88

99
NS_ASSUME_NONNULL_BEGIN
@@ -14,7 +14,7 @@ extern NSDictionary* launchArgsMap;
1414
//
1515
// It creates the correct `identifer` based on the `launchArg`.
1616
// It also generates the correct GoldenImage based on the `identifier`.
17-
@interface PlatformViewGoldenTestManager : NSObject
17+
@interface GoldenTestManager : NSObject
1818

1919
@property(readonly, strong, nonatomic) GoldenImage* goldenImage;
2020
@property(readonly, copy, nonatomic) NSString* identifier;
@@ -25,6 +25,10 @@ extern NSDictionary* launchArgsMap;
2525
// Crahes if the launchArg is not mapped in `Appdelegate.launchArgsMap`.
2626
- (instancetype)initWithLaunchArg:(NSString*)launchArg;
2727

28+
// Take a sceenshot of the test app and check it has the same pixels with
29+
// goldenImage inside the `GoldenTestManager`.
30+
- (void)checkGoldenForTest:(XCTestCase*)test;
31+
2832
@end
2933

3034
NS_ASSUME_NONNULL_END
Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,16 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
#import "PlatformViewGoldenTestManager.h"
6-
5+
#import "GoldenTestManager.h"
76
#import <XCTest/XCTest.h>
87

9-
@interface PlatformViewGoldenTestManager ()
8+
@interface GoldenTestManager ()
109

1110
@property(readwrite, strong, nonatomic) GoldenImage* goldenImage;
1211

1312
@end
1413

15-
@implementation PlatformViewGoldenTestManager
14+
@implementation GoldenTestManager
1615

1716
NSDictionary* launchArgsMap;
1817

@@ -34,6 +33,7 @@ - (instancetype)initWithLaunchArg:(NSString*)launchArg {
3433
@"--platform-view-transform" : @"platform_view_transform",
3534
@"--platform-view-opacity" : @"platform_view_opacity",
3635
@"--platform-view-rotate" : @"platform_view_rotate",
36+
@"--bogus-font-text" : @"bogus_font_text",
3737
};
3838
});
3939
_identifier = launchArgsMap[launchArg];
@@ -44,4 +44,32 @@ - (instancetype)initWithLaunchArg:(NSString*)launchArg {
4444
return self;
4545
}
4646

47+
- (void)checkGoldenForTest:(XCTestCase*)test {
48+
XCUIScreenshot* screenshot = [[XCUIScreen mainScreen] screenshot];
49+
if (!_goldenImage.image) {
50+
XCTAttachment* attachment = [XCTAttachment attachmentWithScreenshot:screenshot];
51+
attachment.name = [_goldenImage.goldenName stringByAppendingString:@"_new"];
52+
attachment.lifetime = XCTAttachmentLifetimeKeepAlways;
53+
[test addAttachment:attachment];
54+
// Instead of XCTFail because that definition changed between Xcode 11 and 12 whereas this impl
55+
// is stable.
56+
_XCTPrimitiveFail(test,
57+
@"This test will fail - no golden named %@ found. "
58+
@"Follow the steps in the README to add a new golden.",
59+
_goldenImage.goldenName);
60+
}
61+
62+
if (![_goldenImage compareGoldenToImage:screenshot.image]) {
63+
XCTAttachment* screenshotAttachment = [XCTAttachment attachmentWithImage:screenshot.image];
64+
screenshotAttachment.name = [_goldenImage.goldenName stringByAppendingString:@"_actual"];
65+
screenshotAttachment.lifetime = XCTAttachmentLifetimeKeepAlways;
66+
[test addAttachment:screenshotAttachment];
67+
68+
_XCTPrimitiveFail(test,
69+
@"Goldens do not match. Follow the steps in the "
70+
@"README to update golden named %@ if needed.",
71+
_goldenImage.goldenName);
72+
}
73+
}
74+
4775
@end

0 commit comments

Comments
 (0)