From 663dd9177efe94c6ead66cb4379009aefdca260c Mon Sep 17 00:00:00 2001 From: Vincent Riemer Date: Mon, 18 Jul 2022 14:12:25 -0700 Subject: [PATCH] Add the ability for tests to be marked as 'skipped' Summary: Changelog: [RNTester][Internal] - Add the ability for platform tests to be marked as skipped There are some properties/tests in the web platform tests that we don't want to especially priorities (especially if they aren't especially relevant to the specification and just legacy browser compat) so this adds the ability for us to mark these tests as skipped. This is so that we can ensure that our platform tests are "complete" while decreasing the noise and distraction from failing tests that don't really apply to RN. Reviewed By: lunaleaps Differential Revision: D37889470 fbshipit-source-id: 6516ac90c242d662518a95cb9ba8ce643f6bb09c --- .../Experimental/PlatformTest/README.md | 6 +- ...RNTesterPlatformTestMinimizedResultView.js | 41 ++++------ .../RNTesterPlatformTestResultView.js | 39 +++++----- .../RNTesterPlatformTestResultsText.js | 78 +++++++++++++++++++ .../PlatformTest/RNTesterPlatformTestTypes.js | 12 ++- .../PlatformTest/usePlatformTestHarness.js | 19 ++++- .../PointerEventSupport.js | 59 ++++++++++---- 7 files changed, 184 insertions(+), 70 deletions(-) create mode 100644 packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestResultsText.js 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}, + ); } });