@multiplatform.one/frappe-ui 7.11.0 → 7.15.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.
Files changed (341) hide show
  1. package/README.md +2 -2
  2. package/dist/cjs/FrappeDashboard.cjs +8 -10
  3. package/dist/cjs/FrappeDashboard.native.js +8 -14
  4. package/dist/cjs/FrappeDashboard.native.js.map +1 -1
  5. package/dist/cjs/FrappeForm.cjs +465 -175
  6. package/dist/cjs/FrappeForm.native.js +611 -207
  7. package/dist/cjs/FrappeForm.native.js.map +1 -1
  8. package/dist/cjs/FrappeFormConnections.cjs +125 -0
  9. package/dist/cjs/FrappeFormConnections.native.js +149 -0
  10. package/dist/cjs/FrappeFormConnections.native.js.map +1 -0
  11. package/dist/cjs/FrappeImageView.cjs +7 -9
  12. package/dist/cjs/FrappeImageView.native.js +7 -13
  13. package/dist/cjs/FrappeImageView.native.js.map +1 -1
  14. package/dist/cjs/FrappeList.cjs +29 -4
  15. package/dist/cjs/FrappeList.native.js +37 -5
  16. package/dist/cjs/FrappeList.native.js.map +1 -1
  17. package/dist/cjs/FrappeListView.cjs +102 -29
  18. package/dist/cjs/FrappeListView.native.js +109 -29
  19. package/dist/cjs/FrappeListView.native.js.map +1 -1
  20. package/dist/cjs/FrappeProvider.cjs +7 -2
  21. package/dist/cjs/FrappeProvider.native.js +7 -2
  22. package/dist/cjs/FrappeProvider.native.js.map +1 -1
  23. package/dist/cjs/FrappeReportBuilder.cjs +10 -11
  24. package/dist/cjs/FrappeReportBuilder.native.js +10 -16
  25. package/dist/cjs/FrappeReportBuilder.native.js.map +1 -1
  26. package/dist/cjs/FrappeRowsReader.cjs +49 -0
  27. package/dist/cjs/FrappeRowsReader.native.js +53 -0
  28. package/dist/cjs/FrappeRowsReader.native.js.map +1 -0
  29. package/dist/cjs/FrappeTable.cjs +18 -6
  30. package/dist/cjs/FrappeTable.native.js +24 -6
  31. package/dist/cjs/FrappeTable.native.js.map +1 -1
  32. package/dist/cjs/fieldRegistry.cjs +36 -11
  33. package/dist/cjs/fieldRegistry.native.js +59 -11
  34. package/dist/cjs/fieldRegistry.native.js.map +1 -1
  35. package/dist/cjs/fields/Date/index.native.js +5 -2
  36. package/dist/cjs/fields/Date/index.native.js.map +1 -1
  37. package/dist/cjs/fields/Date/sheetKeyboard.cjs +2 -2
  38. package/dist/cjs/fields/Date/sheetKeyboard.native.js +2 -2
  39. package/dist/cjs/fields/Date/sheetKeyboard.native.js.map +1 -1
  40. package/dist/cjs/fields/DateRange/index.cjs +2 -1
  41. package/dist/cjs/fields/DateRange/index.native.js +4 -1
  42. package/dist/cjs/fields/DateRange/index.native.js.map +1 -1
  43. package/dist/cjs/formEngine/index.cjs +4 -2
  44. package/dist/cjs/formEngine/index.native.js +3 -1
  45. package/dist/cjs/formEngine/index.native.js.map +1 -1
  46. package/dist/cjs/formEngine/useSessionRoles.cjs +77 -0
  47. package/dist/cjs/formEngine/useSessionRoles.native.js +84 -0
  48. package/dist/cjs/formEngine/useSessionRoles.native.js.map +1 -0
  49. package/dist/cjs/frappeConnections.cjs +41 -0
  50. package/dist/cjs/frappeConnections.native.js +50 -0
  51. package/dist/cjs/frappeConnections.native.js.map +1 -0
  52. package/dist/cjs/frappeNavigation.cjs +107 -0
  53. package/dist/cjs/frappeNavigation.native.js +112 -0
  54. package/dist/cjs/frappeNavigation.native.js.map +1 -0
  55. package/dist/cjs/index.cjs +18 -1
  56. package/dist/cjs/index.native.js +18 -1
  57. package/dist/cjs/index.native.js.map +1 -1
  58. package/dist/cjs/schemaForm/index.cjs +4 -1
  59. package/dist/cjs/schemaForm/index.native.js +4 -1
  60. package/dist/cjs/schemaForm/index.native.js.map +1 -1
  61. package/dist/cjs/useConnectionFilters.cjs +146 -0
  62. package/dist/cjs/useConnectionFilters.native.js +213 -0
  63. package/dist/cjs/useConnectionFilters.native.js.map +1 -0
  64. package/dist/cjs/useFrappePagination.cjs +37 -18
  65. package/dist/cjs/useFrappePagination.native.js +59 -23
  66. package/dist/cjs/useFrappePagination.native.js.map +1 -1
  67. package/dist/cjs/useFrappeRows.native.js.map +1 -1
  68. package/dist/esm/FrappeDashboard.mjs +9 -11
  69. package/dist/esm/FrappeDashboard.mjs.map +1 -1
  70. package/dist/esm/FrappeDashboard.native.js +9 -15
  71. package/dist/esm/FrappeDashboard.native.js.map +1 -1
  72. package/dist/esm/FrappeForm.mjs +471 -181
  73. package/dist/esm/FrappeForm.mjs.map +1 -1
  74. package/dist/esm/FrappeForm.native.js +599 -195
  75. package/dist/esm/FrappeForm.native.js.map +1 -1
  76. package/dist/esm/FrappeFormConnections.mjs +99 -0
  77. package/dist/esm/FrappeFormConnections.mjs.map +1 -0
  78. package/dist/esm/FrappeFormConnections.native.js +120 -0
  79. package/dist/esm/FrappeFormConnections.native.js.map +1 -0
  80. package/dist/esm/FrappeImageView.mjs +8 -10
  81. package/dist/esm/FrappeImageView.mjs.map +1 -1
  82. package/dist/esm/FrappeImageView.native.js +8 -14
  83. package/dist/esm/FrappeImageView.native.js.map +1 -1
  84. package/dist/esm/FrappeList.mjs +31 -6
  85. package/dist/esm/FrappeList.mjs.map +1 -1
  86. package/dist/esm/FrappeList.native.js +39 -7
  87. package/dist/esm/FrappeList.native.js.map +1 -1
  88. package/dist/esm/FrappeListView.mjs +103 -30
  89. package/dist/esm/FrappeListView.mjs.map +1 -1
  90. package/dist/esm/FrappeListView.native.js +110 -30
  91. package/dist/esm/FrappeListView.native.js.map +1 -1
  92. package/dist/esm/FrappeProvider.mjs +7 -2
  93. package/dist/esm/FrappeProvider.mjs.map +1 -1
  94. package/dist/esm/FrappeProvider.native.js +7 -2
  95. package/dist/esm/FrappeProvider.native.js.map +1 -1
  96. package/dist/esm/FrappeReportBuilder.mjs +11 -12
  97. package/dist/esm/FrappeReportBuilder.mjs.map +1 -1
  98. package/dist/esm/FrappeReportBuilder.native.js +11 -17
  99. package/dist/esm/FrappeReportBuilder.native.js.map +1 -1
  100. package/dist/esm/FrappeRowsReader.mjs +24 -0
  101. package/dist/esm/FrappeRowsReader.mjs.map +1 -0
  102. package/dist/esm/FrappeRowsReader.native.js +25 -0
  103. package/dist/esm/FrappeRowsReader.native.js.map +1 -0
  104. package/dist/esm/FrappeTable.mjs +18 -6
  105. package/dist/esm/FrappeTable.mjs.map +1 -1
  106. package/dist/esm/FrappeTable.native.js +24 -6
  107. package/dist/esm/FrappeTable.native.js.map +1 -1
  108. package/dist/esm/fieldRegistry.mjs +35 -12
  109. package/dist/esm/fieldRegistry.mjs.map +1 -1
  110. package/dist/esm/fieldRegistry.native.js +58 -12
  111. package/dist/esm/fieldRegistry.native.js.map +1 -1
  112. package/dist/esm/fields/Date/index.native.js +6 -3
  113. package/dist/esm/fields/Date/index.native.js.map +1 -1
  114. package/dist/esm/fields/Date/sheetKeyboard.mjs +2 -2
  115. package/dist/esm/fields/Date/sheetKeyboard.mjs.map +1 -1
  116. package/dist/esm/fields/Date/sheetKeyboard.native.js +2 -2
  117. package/dist/esm/fields/Date/sheetKeyboard.native.js.map +1 -1
  118. package/dist/esm/fields/DateRange/index.mjs +2 -1
  119. package/dist/esm/fields/DateRange/index.mjs.map +1 -1
  120. package/dist/esm/fields/DateRange/index.native.js +4 -1
  121. package/dist/esm/fields/DateRange/index.native.js.map +1 -1
  122. package/dist/esm/formEngine/index.mjs +2 -1
  123. package/dist/esm/formEngine/index.mjs.map +1 -1
  124. package/dist/esm/formEngine/index.native.js +2 -1
  125. package/dist/esm/formEngine/index.native.js.map +1 -1
  126. package/dist/esm/formEngine/useSessionRoles.mjs +52 -0
  127. package/dist/esm/formEngine/useSessionRoles.mjs.map +1 -0
  128. package/dist/esm/formEngine/useSessionRoles.native.js +56 -0
  129. package/dist/esm/formEngine/useSessionRoles.native.js.map +1 -0
  130. package/dist/esm/frappeConnections.mjs +15 -0
  131. package/dist/esm/frappeConnections.mjs.map +1 -0
  132. package/dist/esm/frappeConnections.native.js +21 -0
  133. package/dist/esm/frappeConnections.native.js.map +1 -0
  134. package/dist/esm/frappeNavigation.mjs +78 -0
  135. package/dist/esm/frappeNavigation.mjs.map +1 -0
  136. package/dist/esm/frappeNavigation.native.js +80 -0
  137. package/dist/esm/frappeNavigation.native.js.map +1 -0
  138. package/dist/esm/index.mjs +7 -3
  139. package/dist/esm/index.mjs.map +1 -1
  140. package/dist/esm/index.native.js +7 -3
  141. package/dist/esm/index.native.js.map +1 -1
  142. package/dist/esm/schemaForm/index.mjs +4 -1
  143. package/dist/esm/schemaForm/index.mjs.map +1 -1
  144. package/dist/esm/schemaForm/index.native.js +4 -1
  145. package/dist/esm/schemaForm/index.native.js.map +1 -1
  146. package/dist/esm/useConnectionFilters.mjs +121 -0
  147. package/dist/esm/useConnectionFilters.mjs.map +1 -0
  148. package/dist/esm/useConnectionFilters.native.js +185 -0
  149. package/dist/esm/useConnectionFilters.native.js.map +1 -0
  150. package/dist/esm/useFrappePagination.mjs +38 -19
  151. package/dist/esm/useFrappePagination.mjs.map +1 -1
  152. package/dist/esm/useFrappePagination.native.js +60 -24
  153. package/dist/esm/useFrappePagination.native.js.map +1 -1
  154. package/dist/esm/useFrappeRows.mjs.map +1 -1
  155. package/dist/esm/useFrappeRows.native.js.map +1 -1
  156. package/dist/jsx/FrappeDashboard.mjs +9 -11
  157. package/dist/jsx/FrappeDashboard.mjs.map +1 -1
  158. package/dist/jsx/FrappeDashboard.native.js +8 -14
  159. package/dist/jsx/FrappeDashboard.native.js.map +1 -1
  160. package/dist/jsx/FrappeForm.mjs +471 -181
  161. package/dist/jsx/FrappeForm.mjs.map +1 -1
  162. package/dist/jsx/FrappeForm.native.js +611 -207
  163. package/dist/jsx/FrappeForm.native.js.map +1 -1
  164. package/dist/jsx/FrappeFormConnections.mjs +99 -0
  165. package/dist/jsx/FrappeFormConnections.mjs.map +1 -0
  166. package/dist/jsx/FrappeFormConnections.native.js +149 -0
  167. package/dist/jsx/FrappeFormConnections.native.js.map +1 -0
  168. package/dist/jsx/FrappeImageView.mjs +8 -10
  169. package/dist/jsx/FrappeImageView.mjs.map +1 -1
  170. package/dist/jsx/FrappeImageView.native.js +7 -13
  171. package/dist/jsx/FrappeImageView.native.js.map +1 -1
  172. package/dist/jsx/FrappeList.mjs +31 -6
  173. package/dist/jsx/FrappeList.mjs.map +1 -1
  174. package/dist/jsx/FrappeList.native.js +37 -5
  175. package/dist/jsx/FrappeList.native.js.map +1 -1
  176. package/dist/jsx/FrappeListView.mjs +103 -30
  177. package/dist/jsx/FrappeListView.mjs.map +1 -1
  178. package/dist/jsx/FrappeListView.native.js +109 -29
  179. package/dist/jsx/FrappeListView.native.js.map +1 -1
  180. package/dist/jsx/FrappeProvider.mjs +7 -2
  181. package/dist/jsx/FrappeProvider.mjs.map +1 -1
  182. package/dist/jsx/FrappeProvider.native.js +7 -2
  183. package/dist/jsx/FrappeProvider.native.js.map +1 -1
  184. package/dist/jsx/FrappeReportBuilder.mjs +11 -12
  185. package/dist/jsx/FrappeReportBuilder.mjs.map +1 -1
  186. package/dist/jsx/FrappeReportBuilder.native.js +10 -16
  187. package/dist/jsx/FrappeReportBuilder.native.js.map +1 -1
  188. package/dist/jsx/FrappeRowsReader.mjs +24 -0
  189. package/dist/jsx/FrappeRowsReader.mjs.map +1 -0
  190. package/dist/jsx/FrappeRowsReader.native.js +53 -0
  191. package/dist/jsx/FrappeRowsReader.native.js.map +1 -0
  192. package/dist/jsx/FrappeTable.mjs +18 -6
  193. package/dist/jsx/FrappeTable.mjs.map +1 -1
  194. package/dist/jsx/FrappeTable.native.js +24 -6
  195. package/dist/jsx/FrappeTable.native.js.map +1 -1
  196. package/dist/jsx/fieldRegistry.mjs +35 -12
  197. package/dist/jsx/fieldRegistry.mjs.map +1 -1
  198. package/dist/jsx/fieldRegistry.native.js +59 -11
  199. package/dist/jsx/fieldRegistry.native.js.map +1 -1
  200. package/dist/jsx/fields/Date/index.native.js +5 -2
  201. package/dist/jsx/fields/Date/index.native.js.map +1 -1
  202. package/dist/jsx/fields/Date/sheetKeyboard.mjs +2 -2
  203. package/dist/jsx/fields/Date/sheetKeyboard.mjs.map +1 -1
  204. package/dist/jsx/fields/Date/sheetKeyboard.native.js +2 -2
  205. package/dist/jsx/fields/Date/sheetKeyboard.native.js.map +1 -1
  206. package/dist/jsx/fields/DateRange/index.mjs +2 -1
  207. package/dist/jsx/fields/DateRange/index.mjs.map +1 -1
  208. package/dist/jsx/fields/DateRange/index.native.js +4 -1
  209. package/dist/jsx/fields/DateRange/index.native.js.map +1 -1
  210. package/dist/jsx/formEngine/index.mjs +2 -1
  211. package/dist/jsx/formEngine/index.mjs.map +1 -1
  212. package/dist/jsx/formEngine/index.native.js +3 -1
  213. package/dist/jsx/formEngine/index.native.js.map +1 -1
  214. package/dist/jsx/formEngine/useSessionRoles.mjs +52 -0
  215. package/dist/jsx/formEngine/useSessionRoles.mjs.map +1 -0
  216. package/dist/jsx/formEngine/useSessionRoles.native.js +84 -0
  217. package/dist/jsx/formEngine/useSessionRoles.native.js.map +1 -0
  218. package/dist/jsx/frappeConnections.mjs +15 -0
  219. package/dist/jsx/frappeConnections.mjs.map +1 -0
  220. package/dist/jsx/frappeConnections.native.js +50 -0
  221. package/dist/jsx/frappeConnections.native.js.map +1 -0
  222. package/dist/jsx/frappeNavigation.mjs +78 -0
  223. package/dist/jsx/frappeNavigation.mjs.map +1 -0
  224. package/dist/jsx/frappeNavigation.native.js +112 -0
  225. package/dist/jsx/frappeNavigation.native.js.map +1 -0
  226. package/dist/jsx/index.js +7 -3
  227. package/dist/jsx/index.js.map +1 -1
  228. package/dist/jsx/index.mjs +7 -3
  229. package/dist/jsx/index.mjs.map +1 -1
  230. package/dist/jsx/index.native.js +18 -1
  231. package/dist/jsx/index.native.js.map +1 -1
  232. package/dist/jsx/schemaForm/index.mjs +4 -1
  233. package/dist/jsx/schemaForm/index.mjs.map +1 -1
  234. package/dist/jsx/schemaForm/index.native.js +4 -1
  235. package/dist/jsx/schemaForm/index.native.js.map +1 -1
  236. package/dist/jsx/useConnectionFilters.mjs +121 -0
  237. package/dist/jsx/useConnectionFilters.mjs.map +1 -0
  238. package/dist/jsx/useConnectionFilters.native.js +213 -0
  239. package/dist/jsx/useConnectionFilters.native.js.map +1 -0
  240. package/dist/jsx/useFrappePagination.mjs +38 -19
  241. package/dist/jsx/useFrappePagination.mjs.map +1 -1
  242. package/dist/jsx/useFrappePagination.native.js +59 -23
  243. package/dist/jsx/useFrappePagination.native.js.map +1 -1
  244. package/dist/jsx/useFrappeRows.mjs.map +1 -1
  245. package/dist/jsx/useFrappeRows.native.js.map +1 -1
  246. package/package.json +24 -20
  247. package/src/FileBrowser/AttachLibrary.stories.tsx +23 -0
  248. package/src/FrappeDashboard.tsx +11 -16
  249. package/src/FrappeForm.connections.spec.tsx +280 -0
  250. package/src/FrappeForm.connections.stories.tsx +93 -0
  251. package/src/FrappeForm.deskSemantics.spec.tsx +284 -0
  252. package/src/FrappeForm.tsx +560 -145
  253. package/src/FrappeFormConnections.tsx +148 -0
  254. package/src/FrappeGuestMeta.spec.tsx +143 -0
  255. package/src/FrappeImageView.tsx +8 -12
  256. package/src/FrappeList.tsx +71 -15
  257. package/src/FrappeListView.cards.spec.tsx +175 -0
  258. package/src/FrappeListView.cards.stories.tsx +131 -0
  259. package/src/FrappeListView.connections.spec.tsx +192 -0
  260. package/src/FrappeListView.connections.stories.tsx +99 -0
  261. package/src/FrappeListView.seed.spec.tsx +228 -0
  262. package/src/FrappeListView.tsx +177 -31
  263. package/src/FrappeProvider.tsx +13 -1
  264. package/src/FrappeReportBuilder.tsx +11 -19
  265. package/src/FrappeRowsReader.tsx +38 -0
  266. package/src/FrappeTable.optionalProps.spec.tsx +249 -0
  267. package/src/FrappeTable.spec.tsx +32 -42
  268. package/src/FrappeTable.stories.spec.tsx +55 -0
  269. package/src/FrappeTable.stories.tsx +28 -37
  270. package/src/FrappeTable.tsx +108 -45
  271. package/src/childTableDependsOn.spec.tsx +85 -0
  272. package/src/desk/DeskFormSidebar.spec.tsx +20 -0
  273. package/src/desk/DeskFormSidebar.stories.tsx +42 -0
  274. package/src/fieldRegistry.spec.tsx +27 -64
  275. package/src/fieldRegistry.ts +71 -14
  276. package/src/fields/Date/index.native.tsx +4 -2
  277. package/src/fields/Date/sheetKeyboard.spec.ts +14 -5
  278. package/src/fields/Date/sheetKeyboard.ts +12 -4
  279. package/src/fields/DateRange/DateRange.spec.tsx +67 -0
  280. package/src/fields/DateRange/index.tsx +5 -1
  281. package/src/fields/LinkTree.spec.tsx +8 -0
  282. package/src/fields/LinkTree.stories.tsx +28 -5
  283. package/src/fields/Select/Select.hydration.spec.tsx +177 -0
  284. package/src/formEngine/doctypeMeta.ts +15 -114
  285. package/src/formEngine/index.ts +2 -0
  286. package/src/formEngine/seam.spec.ts +23 -4
  287. package/src/formEngine/useSessionRoles.ts +73 -0
  288. package/src/frappeConnections.ts +50 -0
  289. package/src/frappeNavigation.tsx +112 -0
  290. package/src/frappeRoutes.spec.tsx +335 -0
  291. package/src/index.ts +28 -1
  292. package/src/schemaForm/index.tsx +1 -0
  293. package/src/useConnectionFilters.tsx +157 -0
  294. package/src/useFrappePagination.ts +70 -26
  295. package/src/useFrappeRows.sharedPath.spec.tsx +206 -0
  296. package/src/useFrappeRows.ts +5 -4
  297. package/types/FrappeDashboard.d.ts +3 -4
  298. package/types/FrappeDashboard.d.ts.map +1 -1
  299. package/types/FrappeForm.d.ts +57 -5
  300. package/types/FrappeForm.d.ts.map +1 -1
  301. package/types/FrappeFormConnections.d.ts +18 -0
  302. package/types/FrappeFormConnections.d.ts.map +1 -0
  303. package/types/FrappeImageView.d.ts +2 -3
  304. package/types/FrappeImageView.d.ts.map +1 -1
  305. package/types/FrappeList.d.ts +20 -2
  306. package/types/FrappeList.d.ts.map +1 -1
  307. package/types/FrappeListView.d.ts +53 -3
  308. package/types/FrappeListView.d.ts.map +1 -1
  309. package/types/FrappeProvider.d.ts +8 -1
  310. package/types/FrappeProvider.d.ts.map +1 -1
  311. package/types/FrappeReportBuilder.d.ts.map +1 -1
  312. package/types/FrappeRowsReader.d.ts +26 -0
  313. package/types/FrappeRowsReader.d.ts.map +1 -0
  314. package/types/FrappeTable.d.ts +39 -8
  315. package/types/FrappeTable.d.ts.map +1 -1
  316. package/types/fieldRegistry.d.ts +17 -3
  317. package/types/fieldRegistry.d.ts.map +1 -1
  318. package/types/fields/Date/index.native.d.ts.map +1 -1
  319. package/types/fields/Date/sheetKeyboard.d.ts +4 -3
  320. package/types/fields/Date/sheetKeyboard.d.ts.map +1 -1
  321. package/types/fields/DateRange/index.d.ts.map +1 -1
  322. package/types/formEngine/doctypeMeta.d.ts +10 -114
  323. package/types/formEngine/doctypeMeta.d.ts.map +1 -1
  324. package/types/formEngine/index.d.ts +1 -0
  325. package/types/formEngine/index.d.ts.map +1 -1
  326. package/types/formEngine/useSessionRoles.d.ts +19 -0
  327. package/types/formEngine/useSessionRoles.d.ts.map +1 -0
  328. package/types/frappeConnections.d.ts +33 -0
  329. package/types/frappeConnections.d.ts.map +1 -0
  330. package/types/frappeNavigation.d.ts +49 -0
  331. package/types/frappeNavigation.d.ts.map +1 -0
  332. package/types/index.d.ts +7 -3
  333. package/types/index.d.ts.map +1 -1
  334. package/types/schemaForm/index.d.ts.map +1 -1
  335. package/types/useConnectionFilters.d.ts +34 -0
  336. package/types/useConnectionFilters.d.ts.map +1 -0
  337. package/types/useFrappePagination.d.ts +18 -5
  338. package/types/useFrappePagination.d.ts.map +1 -1
  339. package/types/useFrappeRows.d.ts +5 -4
  340. package/types/useFrappeRows.d.ts.map +1 -1
  341. package/src/FileBrowser/AttachLibrary.spec.tsx +0 -74
