diff --git a/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestResultView.js b/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestResultView.js
index 19c418dd529..590d49d40ca 100644
--- a/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestResultView.js
+++ b/packages/rn-tester/js/examples/Experimental/PlatformTest/RNTesterPlatformTestResultView.js
@@ -19,8 +19,19 @@ import type {
} from './RNTesterPlatformTestTypes';
import * as React from 'react';
-import {useMemo} from 'react';
-import {Button, View, Text, StyleSheet, FlatList} from 'react-native';
+import {useMemo, useState, useCallback} from 'react';
+import {
+ Button,
+ View,
+ Text,
+ StyleSheet,
+ FlatList,
+ Modal,
+ SafeAreaView,
+ TextInput,
+ KeyboardAvoidingView,
+ Platform,
+} from 'react-native';
const DISPLAY_STATUS_MAPPING: {[PlatformTestResultStatus]: string} = {
PASS: 'Pass',
@@ -28,6 +39,75 @@ const DISPLAY_STATUS_MAPPING: {[PlatformTestResultStatus]: string} = {
ERROR: 'Error',
};
+type FilterModalProps = $ReadOnly<{
+ filterText: string,
+ setFilterText: (newFilterText: string) => void,
+}>;
+function FilterModalButton(props: FilterModalProps) {
+ const {filterText, setFilterText} = props;
+
+ const [modalVisible, setModalVisible] = useState(false);
+ const [pendingFilterText, setPendingFilterText] = useState(filterText);
+
+ const onFilterButtonPress = useCallback(() => {
+ setPendingFilterText(filterText);
+ setModalVisible(true);
+ }, [filterText]);
+
+ const onFilterSubmit = useCallback(() => {
+ setFilterText(pendingFilterText);
+ setModalVisible(false);
+ }, [pendingFilterText, setFilterText]);
+
+ const onFilterCancel = useCallback(() => {
+ setModalVisible(false);
+ }, []);
+
+ const onPendingTextChange = useCallback(newText => {
+ setPendingFilterText(newText);
+ }, []);
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+ Enter a test name filter
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
+
function TableHeader() {
return (
@@ -89,9 +169,20 @@ export default function RNTesterPlatformTestResultView(
): React.MixedElement {
const {numPending, reset, results, style} = props;
+ const [filterText, setFilterText] = useState('');
+
+ const filteredResults = useMemo(() => {
+ if (filterText === '') {
+ return results;
+ }
+ return results.filter(result =>
+ result.name.toLowerCase().includes(filterText.toLowerCase()),
+ );
+ }, [filterText, results]);
+
const {numPass, numFail, numError} = useMemo(
() =>
- results.reduce(
+ filteredResults.reduce(
(acc, result) => {
switch (result.status) {
case 'PASS':
@@ -108,14 +199,36 @@ export default function RNTesterPlatformTestResultView(
numError: 0,
},
),
- [results],
+ [filteredResults],
);
+ const handleReset = useCallback(() => {
+ setFilterText('');
+ reset();
+ }, [reset]);
+
return (
- Results
-
+
+ Results
+ {filterText !== '' ? (
+ <>
+ {' '}
+
+ (Filtered: '{filterText}')
+
+ >
+ ) : null}
+
+
+
+
+
+
@@ -142,19 +255,82 @@ export default function RNTesterPlatformTestResultView(
-
+
);
}
const styles = StyleSheet.create({
+ actionsContainer: {
+ flexDirection: 'row',
+ },
+ buttonSpacer: {
+ width: 8,
+ },
errorText: {
color: 'orange',
},
failText: {
color: 'red',
},
+ filteredText: {
+ fontSize: 18,
+ fontWeight: 'normal',
+ opacity: 0.5,
+ },
+ filterModalActionButton: {
+ flex: 1,
+ },
+ filterModalActionsContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-around',
+ minHeight: 50,
+ },
+ filterModalContainer: {
+ minWidth: 250,
+ backgroundColor: 'white',
+ borderRadius: 20,
+ shadowColor: '#000',
+ shadowOffset: {
+ width: 0,
+ height: 2,
+ },
+ shadowOpacity: 0.25,
+ shadowRadius: 4,
+ elevation: 5,
+ },
+ filterModalContentContainer: {
+ paddingHorizontal: 12,
+ },
+ filterModalPromptContainer: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ filterModalRoot: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'stretch',
+ backgroundColor: 'rgba(0, 0, 0, 0.2)',
+ },
+ filterModalPromptText: {
+ paddingVertical: 12,
+ fontSize: 16,
+ },
+ filterModalPendingTextInput: {
+ // height: 40,
+ padding: 6,
+ backgroundColor: 'white',
+ borderWidth: StyleSheet.hairlineWidth,
+ borderColor: 'rgb(171, 171, 171)',
+ borderRadius: 8,
+ },
+ filterModalKeboardAvoidingRoot: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
passText: {
color: 'green',
},
@@ -198,7 +374,7 @@ const styles = StyleSheet.create({
},
titleContainer: {
flexDirection: 'row',
- alignItems: 'center',
+ alignItems: 'flex-end',
justifyContent: 'space-between',
},
});