Skip to content

Commit 4659bba

Browse files
feat: toBeDisabled matcher (#1469)
* feat: add toBeDisabled matcher * add tests and toBeEnabled matcher * update logic and tests * add test to validate toBeDisabled with parent elements * better name * refactor: tweaks and improvements * chore: tweak fo * refactor: tests * chore: fix tests --------- Co-authored-by: Maciej Jastrzebski <[email protected]>
1 parent 3ff0afb commit 4659bba

File tree

12 files changed

+422
-70
lines changed

12 files changed

+422
-70
lines changed

src/helpers/__tests__/format-default.test.tsx

Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
1-
import { ReactTestRendererJSON } from 'react-test-renderer';
21
import { defaultMapProps } from '../format-default';
32

4-
const node: ReactTestRendererJSON = {
5-
type: 'View',
6-
props: {},
7-
children: null,
8-
};
9-
103
describe('mapPropsForQueryError', () => {
114
test('preserves props that are helpful for debugging', () => {
125
const props = {
@@ -32,89 +25,79 @@ describe('mapPropsForQueryError', () => {
3225
defaultValue: 'DEFAULT_VALUE',
3326
};
3427

35-
const result = defaultMapProps(props, node);
28+
const result = defaultMapProps(props);
3629
expect(result).toStrictEqual(props);
3730
});
3831

3932
test('does not preserve less helpful props', () => {
40-
const result = defaultMapProps(
41-
{
42-
style: [{ flex: 1 }, { display: 'flex' }],
43-
onPress: () => null,
44-
key: 'foo',
45-
},
46-
node
47-
);
33+
const result = defaultMapProps({
34+
style: [{ flex: 1 }, { flexDirection: 'row' }],
35+
onPress: () => null,
36+
key: 'foo',
37+
});
4838

4939
expect(result).toStrictEqual({});
5040
});
5141

52-
test('preserves "display: none" style but no other style', () => {
53-
const result = defaultMapProps(
54-
{ style: [{ flex: 1 }, { display: 'none', flex: 2 }] },
55-
node
56-
);
42+
test('preserves "display: none" and "opacity: 0" styles but no other style', () => {
43+
const result = defaultMapProps({
44+
style: [{ flex: 1 }, { display: 'none', flex: 2 }, { opacity: 0 }],
45+
});
5746

5847
expect(result).toStrictEqual({
59-
style: { display: 'none' },
48+
style: { display: 'none', opacity: 0 },
6049
});
6150
});
6251

6352
test('removes undefined keys from accessibilityState', () => {
64-
const result = defaultMapProps(
65-
{ accessibilityState: { checked: undefined, selected: false } },
66-
node
67-
);
53+
const result = defaultMapProps({
54+
accessibilityState: { checked: undefined, selected: false },
55+
});
6856

6957
expect(result).toStrictEqual({
7058
accessibilityState: { selected: false },
7159
});
7260
});
7361

7462
test('removes accessibilityState if all keys are undefined', () => {
75-
const result = defaultMapProps(
76-
{ accessibilityState: { checked: undefined, selected: undefined } },
77-
node
78-
);
63+
const result = defaultMapProps({
64+
accessibilityState: { checked: undefined, selected: undefined },
65+
});
7966

8067
expect(result).toStrictEqual({});
8168
});
8269

8370
test('does not fail if accessibilityState is a string, passes through', () => {
84-
const result = defaultMapProps({ accessibilityState: 'foo' }, node);
71+
const result = defaultMapProps({ accessibilityState: 'foo' });
8572
expect(result).toStrictEqual({ accessibilityState: 'foo' });
8673
});
8774

8875
test('does not fail if accessibilityState is an array, passes through', () => {
89-
const result = defaultMapProps({ accessibilityState: [1] }, node);
76+
const result = defaultMapProps({ accessibilityState: [1] });
9077
expect(result).toStrictEqual({ accessibilityState: [1] });
9178
});
9279

9380
test('does not fail if accessibilityState is null, passes through', () => {
94-
const result = defaultMapProps({ accessibilityState: null }, node);
81+
const result = defaultMapProps({ accessibilityState: null });
9582
expect(result).toStrictEqual({ accessibilityState: null });
9683
});
9784

9885
test('does not fail if accessibilityState is nested object, passes through', () => {
9986
const accessibilityState = { 1: { 2: 3 }, 2: undefined };
100-
const result = defaultMapProps({ accessibilityState }, node);
87+
const result = defaultMapProps({ accessibilityState });
10188
expect(result).toStrictEqual({ accessibilityState: { 1: { 2: 3 } } });
10289
});
10390

10491
test('removes undefined keys from accessibilityValue', () => {
105-
const result = defaultMapProps(
106-
{ accessibilityValue: { min: 1, max: undefined } },
107-
node
108-
);
92+
const result = defaultMapProps({
93+
accessibilityValue: { min: 1, max: undefined },
94+
});
10995

11096
expect(result).toStrictEqual({ accessibilityValue: { min: 1 } });
11197
});
11298

11399
test('removes accessibilityValue if all keys are undefined', () => {
114-
const result = defaultMapProps(
115-
{ accessibilityValue: { min: undefined } },
116-
node
117-
);
100+
const result = defaultMapProps({ accessibilityValue: { min: undefined } });
118101

119102
expect(result).toStrictEqual({});
120103
});

src/helpers/format-default.ts

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { StyleSheet, ViewStyle } from 'react-native';
2-
import { MapPropsFunction } from './format';
32

43
const propsToDisplay = [
4+
'accessible',
55
'accessibilityElementsHidden',
66
'accessibilityHint',
77
'accessibilityLabel',
@@ -24,17 +24,20 @@ const propsToDisplay = [
2424
'testID',
2525
'title',
2626
'value',
27-
];
27+
] as const;
2828

2929
/**
3030
* Preserve props that are helpful in diagnosing test failures, while stripping rest
3131
*/
32-
export const defaultMapProps: MapPropsFunction = (props) => {
32+
export function defaultMapProps(
33+
props: Record<string, unknown>
34+
): Record<string, unknown> {
3335
const result: Record<string, unknown> = {};
3436

3537
const styles = StyleSheet.flatten(props.style as ViewStyle);
36-
if (styles?.display === 'none') {
37-
result.style = { display: 'none' };
38+
const styleToDisplay = extractStyle(styles);
39+
if (styleToDisplay !== undefined) {
40+
result.style = styleToDisplay;
3841
}
3942

4043
const accessibilityState = removeUndefinedKeys(props.accessibilityState);
@@ -54,7 +57,7 @@ export const defaultMapProps: MapPropsFunction = (props) => {
5457
});
5558

5659
return result;
57-
};
60+
}
5861

5962
function isObject(value: unknown): value is Record<string, unknown> {
6063
return typeof value === 'object' && value !== null && !Array.isArray(value);
@@ -65,17 +68,32 @@ function removeUndefinedKeys(prop: unknown) {
6568
return prop;
6669
}
6770

71+
let hasKeys = false;
6872
const result: Record<string, unknown> = {};
6973
Object.entries(prop).forEach(([key, value]) => {
7074
if (value !== undefined) {
7175
result[key] = value;
76+
hasKeys = true;
7277
}
7378
});
7479

75-
// If object does not have any props we will ignore it.
76-
if (Object.keys(result).length === 0) {
80+
return hasKeys ? result : undefined;
81+
}
82+
83+
function extractStyle(style: ViewStyle | undefined) {
84+
if (style == null) {
7785
return undefined;
7886
}
7987

80-
return result;
88+
const result: Record<string, unknown> = {};
89+
if (style.display === 'none') {
90+
result.display = 'none';
91+
}
92+
93+
if (style.opacity === 0) {
94+
result.opacity = 0;
95+
}
96+
97+
const hasAnyKeys = Object.keys(result).length > 0;
98+
return hasAnyKeys ? result : undefined;
8199
}

0 commit comments

Comments
 (0)