@@ -0,0 +1,249 @@
1
+ /**
2
+ * FrappeTable's two props that read as optional and were not (MPO-230).
3
+ *
4
+ * `filterableFields`: omitted under a provider carrying fixtures, the meta
5
+ * read stays inside the corpus. A fixture host that also carries a baseURL
6
+ * (what a generated app has) used to dial getdoctype on every page and fail
7
+ * CORS; now nothing reaches the network, DocType entry in the corpus or not.
8
+ *
9
+ * `fields`: omitted on a bench read (serverSide, or client mode without
10
+ * fixtures), the request used to ask for `name` alone and every other column
11
+ * rendered blank with no error. Now it asks for the columns' accessor keys,
12
+ * and the derived list is content-keyed so an inline `columns` literal does
13
+ * not refetch every render. Client mode over a corpus still reads whole
14
+ * documents.
15
+ */
16
+
17
+ import { InMemoryFixtureProvider } from "@multiplatform.one/frappe";
18
+ import type { DataTableColumn } from "@multiplatform.one/table";
19
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
20
+ import { cleanup, screen, waitFor } from "@testing-library/react";
21
+ import i18next from "i18next";
22
+ import { initReactI18next } from "react-i18next";
23
+ import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
24
+ import { FrappeProvider } from "./FrappeProvider";
25
+ import { FrappeTable } from "./FrappeTable";
26
+
27
+ beforeAll(async () => {
28
+ await i18next.use(initReactI18next).init({
29
+ lng: "en",
30
+ interpolation: { escapeValue: false },
31
+ resources: { en: { translation: {} } },
32
+ });
33
+ });
34
+
35
+ afterEach(() => {
36
+ cleanup();
37
+ vi.restoreAllMocks();
38
+ });
39
+
40
+ interface Customer {
41
+ name: string;
42
+ doctype: string;
43
+ customer_name: string;
44
+ status: string;
45
+ }
46
+
47
+ const customers: Customer[] = [
48
+ { name: "CUST-001", doctype: "Customer", customer_name: "Acme Corp", status: "Active" },
49
+ { name: "CUST-002", doctype: "Customer", customer_name: "Globex", status: "Lead" },
50
+ ];
51
+
52
+ const columns: DataTableColumn<Partial<Customer>>[] = [
53
+ { id: "name", accessorKey: "name", header: "ID" },
54
+ { id: "customer_name", accessorKey: "customer_name", header: "Customer Name" },
55
+ { id: "status", accessorKey: "status", header: "Status" },
56
+ { id: "actions", header: "Actions", cell: () => null },
57
+ ];
58
+
59
+ function forbidFetch() {
60
+ return vi.spyOn(globalThis, "fetch").mockImplementation((input) => {
61
+ throw new Error(`unexpected network request: ${String(input)}`);
62
+ });
63
+ }
64
+
65
+ function pressRows(container: HTMLElement): HTMLElement[] {
66
+ return Array.from(container.querySelectorAll('[data-row-press="true"]')) as HTMLElement[];
67
+ }
68
+
69
+ describe("FrappeTable under a fixture corpus with a baseURL and no filterableFields", () => {
70
+ it("issues zero requests when the corpus has no DocType entry", async () => {
71
+ const fetchSpy = forbidFetch();
72
+ const { container } = renderWithProviders(
73
+ <FrappeProvider
74
+ baseURL="https://frappetable-optional.spec.test"
75
+ fixtures={new InMemoryFixtureProvider({ Customer: customers })}
76
+ >
77
+ <FrappeTable<Customer>
78
+ doctype="Customer"
79
+ columns={columns}
80
+ layout="table"
81
+ enablePagination={false}
82
+ onRowClick={() => {}}
83
+ />
84
+ </FrappeProvider>,
85
+ );
86
+
87
+ expect(await screen.findByText("Acme Corp")).toBeTruthy();
88
+ expect(await screen.findByText("Globex")).toBeTruthy();
89
+ // No meta: rows fall back to the document name for their label.
90
+ await waitFor(() => {
91
+ expect(pressRows(container).map((row) => row.getAttribute("aria-label"))).toEqual([
92
+ "CUST-001",
93
+ "CUST-002",
94
+ ]);
95
+ });
96
+ expect(fetchSpy).not.toHaveBeenCalled();
97
+ });
98
+
99
+ it("issues zero requests when the corpus carries the DocType, and reads whole documents", async () => {
100
+ const fetchSpy = forbidFetch();
101
+ const { container } = renderWithProviders(
102
+ <FrappeProvider
103
+ baseURL="https://frappetable-optional.spec.test"
104
+ fixtures={
105
+ new InMemoryFixtureProvider({
106
+ DocType: [
107
+ {
108
+ name: "Customer",
109
+ doctype: "DocType",
110
+ module: "Selling",
111
+ title_field: "customer_name",
112
+ fields: [
113
+ { fieldname: "customer_name", fieldtype: "Data", label: "Customer Name" },
114
+ { fieldname: "status", fieldtype: "Data", label: "Status" },
115
+ ],
116
+ permissions: [],
117
+ },
118
+ ],
119
+ Customer: customers,
120
+ })
121
+ }
122
+ >
123
+ <FrappeTable<Customer>
124
+ doctype="Customer"
125
+ columns={columns.filter((column) => column.id !== "customer_name")}
126
+ layout="table"
127
+ enablePagination={false}
128
+ onRowClick={() => {}}
129
+ />
130
+ </FrappeProvider>,
131
+ );
132
+
133
+ expect(await screen.findByText("Lead")).toBeTruthy();
134
+ // The title field is no column: its value labels the rows only because
135
+ // the corpus handed over whole documents.
136
+ await waitFor(() => {
137
+ expect(pressRows(container).map((row) => row.getAttribute("aria-label"))).toEqual([
138
+ "Acme Corp",
139
+ "Globex",
140
+ ]);
141
+ });
142
+ expect(fetchSpy).not.toHaveBeenCalled();
143
+ });
144
+ });
145
+
146
+ describe("FrappeTable serverSide with columns and no fields", () => {
147
+ const host = "https://frappetable-serverfields.spec.test";
148
+
149
+ function jsonResponse(body: unknown): Response {
150
+ return new Response(JSON.stringify(body), {
151
+ status: 200,
152
+ headers: { "Content-Type": "application/json" },
153
+ });
154
+ }
155
+
156
+ it("requests name plus every column accessor key, once", async () => {
157
+ const listRequests: URL[] = [];
158
+ vi.spyOn(globalThis, "fetch").mockImplementation((input) => {
159
+ const urlStr =
160
+ typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
161
+ const url = new URL(urlStr);
162
+ if (url.pathname === "/api/method/frappe.client.get_count") {
163
+ return Promise.resolve(jsonResponse({ message: customers.length }));
164
+ }
165
+ if (url.pathname === "/api/resource/Customer") {
166
+ listRequests.push(url);
167
+ return Promise.resolve(jsonResponse({ data: customers }));
168
+ }
169
+ throw new Error(`unexpected network request: ${urlStr}`);
170
+ });
171
+
172
+ renderWithProviders(
173
+ <FrappeProvider baseURL={host}>
174
+ <FrappeTable<Customer>
175
+ doctype="Customer"
176
+ columns={[...columns]}
177
+ filterableFields={[{ id: "status", label: "Status", type: "text" }]}
178
+ serverSide
179
+ layout="table"
180
+ initialState={{ pagination: { pageIndex: 0, pageSize: 10 } }}
181
+ />
182
+ </FrappeProvider>,
183
+ );
184
+
185
+ expect(await screen.findByText("Acme Corp")).toBeTruthy();
186
+ expect(await screen.findByText("Lead")).toBeTruthy();
187
+ expect(listRequests.length).toBe(1);
188
+ expect(JSON.parse(listRequests[0].searchParams.get("fields") ?? "[]")).toEqual([
189
+ "name",
190
+ "customer_name",
191
+ "status",
192
+ ]);
193
+
194
+ // The derived list is content-keyed: the post-load re-renders must not
195
+ // re-key the fetch and refetch.
196
+ await new Promise((resolve) => setTimeout(resolve, 300));
197
+ expect(listRequests.length).toBe(1);
198
+ });
199
+ });
200
+
201
+ describe("FrappeTable client mode against a bench with columns and no fields", () => {
202
+ const host = "https://frappetable-clientfields.spec.test";
203
+
204
+ it("subscribes with name plus every column accessor key", async () => {
205
+ const listRequests: URL[] = [];
206
+ vi.spyOn(globalThis, "fetch").mockImplementation((input) => {
207
+ const urlStr =
208
+ typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
209
+ const url = new URL(urlStr);
210
+ if (url.pathname === "/api/resource/Customer") {
211
+ listRequests.push(url);
212
+ const fields: string[] = JSON.parse(url.searchParams.get("fields") ?? '["name"]');
213
+ const projected = customers.map((doc) =>
214
+ Object.fromEntries(
215
+ fields.map((field) => [field, (doc as unknown as Record<string, unknown>)[field]]),
216
+ ),
217
+ );
218
+ return Promise.resolve(
219
+ new Response(JSON.stringify({ data: projected }), {
220
+ status: 200,
221
+ headers: { "Content-Type": "application/json" },
222
+ }),
223
+ );
224
+ }
225
+ throw new Error(`unexpected network request: ${urlStr}`);
226
+ });
227
+
228
+ renderWithProviders(
229
+ <FrappeProvider baseURL={host} realtime={false}>
230
+ <FrappeTable<Customer>
231
+ doctype="Customer"
232
+ columns={columns}
233
+ filterableFields={[{ id: "status", label: "Status", type: "text" }]}
234
+ layout="table"
235
+ enablePagination={false}
236
+ />
237
+ </FrappeProvider>,
238
+ );
239
+
240
+ // A bench answers a list read with no `fields` with `name` alone, so
241
+ // these cells render only because the request named the columns.
242
+ expect(await screen.findByText("Acme Corp")).toBeTruthy();
243
+ expect(await screen.findByText("Lead")).toBeTruthy();
244
+ expect(listRequests.length).toBeGreaterThan(0);
245
+ const requested: string[] = JSON.parse(listRequests[0].searchParams.get("fields") ?? "[]");
246
+ expect(requested).toEqual(expect.arrayContaining(["name", "customer_name", "status"]));
247
+ expect(requested).not.toContain("actions");
248
+ });
249
+ });
@@ -11,7 +11,7 @@
11
11
  * document name (DG-A11Y-06).
