組與帶類型簽名回調(diào)函數(shù)是如何被 Fake 的)
揭秘 react-fake-props 類型生成原理:嵌套對象、數(shù)組與帶類型簽名回調(diào)函數(shù)是如何被 Fake 的【免費(fèi)下載鏈接】react-fake-props Magically generate fake props for your React tests項目地址: https://gitcode.com/gh_mirrors/re/react-fake-propsreact-fake-props 是 React 測試中的假 props(mock props)自動生成工具:傳入組件文件路徑,它就能基于 TypeScript、Flow 或 PropTypes 的類型定義,遞歸產(chǎn)出一組可直接{...props}展開渲染的測試數(shù)據(jù)。本文拆解它的類型生成原理,重點(diǎn)看嵌套對象、數(shù)組、帶類型簽名的回調(diào)函數(shù)這三類深水區(qū)類型分別是如何被 Fake 的。一、react-fake-props 是什么:React 測試假 Props 自動生成工具 一句話:把組件的 props 類型讀出來,再按類型自動填上合理的假值,省去手寫測試數(shù)據(jù)。支持 3 種 props 類型系統(tǒng):TypeScript、Flow、PropTypes常與 Jest 快照測試、Enzyme 渲染配合使用默認(rèn)只生成必填 prop;傳{ optional: true }才連可選 prop 一起生成整個核心實(shí)現(xiàn)只有 280 多行,全部集中在src/index.js,這也是本文解剖的主角。二、整體流程:一次 fakeProps() 調(diào)用背后發(fā)生了什么流程分 3 步,入口是src/index.js的模塊導(dǎo)出函數(shù)(約 L259-L284):讀文件:fs.readFileSync讀取組件源碼;解析類型樹:交給 react-docgen 解析,得到每個 prop 的類型描述(tsType/flowType/ 普通 propTypes 描述);遞歸生成假值:fakeDataForProps()(L246-L257)遍歷頂層 prop,只處理required的(或開啟 optional 的),再交給分發(fā)函數(shù)。關(guān)鍵在于它維護(hù)了兩條并行的類型分發(fā)管線:類型系統(tǒng)分發(fā)函數(shù)分支依據(jù)PropTypesgetFakePropType()prop.type.nameFlow / TypeScriptgetFakeTyped()type.namegetFakeProp()(L240-L244)只做一件事:看這個 prop 有沒有flowType或tsType,有就走 Flow/TS 管線,沒有就走 PropTypes 管線。三套類型體系由此被統(tǒng)一到一個入口。三、嵌套對象是如何被 Fake 的:遞歸展開 路徑前綴TS / Flow:signature.properties 逐層拆開以fixtures/typescript/Component.tsx中的Person類型為例,person里又嵌套了address: Address、repos: ArrayRepo。react-docgen 解析后,每個具名類型都會變成帶signature.properties的結(jié)構(gòu),由fakeSignature()(L148-L192)的 object 分支處理:過濾出required(或 optional 開啟時全保留)的屬性;逐個遞歸調(diào)用getFakeTyped(prefix . prop.key, ...),一層層把Person → Address → Commit全部展開成真實(shí)對象。路徑前綴:字符串假值的指紋?fakeString()的返回值就是傳入的 prefix 本身,所以每個字符串 prop 的假值 它的完整點(diǎn)分路徑:person.address.street → person.address.street person.repos.url → person.repos.url這個設(shè)計有兩個好處:任意深度的字符串都天然唯一,快照對比時一眼能看出差異在哪一層;斷言時推薦寫props.person.name而不是硬編碼字符串,因?yàn)檩敵龈袷娇赡茈S版本變化(README 的 Tip 一節(jié)也是這么建議的)。PropTypes 的嵌套走getShape()(L30-L41),邏輯完全同構(gòu):遍歷 shape 的 key,按required || optional過濾,前綴拼接后遞歸。fixtures/propTypes/NestedShape.jsx的兩層嵌套shape,在快照里生成了requiredShape.nestedRequiredShape.optionalString這樣的值。四、數(shù)組是如何被 Fake 的:為什么永遠(yuǎn)只有一個元素數(shù)組的 Fake 策略出奇地一致——只放一個元素:聲明方式生成結(jié)果實(shí)現(xiàn)位置TSArrayRepo[{ url: ..., ... }]getFakeTyped()的Array分支(L213-L230)PropTypesarrayOf(shape(...))[ { 假對象 } ]getArrayOf()(L22-L24)無元素類型的裸數(shù)組[]fakeArray()(L51-L53)實(shí)現(xiàn)上,TS 的ArrayT解析后帶elements字段,代碼對每個元素類型遞歸getFakeTyped()生成數(shù)組。注意前綴跨數(shù)組時不加下標(biāo),所以ArrayRepo里元素的字符串前綴直接是person.repos,而不是person.repos[0]。為什么只要一個元素?對渲染測試來說,列表能畫出一項就足以覆蓋布局邏輯,輸出更簡潔、快照更穩(wěn)定。五、帶類型簽名的回調(diào)函數(shù):動態(tài)構(gòu)造一個真函數(shù)這是整個庫里最有意思的機(jī)制。普通PropTypes.func只會得到一個空函數(shù);但 TS/Flow 里聲明了簽名的回調(diào)(如getFriend?: (person: Person) Person),react-docgen 會解析出完整的signature(參數(shù)名列表 返回類型)。fakeTypedFunction()(L132-L146)就利用這一點(diǎn):從signature.arguments取出每個參數(shù)名;遞歸 Fake 出返回類型的完整假值,并JSON.stringify凍結(jié)成代碼文本;用Function.apply(null, [...參數(shù)名, return 凍結(jié)的返回值])動態(tài)構(gòu)造出一個真正可調(diào)用的函數(shù)。也就是說,生成 props 里的getFriend不是擺設(shè):調(diào)用allProps.getFriend()真的會返回一個假Person,即{ name: getFriend.name, age: 1, ... }。注意返回對象里的字符串前綴用的是函數(shù)名getFriend,因?yàn)檫f歸時傳入的 prefix 就是這個 prop 的名字。__tests__/typescript.js里就有專門用例驗(yàn)證這一點(diǎn)(L25-L32)。若回調(diào)沒有類型簽名(比如 PropTypes 的func),則回退到fakeFunction(),返回一個什么都不做的空函數(shù),保證組件至少能正常渲染。六、optional 開關(guān)與兜底類型optional:默認(rèn)只 Fakerequired的 prop;傳{ optional: true }后,fakeDataForProps()、getShape()、fakeSignature()三處過濾條件都會放行可選字段,生成的對象會明顯變大。不支持的類型:instanceOf和 custom 校驗(yàn)器無法憑空造出合法實(shí)例,庫會生成一句人話提示,如instanceOf type not supported, please set the correct value for X prop,提醒手動補(bǔ)值(fakeInstanceOf()L75-L77、fakeCustom()L83-L85)。all: true:一個文件導(dǎo)出多個組件時,改用 react-docgen 的findAllComponentDefinitions解析器,返回{ displayName, props }數(shù)組,連未導(dǎo)出的組件也能拿到(L263-L276)。七、關(guān)鍵文件導(dǎo)航 想動手驗(yàn)證,這幾個文件值得一看:src/index.js—— 核心實(shí)現(xiàn):類型分發(fā)、遞歸生成、動態(tài)函數(shù)構(gòu)造全在這里fixtures/typescript/Component.tsx—— 嵌套對象 數(shù)組 簽名回調(diào)的完整示例類型fixtures/propTypes/NestedShape.jsx—— PropTypes 嵌套 shape 示例__tests__/typescript.js—— 斷言getFriend()返回值、前綴命名等行為的測試__tests__/__snapshots__/typescript.js.snap—— 完整的 Fake 輸出快照,直接看效果README.md—— API 與使用建議(含props.A斷言技巧)一句話總結(jié):react-fake-props 的類型生成 用 react-docgen 拿到類型樹 雙管線遞歸分發(fā) 路徑前綴命名 數(shù)組只留一個元素 動態(tài)構(gòu)造簽名函數(shù),用 280 行代碼覆蓋了 TS、Flow、PropTypes 三條體系的深水區(qū)?!久赓M(fèi)下載鏈接】react-fake-props Magically generate fake props for your React tests項目地址: https://gitcode.com/gh_mirrors/re/react-fake-props創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考