diff --git a/packages/rn-tester/js/examples/Experimental/PlatformTest/README.md b/packages/rn-tester/js/examples/Experimental/PlatformTest/README.md index 7814ecb2405..804e80900fb 100644 --- a/packages/rn-tester/js/examples/Experimental/PlatformTest/README.md +++ b/packages/rn-tester/js/examples/Experimental/PlatformTest/README.md @@ -24,7 +24,7 @@ function ExampleTestCase ({ harness }) { /* ... */ } As of writting this README there are 2 different types of tests that the `harness` prop provides: -### `test(testcase: (TestContext) => void, testName: string)` +### `test(testcase: (TestContext) => void, testName: string, options?: TestOptions)` This is a method to create "regular" test reminicent of other frameworks such as Jest. These are meant to be run imperatively, and while that means that they technically could work in a `useEffect` hook as a way to run the test "on mount" — it is instead recommended to try and keep these tests in callbacks instead. A good alternative to running the test on mount would be to instead put the test in a callback and render a "Start Test" button which executes the callback. @@ -35,6 +35,10 @@ The first argument is the closure in which you will run your test and make asser * `assert_greater_than_equal(a: number, b: number, description: string): void` * `assert_less_than_equal(a: number, b: number, description: string): void` +An optional third argument can be used for specifying additional options to the test — that object currently has the following properties (all of which are optional themselves): + +* `skip: boolean`: In cases where we want the test to be registered but we don't want it to contribute to the pass/fail count. + Here's what a basic/contrived example which verifies the layout of a basic view: ```js diff --git a/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestMinimizedResultView.js b/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestMinimizedResultView.js index 275ede2a710..ed9a2b2080a 100644 --- a/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestMinimizedResultView.js +++ b/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestMinimizedResultView.js @@ -10,6 +10,8 @@ import type {ViewStyleProp} from 'react-native/Libraries/StyleSheet/StyleSheet'; +import RNTesterPlatformTestResultsText from './RNTesterPlatformTestResultsText'; + import * as React from 'react'; import {View, Text, StyleSheet, TouchableHighlight} from 'react-native'; @@ -18,6 +20,7 @@ type Props = $ReadOnly<{| numError: number, numPass: number, numPending: number, + numSkipped: number, onPress?: () => void, style?: ?ViewStyleProp, |}>; @@ -26,26 +29,22 @@ export default function RNTesterPlatformTestMinimizedResultView({ numError, numPass, numPending, + numSkipped, onPress, style, }: Props): React.MixedElement { return ( - - - {numPass} Pass - - - {numFail} Fail - - - {numError} Error - - - {numPending} Pending - - + + + @@ -59,12 +58,6 @@ const styles = StyleSheet.create({ marginEnd: 8, opacity: 0.5, }, - errorText: { - color: 'orange', - }, - failText: { - color: 'red', - }, innerContainer: { width: '100%', height: '100%', @@ -74,12 +67,6 @@ const styles = StyleSheet.create({ paddingHorizontal: 8, backgroundColor: 'white', }, - passText: { - color: 'green', - }, - pendingText: { - color: 'gray', - }, root: { borderTopColor: 'rgb(171, 171, 171)', borderTopWidth: StyleSheet.hairlineWidth, @@ -89,8 +76,6 @@ const styles = StyleSheet.create({ flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-start', - }, - summaryText: { marginStart: 8, }, }); diff --git a/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestResultView.js b/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestResultView.js index fbe4696c7bb..d33f5ba82c1 100644 --- a/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestResultView.js +++ b/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestResultView.js @@ -19,6 +19,7 @@ import type { } from './RNTesterPlatformTestTypes'; import RNTesterPlatformTestMinimizedResultView from './RNTesterPlatformTestMinimizedResultView'; +import RNTesterPlatformTestResultsText from './RNTesterPlatformTestResultsText'; import * as React from 'react'; import {useMemo, useState, useCallback} from 'react'; @@ -40,6 +41,7 @@ const DISPLAY_STATUS_MAPPING: {[PlatformTestResultStatus]: string} = { PASS: 'Pass', FAIL: 'Fail', ERROR: 'Error', + SKIPPED: 'Skipped', }; type FilterModalProps = $ReadOnly<{ @@ -183,7 +185,7 @@ export default function RNTesterPlatformTestResultView( ); }, [filterText, results]); - const {numPass, numFail, numError} = useMemo( + const {numPass, numFail, numError, numSkipped} = useMemo( () => filteredResults.reduce( (acc, result) => { @@ -194,12 +196,15 @@ export default function RNTesterPlatformTestResultView( return {...acc, numFail: acc.numFail + 1}; case 'ERROR': return {...acc, numError: acc.numError + 1}; + case 'SKIPPED': + return {...acc, numSkipped: acc.numSkipped + 1}; } }, { numPass: 0, numFail: 0, numError: 0, + numSkipped: 0, }, ), [filteredResults], @@ -228,6 +233,7 @@ export default function RNTesterPlatformTestResultView( numError={numError} numPass={numPass} numPending={numPending} + numSkipped={numSkipped} onPress={handleMinimizedPress} style={style} /> @@ -250,26 +256,13 @@ export default function RNTesterPlatformTestResultView( ) : null} - - {numPass} Pass - - {' '} - - {numFail} Fail - - {' '} - - {numError} Error - - {numPending > 0 ? ( - <> - {' '} - - {numPending}{' '} - Pending - - - ) : null} + @@ -399,6 +392,9 @@ const styles = StyleSheet.create({ paddingTop: 8, flex: 0, }, + skippedText: { + color: 'blue', + }, table: { flex: 1, }, @@ -446,4 +442,5 @@ const STATUS_TEXT_STYLE_MAPPING: {[PlatformTestResultStatus]: TextStyle} = { PASS: styles.passText, FAIL: styles.failText, ERROR: styles.errorText, + SKIPPED: styles.skippedText, }; diff --git a/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestResultsText.js b/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestResultsText.js new file mode 100644 index 00000000000..ee35d22d976 --- /dev/null +++ b/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestResultsText.js @@ -0,0 +1,78 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + * @flow + */ + +import {Text, StyleSheet} from 'react-native'; +import * as React from 'react'; + +type Props = $ReadOnly<{ + numPass: number, + numFail: number, + numError: number, + numPending: number, + numSkipped: number, +}>; +export default function RNTesterPlatformTestResultsText( + props: Props, +): React.MixedElement { + const {numPass, numFail, numError, numPending, numSkipped} = props; + return ( + <> + + {numPass} Pass + + {' '} + + {numFail} Fail + + {numSkipped > 0 ? ( + <> + {' '} + + {numSkipped} Skipped + + + ) : null} + {numError > 0 ? ( + <> + {' '} + + {numError} Error + + + ) : null} + {numPending > 0 ? ( + <> + {' '} + + {numPending} Pending + + + ) : null} + + ); +} + +const styles = StyleSheet.create({ + errorText: { + color: 'orange', + }, + failText: { + color: 'red', + }, + passText: { + color: 'green', + }, + pendingText: { + color: 'gray', + }, + skippedText: { + color: 'blue', + }, +}); diff --git a/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestTypes.js b/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestTypes.js index 2097d43dd8d..44184035bb6 100644 --- a/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestTypes.js +++ b/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestTypes.js @@ -28,7 +28,7 @@ export type PlatformTestAssertionResult = | PassingPlatformTestAssertionResult | FailingPlatformTestAssertionResult; -export type PlatformTestResultStatus = 'PASS' | 'FAIL' | 'ERROR'; +export type PlatformTestResultStatus = 'PASS' | 'FAIL' | 'ERROR' | 'SKIPPED'; export type PlatformTestResult = $ReadOnly<{| name: string, @@ -50,8 +50,16 @@ export type AsyncPlatformTest = $ReadOnly<{| done(): void, |}>; +export type SyncTestOptions = $ReadOnly<{| + skip?: boolean, +|}>; + export type PlatformTestHarness = $ReadOnly<{| - test(testcase: PlatformTestCase, name: string): void, + test( + testcase: PlatformTestCase, + name: string, + options?: SyncTestOptions, + ): void, useAsyncTest(description: string, timeout?: number): AsyncPlatformTest, |}>; diff --git a/packages/rn-tester/js/examples/Experimental/PlatformTest/usePlatformTestHarness.js b/packages/rn-tester/js/examples/Experimental/PlatformTest/usePlatformTestHarness.js index 4216839d019..b06f3298201 100644 --- a/packages/rn-tester/js/examples/Experimental/PlatformTest/usePlatformTestHarness.js +++ b/packages/rn-tester/js/examples/Experimental/PlatformTest/usePlatformTestHarness.js @@ -16,6 +16,7 @@ import type { PlatformTestCase, PlatformTestAssertionResult, PlatformTestContext, + SyncTestOptions, } from './RNTesterPlatformTestTypes'; type AsyncTestStatus = 'NOT_RAN' | 'COMPLETED' | 'TIMED_OUT'; @@ -174,7 +175,23 @@ export default function usePlatformTestHarness(): PlatformTestHarnessHookResult }, []); const testFunction: PlatformTestHarness['test'] = useCallback( - (testCase: PlatformTestCase, name: string): void => { + ( + testCase: PlatformTestCase, + name: string, + options?: SyncTestOptions, + ): void => { + const {skip = false} = options ?? {}; + + if (skip) { + addTestResult({ + name, + status: 'SKIPPED', + assertions: [], + error: null, + }); + return; + } + const assertionResults: Array = []; const baseAssert = ( diff --git a/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventSupport.js b/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventSupport.js index 0fa7ceb46b5..35710998567 100644 --- a/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventSupport.js +++ b/packages/rn-tester/js/examples/Experimental/W3CPointerEventPlatformTests/PointerEventSupport.js @@ -14,6 +14,10 @@ import type {PointerEvent} from 'react-native/Libraries/Types/CoreEventTypes'; import {useMemo} from 'react'; +// These props are not in the specification but are present in the WPT so we keep them +// but marked as skipped so we don't prioritize them +const SKIPPED_PROPS = ['fromElement', 'toElement']; + // Check for conformance to PointerEvent interface // TA: 1.1, 1.2, 1.6, 1.7, 1.8, 1.9, 1.10, 1.11, 1.12, 1.13 // Adapted from https://github.com/web-platform-tests/wpt/blob/6c26371ea1c144dd612864a278e88b6ba2f3d883/pointerevents/pointerevent_support.js#L15 @@ -95,33 +99,54 @@ export function check_PointerEvent( const name = attr[2]; const value = attr[3]; + const skip = SKIPPED_PROPS.includes(name); + // existence check - harness.test(({assert_true}) => { - assert_true( - name in nativeEvent, - name + ' attribute in ' + eventType + ' event', - ); - }, pointerTestName + '.' + name + ' attribute exists'); + harness.test( + ({assert_true}) => { + assert_true( + name in nativeEvent, + name + ' attribute in ' + eventType + ' event', + ); + }, + pointerTestName + '.' + name + ' attribute exists', + {skip}, + ); // readonly check // TODO // type check - harness.test(({assert_true}) => { - assert_true( + harness.test( + ({assert_true}) => { + assert_true( + // $FlowFixMe + idl_type_check[type](nativeEvent[name]), + name + ' attribute of type ' + type, + ); + }, + pointerTestName + + '.' + + name + + ' IDL type ' + + type + + ' (JS type was ' + // $FlowFixMe - idl_type_check[type](nativeEvent[name]), - name + ' attribute of type ' + type, - ); - // $FlowFixMe - }, pointerTestName + '.' + name + ' IDL type ' + type + ' (JS type was ' + typeof nativeEvent[name] + ')'); + typeof nativeEvent[name] + + ')', + {skip}, + ); // value check if defined if (value !== undefined) { - harness.test(({assert_equals}) => { - // $FlowFixMe - assert_equals(nativeEvent[name], value, name + ' attribute value'); - }, pointerTestName + '.' + name + ' value is ' + String(value) + '.'); + harness.test( + ({assert_equals}) => { + // $FlowFixMe + assert_equals(nativeEvent[name], value, name + ' attribute value'); + }, + pointerTestName + '.' + name + ' value is ' + String(value) + '.', + {skip}, + ); } });