12
12
  *
13
13
  * Fixture-hermetic: documents ride InMemoryFixtureProvider; the one test
14
- * that needs doctype meta mocks the `getdoctype` fetch.
14
+ * that needs doctype meta carries it in the corpus's DocType entry.
15
15
  */
16
16
 
17
17
  import { InMemoryFixtureProvider } from "@multiplatform.one/frappe";
@@ -56,9 +56,9 @@ const columns: DataTableColumn<Partial<Customer>>[] = [
56
56
  { id: "status", accessorKey: "status", header: "Status" },
57
57
  ];
58
58
 
59
- // Explicit filterableFields skip the doctype-meta fetch (hermetic — same
60
- // contract DoctypeListScreen uses); the title-field test omits them and
61
- // mocks the meta endpoint instead.
59
+ // Explicit filterableFields skip the doctype-meta read (same contract
60
+ // DoctypeListScreen uses); the title-field test omits them and answers the
61
+ // read from the corpus instead.
62
62
  const filterFields = [{ id: "status", label: "Status", type: "text" as const }];
63
63
 
64
64
  function pressRows(container: HTMLElement): HTMLElement[] {
@@ -143,49 +143,38 @@ describe("FrappeTable onRowClick → DataTable onRowPress", () => {
143
143
  });
144
144
 
145
145
  it("labels rows by the doctype title-field value once meta loads", async () => {
146
- // Distinct host: useDocTypeMeta caches per `${baseURL}:${doctype}`.
147
- const metaHost = "https://frappetable-meta.spec.test";
148
- const realFetch = globalThis.fetch;
149
- vi.spyOn(globalThis, "fetch").mockImplementation(async (input: any, init?: any) => {
150
- const url =
151
- typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
152
- if (url.startsWith(metaHost)) {
153
- if (url.includes("/api/method/frappe.desk.form.load.getdoctype")) {
154
- return new Response(
155
- JSON.stringify({
156
- docs: [
157
- {
158
- name: "Customer",
159
- module: "Selling",
160
- title_field: "customer_name",
161
- fields: [
162
- {
163
- fieldname: "customer_name",
164
- fieldtype: "Data",
165
- label: "Customer Name",
166
- in_list_view: 1,
167
- },
168
- ],
169
- permissions: [],
170
- },
171
- ],
172
- }),
173
- { status: 200, headers: { "Content-Type": "application/json" } },
174
- );
175
- }
176
- return new Response(JSON.stringify({ data: [] }), {
177
- status: 200,
178
- headers: { "Content-Type": "application/json" },
179
- });
180
- }
181
- return realFetch(input, init);
146
+ // Meta comes from the corpus's DocType entry: a fixture host never dials
147
+ // getdoctype, whatever baseURL it carries (MPO-230).
148
+ const fetchSpy = vi.spyOn(globalThis, "fetch").mockImplementation((input) => {
149
+ throw new Error(`unexpected network request: ${String(input)}`);
182
150
  });
183
151
 
184
152
  const onRowClick = vi.fn();
185
153
  const { container } = renderWithProviders(
186
154
  <FrappeProvider
187
- baseURL={metaHost}
188
- fixtures={new InMemoryFixtureProvider({ Customer: customers })}
155
+ baseURL="https://frappetable-meta.spec.test"
156
+ fixtures={
157
+ new InMemoryFixtureProvider({
158
+ DocType: [
159
+ {
160
+ name: "Customer",
161
+ doctype: "DocType",
162
+ module: "Selling",
163
+ title_field: "customer_name",
164
+ fields: [
165
+ {
166
+ fieldname: "customer_name",
167
+ fieldtype: "Data",
168
+ label: "Customer Name",
169
+ in_list_view: 1,
170
+ },
171
+ ],
172
+ permissions: [],
173
+ },
174
+ ],
175
+ Customer: customers,
176
+ })
177
+ }
189
178
  >
190
179
  <FrappeTable<Customer>
191
180
  doctype="Customer"
@@ -205,6 +194,7 @@ describe("FrappeTable onRowClick → DataTable onRowPress", () => {
205
194
  "Initech",
206
195
  ]);
207
196
  });
197
+ expect(fetchSpy).not.toHaveBeenCalled();
208
198
  });
209
199
  });
