[ReactNative] Add snapshot tests for examples

This commit is contained in:
Spencer Ahrens 2015-03-24 22:07:16 -07:00
parent c7056c6d6d
commit 15f6783f34
13 changed files with 138 additions and 17 deletions

View File

@ -53,6 +53,7 @@ var styles = StyleSheet.create({
});
exports.title = '<SliderIOS>';
exports.displayName = 'SliderExample';
exports.description = 'Slider input for numeric values';
exports.examples = [
{

View File

@ -121,6 +121,7 @@ var EventSwitchExample = React.createClass({
});
exports.title = '<SwitchIOS>';
exports.displayName = 'SwitchExample';
exports.description = 'Native boolean input';
exports.examples = [
{

View File

@ -59,6 +59,7 @@ var AttributeToggler = React.createClass({
exports.title = '<Text>';
exports.description = 'Base component for rendering styled text.';
exports.displayName = 'TextExample';
exports.examples = [
{
title: 'Wrap',

View File

@ -22,6 +22,7 @@
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
147CED4C1AB3532B00DA3E4C /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 147CED4B1AB34F8C00DA3E4C /* libRCTActionSheet.a */; };
14DC67F41AB71881001358AB /* libRCTPushNotification.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14DC67F11AB71876001358AB /* libRCTPushNotification.a */; };
58005BF21ABA80A60062E044 /* libRCTTest.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58005BEE1ABA80530062E044 /* libRCTTest.a */; };
D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D85B829C1AB6D5CE003F4FE2 /* libRCTVibration.a */; };
/* End PBXBuildFile section */
@ -96,6 +97,13 @@
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RCTPushNotification;
};
58005BED1ABA80530062E044 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 58005BE41ABA80530062E044 /* RCTTest.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 580C376F1AB104AF0015E709;
remoteInfo = RCTTest;
};
D85B829B1AB6D5CE003F4FE2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */;
@ -126,6 +134,7 @@
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = UIExplorer/main.m; sourceTree = "<group>"; };
14DC67E71AB71876001358AB /* RCTPushNotification.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTPushNotification.xcodeproj; path = ../../Libraries/PushNotificationIOS/RCTPushNotification.xcodeproj; sourceTree = "<group>"; };
14E0EEC81AB118F7000DECC3 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = ../../Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj; sourceTree = "<group>"; };
58005BE41ABA80530062E044 /* RCTTest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTTest.xcodeproj; path = ../../Libraries/RCTTest/RCTTest.xcodeproj; sourceTree = "<group>"; };
D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = ../../Libraries/Vibration/RCTVibration.xcodeproj; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -143,6 +152,7 @@
files = (
00D2771C1AB8C55500DC1E48 /* libicucore.dylib in Frameworks */,
00D2771A1AB8C3E100DC1E48 /* libRCTWebSocketDebugger.a in Frameworks */,
58005BF21ABA80A60062E044 /* libRCTTest.a in Frameworks */,
D85B829E1AB6D5D7003F4FE2 /* libRCTVibration.a in Frameworks */,
14DC67F41AB71881001358AB /* libRCTPushNotification.a in Frameworks */,
147CED4C1AB3532B00DA3E4C /* libRCTActionSheet.a in Frameworks */,
@ -186,16 +196,17 @@
1316A21D1AA397F400C0188E /* Libraries */ = {
isa = PBXGroup;
children = (
D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */,
13417FFA1AA91531003F314A /* ReactKit.xcodeproj */,
14DC67E71AB71876001358AB /* RCTPushNotification.xcodeproj */,
14E0EEC81AB118F7000DECC3 /* RCTActionSheet.xcodeproj */,
13417FFA1AA91531003F314A /* ReactKit.xcodeproj */,
134454551AAFCAAE003F0779 /* RCTAdSupport.xcodeproj */,
134A8A201AACED6A00945AAE /* RCTGeolocation.xcodeproj */,
13417FE31AA91428003F314A /* RCTImage.xcodeproj */,
134180261AA91779003F314A /* RCTNetwork.xcodeproj */,
58005BE41ABA80530062E044 /* RCTTest.xcodeproj */,
13417FEA1AA914B8003F314A /* RCTText.xcodeproj */,
00D2770E1AB8C2C700DC1E48 /* RCTWebSocketDebugger.xcodeproj */,
D85B82911AB6D5CE003F4FE2 /* RCTVibration.xcodeproj */,
00D2771B1AB8C55500DC1E48 /* libicucore.dylib */,
);
name = Libraries;
@ -278,6 +289,14 @@
name = Products;
sourceTree = "<group>";
};
58005BE51ABA80530062E044 /* Products */ = {
isa = PBXGroup;
children = (
58005BEE1ABA80530062E044 /* libRCTTest.a */,
);
name = Products;
sourceTree = "<group>";
};
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
@ -394,6 +413,10 @@
ProductGroup = 14DC67E81AB71876001358AB /* Products */;
ProjectRef = 14DC67E71AB71876001358AB /* RCTPushNotification.xcodeproj */;
},
{
ProductGroup = 58005BE51ABA80530062E044 /* Products */;
ProjectRef = 58005BE41ABA80530062E044 /* RCTTest.xcodeproj */;
},
{
ProductGroup = 13417FEB1AA914B8003F314A /* Products */;
ProjectRef = 13417FEA1AA914B8003F314A /* RCTText.xcodeproj */;
@ -483,6 +506,13 @@
remoteRef = 14DC67F01AB71876001358AB /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
58005BEE1ABA80530062E044 /* libRCTTest.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRCTTest.a;
remoteRef = 58005BED1ABA80530062E044 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
D85B829C1AB6D5CE003F4FE2 /* libRCTVibration.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@ -562,6 +592,7 @@
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"FB_REFERENCE_IMAGE_DIR=\"\\\"$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages\\\"\"",
"$(inherited)",
);
INFOPLIST_FILE = UIExplorerTests/Info.plist;

View File

@ -12,6 +12,7 @@
var React = require('react-native');
var {
AppRegistry,
ListView,
PixelRatio,
ScrollView,
@ -23,6 +24,8 @@ var {
} = React;
var ReactNavigatorExample = require('./ReactNavigator/ReactNavigatorExample');
var { TestModule } = React.addons;
var createExamplePage = require('./createExamplePage');
var COMPONENTS = [
@ -69,6 +72,33 @@ var ds = new ListView.DataSource({
sectionHeaderHasChanged: (h1, h2) => h1 !== h2,
});
function makeRenderable(example: any): ReactClass<any, any, any> {
return example.examples ?
createExamplePage(null, example) :
example;
}
// Register suitable examples for snapshot tests
COMPONENTS.concat(APIS).forEach((Example) => {
if (Example.displayName) {
var Snapshotter = React.createClass({
componentDidMount: function() {
// View is still blank after first RAF :\
global.requestAnimationFrame(() =>
global.requestAnimationFrame(() => TestModule.verifySnapshot(
TestModule.markTestCompleted
)
));
},
render: function() {
var Renderable = makeRenderable(Example);
return <Renderable />;
},
});
AppRegistry.registerComponent(Example.displayName, () => Snapshotter);
}
});
class UIExplorerList extends React.Component {
constructor(props) {
@ -152,9 +182,7 @@ class UIExplorerList extends React.Component {
);
return;
}
var Component = example.examples ?
createExamplePage(null, example) :
example;
var Component = makeRenderable(example);
this.props.navigator.push({
title: Component.title,
component: Component,

View File

@ -10,16 +10,36 @@
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import <RCTTest/RCTTestRunner.h>
#import "RCTAssert.h"
#import "RCTRedBox.h"
#import "RCTRootView.h"
#define TIMEOUT_SECONDS 240
@interface UIExplorerTests : XCTestCase
{
RCTTestRunner *_runner;
}
@end
@implementation UIExplorerTests
- (void)setUp
{
#ifdef __LP64__
RCTAssert(!__LP64__, @"Snapshot tests should be run on 32-bit device simulators (e.g. iPhone 5)");
#endif
NSString *version = [[UIDevice currentDevice] systemVersion];
RCTAssert([version isEqualToString:@"8.1"], @"Snapshot tests should be run on iOS 8.1, found %@", version);
_runner = initRunnerForApp(@"Examples/UIExplorer/UIExplorerApp");
// If tests have changes, set recordMode = YES below and run the affected tests on an iPhone5, iOS 8.1 simulator.
_runner.recordMode = NO;
}
- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
{
if (test(view)) {
@ -33,9 +53,10 @@
return NO;
}
- (void)testRootViewLoadsAndRenders {
// Make sure this test runs first (underscores sort early) otherwise the other tests will tear out the rootView
- (void)test__RootViewLoadsAndRenders {
UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
RCTAssert([vc.view isKindOfClass:[RCTRootView class]], @"This test must run first.");
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
BOOL foundElement = NO;
NSString *redboxError = nil;
@ -61,5 +82,39 @@
XCTAssertTrue(foundElement, @"Cound't find element with '<View>' text in %d seconds", TIMEOUT_SECONDS);
}
- (void)testViewExampleSnapshot
{
[_runner runTest:_cmd module:@"ViewExample"];
}
- (void)testLayoutExampleSnapshot
{
[_runner runTest:_cmd module:@"LayoutExample"];
}
- (void)testTextExampleSnapshot
{
[_runner runTest:_cmd module:@"TextExample"];
}
- (void)testSwitchExampleSnapshot
{
[_runner runTest:_cmd module:@"SwitchExample"];
}
- (void)testSliderExampleSnapshot
{
[_runner runTest:_cmd module:@"SliderExample"];
}
- (void)testTabBarExampleSnapshot
{
[_runner runTest:_cmd module:@"TabBarExample"];
}
- (void)testZZZ_NotInRecordMode
{
RCTAssert(_runner.recordMode == NO, @"Don't forget to turn record mode back to NO before commit.");
}
@end

View File

@ -39,22 +39,26 @@
return;
}
NSError *error = nil;
NSString *testName = NSStringFromSelector(_testSelector);
_snapshotCounter[testName] = @([_snapshotCounter[testName] integerValue] + 1);
BOOL success = [_snapshotController compareSnapshotOfView:_view
selector:_testSelector
identifier:[_snapshotCounter[testName] stringValue]
error:&error];
RCTAssert(success, @"Snapshot comparison failed: %@", error);
callback(@[]);
dispatch_async(dispatch_get_main_queue(), ^{
NSString *testName = NSStringFromSelector(_testSelector);
_snapshotCounter[testName] = @([_snapshotCounter[testName] integerValue] + 1);
NSError *error = nil;
BOOL success = [_snapshotController compareSnapshotOfView:_view
selector:_testSelector
identifier:[_snapshotCounter[testName] stringValue]
error:&error];
RCTAssert(success, @"Snapshot comparison failed: %@", error);
callback(@[]);
});
}
- (void)markTestCompleted
{
RCT_EXPORT();
_done = YES;
dispatch_async(dispatch_get_main_queue(), ^{
_done = YES;
});
}
@end