Migrate unit tests from FBReactKitModules to FBReactKit
|
@ -62,8 +62,11 @@ var CircleBlock = React.createClass({
|
|||
var LayoutExample = React.createClass({
|
||||
statics: {
|
||||
title: 'Layout - Flexbox',
|
||||
description: 'Examples of using the flexbox API to layout views.'
|
||||
description: 'Examples of using the flexbox API to layout views.',
|
||||
},
|
||||
|
||||
displayName: 'LayoutExample',
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<UIExplorerPage title={this.props.navigator ? null : 'Layout'}>
|
||||
|
|
|
@ -26,9 +26,11 @@ var {
|
|||
var TabBarExample = React.createClass({
|
||||
statics: {
|
||||
title: '<TabBarIOS>',
|
||||
description: 'Tab-based navigation.'
|
||||
description: 'Tab-based navigation.',
|
||||
},
|
||||
|
||||
displayName: 'TabBarExample',
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
selectedTab: 'redTab',
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
141FC1211B222EBB004D5FFB /* IntegrationTestsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 141FC1201B222EBB004D5FFB /* IntegrationTestsTests.m */; };
|
||||
143BC5A11B21E45C00462512 /* UIExplorerIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 143BC5A01B21E45C00462512 /* UIExplorerIntegrationTests.m */; };
|
||||
141FC1211B222EBB004D5FFB /* IntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 141FC1201B222EBB004D5FFB /* IntegrationTests.m */; };
|
||||
143BC5A11B21E45C00462512 /* UIExplorerSnapshotTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 143BC5A01B21E45C00462512 /* UIExplorerSnapshotTests.m */; };
|
||||
144D21241B2204C5006DB32B /* RCTClippingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 144D21231B2204C5006DB32B /* RCTClippingTests.m */; };
|
||||
147CED4C1AB3532B00DA3E4C /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 147CED4B1AB34F8C00DA3E4C /* libRCTActionSheet.a */; };
|
||||
1497CFAC1B21F5E400C1F8F2 /* RCTAllocationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1497CFA41B21F5E400C1F8F2 /* RCTAllocationTests.m */; };
|
||||
|
@ -167,7 +167,7 @@
|
|||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = UIExplorer/Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = UIExplorer/main.m; sourceTree = "<group>"; };
|
||||
13CC9D481AEED2B90020D1C2 /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = ../../Libraries/Settings/RCTSettings.xcodeproj; sourceTree = "<group>"; };
|
||||
141FC1201B222EBB004D5FFB /* IntegrationTestsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IntegrationTestsTests.m; sourceTree = "<group>"; };
|
||||
141FC1201B222EBB004D5FFB /* IntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IntegrationTests.m; sourceTree = "<group>"; };
|
||||
143BC57E1B21E18100462512 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
143BC5811B21E18100462512 /* testLayoutExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testLayoutExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
|
||||
143BC5821B21E18100462512 /* testSliderExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testSliderExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
|
||||
|
@ -177,7 +177,7 @@
|
|||
143BC5861B21E18100462512 /* testViewExampleSnapshot_1@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "testViewExampleSnapshot_1@2x.png"; sourceTree = "<group>"; };
|
||||
143BC5951B21E3E100462512 /* UIExplorerIntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UIExplorerIntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
143BC5981B21E3E100462512 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
143BC5A01B21E45C00462512 /* UIExplorerIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIExplorerIntegrationTests.m; sourceTree = "<group>"; };
|
||||
143BC5A01B21E45C00462512 /* UIExplorerSnapshotTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIExplorerSnapshotTests.m; sourceTree = "<group>"; };
|
||||
144D21231B2204C5006DB32B /* RCTClippingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTClippingTests.m; sourceTree = "<group>"; };
|
||||
1497CFA41B21F5E400C1F8F2 /* RCTAllocationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAllocationTests.m; sourceTree = "<group>"; };
|
||||
1497CFA51B21F5E400C1F8F2 /* RCTBridgeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTBridgeTests.m; sourceTree = "<group>"; };
|
||||
|
@ -381,8 +381,8 @@
|
|||
143BC5961B21E3E100462512 /* UIExplorerIntegrationTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
141FC1201B222EBB004D5FFB /* IntegrationTestsTests.m */,
|
||||
143BC5A01B21E45C00462512 /* UIExplorerIntegrationTests.m */,
|
||||
141FC1201B222EBB004D5FFB /* IntegrationTests.m */,
|
||||
143BC5A01B21E45C00462512 /* UIExplorerSnapshotTests.m */,
|
||||
143BC5971B21E3E100462512 /* Supporting Files */,
|
||||
);
|
||||
path = UIExplorerIntegrationTests;
|
||||
|
@ -796,8 +796,8 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
141FC1211B222EBB004D5FFB /* IntegrationTestsTests.m in Sources */,
|
||||
143BC5A11B21E45C00462512 /* UIExplorerIntegrationTests.m in Sources */,
|
||||
141FC1211B222EBB004D5FFB /* IntegrationTests.m in Sources */,
|
||||
143BC5A11B21E45C00462512 /* UIExplorerSnapshotTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
13
Examples/UIExplorer/UIExplorer/Images.xcassets/uie_thumb_big.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x",
|
||||
"filename" : "uie_thumb_big.png"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
Examples/UIExplorer/UIExplorer/Images.xcassets/uie_thumb_big.imageset/uie_thumb_big.png
vendored
Normal file
After Width: | Height: | Size: 6.6 KiB |
|
@ -14,11 +14,11 @@
|
|||
|
||||
#import "RCTAssert.h"
|
||||
|
||||
@interface IntegrationTestsTests : XCTestCase
|
||||
@interface IntegrationTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation IntegrationTestsTests
|
||||
@implementation IntegrationTests
|
||||
{
|
||||
RCTTestRunner *_runner;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
|||
|
||||
NSOperatingSystemVersion version = [[NSProcessInfo processInfo] operatingSystemVersion];
|
||||
RCTAssert(version.majorVersion == 8 || version.minorVersion == 3, @"Tests should be run on iOS 8.3, found %zd.%zd.%zd", version.majorVersion, version.minorVersion, version.patchVersion);
|
||||
_runner = RCTInitRunnerForApp(@"Examples/UIExplorer/UIExplorerIntegrationTests/js/IntegrationTestsApp");
|
||||
_runner = RCTInitRunnerForApp(@"Examples/UIExplorer/UIExplorerIntegrationTests/js/IntegrationTestsApp", nil);
|
||||
}
|
||||
|
||||
#pragma mark Logic Tests
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 87 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 269 KiB |
After Width: | Height: | Size: 265 KiB |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 95 KiB |
|
@ -21,14 +21,14 @@
|
|||
#import "RCTRedBox.h"
|
||||
#import "RCTRootView.h"
|
||||
|
||||
@interface UIExplorerTests : XCTestCase
|
||||
@interface UIExplorerSnapshotTests : XCTestCase
|
||||
{
|
||||
RCTTestRunner *_runner;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation UIExplorerTests
|
||||
@implementation UIExplorerSnapshotTests
|
||||
|
||||
- (void)setUp
|
||||
{
|
||||
|
@ -37,21 +37,26 @@
|
|||
#endif
|
||||
NSString *version = [[UIDevice currentDevice] systemVersion];
|
||||
RCTAssert([version isEqualToString:@"8.3"], @"Snapshot tests should be run on iOS 8.3, found %@", version);
|
||||
_runner = RCTInitRunnerForApp(@"Examples/UIExplorer/UIExplorerApp.ios");
|
||||
_runner = RCTInitRunnerForApp(@"Examples/UIExplorer/UIExplorerApp.ios", nil);
|
||||
_runner.recordMode = NO;
|
||||
}
|
||||
|
||||
#define RCT_SNAPSHOT_TEST(name, reRecord) \
|
||||
- (void)test##name##Snapshot \
|
||||
#define RCT_TEST(name) \
|
||||
- (void)test##name \
|
||||
{ \
|
||||
_runner.recordMode |= reRecord; \
|
||||
[_runner runTest:_cmd module:@#name]; \
|
||||
}
|
||||
|
||||
RCT_SNAPSHOT_TEST(ViewExample, NO)
|
||||
RCT_SNAPSHOT_TEST(LayoutExample, NO)
|
||||
RCT_SNAPSHOT_TEST(TextExample, NO)
|
||||
RCT_SNAPSHOT_TEST(SwitchExample, NO)
|
||||
RCT_SNAPSHOT_TEST(SliderExample, NO)
|
||||
RCT_SNAPSHOT_TEST(TabBarExample, NO)
|
||||
RCT_TEST(ViewExample)
|
||||
RCT_TEST(LayoutExample)
|
||||
RCT_TEST(TextExample)
|
||||
RCT_TEST(SwitchExample)
|
||||
RCT_TEST(SliderExample)
|
||||
RCT_TEST(TabBarExample)
|
||||
|
||||
- (void)testZZZNotInRecordMode
|
||||
{
|
||||
XCTAssertFalse(_runner.recordMode, @"Don't forget to turn record mode back to off");
|
||||
}
|
||||
|
||||
@end
|
|
@ -53,7 +53,7 @@ var IntegrationTestsApp = React.createClass({
|
|||
<View style={styles.container}>
|
||||
<Text style={styles.row}>
|
||||
Click on a test to run it in this shell for easier debugging and
|
||||
development. Run all tests in the testing envirnment with cmd+U in
|
||||
development. Run all tests in the testing environment with cmd+U in
|
||||
Xcode.
|
||||
</Text>
|
||||
<View style={styles.separator} />
|
||||
|
|
|
@ -121,7 +121,7 @@ var LayoutEventsTest = React.createClass({
|
|||
ref="img"
|
||||
onLayout={this.onImageLayout}
|
||||
style={styles.image}
|
||||
source={{uri: 'https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-prn1/t39.1997/p128x128/851561_767334496626293_1958532586_n.png'}}
|
||||
source={{uri: 'uie_thumb_big.png'}}
|
||||
/>
|
||||
<Text>
|
||||
ViewLayout: {JSON.stringify(this.state.viewLayout, null, ' ') + '\n\n'}
|
||||
|
|
|
@ -7,11 +7,18 @@
|
|||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule AnimationExperimental
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
var RCTAnimationManager = require('NativeModules').AnimationExperimentalManager;
|
||||
if (!RCTAnimationManager) {
|
||||
// AnimationExperimental isn't available internally - this is a temporary
|
||||
// workaround to enable its availability to be determined at runtime.
|
||||
// For Flow let's pretend like we always export AnimationExperimental
|
||||
// so all our users don't need to do null checks
|
||||
module.exports = null;
|
||||
} else {
|
||||
|
||||
var React = require('React');
|
||||
var AnimationUtils = require('AnimationUtils');
|
||||
|
||||
|
@ -88,3 +95,5 @@ if (__DEV__) {
|
|||
}
|
||||
|
||||
module.exports = AnimationExperimental;
|
||||
|
||||
}
|
||||
|
|
|
@ -25,12 +25,12 @@ typedef NS_ENUM(NSInteger, RCTTestStatus) {
|
|||
/**
|
||||
* The snapshot test controller for this module.
|
||||
*/
|
||||
@property (nonatomic, weak) FBSnapshotTestController *controller;
|
||||
@property (nonatomic, strong) FBSnapshotTestController *controller;
|
||||
|
||||
/**
|
||||
* This is the view to be snapshotted.
|
||||
*/
|
||||
@property (nonatomic, weak) UIView *view;
|
||||
@property (nonatomic, strong) UIView *view;
|
||||
|
||||
/**
|
||||
* This is used to give meaningful names to snapshot image files.
|
||||
|
|
|
@ -16,7 +16,10 @@
|
|||
*
|
||||
* FB_REFERENCE_IMAGE_DIR="\"$(SOURCE_ROOT)/$(PROJECT_NAME)Tests/ReferenceImages\""
|
||||
*/
|
||||
#define RCTInitRunnerForApp(app__) [[RCTTestRunner alloc] initWithApp:(app__) referenceDir:@FB_REFERENCE_IMAGE_DIR]
|
||||
#define RCTInitRunnerForApp(app__, moduleProvider__) \
|
||||
[[RCTTestRunner alloc] initWithApp:(app__) \
|
||||
referenceDirectory:@FB_REFERENCE_IMAGE_DIR \
|
||||
moduleProvider:(moduleProvider__)]
|
||||
|
||||
@interface RCTTestRunner : NSObject
|
||||
|
||||
|
@ -28,10 +31,12 @@
|
|||
* macro instead of calling this directly.
|
||||
*
|
||||
* @param app The path to the app bundle without suffixes, e.g. IntegrationTests/IntegrationTestsApp
|
||||
* @param referenceDir The path for snapshot references images. The RCTInitRunnerForApp macro uses
|
||||
* FB_REFERENCE_IMAGE_DIR for this automatically.
|
||||
* @param referenceDirectory The path for snapshot references images. The RCTInitRunnerForApp macro uses FB_REFERENCE_IMAGE_DIR for this automatically.
|
||||
* @param block A block that returns an array of extra modules to be used by the test runner.
|
||||
*/
|
||||
- (instancetype)initWithApp:(NSString *)app referenceDir:(NSString *)referenceDir NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithApp:(NSString *)app
|
||||
referenceDirectory:(NSString *)referenceDirectory
|
||||
moduleProvider:(NSArray *(^)(void))block NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Simplest runTest function simply mounts the specified JS module with no
|
||||
|
|
|
@ -27,20 +27,27 @@
|
|||
@implementation RCTTestRunner
|
||||
{
|
||||
FBSnapshotTestController *_testController;
|
||||
RCTBridgeModuleProviderBlock _moduleProvider;
|
||||
}
|
||||
|
||||
- (instancetype)initWithApp:(NSString *)app referenceDir:(NSString *)referenceDir
|
||||
- (instancetype)initWithApp:(NSString *)app
|
||||
referenceDirectory:(NSString *)referenceDirectory
|
||||
moduleProvider:(RCTBridgeModuleProviderBlock)block
|
||||
{
|
||||
RCTAssertParam(app);
|
||||
RCTAssertParam(referenceDir);
|
||||
RCTAssertParam(referenceDirectory);
|
||||
|
||||
if ((self = [super init])) {
|
||||
|
||||
NSString *sanitizedAppName = [app stringByReplacingOccurrencesOfString:@"/" withString:@"-"];
|
||||
sanitizedAppName = [sanitizedAppName stringByReplacingOccurrencesOfString:@"\\" withString:@"-"];
|
||||
_testController = [[FBSnapshotTestController alloc] initWithTestName:sanitizedAppName];
|
||||
_testController.referenceImagesDirectory = referenceDir;
|
||||
_testController.referenceImagesDirectory = referenceDirectory;
|
||||
_moduleProvider = [block copy];
|
||||
|
||||
#if RUNNING_ON_CI
|
||||
_scriptURL = [[NSBundle bundleForClass:[RCTBridge class]] URLForResource:@"main" withExtension:@"jsbundle"];
|
||||
RCTAssert(_scriptURL != nil, @"Could not locate main.jsBundle");
|
||||
#else
|
||||
_scriptURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost:8081/%@.includeRequire.runModule.bundle?dev=true", app]];
|
||||
#endif
|
||||
|
@ -73,16 +80,20 @@ RCT_NOT_IMPLEMENTED(-init)
|
|||
}];
|
||||
}
|
||||
|
||||
- (void)runTest:(SEL)test module:(NSString *)moduleName initialProps:(NSDictionary *)initialProps expectErrorBlock:(BOOL(^)(NSString *error))expectErrorBlock
|
||||
- (void)runTest:(SEL)test module:(NSString *)moduleName
|
||||
initialProps:(NSDictionary *)initialProps expectErrorBlock:(BOOL(^)(NSString *error))expectErrorBlock
|
||||
{
|
||||
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:_scriptURL
|
||||
moduleName:moduleName
|
||||
RCTBridge *bridge = [[RCTBridge alloc] initWithBundleURL:_scriptURL
|
||||
moduleProvider:_moduleProvider
|
||||
launchOptions:nil];
|
||||
|
||||
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:moduleName];
|
||||
rootView.initialProperties = initialProps;
|
||||
rootView.frame = CGRectMake(0, 0, 320, 2000); // Constant size for testing on multiple devices
|
||||
|
||||
NSString *testModuleName = RCTBridgeModuleNameForClass([RCTTestModule class]);
|
||||
RCTTestModule *testModule = rootView.bridge.batchedBridge.modules[testModuleName];
|
||||
RCTAssert(_testController != nil, @"_testController should not be nil");
|
||||
testModule.controller = _testController;
|
||||
testModule.testSelector = test;
|
||||
testModule.view = rootView;
|
||||
|
@ -100,14 +111,11 @@ RCT_NOT_IMPLEMENTED(-init)
|
|||
}
|
||||
[rootView removeFromSuperview];
|
||||
|
||||
|
||||
NSArray *nonLayoutSubviews = [vc.view.subviews filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id subview, NSDictionary *bindings) {
|
||||
return ![NSStringFromClass([subview class]) isEqualToString:@"_UILayoutGuide"];
|
||||
}]];
|
||||
RCTAssert(nonLayoutSubviews.count == 0, @"There shouldn't be any other views: %@", nonLayoutSubviews);
|
||||
|
||||
|
||||
vc.view = nil;
|
||||
[[RCTRedBox sharedInstance] dismiss];
|
||||
if (expectErrorBlock) {
|
||||
RCTAssert(expectErrorBlock(error), @"Expected an error but nothing matched.");
|
||||
|
@ -116,7 +124,6 @@ RCT_NOT_IMPLEMENTED(-init)
|
|||
RCTAssert(testModule.status != RCTTestStatusPending, @"Test didn't finish within %d seconds", TIMEOUT_SECONDS);
|
||||
RCTAssert(testModule.status == RCTTestStatusPassed, @"Test failed");
|
||||
}
|
||||
RCTAssert(self.recordMode == NO, @"Don't forget to turn record mode back to NO before commit.");
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
- (instancetype)initWithBridge:(RCTBridge *)bridge
|
||||
{
|
||||
RCTAssert(bridge, @"birdge parameter is required");
|
||||
RCTAssert(bridge, @"bridge parameter is required");
|
||||
|
||||
if ((self = [super init])) {
|
||||
_bridge = bridge;
|
||||
|
|
|
@ -79,7 +79,7 @@ RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RCTMap)
|
|||
}
|
||||
}
|
||||
|
||||
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(RCTPointAnnotation *)annotation
|
||||
- (MKAnnotationView *)mapView:(__unused MKMapView *)mapView viewForAnnotation:(RCTPointAnnotation *)annotation
|
||||
{
|
||||
if ([annotation isKindOfClass:[MKUserLocation class]]) {
|
||||
return nil;
|
||||
|
|