@unif/react-native-design 0.23.1 → 0.24.1
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/README.md +2 -0
- package/jest-preset.js +62 -0
- package/jest-resolver.js +31 -0
- package/jest-setup.js +49 -0
- package/package.json +8 -1
package/README.md
CHANGED
|
@@ -131,6 +131,8 @@ decode 仍按 `example/README.md` 的 Android/iOS 手工矩阵标记为待执行
|
|
|
131
131
|
## 文档
|
|
132
132
|
|
|
133
133
|
- **文档站**(快速开始 · 组件 API · 设计令牌 · 设计原则):https://unif-design.github.io/react-native-design/
|
|
134
|
+
- **在宿主工程里测试**(一行接入 `@unif/react-native-design/jest-preset`):
|
|
135
|
+
https://unif-design.github.io/react-native-design/docs/testing
|
|
134
136
|
- **AI / LLM**(纯 Markdown,按需 fetch,别凭记忆猜 API):
|
|
135
137
|
[llms.txt 索引](https://unif-design.github.io/react-native-design/llms.txt) · [llms-full.txt 全文](https://unif-design.github.io/react-native-design/llms-full.txt)
|
|
136
138
|
- **Agent Skill** `design`(`unif` plugin,覆盖组件 API、token 规则、与原生 RN 的关键差异):
|
package/jest-preset.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `@unif/react-native-design/jest-preset` —— RN 官方 preset + 本库需要的
|
|
5
|
+
* resolver / transform 放行清单 / setup 接线。消费者:
|
|
6
|
+
*
|
|
7
|
+
* module.exports = { preset: '@unif/react-native-design/jest-preset' };
|
|
8
|
+
*
|
|
9
|
+
* 需要再放行别的包时,spread 本 preset 的 transformIgnorePatterns[0] 后自行追加。
|
|
10
|
+
* 前提:消费者装有 @react-native/jest-preset(RN 应用测试的既有 devDependency)。
|
|
11
|
+
*
|
|
12
|
+
* 注意 package.json#exports 里那条看着重复的 `"./jest-preset/jest-preset"` 别名:
|
|
13
|
+
* jest 解析 `preset` 时只豁免以 `.` 开头(部分版本另豁免绝对路径)的说明符,其余
|
|
14
|
+
* 一律拼上 `/jest-preset`(jest-config normalize.js 的 `PRESET_NAME`)。所以上面那行
|
|
15
|
+
* 文档化用法实际要解析的是 `@unif/react-native-design/jest-preset/jest-preset`。
|
|
16
|
+
* 删掉别名,消费者会直接吃到
|
|
17
|
+
* `Validation Error: Module ... should have "jest-preset.js" or "jest-preset.json" file at the root.`
|
|
18
|
+
*
|
|
19
|
+
* 下面那段 try/catch 就是为了不让「漏装 @react-native/jest-preset」也塌进同一句报错:
|
|
20
|
+
* jest-config 捕获 preset 模块抛出的 MODULE_NOT_FOUND 后,只判 error.message 里有没有
|
|
21
|
+
* preset 路径,而 Node 的 Require stack 恰好带着本文件路径 —— 裸 require 的真因
|
|
22
|
+
* (`Cannot find module '@react-native/jest-preset'`)会被换成上面那句畸形 Validation
|
|
23
|
+
* Error。改抛一个不带 MODULE_NOT_FOUND code 的错误,jest-config 就走
|
|
24
|
+
* `An unknown error occurred in <path>: <message>` 分支,下面这句话原样透出。
|
|
25
|
+
* 于是两个成因彻底分开:漏装有专属报错,Validation Error 只剩别名缺失一个成因。
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
let reactNativePreset;
|
|
29
|
+
try {
|
|
30
|
+
reactNativePreset = require('@react-native/jest-preset');
|
|
31
|
+
} catch (error) {
|
|
32
|
+
// 只认「@react-native/jest-preset 自己没装」这一种 MODULE_NOT_FOUND:它装了但内部
|
|
33
|
+
// 依赖断裂时抛的也是这个 code,那时报「需要自行安装」是误诊,会把人引向装了又装。
|
|
34
|
+
// Node 的 MODULE_NOT_FOUND 正文首行是 `Cannot find module '<说明符>'`,带引号的模块名
|
|
35
|
+
// 就是判据 —— 后面的 Require stack 只有裸路径,不会误命中。
|
|
36
|
+
if (
|
|
37
|
+
error &&
|
|
38
|
+
error.code === 'MODULE_NOT_FOUND' &&
|
|
39
|
+
String(error.message).includes("'@react-native/jest-preset'")
|
|
40
|
+
) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
'@unif/react-native-design/jest-preset 需要宿主工程自行安装 @react-native/jest-preset' +
|
|
43
|
+
'(它不是本包的依赖):yarn add -D @react-native/jest-preset'
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = {
|
|
50
|
+
...reactNativePreset,
|
|
51
|
+
// 组合 resolver:worklets 的 .native.* 过滤 + RN 官方的 exports 剥离,见该文件注释。
|
|
52
|
+
resolver: require.resolve('./jest-resolver.js'),
|
|
53
|
+
setupFilesAfterEnv: [
|
|
54
|
+
...(reactNativePreset.setupFilesAfterEnv ?? []),
|
|
55
|
+
require.resolve('./jest-setup.js'),
|
|
56
|
+
],
|
|
57
|
+
// 本库与这些 peer 都发 ESM / TS 源码,RN preset 默认只放行
|
|
58
|
+
// react-native / @react-native / @react-native-community 三个前缀。
|
|
59
|
+
transformIgnorePatterns: [
|
|
60
|
+
'node_modules/(?!((jest-)?react-native|@react-native(-community)?|@unif/react-native-design|@sbaiahmed1/react-native-blur|react-native-(gesture-handler|reanimated|worklets|safe-area-context|svg|reanimated-carousel))/)',
|
|
61
|
+
],
|
|
62
|
+
};
|
package/jest-resolver.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 组合两个上游 resolver —— 二者缺一都会静默坏掉一类场景:
|
|
5
|
+
*
|
|
6
|
+
* - RN 官方 resolver(`@react-native/jest-preset/jest/resolver.js`,该包无
|
|
7
|
+
* exports 字段,子路径 require 合法):临时剥掉 react-native 的 package
|
|
8
|
+
* exports,jest 才能解析 / mock 其深路径(如消费仓在 mock 的
|
|
9
|
+
* `react-native/Libraries/Utilities/Dimensions`)。
|
|
10
|
+
* - worklets 官方 resolver(`react-native-worklets/jest/resolver`)的语义:
|
|
11
|
+
* 对 worklets 相关请求过滤 .native.* extension,让 jest 走 web 实现,
|
|
12
|
+
* 不触发 native init。
|
|
13
|
+
*
|
|
14
|
+
* jest 的 config `resolver` 是标量,直接写 worklets 的会把 RN 的顶掉,
|
|
15
|
+
* 所以把 worklets 的 extension 过滤内联在这里,再委托给 RN 的 resolver。
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const reactNativeResolver = require('@react-native/jest-preset/jest/resolver.js');
|
|
19
|
+
|
|
20
|
+
module.exports = (request, options) => {
|
|
21
|
+
if (
|
|
22
|
+
options.basedir.includes('react-native-worklets') ||
|
|
23
|
+
request.includes('react-native-worklets')
|
|
24
|
+
) {
|
|
25
|
+
options = {
|
|
26
|
+
...options,
|
|
27
|
+
extensions: options.extensions?.filter((ext) => !ext.includes('native')),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return reactNativeResolver(request, options);
|
|
31
|
+
};
|
package/jest-setup.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/* global jest */
|
|
2
|
+
// ↑ 根 eslint flat config 不给非测试目录注入 jest 全局,显式声明,否则 yarn lint 报 no-undef。
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `@unif/react-native-design/jest-setup` —— 把本库 9 个 runtime peer 里在 Jest 中
|
|
7
|
+
* 需要接线的那 4 个接上各自的**官方**桩 / mock / setup。放进消费者的
|
|
8
|
+
* `setupFilesAfterEnv`。(4 个里只有 3 个换了替身,reanimated 走真实模块。)
|
|
9
|
+
*
|
|
10
|
+
* 为什么由库提供:这份接线完全由本库的 peer 集决定,peer range 一变它就得变。
|
|
11
|
+
* 让每个消费仓自己推导的结果是 5 个仓 5 种写法、3 个仓各自踩同一个坑
|
|
12
|
+
* (见 docs/specs/2026-08-05-jest-setup-entry-design.md §1)。
|
|
13
|
+
*
|
|
14
|
+
* `transformIgnorePatterns` 是 resolver 层配置,进不了 setup 文件 —— 那部分在
|
|
15
|
+
* `./jest-preset.js`。
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// RNGH 官方 jest 桩:让 TurboModuleRegistry.getEnforcing('RNGestureHandlerModule') 不炸。
|
|
19
|
+
require('react-native-gesture-handler/jestSetup');
|
|
20
|
+
|
|
21
|
+
// worklets 的 native 侧在 Jest 里不存在,直接 import 会在 `loadUnpackersWithCode` 处崩。
|
|
22
|
+
jest.mock('react-native-worklets', () =>
|
|
23
|
+
require('react-native-worklets/lib/module/mock')
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
// safe-area 官方 mock:零 inset + 透传 Provider。不接的话 SafeAreaProvider 子树整棵不渲染。
|
|
27
|
+
jest.mock(
|
|
28
|
+
'react-native-safe-area-context',
|
|
29
|
+
() => require('react-native-safe-area-context/jest/mock').default
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// RNGH 3 的包根 Pressable 与 GestureDetector 换成不依赖手势的壳。
|
|
33
|
+
// Jest 不触发真实手势,壳不损失可验证行为;保留它们,消费者的用例才不必
|
|
34
|
+
// 每一个都包一层 GestureHandlerRootView(否则 RNGH 3 会抛
|
|
35
|
+
// "GestureDetector must be used as a descendant of GestureHandlerRootView")。
|
|
36
|
+
// 其余导出走真实实现。
|
|
37
|
+
jest.mock('react-native-gesture-handler', () => ({
|
|
38
|
+
...jest.requireActual('react-native-gesture-handler'),
|
|
39
|
+
Pressable: require('react-native').Pressable,
|
|
40
|
+
GestureDetector: ({ children }) => children,
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
// reanimated 走**真实模块** + 官方 setUpTests。
|
|
44
|
+
// 不要映射到 `react-native-reanimated/mock`:那是上游刻意残缺的便利 mock
|
|
45
|
+
// (src/mock.ts 里 19 处 `ADD ME IF NEEDED`),缺 useReducedMotion(本库
|
|
46
|
+
// usePrefersReducedMotion 直接调)与 useComposedEventHandler(RNGH 3 Pressable 要用),
|
|
47
|
+
// 且它的 useSharedValue 每次 render 返回新 Proxy,会让把 shared value 放进 effect
|
|
48
|
+
// 依赖数组的组件(本库 ToastHost)在 fake timers 下堆内存耗尽。
|
|
49
|
+
require('react-native-reanimated').setUpTests();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unif/react-native-design",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.1",
|
|
4
4
|
"description": "Unif 设计系统:theme + icons + utils + components",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -14,12 +14,18 @@
|
|
|
14
14
|
"default": "./lib/module/index.js"
|
|
15
15
|
},
|
|
16
16
|
"./package.json": "./package.json",
|
|
17
|
+
"./jest-setup": "./jest-setup.js",
|
|
18
|
+
"./jest-preset": "./jest-preset.js",
|
|
19
|
+
"./jest-preset/jest-preset": "./jest-preset.js",
|
|
17
20
|
"./docs-home.css": "./docs-home.css"
|
|
18
21
|
},
|
|
19
22
|
"files": [
|
|
20
23
|
"src",
|
|
21
24
|
"lib",
|
|
22
25
|
"docs-home.css",
|
|
26
|
+
"jest-setup.js",
|
|
27
|
+
"jest-preset.js",
|
|
28
|
+
"jest-resolver.js",
|
|
23
29
|
"android",
|
|
24
30
|
"ios",
|
|
25
31
|
"cpp",
|
|
@@ -46,6 +52,7 @@
|
|
|
46
52
|
"test": "jest --passWithNoTests",
|
|
47
53
|
"check:config": "node scripts/check-config.js",
|
|
48
54
|
"check:icons": "node scripts/check-icons-generated.js",
|
|
55
|
+
"check:jest-entries": "node scripts/check-jest-entries.js",
|
|
49
56
|
"check:runtime-peers": "node scripts/check-runtime-peers.js",
|
|
50
57
|
"verify:example-showcase": "node --test scripts/__tests__/verify-example-showcase.test.mjs && node scripts/verify-example-showcase.mjs",
|
|
51
58
|
"create:runtime-harness": "node scripts/create-runtime-api-harness.js",
|