210
200
 
@@ -0,0 +1,55 @@
1
+ /**
2
+ * FrappeTable's fixture stories carry a baseURL, and FrappeTable under a
3
+ * fixture corpus never dials it for meta (MPO-230), so their filter menu and
4
+ * title-field row labels exist only if the corpus carries the DocType entry.
5
+ */
6
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
7
+ import { cleanup, waitFor } from "@testing-library/react";
8
+ import i18next from "i18next";
9
+ import { initReactI18next } from "react-i18next";
10
+ import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
11
+ import { Default } from "./FrappeTable.stories";
12
+
13
+ vi.mock("@multiplatform.one/storybook", () => ({ action: () => vi.fn() }));
14
+
15
+ beforeAll(async () => {
16
+ await i18next.use(initReactI18next).init({
17
+ lng: "en",
18
+ interpolation: { escapeValue: false },
19
+ resources: { en: { translation: {} } },
20
+ });
21
+ });
22
+
23
+ afterEach(() => {
24
+ cleanup();
25
+ vi.restoreAllMocks();
26
+ });
27
+
28
+ const customerNames = new Set([
29
+ "Acme Corp",
30
+ "Global Tech",
31
+ "John Smith",
32
+ "Jane Doe",
33
+ "Tech Solutions",
34
+ "Startup Inc",
35
+ "Bob Wilson",
36
+ "Enterprise Ltd",
37
+ ]);
38
+
39
+ describe("FrappeTable stories", () => {
40
+ it("Main labels rows by the corpus meta's title field and issues no request", async () => {
41
+ const fetchSpy = vi.spyOn(globalThis, "fetch").mockImplementation((input) => {
42
+ throw new Error(`unexpected network request: ${String(input)}`);
43
+ });
44
+ const { container } = renderWithProviders(<Default />);
45
+
46
+ await waitFor(() => {
47
+ const labels = Array.from(container.querySelectorAll('[data-row-press="true"]')).map(
48
+ (row) => row.getAttribute("aria-label") ?? "",
49
+ );
50
+ expect(labels.length).toBeGreaterThan(0);
51
+ expect(labels.filter((label) => !customerNames.has(label))).toEqual([]);
52
+ });
53
+ expect(fetchSpy).not.toHaveBeenCalled();
54
+ });
55
+ });
@@ -15,7 +15,7 @@ export default {
15
15
  docs: {
16
16
  description: {
17
17
  component:
18
- "Table over useFrappeCollection / useLiveQuery (client) or Frappe REST (serverSide). Fixture stories are network-hermetic (G-15/D-05): documents come from InMemoryFixtureProvider and DocType meta from an in-story fetch mock, so nothing leaves the machine. The separately-named Live and ServerSide stories are the live-bench arm — they target STORYBOOK_FRAPPE_URL when reachable and fall back to fixtures otherwise.",
18
+ "Table over useFrappeCollection / useLiveQuery (client) or Frappe REST (serverSide). Fixture stories are network-hermetic (G-15/D-05): documents and DocType meta both come from InMemoryFixtureProvider, so nothing leaves the machine. The separately-named Live and ServerSide stories are the live-bench arm — they target STORYBOOK_FRAPPE_URL when reachable and fall back to fixtures otherwise.",
19
19
  },
20
20
  },
21
21
  },
