@react-native-ama/core 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{core/src/components → components}/AMAProvider.js +1 -2
- package/dist/{core/src/index.js → index.js} +3 -3
- package/package.json +31 -6
- package/src/components/AMAProvider.d.ts +26 -0
- package/src/components/AMAProvider.integration.test.tsx +145 -0
- package/src/components/AMAProvider.js +147 -0
- package/src/components/AMAProvider.test.tsx +199 -0
- package/src/components/AMAProvider.tsx +229 -0
- package/src/components/AutofocusContainer.d.ts +9 -0
- package/src/components/AutofocusContainer.js +58 -0
- package/src/components/AutofocusContainer.test.tsx +69 -0
- package/src/components/AutofocusContainer.tsx +43 -0
- package/src/components/HideChildrenFromAccessibilityTree.d.ts +6 -0
- package/src/components/HideChildrenFromAccessibilityTree.js +40 -0
- package/src/components/HideChildrenFromAccessibilityTree.test.tsx +129 -0
- package/src/components/HideChildrenFromAccessibilityTree.tsx +55 -0
- package/src/hooks/useButtonChecks.d.ts +8 -0
- package/src/hooks/useButtonChecks.js +51 -0
- package/src/hooks/useButtonChecks.ts +73 -0
- package/src/hooks/useChecks.d.ts +15 -0
- package/src/hooks/useChecks.js +152 -0
- package/src/hooks/useChecks.test.ts +214 -0
- package/src/hooks/useChecks.ts +207 -0
- package/src/hooks/useFocus.d.ts +4 -0
- package/{dist/internal/src/utils/maybeGenerateStringFromElement.js → src/hooks/useFocus.js} +26 -22
- package/src/hooks/useFocus.test.ts +99 -0
- package/src/hooks/useFocus.ts +42 -0
- package/src/hooks/useTimedAction.android.test.ts +39 -0
- package/src/hooks/useTimedAction.d.ts +3 -0
- package/src/hooks/useTimedAction.ios.test.ts +46 -0
- package/src/hooks/useTimedAction.js +63 -0
- package/src/hooks/useTimedAction.ts +40 -0
- package/src/index.d.ts +7 -0
- package/src/index.js +20 -0
- package/src/index.ts +16 -0
- package/src/utils/numerify.test.ts +11 -0
- package/src/utils/numerify.ts +3 -0
- package/dist/internal/src/checks/checkAccessibilityRole.d.ts +0 -3
- package/dist/internal/src/checks/checkAccessibilityRole.js +0 -32
- package/dist/internal/src/checks/checkFocusTrap.d.ts +0 -8
- package/dist/internal/src/checks/checkFocusTrap.js +0 -34
- package/dist/internal/src/checks/checkForAccessibilityState.d.ts +0 -7
- package/dist/internal/src/checks/checkForAccessibilityState.js +0 -48
- package/dist/internal/src/checks/checkMinimumSize.d.ts +0 -3
- package/dist/internal/src/checks/checkMinimumSize.js +0 -29
- package/dist/internal/src/checks/contrastChecker.d.ts +0 -8
- package/dist/internal/src/checks/contrastChecker.js +0 -77
- package/dist/internal/src/checks/noUndefinedProperty.d.ts +0 -8
- package/dist/internal/src/checks/noUndefinedProperty.js +0 -14
- package/dist/internal/src/checks/uppercaseChecker.d.ts +0 -9
- package/dist/internal/src/checks/uppercaseChecker.js +0 -18
- package/dist/internal/src/checks/uppercaseStringChecker.d.ts +0 -8
- package/dist/internal/src/checks/uppercaseStringChecker.js +0 -29
- package/dist/internal/src/index.d.ts +0 -20
- package/dist/internal/src/index.js +0 -56
- package/dist/internal/src/types.d.ts +0 -17
- package/dist/internal/src/types.js +0 -2
- package/dist/internal/src/utils/applyStyle.d.ts +0 -10
- package/dist/internal/src/utils/applyStyle.js +0 -33
- package/dist/internal/src/utils/constants.d.ts +0 -3
- package/dist/internal/src/utils/constants.js +0 -32
- package/dist/internal/src/utils/error.style.d.ts +0 -6
- package/dist/internal/src/utils/error.style.js +0 -11
- package/dist/internal/src/utils/generateAccessibilityStateFromProp.d.ts +0 -9
- package/dist/internal/src/utils/generateAccessibilityStateFromProp.js +0 -35
- package/dist/internal/src/utils/getPropertyFromStyle.d.ts +0 -2
- package/dist/internal/src/utils/getPropertyFromStyle.js +0 -10
- package/dist/internal/src/utils/interpolateAnimationStates.d.ts +0 -2
- package/dist/internal/src/utils/interpolateAnimationStates.js +0 -43
- package/dist/internal/src/utils/isFocused.d.ts +0 -2
- package/dist/internal/src/utils/isFocused.js +0 -7
- package/dist/internal/src/utils/logger.d.ts +0 -16
- package/dist/internal/src/utils/logger.js +0 -53
- package/dist/internal/src/utils/logger.rules.d.ts +0 -15
- package/dist/internal/src/utils/logger.rules.js +0 -74
- package/dist/internal/src/utils/maybeGenerateStringFromElement.d.ts +0 -3
- package/dist/internal/src/utils/minimumTouchableSize.d.ts +0 -3
- package/dist/internal/src/utils/minimumTouchableSize.js +0 -9
- package/dist/{core/src/components → components}/AMAProvider.d.ts +0 -0
- package/dist/{core/src/components → components}/AutofocusContainer.d.ts +0 -0
- package/dist/{core/src/components → components}/AutofocusContainer.js +0 -0
- package/dist/{core/src/components → components}/HideChildrenFromAccessibilityTree.d.ts +0 -0
- package/dist/{core/src/components → components}/HideChildrenFromAccessibilityTree.js +0 -0
- package/dist/{core/src/hooks → hooks}/useButtonChecks.d.ts +0 -0
- package/dist/{core/src/hooks → hooks}/useButtonChecks.js +0 -0
- package/dist/{core/src/hooks → hooks}/useChecks.d.ts +0 -0
- package/dist/{core/src/hooks → hooks}/useChecks.js +0 -0
- package/dist/{core/src/hooks → hooks}/useFocus.d.ts +0 -0
- package/dist/{core/src/hooks → hooks}/useFocus.js +0 -0
- package/dist/{core/src/hooks → hooks}/useTimedAction.d.ts +0 -0
- package/dist/{core/src/hooks → hooks}/useTimedAction.js +0 -0
- package/dist/{core/src/index.d.ts → index.d.ts} +1 -1
- /package/dist/{core/src/utils → utils}/numerify.d.ts +0 -0
- /package/dist/{core/src/utils → utils}/numerify.js +0 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useButtonChecks = void 0;
|
|
4
|
+
const internal_1 = require("@react-native-ama/internal");
|
|
5
|
+
const useChecks_1 = require("./useChecks");
|
|
6
|
+
exports.useButtonChecks = __DEV__
|
|
7
|
+
? (props, children, shouldPerformContrastCheck = true) => {
|
|
8
|
+
const checks = (0, useChecks_1.useChecks)();
|
|
9
|
+
if (checks === null) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
const { noUndefinedProperty, contrastChecker, onLayout, noUppercaseStringChecker, checkCompatibleAccessibilityState, checkAccessibilityRole, debugStyle, } = checks;
|
|
13
|
+
let style = props.style || {};
|
|
14
|
+
const isAccessible = props.accessible !== false;
|
|
15
|
+
isAccessible &&
|
|
16
|
+
noUndefinedProperty({
|
|
17
|
+
properties: props,
|
|
18
|
+
property: 'accessibilityRole',
|
|
19
|
+
rule: 'NO_ACCESSIBILITY_ROLE',
|
|
20
|
+
});
|
|
21
|
+
isAccessible &&
|
|
22
|
+
noUndefinedProperty({
|
|
23
|
+
properties: props,
|
|
24
|
+
property: 'accessibilityLabel',
|
|
25
|
+
rule: 'NO_ACCESSIBILITY_LABEL',
|
|
26
|
+
});
|
|
27
|
+
isAccessible &&
|
|
28
|
+
noUppercaseStringChecker({
|
|
29
|
+
text: props.accessibilityLabel,
|
|
30
|
+
});
|
|
31
|
+
checkCompatibleAccessibilityState({
|
|
32
|
+
accessibilityStates: props === null || props === void 0 ? void 0 : props.accessibilityState,
|
|
33
|
+
accessibilityRole: props === null || props === void 0 ? void 0 : props.accessiblityRole,
|
|
34
|
+
});
|
|
35
|
+
checkAccessibilityRole(props.accessibilityRole);
|
|
36
|
+
const contrastCheckerCallback = shouldPerformContrastCheck
|
|
37
|
+
? contrastChecker
|
|
38
|
+
: undefined;
|
|
39
|
+
const theStyle = internal_1.applyStyle === null || internal_1.applyStyle === void 0 ? void 0 : (0, internal_1.applyStyle)({
|
|
40
|
+
style,
|
|
41
|
+
debugStyle,
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
children,
|
|
44
|
+
contrastCheckerCallback,
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
onLayout,
|
|
48
|
+
debugStyle: theStyle,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
: null;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { applyStyle } from '@react-native-ama/internal';
|
|
2
|
+
import type React from 'react';
|
|
3
|
+
import type { PressableStateCallbackType } from 'react-native';
|
|
4
|
+
|
|
5
|
+
import { useChecks } from './useChecks';
|
|
6
|
+
|
|
7
|
+
export const useButtonChecks = __DEV__
|
|
8
|
+
? (
|
|
9
|
+
props: Record<string, any>,
|
|
10
|
+
children?:
|
|
11
|
+
| React.ReactNode
|
|
12
|
+
| ((state: PressableStateCallbackType) => React.ReactNode)
|
|
13
|
+
| undefined,
|
|
14
|
+
shouldPerformContrastCheck: boolean = true,
|
|
15
|
+
) => {
|
|
16
|
+
const checks = useChecks();
|
|
17
|
+
if (checks === null) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const {
|
|
21
|
+
noUndefinedProperty,
|
|
22
|
+
contrastChecker,
|
|
23
|
+
onLayout,
|
|
24
|
+
noUppercaseStringChecker,
|
|
25
|
+
checkCompatibleAccessibilityState,
|
|
26
|
+
checkAccessibilityRole,
|
|
27
|
+
debugStyle,
|
|
28
|
+
} = checks;
|
|
29
|
+
|
|
30
|
+
let style = props.style || {};
|
|
31
|
+
|
|
32
|
+
const isAccessible = props.accessible !== false;
|
|
33
|
+
|
|
34
|
+
isAccessible &&
|
|
35
|
+
noUndefinedProperty({
|
|
36
|
+
properties: props,
|
|
37
|
+
property: 'accessibilityRole',
|
|
38
|
+
rule: 'NO_ACCESSIBILITY_ROLE',
|
|
39
|
+
});
|
|
40
|
+
isAccessible &&
|
|
41
|
+
noUndefinedProperty({
|
|
42
|
+
properties: props,
|
|
43
|
+
property: 'accessibilityLabel',
|
|
44
|
+
rule: 'NO_ACCESSIBILITY_LABEL',
|
|
45
|
+
});
|
|
46
|
+
isAccessible &&
|
|
47
|
+
noUppercaseStringChecker({
|
|
48
|
+
text: props.accessibilityLabel,
|
|
49
|
+
});
|
|
50
|
+
checkCompatibleAccessibilityState({
|
|
51
|
+
accessibilityStates: props?.accessibilityState,
|
|
52
|
+
accessibilityRole: props?.accessiblityRole,
|
|
53
|
+
});
|
|
54
|
+
checkAccessibilityRole(props.accessibilityRole);
|
|
55
|
+
|
|
56
|
+
const contrastCheckerCallback = shouldPerformContrastCheck
|
|
57
|
+
? contrastChecker
|
|
58
|
+
: undefined;
|
|
59
|
+
|
|
60
|
+
const theStyle = applyStyle?.({
|
|
61
|
+
style,
|
|
62
|
+
debugStyle,
|
|
63
|
+
// @ts-ignore
|
|
64
|
+
children,
|
|
65
|
+
contrastCheckerCallback,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
onLayout,
|
|
70
|
+
debugStyle: theStyle,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
: null;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { LogParams, type CheckFocusTrap, type ContrastChecker, type NoUndefinedProperty, type UppercaseChecker, type UppercaseStringChecker } from '@react-native-ama/internal';
|
|
2
|
+
import { AccessibilityRole, LayoutChangeEvent } from 'react-native';
|
|
3
|
+
export declare const useChecks: () => {
|
|
4
|
+
logResult: (name: string, result: LogParams | LogParams[] | null) => Record<string, any>;
|
|
5
|
+
noUndefinedProperty: <T>(params: NoUndefinedProperty<T>) => Record<string, any>;
|
|
6
|
+
contrastChecker: (params: ContrastChecker) => Record<string, any>;
|
|
7
|
+
onLayout: (event: LayoutChangeEvent) => void;
|
|
8
|
+
noUppercaseStringChecker: (params: UppercaseStringChecker) => Record<string, any>;
|
|
9
|
+
uppercaseChecker: (params: UppercaseChecker) => Record<string, any>;
|
|
10
|
+
checkFocusTrap: (params: CheckFocusTrap) => void;
|
|
11
|
+
minimumSizeFailed: boolean;
|
|
12
|
+
checkCompatibleAccessibilityState: (props: Record<string, any>) => void;
|
|
13
|
+
checkAccessibilityRole: (param: AccessibilityRole) => void;
|
|
14
|
+
debugStyle: any;
|
|
15
|
+
} | null;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.useChecks = void 0;
|
|
27
|
+
const internal_1 = require("@react-native-ama/internal");
|
|
28
|
+
const React = __importStar(require("react"));
|
|
29
|
+
const react_native_1 = require("react-native");
|
|
30
|
+
const AMAProvider_1 = require("../components/AMAProvider");
|
|
31
|
+
const useChecks = () => {
|
|
32
|
+
const context = (0, AMAProvider_1.useAMAContext)();
|
|
33
|
+
if (!(0, AMAProvider_1.isDevContextValue)(context)) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Because the AMA Error view cannot be removed by default, this hacky solution
|
|
38
|
+
* allows the dev to hide it if all the issues have been solved.
|
|
39
|
+
*/
|
|
40
|
+
const fakeRandom = React.useRef('' + Date.now() + Math.random() * 42);
|
|
41
|
+
const hasErrors = React.useRef(false);
|
|
42
|
+
const failedTests = React.useRef([]);
|
|
43
|
+
const shouldCheckLayout = React.useRef(true);
|
|
44
|
+
const layoutCheckTimeout = React.useRef();
|
|
45
|
+
const [minimumSizeFailed, setMinimumSizeFailed] = React.useState(false);
|
|
46
|
+
const [debugStyle, setDebugStyle] = React.useState({});
|
|
47
|
+
const { trackError, removeError } = context;
|
|
48
|
+
const logResult = (name, result) => {
|
|
49
|
+
const index = failedTests.current.indexOf(name);
|
|
50
|
+
if (result === null) {
|
|
51
|
+
if (index >= 0 && hasErrors.current) {
|
|
52
|
+
failedTests.current.splice(index);
|
|
53
|
+
hasErrors.current = false;
|
|
54
|
+
react_native_1.InteractionManager.runAfterInteractions(() => {
|
|
55
|
+
removeError(fakeRandom.current);
|
|
56
|
+
setTimeout(() => {
|
|
57
|
+
setDebugStyle({});
|
|
58
|
+
}, 100);
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const results = Array.isArray(result) ? result : [result];
|
|
63
|
+
results.forEach(logParam => {
|
|
64
|
+
if (logParam === null) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const action = internal_1.getRuleAction === null || internal_1.getRuleAction === void 0 ? void 0 : (0, internal_1.getRuleAction)(logParam.rule);
|
|
68
|
+
const hasFailed = action === 'MUST_NOT' || action === 'MUST';
|
|
69
|
+
if (index < 0) {
|
|
70
|
+
// @ts-ignore
|
|
71
|
+
internal_1.logFailure === null || internal_1.logFailure === void 0 ? void 0 : (0, internal_1.logFailure)(Object.assign({ action }, logParam));
|
|
72
|
+
}
|
|
73
|
+
if (!hasFailed) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
else if (index >= 0) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
failedTests.current.push(name);
|
|
80
|
+
react_native_1.InteractionManager.runAfterInteractions(() => {
|
|
81
|
+
trackError(fakeRandom.current);
|
|
82
|
+
setDebugStyle(internal_1.ERROR_STYLE);
|
|
83
|
+
});
|
|
84
|
+
hasErrors.current = true;
|
|
85
|
+
});
|
|
86
|
+
// @ts-ignore
|
|
87
|
+
return hasErrors.current ? internal_1.ERROR_STYLE : {};
|
|
88
|
+
};
|
|
89
|
+
const noUndefinedProperty = (params) => logResult(`noUndefinedProperty ${params.property}`, (0, internal_1.noUndefinedProperty)(params));
|
|
90
|
+
const contrastChecker = (params) => logResult('contrastChecker', (0, internal_1.contrastChecker)(params));
|
|
91
|
+
const checkMinimumSize = (params) => {
|
|
92
|
+
return logResult('checkMinimumSize', (0, internal_1.checkMinimumSize)(params));
|
|
93
|
+
};
|
|
94
|
+
const noUppercaseStringChecker = (params) => logResult('accessibilityLabelChecker', (0, internal_1.uppercaseStringChecker)(params));
|
|
95
|
+
const uppercaseChecker = (params) => logResult('uppercaseChecker', (0, internal_1.uppercaseChecker)(params));
|
|
96
|
+
const checkFocusTrap = (params) => {
|
|
97
|
+
(0, internal_1.checkFocusTrap)(params).then(result => {
|
|
98
|
+
logResult('checkFocusTrap', result);
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
const checkAccessibilityRole = (param) => {
|
|
102
|
+
logResult('checkAccessibilityRole', (0, internal_1.checkAccessibilityRole)(param));
|
|
103
|
+
};
|
|
104
|
+
const checkCompatibleAccessibilityState = (props) => {
|
|
105
|
+
const amaStates = ['checked', 'selected'];
|
|
106
|
+
const params = {
|
|
107
|
+
accessibilityRole: props.accessibilityRole,
|
|
108
|
+
accessibilityState: props === null || props === void 0 ? void 0 : props.accessibilityState,
|
|
109
|
+
};
|
|
110
|
+
amaStates.forEach(amaState => {
|
|
111
|
+
if (amaState in props) {
|
|
112
|
+
// @ts-ignore
|
|
113
|
+
params[amaState] = props[amaState];
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
logResult('checkCompatibleAccessibilityState', (0, internal_1.checkForAccessibilityState)(params));
|
|
117
|
+
};
|
|
118
|
+
const onLayout = (event) => {
|
|
119
|
+
/**
|
|
120
|
+
* When the check fails there are situation when adding a border makes the
|
|
121
|
+
* component meet the minimum size requirement, and this causes a loop as the
|
|
122
|
+
* state is update continuously between true and false.
|
|
123
|
+
* To "avoid" that we wait at least 100ms before checking the size again, as
|
|
124
|
+
* this gives the dev time to hot-reload the changes.
|
|
125
|
+
*/
|
|
126
|
+
if (!shouldCheckLayout.current) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
shouldCheckLayout.current = false;
|
|
130
|
+
// @ts-ignore
|
|
131
|
+
clearTimeout(layoutCheckTimeout.current);
|
|
132
|
+
layoutCheckTimeout.current = setTimeout(() => {
|
|
133
|
+
shouldCheckLayout.current = true;
|
|
134
|
+
}, 1000);
|
|
135
|
+
const result = checkMinimumSize(event);
|
|
136
|
+
setMinimumSizeFailed(Object.keys(result).length > 0);
|
|
137
|
+
};
|
|
138
|
+
return {
|
|
139
|
+
logResult,
|
|
140
|
+
noUndefinedProperty,
|
|
141
|
+
contrastChecker,
|
|
142
|
+
onLayout,
|
|
143
|
+
noUppercaseStringChecker,
|
|
144
|
+
uppercaseChecker,
|
|
145
|
+
checkFocusTrap,
|
|
146
|
+
minimumSizeFailed,
|
|
147
|
+
checkCompatibleAccessibilityState,
|
|
148
|
+
checkAccessibilityRole,
|
|
149
|
+
debugStyle,
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
exports.useChecks = useChecks;
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { type RuleAction } from '@react-native-ama/internal';
|
|
2
|
+
import * as CheckForAccessibilityRole from '@react-native-ama/internal/src/checks/checkAccessibilityRole';
|
|
3
|
+
import * as CheckForAccessibilityState from '@react-native-ama/internal/src/checks/checkForAccessibilityState';
|
|
4
|
+
import * as Logger from '@react-native-ama/internal/src/utils/logger';
|
|
5
|
+
import { renderHook } from '@testing-library/react-native';
|
|
6
|
+
|
|
7
|
+
import * as AMAProvider from '../components/AMAProvider';
|
|
8
|
+
import { useChecks } from './useChecks';
|
|
9
|
+
|
|
10
|
+
const trackError = jest.fn();
|
|
11
|
+
const removeError = jest.fn();
|
|
12
|
+
|
|
13
|
+
beforeEach(() => {
|
|
14
|
+
jest.clearAllMocks();
|
|
15
|
+
|
|
16
|
+
jest.spyOn(console, 'warn').mockImplementation();
|
|
17
|
+
jest.spyOn(console, 'error').mockImplementation();
|
|
18
|
+
jest.spyOn(console, 'info').mockImplementation();
|
|
19
|
+
|
|
20
|
+
jest.spyOn(AMAProvider, 'useAMAContext').mockReturnValue({
|
|
21
|
+
trackError,
|
|
22
|
+
removeError,
|
|
23
|
+
} as any);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('useChecks', () => {
|
|
27
|
+
it.each(['MUST_NOT', 'MUST'])(
|
|
28
|
+
'tracks the error only if the rule is %s',
|
|
29
|
+
ruleValue => {
|
|
30
|
+
jest
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
.spyOn(Logger, 'getRuleAction')
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
.mockReturnValue(ruleValue as RuleAction);
|
|
35
|
+
|
|
36
|
+
const { result } = renderHook(() => useChecks());
|
|
37
|
+
|
|
38
|
+
result.current?.logResult('test-me', {
|
|
39
|
+
rule: 'NO_UNDEFINED',
|
|
40
|
+
extra: 'extra',
|
|
41
|
+
message: 'message',
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
expect(trackError).toHaveBeenCalledTimes(1);
|
|
45
|
+
expect(trackError).toHaveBeenCalledWith(expect.any(String));
|
|
46
|
+
},
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
it.each(['SHOULD', 'SHOULD_NOT'])(
|
|
50
|
+
'does not track the error if the rule is %s',
|
|
51
|
+
ruleValue => {
|
|
52
|
+
const spy = jest.spyOn(console, 'warn');
|
|
53
|
+
|
|
54
|
+
jest
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
.spyOn(Logger, 'getRuleAction')
|
|
57
|
+
// @ts-ignore
|
|
58
|
+
.mockReturnValue(ruleValue as RuleAction);
|
|
59
|
+
|
|
60
|
+
const { result } = renderHook(() => useChecks());
|
|
61
|
+
|
|
62
|
+
result.current?.logResult('test-me', {
|
|
63
|
+
rule: 'NO_UNDEFINED',
|
|
64
|
+
extra: 'extra',
|
|
65
|
+
message: 'message',
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
expect(trackError).not.toHaveBeenCalled();
|
|
69
|
+
|
|
70
|
+
expect(spy).toHaveBeenCalled();
|
|
71
|
+
},
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
it.each(['MUST_NOT', 'MUST'])(
|
|
75
|
+
'tracks the same error only once',
|
|
76
|
+
ruleValue => {
|
|
77
|
+
jest
|
|
78
|
+
// @ts-ignore
|
|
79
|
+
.spyOn(Logger, 'getRuleAction')
|
|
80
|
+
// @ts-ignore
|
|
81
|
+
.mockReturnValue(ruleValue as RuleAction);
|
|
82
|
+
|
|
83
|
+
const { result } = renderHook(() => useChecks());
|
|
84
|
+
|
|
85
|
+
result.current?.logResult('test-me', {
|
|
86
|
+
rule: 'NO_UNDEFINED',
|
|
87
|
+
extra: 'extra',
|
|
88
|
+
message: 'message',
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
expect(trackError).toHaveBeenCalledTimes(1);
|
|
92
|
+
|
|
93
|
+
trackError.mockClear();
|
|
94
|
+
|
|
95
|
+
result.current?.logResult('test-me', {
|
|
96
|
+
rule: 'NO_UNDEFINED',
|
|
97
|
+
extra: 'extra',
|
|
98
|
+
message: 'message',
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
expect(trackError).toHaveBeenCalledTimes(0);
|
|
102
|
+
},
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
it('removes the tracked error after has been fixed', () => {
|
|
106
|
+
// @ts-ignore
|
|
107
|
+
jest.spyOn(Logger, 'getRuleAction').mockReturnValue('MUST');
|
|
108
|
+
|
|
109
|
+
const { result } = renderHook(() => useChecks());
|
|
110
|
+
|
|
111
|
+
result.current?.logResult('test-me', {
|
|
112
|
+
rule: 'NO_UNDEFINED',
|
|
113
|
+
extra: 'extra',
|
|
114
|
+
message: 'message',
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
expect(trackError).toHaveBeenCalledWith(expect.any(String));
|
|
118
|
+
|
|
119
|
+
result.current?.logResult('test-me', null);
|
|
120
|
+
|
|
121
|
+
expect(removeError).toHaveBeenCalledWith(trackError.mock.calls[0][0]);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('checks for compatible accessibility state', () => {
|
|
125
|
+
const check = jest
|
|
126
|
+
.spyOn(CheckForAccessibilityState, 'checkForAccessibilityState')
|
|
127
|
+
.mockReturnValue(null);
|
|
128
|
+
const { result } = renderHook(() => useChecks());
|
|
129
|
+
|
|
130
|
+
result.current?.checkCompatibleAccessibilityState({
|
|
131
|
+
hello: 'world',
|
|
132
|
+
busy: true,
|
|
133
|
+
checked: 'wow',
|
|
134
|
+
accessibilityRole: 'button',
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
expect(check).toHaveBeenCalledWith({
|
|
138
|
+
accessibilityRole: 'button',
|
|
139
|
+
accessibilityState: undefined,
|
|
140
|
+
checked: 'wow',
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('checks for compatible accessibility state when accessibilityState is passed', () => {
|
|
145
|
+
const check = jest
|
|
146
|
+
.spyOn(CheckForAccessibilityState, 'checkForAccessibilityState')
|
|
147
|
+
.mockReturnValue(null);
|
|
148
|
+
const { result } = renderHook(() => useChecks());
|
|
149
|
+
|
|
150
|
+
result.current?.checkCompatibleAccessibilityState({
|
|
151
|
+
hello: 'world',
|
|
152
|
+
checked: false,
|
|
153
|
+
accessibilityState: {
|
|
154
|
+
selected: 'yeah',
|
|
155
|
+
},
|
|
156
|
+
accessibilityRole: 'button',
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
expect(check).toHaveBeenCalledWith({
|
|
160
|
+
accessibilityRole: 'button',
|
|
161
|
+
accessibilityState: {
|
|
162
|
+
selected: 'yeah',
|
|
163
|
+
},
|
|
164
|
+
checked: false,
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('checks for compatible accessibility role', () => {
|
|
169
|
+
const check = jest
|
|
170
|
+
.spyOn(CheckForAccessibilityRole, 'checkAccessibilityRole')
|
|
171
|
+
.mockReturnValue(null);
|
|
172
|
+
const { result } = renderHook(() => useChecks());
|
|
173
|
+
|
|
174
|
+
result.current?.checkAccessibilityRole('button');
|
|
175
|
+
|
|
176
|
+
expect(check).toHaveBeenCalledWith('button');
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
jest.mock('react-native', () => {
|
|
181
|
+
const ReactNative = jest.requireActual('react-native');
|
|
182
|
+
|
|
183
|
+
// Extend ReactNative
|
|
184
|
+
return Object.setPrototypeOf(
|
|
185
|
+
{
|
|
186
|
+
// Redefine an export, like a component
|
|
187
|
+
Button: 'Button',
|
|
188
|
+
// Mock out properties of an already mocked export
|
|
189
|
+
LayoutAnimation: {
|
|
190
|
+
...ReactNative.LayoutAnimation,
|
|
191
|
+
configureNext: jest.fn(),
|
|
192
|
+
},
|
|
193
|
+
Platform: {
|
|
194
|
+
...ReactNative.Platform,
|
|
195
|
+
OS: 'ios',
|
|
196
|
+
Version: 123,
|
|
197
|
+
isTesting: true,
|
|
198
|
+
select: (objs: { ios: any }) => objs.ios,
|
|
199
|
+
},
|
|
200
|
+
// Mock a native module
|
|
201
|
+
NativeModules: {
|
|
202
|
+
...ReactNative.NativeModules,
|
|
203
|
+
Override: { great: 'success' },
|
|
204
|
+
},
|
|
205
|
+
InteractionManager: {
|
|
206
|
+
// @ts-ignore
|
|
207
|
+
runAfterInteractions: callback => {
|
|
208
|
+
callback();
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
ReactNative,
|
|
213
|
+
);
|
|
214
|
+
});
|