@@ -24,13 +24,11 @@ export default {
24
24
  // ---------------------------------------------------------------------------
25
25
  // Hermetic story host (G-15 story honesty / D-05, closes UX-P18).
26
26
  //
27
- // Fixture-backed stories previously pointed at https://demo.frappe.cloud. The
28
- // fixture provider serves the *collection*, but FrappeTable still resolves
29
- // DocType meta over HTTP — so every one of those stories fired a real
30
- // cross-origin request that the browser rejected with a CORS error, poisoning
31
- // the console for every automated probe. MOCK_HOST keeps the same code path
32
- // (real fetch, real meta shape) without leaving the machine; ERR_HOST is the
33
- // deliberate failure host for the error-state story.
27
+ // Fixture-backed stories carry a baseURL the way a generated app does, and
28
+ // FrappeTable under a fixture corpus reads DocType meta from the corpus's
29
+ // "DocType" entry, never that host (MPO-230). MOCK_HOST still answers
30
+ // anything else locally so no stray request leaves the machine; ERR_HOST is
31
+ // the deliberate failure host for the error-state story.
34
32
  // ---------------------------------------------------------------------------
35
33
 
36
34
  const MOCK_HOST = "https://frappetable.mock.test";
@@ -39,6 +37,7 @@ const ERR_HOST = "https://forbidden.frappetable.mock.test";
39
37
  function customerMetaRaw(name: string) {
40
38
  return {
41
39
  name,
40
+ doctype: "DocType",
42
41
  module: "Selling",
43
42
  title_field: "customer_name",
44
43
  fields: [
@@ -85,9 +84,6 @@ function jsonResponse(body: unknown, status = 200): Response {
85
84
  if (urlStr.startsWith(ERR_HOST)) return jsonResponse({ message: "Not permitted" }, 403);
86
85
  if (urlStr.startsWith(MOCK_HOST)) {
87
86
  const url = new URL(urlStr);
88
- const metaMatch = url.pathname.match(/^\/api\/resource\/DocType\/(.+)$/);
89
- if (metaMatch)
90
- return jsonResponse({ data: customerMetaRaw(decodeURIComponent(metaMatch[1])) });
91
87
  if (url.pathname === "/api/resource/DocType") {
92
88
  return jsonResponse({ data: [{ name: "Customer", module: "Selling" }] });
93
89
  }
@@ -183,6 +179,13 @@ const customerFixtures: Customer[] = [
183
179
  },
184
180
  ];
185
181
 
182
+ function customerCorpus(customers: Customer[] = customerFixtures): InMemoryFixtureProvider {
183
+ return new InMemoryFixtureProvider({
184
+ DocType: [customerMetaRaw("Customer")],
185
+ Customer: customers,
186
+ });
187
+ }
188
+
186
189
  const customerColumns: DataTableColumn<Partial<Customer>>[] = [
187
190
  { id: "name", header: "ID", accessorKey: "name" },
188
191
  { id: "customer_name", header: "Customer Name", accessorKey: "customer_name" },
@@ -212,10 +215,7 @@ const customerColumns: DataTableColumn<Partial<Customer>>[] = [
212
215
  ];
213
216
 
214
217
  export const Default = () => (
215
- <FrappeProvider
216
- baseURL={MOCK_HOST}
217
- fixtures={new InMemoryFixtureProvider({ Customer: customerFixtures })}
218
- >
218
+ <FrappeProvider baseURL={MOCK_HOST} fixtures={customerCorpus()}>
219
219
  <FrappeTable<Customer>
220
220
  doctype="Customer"
221
221
  columns={customerColumns}
@@ -236,10 +236,7 @@ Default.parameters = {
236
236
 
237
237
  Default.storyName = "Main";
238
238
  export const WithPagination = () => (
239
- <FrappeProvider
240
- baseURL={MOCK_HOST}
241
- fixtures={new InMemoryFixtureProvider({ Customer: customerFixtures })}
242
- >
239
+ <FrappeProvider baseURL={MOCK_HOST} fixtures={customerCorpus()}>
243
240
  <FrappeTable<Customer>
244
241
  doctype="Customer"
245
242
  columns={customerColumns}
@@ -258,10 +255,7 @@ WithPagination.parameters = {
258
255
  };
259
256
 
260
257
  export const WithSavedFilters = () => (
261
- <FrappeProvider
262
- baseURL={MOCK_HOST}
263
- fixtures={new InMemoryFixtureProvider({ Customer: customerFixtures })}
264
- >
258
+ <FrappeProvider baseURL={MOCK_HOST} fixtures={customerCorpus()}>
265
259
  <FrappeTable<Customer>
266
260
  doctype="Customer"
267
261
  columns={customerColumns}
@@ -376,14 +370,17 @@ class PendingFixtureProvider extends InMemoryFixtureProvider {
376
370
 
377
371
  /** Collection stuck syncing: the built-in loading panel renders (W9 / DG-ST-02). */
378
372
  export const Loading = () => (
379
- <FrappeProvider baseURL={MOCK_HOST} fixtures={new PendingFixtureProvider()}>
373
+ <FrappeProvider
374
+ baseURL={MOCK_HOST}
375
+ fixtures={new PendingFixtureProvider({ DocType: [customerMetaRaw("Customer")] })}
376
+ >
380
377
  <FrappeTable<Customer> doctype="Customer" columns={customerColumns} />
381
378
  </FrappeProvider>
382
379
  );
383
380
 
384
381
  /** Zero documents, no filters, no failure — "No Customer records found" (empty ≠ error). */
385
382
  export const Empty = () => (
386
- <FrappeProvider baseURL={MOCK_HOST} fixtures={new InMemoryFixtureProvider({ Customer: [] })}>
383
+ <FrappeProvider baseURL={MOCK_HOST} fixtures={customerCorpus([])}>
387
384
  <FrappeTable<Customer> doctype="Customer" columns={customerColumns} />
388
385
  </FrappeProvider>
389
386
  );
@@ -394,10 +391,7 @@ export const Empty = () => (
394
391
  * from Empty per DG-TBL-06.
395
392
  */
396
393
  export const NoResults = () => (
397
- <FrappeProvider
398
- baseURL={MOCK_HOST}
399
- fixtures={new InMemoryFixtureProvider({ Customer: customerFixtures })}
400
- >
394
+ <FrappeProvider baseURL={MOCK_HOST} fixtures={customerCorpus()}>
401
395
  <FrappeTable<Customer>
402
396
  doctype="Customer"
403
397
  columns={customerColumns}
@@ -440,10 +434,10 @@ const minimalCustomerColumns: DataTableColumn<Partial<Customer>>[] = [
440
434
  ];
441
435
 
442
436
  /**
443
- * With a live bench, FrappeTable derives this list automatically from the
444
- * doctype metadata (docFieldsToFilterFields). Fixtures have no /api/method
445
- * metadata endpoint, so the story passes the equivalent list explicitly —
446
- * same contract, same UI.
437
+ * Omitted, FrappeTable derives this list from the doctype meta
438
+ * (docFieldsToFilterFields), here the corpus's DocType entry. The story
439
+ * passes the equivalent list explicitly to show the prop — same contract,
440
+ * same UI.
447
441
  */
448
442
  const customerFilterFields = [
449
443
  { id: "territory", label: "Territory", type: "text" as const },
@@ -478,10 +472,7 @@ const customerFilterFields = [
478
472
  * field/operator/value dropdown.
479
473
  */
480
474
  export const HiddenFieldFilters = () => (
481
- <FrappeProvider
482
- baseURL={MOCK_HOST}
483
- fixtures={new InMemoryFixtureProvider({ Customer: customerFixtures })}
484
- >
475
+ <FrappeProvider baseURL={MOCK_HOST} fixtures={customerCorpus()}>
485
476
  <FrappeTable<Customer>
486
477
  doctype="Customer"
487
478
  columns={minimalCustomerColumns}