@plone/volto 19.0.0-alpha.2 → 19.0.0-alpha.20

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 (366) hide show
  1. package/.eslintignore +1 -0
  2. package/.eslintrc +37 -3
  3. package/CHANGELOG.md +338 -1
  4. package/README.md +20 -16
  5. package/babel.js +1 -3
  6. package/cypress/docker/prefixed-rules.yml +26 -0
  7. package/cypress/docker/prefixed.yml +24 -0
  8. package/cypress/support/commands.js +12 -6
  9. package/cypress/support/guillotina.js +1 -0
  10. package/cypress.config.js +1 -0
  11. package/global-test-setup.js +1 -2
  12. package/locales/af.json +1 -0
  13. package/locales/ar.json +1 -0
  14. package/locales/bg.json +1 -0
  15. package/locales/bn.json +1 -0
  16. package/locales/ca/LC_MESSAGES/volto.po +124 -17
  17. package/locales/ca.json +1 -1
  18. package/locales/cs.json +1 -0
  19. package/locales/cy.json +1 -0
  20. package/locales/da.json +1 -0
  21. package/locales/de/LC_MESSAGES/volto.po +135 -28
  22. package/locales/de.json +1 -1
  23. package/locales/el.json +1 -0
  24. package/locales/en/LC_MESSAGES/volto.po +125 -18
  25. package/locales/en.json +1 -1
  26. package/locales/en_AU.json +1 -0
  27. package/locales/en_GB.json +1 -0
  28. package/locales/eo.json +1 -0
  29. package/locales/es/LC_MESSAGES/volto.po +125 -18
  30. package/locales/es.json +1 -1
  31. package/locales/et.json +1 -0
  32. package/locales/eu/LC_MESSAGES/volto.po +124 -17
  33. package/locales/eu.json +1 -1
  34. package/locales/fa.json +1 -0
  35. package/locales/fi/LC_MESSAGES/volto.po +124 -17
  36. package/locales/fi.json +1 -1
  37. package/locales/fr/LC_MESSAGES/volto.po +125 -18
  38. package/locales/fr.json +1 -1
  39. package/locales/fu.json +1 -0
  40. package/locales/gl.json +1 -0
  41. package/locales/he.json +1 -0
  42. package/locales/hi/LC_MESSAGES/volto.po +128 -21
  43. package/locales/hi.json +1 -1
  44. package/locales/hr.json +1 -0
  45. package/locales/hu.json +1 -0
  46. package/locales/hy.json +1 -0
  47. package/locales/id.json +1 -0
  48. package/locales/it/LC_MESSAGES/volto.po +129 -22
  49. package/locales/it.json +1 -1
  50. package/locales/ja/LC_MESSAGES/volto.po +124 -17
  51. package/locales/ja.json +1 -1
  52. package/locales/ka.json +1 -0
  53. package/locales/kn.json +1 -0
  54. package/locales/ko.json +1 -0
  55. package/locales/lt.json +1 -0
  56. package/locales/lv.json +1 -0
  57. package/locales/mi.json +1 -0
  58. package/locales/mk.json +1 -0
  59. package/locales/my.json +1 -0
  60. package/locales/nb_NO.json +1 -0
  61. package/locales/nl/LC_MESSAGES/volto.po +128 -21
  62. package/locales/nl.json +1 -1
  63. package/locales/nn.json +1 -0
  64. package/locales/pl.json +1 -0
  65. package/locales/pt/LC_MESSAGES/volto.po +124 -17
  66. package/locales/pt.json +1 -1
  67. package/locales/pt_BR/LC_MESSAGES/volto.po +147 -40
  68. package/locales/pt_BR.json +1 -1
  69. package/locales/rm.json +1 -0
  70. package/locales/ro/LC_MESSAGES/volto.po +128 -21
  71. package/locales/ro.json +1 -1
  72. package/locales/ru/LC_MESSAGES/volto.po +128 -21
  73. package/locales/ru.json +1 -1
  74. package/locales/sk.json +1 -0
  75. package/locales/sl.json +1 -0
  76. package/locales/sm.json +1 -0
  77. package/locales/sq.json +1 -0
  78. package/locales/sr.json +1 -0
  79. package/locales/sr@cyrl.json +1 -0
  80. package/locales/sr@latn.json +1 -0
  81. package/locales/sv.json +1 -1
  82. package/locales/ta.json +1 -0
  83. package/locales/te.json +1 -0
  84. package/locales/th.json +1 -0
  85. package/locales/to.json +1 -0
  86. package/locales/tr.json +1 -0
  87. package/locales/uk.json +1 -0
  88. package/locales/vi.json +1 -0
  89. package/locales/volto.pot +125 -18
  90. package/locales/zh_CN/LC_MESSAGES/volto.po +124 -17
  91. package/locales/zh_CN.json +1 -1
  92. package/locales/zh_Hant.json +1 -0
  93. package/locales/zh_Hant_HK.json +1 -0
  94. package/package.json +43 -100
  95. package/razzle.config.js +21 -21
  96. package/src/actions/content/content.js +0 -1
  97. package/src/actions/controlpanels/controlpanels.js +13 -7
  98. package/src/actions/controlpanels/controlpanels.test.js +11 -5
  99. package/src/actions/users/users.js +2 -2
  100. package/src/components/manage/Actions/Actions.test.jsx +1 -5
  101. package/src/components/manage/Add/Add.jsx +5 -6
  102. package/src/components/manage/BlockChooser/BlockChooser.jsx +1 -0
  103. package/src/components/manage/Blocks/Block/BlocksForm.test.jsx +1 -5
  104. package/src/components/manage/Blocks/Block/Edit.jsx +1 -0
  105. package/src/components/manage/Blocks/Block/EditBlockWrapper.jsx +9 -4
  106. package/src/components/manage/Blocks/Block/Settings.test.jsx +1 -5
  107. package/src/components/manage/Blocks/HTML/Edit.test.jsx +1 -5
  108. package/src/components/manage/Blocks/Image/Edit.jsx +5 -1
  109. package/src/components/manage/Blocks/Image/ImageSidebar.test.jsx +1 -5
  110. package/src/components/manage/Blocks/LeadImage/Edit.jsx +2 -2
  111. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.jsx +1 -1
  112. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.test.jsx +1 -5
  113. package/src/components/manage/Blocks/Listing/ImageGallery.jsx +6 -4
  114. package/src/components/manage/Blocks/Maps/Edit.jsx +2 -1
  115. package/src/components/manage/Blocks/Maps/MapsSidebar.test.jsx +1 -5
  116. package/src/components/manage/Blocks/Search/SearchBlockView.jsx +21 -4
  117. package/src/components/manage/Blocks/Search/components/DateRangeFacet.test.jsx +1 -6
  118. package/src/components/manage/Blocks/Search/components/SelectFacet.test.jsx +1 -6
  119. package/src/components/manage/Blocks/Teaser/Data.jsx +21 -7
  120. package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +1 -1
  121. package/src/components/manage/Blocks/Teaser/schema.js +8 -3
  122. package/src/components/manage/Blocks/Video/Edit.jsx +2 -1
  123. package/src/components/manage/Blocks/Video/VideoSidebar.test.jsx +1 -5
  124. package/src/components/manage/Contents/Contents.jsx +689 -654
  125. package/src/components/manage/Contents/Contents.test.jsx +8 -5
  126. package/src/components/manage/Contents/ContentsBreadcrumbs.Multilingual.test.jsx +18 -5
  127. package/src/components/manage/Contents/ContentsBreadcrumbs.jsx +20 -26
  128. package/src/components/manage/Contents/ContentsBreadcrumbs.test.jsx +14 -0
  129. package/src/components/manage/Contents/ContentsDeleteModal.jsx +258 -206
  130. package/src/components/manage/Contents/ContentsDeleteModal.stories.jsx +26 -8
  131. package/src/components/manage/Contents/ContentsItem.jsx +10 -2
  132. package/src/components/manage/Contents/ContentsPropertiesModal.test.jsx +1 -5
  133. package/src/components/manage/Contents/ContentsRenameModal.test.jsx +1 -5
  134. package/src/components/manage/Contents/ContentsTagsModal.test.jsx +1 -5
  135. package/src/components/manage/Contents/ContentsUploadModal.test.jsx +13 -22
  136. package/src/components/manage/Contents/ContentsWorkflowModal.test.jsx +1 -5
  137. package/src/components/manage/Contents/DropZoneContent.jsx +323 -0
  138. package/src/components/manage/Contents/__mocks__/index.tsx +2 -18
  139. package/src/components/manage/Controlpanels/Aliases.test.jsx +1 -5
  140. package/src/components/manage/Controlpanels/ContentType.jsx +1 -1
  141. package/src/components/manage/Controlpanels/ContentType.test.jsx +1 -5
  142. package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.jsx +3 -2
  143. package/src/components/manage/Controlpanels/Relations/Relations.jsx +1 -1
  144. package/src/components/manage/Controlpanels/Rules/AddRule.test.jsx +1 -5
  145. package/src/components/manage/Controlpanels/Rules/EditRule.test.jsx +1 -5
  146. package/src/components/manage/Controlpanels/UndoControlpanel.test.jsx +1 -5
  147. package/src/components/manage/Controlpanels/Users/RenderUsers.jsx +156 -175
  148. package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +575 -630
  149. package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +4 -3
  150. package/src/components/manage/Diff/Diff.test.jsx +1 -6
  151. package/src/components/manage/Diff/DiffField.test.jsx +1 -6
  152. package/src/components/manage/Display/Display.test.jsx +2 -11
  153. package/src/components/manage/Edit/Edit.jsx +2 -3
  154. package/src/components/manage/Edit/Edit.test.jsx +1 -5
  155. package/src/components/manage/Form/BlockDataForm.test.jsx +1 -5
  156. package/src/components/manage/Form/Form.test.jsx +1 -5
  157. package/src/components/manage/Form/InlineForm.jsx +2 -2
  158. package/src/components/manage/Form/InlineForm.test.jsx +1 -5
  159. package/src/components/manage/Form/ModalForm.jsx +12 -10
  160. package/src/components/manage/Form/ModalForm.test.jsx +27 -5
  161. package/src/components/manage/Form/__mocks__/index.tsx +9 -27
  162. package/src/components/manage/Multilingual/CompareLanguages.jsx +2 -5
  163. package/src/components/manage/Multilingual/CreateTranslation.jsx +8 -8
  164. package/src/components/manage/Multilingual/ManageTranslations.jsx +4 -2
  165. package/src/components/manage/Multilingual/ManageTranslations.test.jsx +5 -1
  166. package/src/components/manage/Multilingual/TranslationObject.jsx +1 -1
  167. package/src/components/manage/Preferences/ChangePassword.test.jsx +1 -5
  168. package/src/components/manage/Preferences/PersonalPreferences.test.jsx +1 -17
  169. package/src/components/manage/Sidebar/ObjectBrowser.jsx +3 -0
  170. package/src/components/manage/Sidebar/ObjectBrowserBody.jsx +13 -1
  171. package/src/components/manage/Sidebar/ObjectBrowserNav.jsx +2 -1
  172. package/src/components/manage/Sidebar/SidebarPortal.test.tsx +42 -0
  173. package/src/components/manage/Sidebar/SidebarPortal.tsx +48 -0
  174. package/src/components/manage/TemplateChooser/TemplateChooser.jsx +2 -1
  175. package/src/components/manage/Toolbar/More.jsx +4 -1
  176. package/src/components/manage/Toolbar/More.test.jsx +3 -0
  177. package/src/components/manage/Toolbar/PersonalTools.jsx +2 -1
  178. package/src/components/manage/Toolbar/Toolbar.jsx +3 -4
  179. package/src/components/manage/Toolbar/Types.jsx +7 -7
  180. package/src/components/manage/UniversalLink/UniversalLink.tsx +1 -0
  181. package/src/components/manage/Widgets/AlignWidget.stories.jsx +9 -0
  182. package/src/components/manage/Widgets/AlignWidget.test.tsx +95 -0
  183. package/src/components/manage/Widgets/{AlignWidget.jsx → AlignWidget.tsx} +23 -7
  184. package/src/components/manage/Widgets/ArrayWidget.test.jsx +1 -6
  185. package/src/components/manage/Widgets/BlockAlignment.stories.tsx +104 -0
  186. package/src/components/manage/Widgets/BlockAlignment.test.tsx +104 -0
  187. package/src/components/manage/Widgets/BlockAlignment.tsx +88 -0
  188. package/src/components/manage/Widgets/BlockWidth.stories.tsx +69 -0
  189. package/src/components/manage/Widgets/BlockWidth.test.tsx +62 -0
  190. package/src/components/manage/Widgets/BlockWidth.tsx +101 -0
  191. package/src/components/manage/Widgets/ButtonsWidget.stories.jsx +61 -0
  192. package/src/components/manage/Widgets/ButtonsWidget.test.tsx +138 -0
  193. package/src/components/manage/Widgets/ButtonsWidget.tsx +176 -0
  194. package/src/components/manage/Widgets/CheckboxGroupWidget.test.jsx +1 -6
  195. package/src/components/manage/Widgets/DatetimeWidget.jsx +16 -1
  196. package/src/components/manage/Widgets/DatetimeWidget.test.jsx +1 -6
  197. package/src/components/manage/Widgets/FileWidget.jsx +14 -8
  198. package/src/components/manage/Widgets/FormFieldWrapper.jsx +146 -168
  199. package/src/components/manage/Widgets/ImageWidget.jsx +171 -38
  200. package/src/components/manage/Widgets/InternalUrlWidget.jsx +2 -0
  201. package/src/components/manage/Widgets/ObjectBrowserWidget.jsx +8 -0
  202. package/src/components/manage/Widgets/ObjectListWidget.test.jsx +2 -11
  203. package/src/components/manage/Widgets/ObjectWidget.test.jsx +1 -5
  204. package/src/components/manage/Widgets/QueryWidget.jsx +137 -9
  205. package/src/components/manage/Widgets/RadioGroupWidget.test.jsx +1 -6
  206. package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.test.jsx +1 -6
  207. package/src/components/manage/Widgets/RegistryImageWidget.test.jsx +3 -2
  208. package/src/components/manage/Widgets/SchemaWidget.test.jsx +1 -6
  209. package/src/components/manage/Widgets/SchemaWidgetFieldset.test.jsx +1 -6
  210. package/src/components/manage/Widgets/SelectAutoComplete.jsx +29 -12
  211. package/src/components/manage/Widgets/SelectAutoComplete.test.jsx +1 -6
  212. package/src/components/manage/Widgets/SelectWidget.test.jsx +1 -6
  213. package/src/components/manage/Widgets/Size.stories.tsx +69 -0
  214. package/src/components/manage/Widgets/Size.test.tsx +59 -0
  215. package/src/components/manage/Widgets/Size.tsx +78 -0
  216. package/src/components/manage/Widgets/TimeWidget.test.jsx +1 -6
  217. package/src/components/manage/Widgets/TokenWidget.test.jsx +1 -6
  218. package/src/components/manage/Widgets/UrlWidget.jsx +2 -0
  219. package/src/components/manage/Widgets/VocabularyTermsWidget.test.jsx +2 -11
  220. package/src/components/manage/Widgets/__mocks__/index.tsx +33 -51
  221. package/src/components/manage/Widgets/index.tsx +21 -0
  222. package/src/components/manage/Workflow/Workflow.test.jsx +2 -11
  223. package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.jsx +1 -3
  224. package/src/components/theme/AlternateHrefLangs/AlternateHrefLangs.test.jsx +0 -4
  225. package/src/components/theme/App/App.jsx +5 -1
  226. package/src/components/theme/App/App.test.jsx +1 -0
  227. package/src/components/theme/Avatar/Avatar.jsx +2 -1
  228. package/src/components/theme/Comments/CommentEditModal.test.jsx +1 -5
  229. package/src/components/theme/Comments/Comments.test.jsx +2 -11
  230. package/src/components/theme/ContactForm/ContactForm.test.jsx +1 -5
  231. package/src/components/theme/FormattedDate/FormattedDate.stories.jsx +20 -2
  232. package/src/components/theme/Image/Image.jsx +11 -8
  233. package/src/components/theme/InjectPloneComponentsCSS/InjectPloneComponentsCSS.tsx +7 -0
  234. package/src/components/theme/LanguageSelector/{LanguageSelector.test.jsx → LanguageSelector.test.tsx} +6 -6
  235. package/src/components/theme/LanguageSelector/LanguageSelector.tsx +89 -0
  236. package/src/components/theme/Logo/Logo.Multilingual.test.jsx +0 -5
  237. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.jsx +10 -14
  238. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.test.jsx +3 -5
  239. package/src/components/theme/Navigation/NavItem.jsx +1 -5
  240. package/src/components/theme/Navigation/Navigation.Multilingual.test.jsx +0 -5
  241. package/src/components/theme/NotFound/NotFound.jsx +5 -2
  242. package/src/components/theme/NotFound/NotFound.test.jsx +3 -0
  243. package/src/components/theme/PasswordReset/RequestPasswordReset.test.jsx +1 -5
  244. package/src/components/theme/PreviewImage/PreviewImage.jsx +1 -1
  245. package/src/components/theme/Register/Register.test.jsx +1 -5
  246. package/src/components/theme/RequestTimeout/RequestTimeout.jsx +1 -1
  247. package/src/components/theme/Sitemap/Sitemap.jsx +6 -5
  248. package/src/components/theme/Sitemap/Sitemap.test.jsx +0 -1
  249. package/src/components/theme/Unauthorized/Unauthorized.jsx +5 -2
  250. package/src/components/theme/View/EventDatesInfo.test.jsx +1 -6
  251. package/src/components/theme/View/EventView.test.jsx +1 -6
  252. package/src/components/theme/View/FileView.jsx +9 -1
  253. package/src/components/theme/View/View.jsx +8 -1
  254. package/src/components/theme/Widgets/ImageWidget.jsx +2 -1
  255. package/src/config/ControlPanels.js +1 -0
  256. package/src/config/Widgets.jsx +7 -0
  257. package/src/config/index.js +18 -25
  258. package/src/config/server.js +0 -2
  259. package/src/config/slots.js +19 -0
  260. package/src/express-middleware/devproxy.js +20 -5
  261. package/src/helpers/Api/APIResourceWithAuth.js +8 -3
  262. package/src/helpers/Api/Api.js +7 -4
  263. package/src/helpers/AsyncConnect/ssr.js +4 -1
  264. package/src/helpers/Content/Content.js +23 -0
  265. package/src/helpers/Content/Content.test.js +39 -0
  266. package/src/helpers/Content/withClientSideContent.jsx +35 -0
  267. package/src/helpers/Extensions/withBlockSchemaEnhancer.jsx +4 -1
  268. package/src/helpers/Html/Html.jsx +13 -7
  269. package/src/helpers/LanguageMap/LanguageMap.js +115 -8
  270. package/src/helpers/Loadable/__mocks__/Loadable.jsx +7 -22
  271. package/src/helpers/MessageLabels/MessageLabels.js +5 -0
  272. package/src/helpers/Sitemap/Sitemap.js +4 -4
  273. package/src/helpers/Url/Url.js +33 -2
  274. package/src/helpers/Url/Url.test.js +62 -0
  275. package/src/hooks/user/useUser.js +1 -1
  276. package/src/internalChecks.test.ts +11 -0
  277. package/src/middleware/Api.test.js +4 -0
  278. package/src/middleware/api.js +82 -28
  279. package/src/middleware/storeProtectLoadUtils.test.js +3 -3
  280. package/src/reducers/content/content.js +3 -18
  281. package/src/reducers/diff/diff.js +5 -1
  282. package/src/reducers/diff/diff.test.js +60 -4
  283. package/src/reducers/querystring/querystring.js +8 -1
  284. package/src/routes.js +4 -2
  285. package/src/server.jsx +45 -14
  286. package/src/start-client.jsx +9 -6
  287. package/src/start-server.js +9 -3
  288. package/test-addons-loader.js +3 -0
  289. package/test-setup-config.jsx +0 -2
  290. package/test-setup-globals.js +30 -2
  291. package/theme/themes/pastanaga/extras/blocks.less +26 -0
  292. package/theme/themes/pastanaga/extras/contents.less +80 -5
  293. package/theme/themes/pastanaga/extras/main.less +17 -2
  294. package/theme/themes/pastanaga/extras/widgets.less +79 -0
  295. package/tsconfig.declarations.json +1 -1
  296. package/tsconfig.json +4 -5
  297. package/types/components/manage/Blocks/Teaser/schema.d.ts +1 -0
  298. package/types/components/manage/Contents/DropZoneContent.d.ts +2 -0
  299. package/types/components/manage/Contents/__mocks__/index.d.ts +2 -2
  300. package/types/components/manage/Controlpanels/Relations/RelationsMatrix.d.ts +1 -1
  301. package/types/components/manage/Controlpanels/Users/RenderUsers.d.ts +18 -2
  302. package/types/components/manage/Controlpanels/Users/UsersControlpanel.d.ts +6 -2
  303. package/types/components/manage/Controlpanels/index.d.ts +2 -2
  304. package/types/components/manage/Form/__mocks__/index.d.ts +8 -8
  305. package/types/components/manage/Multilingual/ManageTranslations.d.ts +1 -1
  306. package/types/components/manage/Sidebar/ObjectBrowser.d.ts +1 -1
  307. package/types/components/manage/Sidebar/SidebarPortal.d.ts +7 -15
  308. package/types/components/manage/Widgets/AlignWidget.d.ts +8 -10
  309. package/types/components/manage/Widgets/AlignWidget.stories.d.ts +1 -0
  310. package/types/components/manage/Widgets/BlockAlignment.d.ts +7 -0
  311. package/types/components/manage/Widgets/BlockAlignment.stories.d.ts +8 -0
  312. package/types/components/manage/Widgets/BlockWidth.d.ts +7 -0
  313. package/types/components/manage/Widgets/BlockWidth.stories.d.ts +6 -0
  314. package/types/components/manage/Widgets/ButtonsWidget.d.ts +48 -1
  315. package/types/components/manage/Widgets/ButtonsWidget.stories.d.ts +3 -0
  316. package/types/components/manage/Widgets/FormFieldWrapper.d.ts +28 -5
  317. package/types/components/manage/Widgets/ImageWidget.d.ts +41 -1
  318. package/types/components/manage/Widgets/InternalUrlWidget.d.ts +1 -1
  319. package/types/components/manage/Widgets/ObjectBrowserWidget.d.ts +2 -0
  320. package/types/components/manage/Widgets/QueryWidget.d.ts +5 -2
  321. package/types/components/manage/Widgets/RecurrenceWidget/Utils.d.ts +12 -18
  322. package/types/components/manage/Widgets/Size.d.ts +7 -0
  323. package/types/components/manage/Widgets/Size.stories.d.ts +6 -0
  324. package/types/components/manage/Widgets/UrlWidget.d.ts +1 -1
  325. package/types/components/manage/Widgets/__mocks__/index.d.ts +33 -33
  326. package/types/components/manage/Widgets/index.d.ts +11 -6
  327. package/types/components/theme/FormattedDate/FormattedDate.stories.d.ts +1 -1
  328. package/types/components/theme/InjectPloneComponentsCSS/InjectPloneComponentsCSS.d.ts +3 -0
  329. package/types/components/theme/LanguageSelector/LanguageSelector.d.ts +3 -10
  330. package/types/components/theme/Unauthorized/Unauthorized.d.ts +2 -2
  331. package/types/config/Widgets.d.ts +6 -0
  332. package/types/config/slots.d.ts +7 -0
  333. package/types/helpers/Content/Content.d.ts +7 -0
  334. package/types/helpers/Content/withClientSideContent.d.ts +1 -0
  335. package/types/helpers/Extensions/withBlockSchemaEnhancer.d.ts +4 -5
  336. package/types/helpers/Helmet/Helmet.d.ts +1 -1
  337. package/types/helpers/LanguageMap/LanguageMap.d.ts +428 -4
  338. package/types/helpers/Loadable/__mocks__/Loadable.d.ts +2 -2
  339. package/types/helpers/MessageLabels/MessageLabels.d.ts +68 -62
  340. package/types/helpers/Url/Url.d.ts +14 -0
  341. package/types/helpers/Url/bulkFlattenToAppURL.d.ts +5 -0
  342. package/types/middleware/api.d.ts +6 -9
  343. package/types/reducers/index.d.ts +1 -0
  344. package/types/start-client.d.ts +0 -1
  345. package/vitest.config.mjs +4 -4
  346. package/webpack-plugins/webpack-scss-plugin.js +172 -0
  347. package/jest-addons-loader.js +0 -3
  348. package/jest-extender-plugin.js +0 -39
  349. package/jest-setup-afterenv.js +0 -2
  350. package/jest-svgsystem-transform.js +0 -10
  351. package/package-why.json +0 -34
  352. package/patches/patchit.sh +0 -2
  353. package/patches/razzle-jest.patch +0 -10
  354. package/src/actions/content/content.multilingual.test.js +0 -17
  355. package/src/components/manage/Contents/__mocks__/index.vitest.tsx +0 -5
  356. package/src/components/manage/Form/__mocks__/index.vitest.tsx +0 -73
  357. package/src/components/manage/Sidebar/SidebarPortal.jsx +0 -47
  358. package/src/components/manage/Sidebar/SidebarPortal.test.jsx +0 -26
  359. package/src/components/manage/Widgets/AlignWidget.test.jsx +0 -59
  360. package/src/components/manage/Widgets/ButtonsWidget.jsx +0 -41
  361. package/src/components/manage/Widgets/ButtonsWidget.test.jsx +0 -70
  362. package/src/components/manage/Widgets/__mocks__/index.vitest.tsx +0 -41
  363. package/src/components/theme/LanguageSelector/LanguageSelector.jsx +0 -77
  364. package/src/helpers/Loadable/__mocks__/Loadable.vitest.jsx +0 -39
  365. package/test-setup-globals-vitest.js +0 -46
  366. package/theme/themes/pastanaga/extras/utils.less +0 -63
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { render, act } from '@testing-library/react';
3
3
  import configureStore from 'redux-mock-store';
4
4
  import { Provider } from 'react-intl-redux';
5
+ import { MemoryRouter } from 'react-router-dom';
5
6
  import jwt from 'jsonwebtoken';
6
7
 
7
8
  import UsersControlpanel from './UsersControlpanel';
@@ -41,10 +42,10 @@ describe('UsersControlpanel', () => {
41
42
  const { container } = await act(async () => {
42
43
  return render(
43
44
  <Provider store={store}>
44
- <>
45
- <UsersControlpanel location={{ pathname: '/blog' }} />
45
+ <MemoryRouter initialEntries={['/controlpanel/users']}>
46
+ <UsersControlpanel />
46
47
  <div id="toolbar"></div>
47
- </>
48
+ </MemoryRouter>
48
49
  </Provider>,
49
50
  );
50
51
  });
@@ -12,12 +12,7 @@ vi.mock('../Toolbar/Toolbar', () => ({
12
12
  default: vi.fn(() => <div id="Portal" />),
13
13
  }));
14
14
 
15
- vi.mock('@plone/volto/helpers/Loadable/Loadable', async () => {
16
- return await import(
17
- '@plone/volto/helpers/Loadable/__mocks__/Loadable.vitest.jsx'
18
- );
19
- });
20
-
15
+ vi.mock('@plone/volto/helpers/Loadable/Loadable');
21
16
  beforeAll(async () => {
22
17
  const { __setLoadables } = await import(
23
18
  '@plone/volto/helpers/Loadable/Loadable'
@@ -4,12 +4,7 @@ import { Provider } from 'react-intl-redux';
4
4
  import { waitFor, render, screen } from '@testing-library/react';
5
5
  import DiffField from './DiffField';
6
6
 
7
- vi.mock('@plone/volto/helpers/Loadable/Loadable', async () => {
8
- return await import(
9
- '@plone/volto/helpers/Loadable/__mocks__/Loadable.vitest.jsx'
10
- );
11
- });
12
-
7
+ vi.mock('@plone/volto/helpers/Loadable/Loadable');
13
8
  beforeAll(async () => {
14
9
  const { __setLoadables } = await import(
15
10
  '@plone/volto/helpers/Loadable/Loadable'
@@ -8,17 +8,8 @@ import Display from './Display';
8
8
 
9
9
  const mockStore = configureStore();
10
10
 
11
- vi.mock('@plone/volto/components/manage/Widgets', async () => {
12
- return await import(
13
- '@plone/volto/components/manage/Widgets/__mocks__/index.vitest.tsx'
14
- );
15
- });
16
- vi.mock('@plone/volto/helpers/Loadable/Loadable', async () => {
17
- return await import(
18
- '@plone/volto/helpers/Loadable/__mocks__/Loadable.vitest.jsx'
19
- );
20
- });
21
-
11
+ vi.mock('@plone/volto/components/manage/Widgets');
12
+ vi.mock('@plone/volto/helpers/Loadable/Loadable');
22
13
  beforeAll(async () => {
23
14
  const { __setLoadables } = await import(
24
15
  '@plone/volto/helpers/Loadable/Loadable'
@@ -44,8 +44,6 @@ import { tryParseJSON } from '@plone/volto/helpers/FormValidation/FormValidation
44
44
  import saveSVG from '@plone/volto/icons/save.svg';
45
45
  import clearSVG from '@plone/volto/icons/clear.svg';
46
46
 
47
- import config from '@plone/volto/registry';
48
-
49
47
  const messages = defineMessages({
50
48
  edit: {
51
49
  id: 'Edit {title}',
@@ -460,7 +458,7 @@ class Edit extends Component {
460
458
  />
461
459
  </Button>
462
460
 
463
- {config.settings.isMultilingual && (
461
+ {this.props.isMultilingual && (
464
462
  <CompareLanguages
465
463
  content={this.props.content}
466
464
  visual={this.state.visual}
@@ -545,6 +543,7 @@ export default compose(
545
543
  updateRequest: state.content.update,
546
544
  pathname: props.location.pathname,
547
545
  returnUrl: qs.parse(props.location.search).return_url,
546
+ isMultilingual: state.site.data.features?.multilingual,
548
547
  }),
549
548
  {
550
549
  updateContent,
@@ -8,11 +8,7 @@ import { __test__ as Edit } from './Edit';
8
8
 
9
9
  const mockStore = configureStore();
10
10
 
11
- vi.mock('@plone/volto/components/manage/Form', async () => {
12
- return await import(
13
- '@plone/volto/components/manage/Form/__mocks__/index.vitest.tsx'
14
- );
15
- });
11
+ vi.mock('@plone/volto/components/manage/Form');
16
12
  vi.mock('../Toolbar/Toolbar', () => ({
17
13
  default: vi.fn(() => <div id="Portal" />),
18
14
  }));
@@ -5,11 +5,7 @@ import configureStore from 'redux-mock-store';
5
5
  import config from '@plone/volto/registry';
6
6
  import { Provider } from 'react-intl-redux';
7
7
 
8
- vi.mock('@plone/volto/components/manage/Form', async () => {
9
- return await import(
10
- '@plone/volto/components/manage/Form/__mocks__/index.vitest.tsx'
11
- );
12
- });
8
+ vi.mock('@plone/volto/components/manage/Form');
13
9
 
14
10
  const mockStore = configureStore();
15
11
 
@@ -9,11 +9,7 @@ const mockStore = configureStore();
9
9
  const errorMessage =
10
10
  "[{'message': 'The specified email is not valid.', 'field': 'contact_email', 'error': 'ValidationError'}";
11
11
 
12
- vi.mock('@plone/volto/components/manage/Form', async () => {
13
- return await import(
14
- '@plone/volto/components/manage/Form/__mocks__/index.vitest.tsx'
15
- );
16
- });
12
+ vi.mock('@plone/volto/components/manage/Form');
17
13
 
18
14
  describe('Form', () => {
19
15
  it('renders a form component', () => {
@@ -158,7 +158,7 @@ const InlineForm = (props) => {
158
158
  onChangeField(id, value, itemInfo);
159
159
  }}
160
160
  key={field}
161
- error={errors?.[block]?.[field] || {}}
161
+ error={errors?.[block]?.[field] || []}
162
162
  block={block}
163
163
  />
164
164
  ))}
@@ -199,7 +199,7 @@ const InlineForm = (props) => {
199
199
  onChangeField(id, value);
200
200
  }}
201
201
  key={field}
202
- error={errors?.[block]?.[field] || {}}
202
+ error={errors?.[block]?.[field] || []}
203
203
  block={block}
204
204
  />
205
205
  ))}
@@ -6,11 +6,7 @@ import config from '@plone/volto/registry';
6
6
 
7
7
  import InlineForm from './InlineForm';
8
8
 
9
- vi.mock('@plone/volto/components/manage/Form', async () => {
10
- return await import(
11
- '@plone/volto/components/manage/Form/__mocks__/index.vitest.tsx'
12
- );
13
- });
9
+ vi.mock('@plone/volto/components/manage/Form');
14
10
 
15
11
  const mockStore = configureStore();
16
12
 
@@ -245,15 +245,17 @@ class ModalForm extends Component {
245
245
  const { schema, onCancel, description } = this.props;
246
246
  const currentFieldset = schema.fieldsets[this.state.currentTab];
247
247
 
248
- const fields = map(currentFieldset.fields, (field) => ({
249
- ...schema.properties[field],
250
- id: field,
251
- value: this.state.formData[field],
252
- required: schema.required.indexOf(field) !== -1,
253
- onChange: this.onChangeField,
254
- onBlur: this.onBlurField,
255
- onClick: this.onClickInput,
256
- }));
248
+ const fields = currentFieldset
249
+ ? map(currentFieldset.fields, (field) => ({
250
+ ...schema.properties[field],
251
+ id: field,
252
+ value: this.state.formData[field],
253
+ required: schema.required.indexOf(field) !== -1,
254
+ onChange: this.onChangeField,
255
+ onBlur: this.onBlurField,
256
+ onClick: this.onClickInput,
257
+ }))
258
+ : [];
257
259
 
258
260
  const state_errors = keys(this.state.errors).length > 0;
259
261
  return (
@@ -288,7 +290,7 @@ class ModalForm extends Component {
288
290
  )}
289
291
  <div>{this.props.submitError}</div>
290
292
  </Message>
291
- {schema.fieldsets.length > 1 && (
293
+ {schema.fieldsets?.length > 1 && (
292
294
  <Menu tabular stackable>
293
295
  {map(schema.fieldsets, (item, index) => (
294
296
  <Menu.Item
@@ -8,11 +8,7 @@ import ModalForm from './ModalForm';
8
8
 
9
9
  const mockStore = configureStore();
10
10
 
11
- vi.mock('@plone/volto/components/manage/Form', async () => {
12
- return await import(
13
- '@plone/volto/components/manage/Form/__mocks__/index.vitest.tsx'
14
- );
15
- });
11
+ vi.mock('@plone/volto/components/manage/Form');
16
12
 
17
13
  describe('ModalForm', () => {
18
14
  it('renders a modal form component', () => {
@@ -93,4 +89,30 @@ describe('ModalForm', () => {
93
89
  const loadingMessage = getByText(/renaming items.../i);
94
90
  expect(loadingMessage).toBeInTheDocument();
95
91
  });
92
+
93
+ it('renders with empty fieldsets array', () => {
94
+ const store = mockStore({
95
+ intl: {
96
+ locale: 'en',
97
+ messages: {},
98
+ },
99
+ });
100
+ const component = renderer.create(
101
+ <Provider store={store}>
102
+ <ModalForm
103
+ schema={{
104
+ fieldsets: [],
105
+ properties: {},
106
+ required: [],
107
+ }}
108
+ onSubmit={() => {}}
109
+ onCancel={() => {}}
110
+ open={false}
111
+ title="Action without form"
112
+ />
113
+ </Provider>,
114
+ );
115
+ const json = component.toJSON();
116
+ expect(json).toMatchSnapshot();
117
+ });
96
118
  });
@@ -1,25 +1,7 @@
1
- /* TODO: When the Volto Team removes Jest configuration support from Volto core, update this file with the Vitest version of the mock.
2
- Then, in the tests, we need to replace:
3
-
4
- vi.mock('@plone/volto/components/manage/Form', async () => {
5
- return await import(
6
- '@plone/volto/components/manage/Form/__mocks__/index.vitest.tsx'
7
- );
8
- });
9
-
10
-
11
- with the following:
12
-
13
- vi.mock('@plone/volto/components/manage/Form');
14
-
15
- Finally, remove this comment.
16
- */
17
-
18
1
  import type { JSONSchema } from '@plone/types';
19
2
  import type { Ref } from 'react';
20
- const { forwardRef } = jest.requireActual('react');
3
+ import { forwardRef } from 'react';
21
4
 
22
- // Field descriptions can contain react elements and those are not JSON stringifiable
23
5
  const cleanupSchema = (schema: JSONSchema | null): JSONSchema | null => {
24
6
  if (!schema || !schema.properties) return schema;
25
7
  return {
@@ -40,38 +22,38 @@ const cleanupSchema = (schema: JSONSchema | null): JSONSchema | null => {
40
22
  };
41
23
  };
42
24
 
43
- export const Field = jest.fn((props) => (
25
+ export const Field = vi.fn((props) => (
44
26
  <div className="Field" id={props.id}>
45
27
  {props.title}
46
28
  </div>
47
29
  ));
48
30
 
49
- export const InlineForm = jest.fn((props) => (
31
+ export const InlineForm = vi.fn((props) => (
50
32
  <div
51
33
  id="InlineForm"
52
34
  data-schema={JSON.stringify(cleanupSchema(props.schema), null, 2)}
53
35
  />
54
36
  ));
55
37
 
56
- export const ModalForm = jest.fn((props) => (
38
+ export const ModalForm = vi.fn((props) => (
57
39
  <div
58
40
  id="ModalForm"
59
41
  data-schema={JSON.stringify(cleanupSchema(props.schema), null, 2)}
60
42
  />
61
43
  ));
62
44
 
63
- export const UndoToolbar = jest.fn(() => <div id="UndoToolbar" />);
45
+ export const UndoToolbar = vi.fn(() => <div id="UndoToolbar" />);
64
46
 
65
- export const BlocksToolbar = jest.fn(() => <div id="BlocksToolbar" />);
47
+ export const BlocksToolbar = vi.fn(() => <div id="BlocksToolbar" />);
66
48
 
67
- export const BlockDataForm = jest.fn((props) => (
49
+ export const BlockDataForm = vi.fn((props) => (
68
50
  <div
69
51
  id="BlockDataForm"
70
52
  data-schema={JSON.stringify(cleanupSchema(props.schema), null, 2)}
71
53
  />
72
54
  ));
73
55
 
74
- export const BlocksForm = jest.fn((props) => (
56
+ export const BlocksForm = vi.fn((props) => (
75
57
  <div
76
58
  id="BlocksForm"
77
59
  data-schema={JSON.stringify(cleanupSchema(props.schema), null, 2)}
@@ -88,4 +70,4 @@ const MockForm = forwardRef(
88
70
  ),
89
71
  );
90
72
 
91
- export const Form = jest.fn((props) => <MockForm {...props} />);
73
+ export const Form = vi.fn((props) => <MockForm {...props} />);
@@ -1,6 +1,5 @@
1
1
  import React, { useState } from 'react';
2
2
  import { defineMessages, useIntl } from 'react-intl';
3
- import config from '@plone/volto/registry';
4
3
  import langmap from '@plone/volto/helpers/LanguageMap/LanguageMap';
5
4
  import { useDetectClickOutside } from '@plone/volto/helpers/Utils/useDetectClickOutside';
6
5
 
@@ -106,16 +105,14 @@ const CompareLanguages = React.forwardRef((props, ref) => {
106
105
 
107
106
  const intl = useIntl();
108
107
  const [viewMenu, setViewMenu] = useState(false);
109
- const translations = config.settings.isMultilingual
110
- ? content?.['@components']?.translations?.items || []
111
- : [];
108
+ const translations = content?.['@components']?.translations?.items || [];
112
109
 
113
110
  const translationsObject = {};
114
111
  translations.forEach((t) => {
115
112
  translationsObject[t.language] = t['@id'];
116
113
  });
117
114
 
118
- if (config.settings.isMultilingual && translations.length > 0) {
115
+ if (translations.length > 0) {
119
116
  return (
120
117
  <div className="toolbar-compare-translations-wrapper">
121
118
  <div className="toolbar-button-spacer" />
@@ -12,9 +12,12 @@ const CreateTranslation = (props) => {
12
12
  const dispatch = useDispatch();
13
13
  const { language, translationOf } = props.location.state;
14
14
  const [translationLocation, setTranslationLocation] = React.useState(null);
15
- const [translationObject, setTranslationObject] = React.useState(null);
16
15
  const languageFrom = useSelector((state) => state.intl.locale);
17
16
 
17
+ const translationObject = useSelector(
18
+ (state) => state.content.subrequests['translationObject'],
19
+ );
20
+
18
21
  React.useEffect(() => {
19
22
  // Only on mount, we dispatch the locator query
20
23
  dispatch(getTranslationLocator(translationOf, language)).then((resp) => {
@@ -22,11 +25,7 @@ const CreateTranslation = (props) => {
22
25
  });
23
26
 
24
27
  //and we load the translationObject
25
- dispatch(getContent(translationOf, null, 'translationObject')).then(
26
- (resp) => {
27
- setTranslationObject(resp);
28
- },
29
- );
28
+ dispatch(getContent(translationOf, null, 'translationObject'));
30
29
 
31
30
  // On unmount we dispatch the language change
32
31
  return () => {
@@ -46,7 +45,8 @@ const CreateTranslation = (props) => {
46
45
 
47
46
  return (
48
47
  translationLocation &&
49
- translationObject && (
48
+ translationObject.data &&
49
+ translationObject.loaded > 0 && (
50
50
  <Redirect
51
51
  to={{
52
52
  pathname: `${flattenToAppURL(translationLocation)}/add`,
@@ -54,7 +54,7 @@ const CreateTranslation = (props) => {
54
54
  state: {
55
55
  translationOf: props.location.state.translationOf,
56
56
  language: props.location.state.language,
57
- translationObject: translationObject,
57
+ translationObject: translationObject.data,
58
58
  languageFrom,
59
59
  },
60
60
  }}
@@ -8,7 +8,6 @@ import { Link, useLocation } from 'react-router-dom';
8
8
  import Icon from '@plone/volto/components/theme/Icon/Icon';
9
9
  import Toast from '@plone/volto/components/manage/Toast/Toast';
10
10
  import Toolbar from '@plone/volto/components/manage/Toolbar/Toolbar';
11
- import config from '@plone/volto/registry';
12
11
 
13
12
  import withObjectBrowser from '@plone/volto/components/manage/Sidebar/ObjectBrowser';
14
13
  import {
@@ -66,6 +65,9 @@ const ManageTranslations = (props) => {
66
65
  const pathname = useLocation().pathname;
67
66
  const content = useSelector((state) => state.content.data);
68
67
  const dispatch = useDispatch();
68
+ const availableLanguages = useSelector(
69
+ (state) => state.site.data['plone.available_languages'],
70
+ );
69
71
 
70
72
  const [isClient, setIsClient] = useState(false);
71
73
 
@@ -189,7 +191,7 @@ const ManageTranslations = (props) => {
189
191
  </Table.Row>
190
192
  </Table.Header>
191
193
  <Table.Body>
192
- {config.settings.supportedLanguages.map((lang) => (
194
+ {availableLanguages.map((lang) => (
193
195
  <Table.Row key={lang}>
194
196
  <Table.Cell collapsing>
195
197
  {lang === content.language.token ? (
@@ -8,7 +8,6 @@ import config from '@plone/volto/registry';
8
8
  import ManageTranslations from './ManageTranslations';
9
9
 
10
10
  beforeAll(() => {
11
- config.settings.isMultilingual = true;
12
11
  config.settings.supportedLanguages = ['de', 'es'];
13
12
  });
14
13
  vi.mock('../Toolbar/Toolbar', () => ({
@@ -34,6 +33,11 @@ describe('ManageTranslations', () => {
34
33
  language: 'en',
35
34
  },
36
35
  },
36
+ site: {
37
+ data: {
38
+ 'plone.available_languages': ['de', 'es'],
39
+ },
40
+ },
37
41
  });
38
42
  const { container } = render(
39
43
  <Provider store={store}>
@@ -63,7 +63,7 @@ const TranslationObject = ({
63
63
  {
64
64
  ...window.__data,
65
65
  intl: {
66
- defaultLocale: config.settings.defaultLanguage,
66
+ defaultLocale: translationObject.language.token,
67
67
  locale: translationObject.language.token,
68
68
  messages: locales[translationObject.language.token],
69
69
  },
@@ -9,11 +9,7 @@ import ChangePassword from './ChangePassword';
9
9
 
10
10
  const mockStore = configureStore();
11
11
 
12
- vi.mock('@plone/volto/components/manage/Form', async () => {
13
- return await import(
14
- '@plone/volto/components/manage/Form/__mocks__/index.vitest.tsx'
15
- );
16
- });
12
+ vi.mock('@plone/volto/components/manage/Form');
17
13
 
18
14
  vi.mock('../Toolbar/Toolbar', () => ({
19
15
  default: vi.fn(() => <div id="Portal" />),
@@ -12,23 +12,7 @@ vi.mock('../Toolbar/Toolbar', () => ({
12
12
  default: vi.fn(() => <div id="Portal" />),
13
13
  }));
14
14
 
15
- vi.mock('@plone/volto/components/manage/Form', async () => {
16
- return await import(
17
- '@plone/volto/components/manage/Form/__mocks__/index.vitest.tsx'
18
- );
19
- });
20
- vi.mock('@plone/volto/helpers/Loadable/Loadable', async () => {
21
- return await import(
22
- '@plone/volto/helpers/Loadable/__mocks__/Loadable.vitest.jsx'
23
- );
24
- });
25
-
26
- beforeAll(async () => {
27
- const { __setLoadables } = await import(
28
- '@plone/volto/helpers/Loadable/Loadable'
29
- );
30
- await __setLoadables();
31
- });
15
+ vi.mock('@plone/volto/components/manage/Form');
32
16
 
33
17
  describe('PersonalPreferences', () => {
34
18
  it('renders a personal preferences component', () => {
@@ -58,6 +58,7 @@ const withObjectBrowser = (WrappedComponent) =>
58
58
  selectableTypes,
59
59
  maximumSelectionSize,
60
60
  currentPath,
61
+ onlyFolderishSelectable,
61
62
  } = {}) =>
62
63
  this.setState(() => ({
63
64
  isObjectBrowserOpen: true,
@@ -70,6 +71,7 @@ const withObjectBrowser = (WrappedComponent) =>
70
71
  selectableTypes,
71
72
  maximumSelectionSize,
72
73
  currentPath,
74
+ onlyFolderishSelectable,
73
75
  }));
74
76
 
75
77
  closeObjectBrowser = () => this.setState({ isObjectBrowserOpen: false });
@@ -110,6 +112,7 @@ const withObjectBrowser = (WrappedComponent) =>
110
112
  searchableTypes={this.state.searchableTypes}
111
113
  selectableTypes={this.state.selectableTypes}
112
114
  maximumSelectionSize={this.state.maximumSelectionSize}
115
+ onlyFolderishSelectable={this.state.onlyFolderishSelectable}
113
116
  />
114
117
  </SidebarPopup>
115
118
  </>
@@ -86,6 +86,7 @@ class ObjectBrowserBody extends Component {
86
86
  maximumSelectionSize: PropTypes.number,
87
87
  contextURL: PropTypes.string,
88
88
  searchableTypes: PropTypes.arrayOf(PropTypes.string),
89
+ onlyFolderishSelectable: PropTypes.bool,
89
90
  };
90
91
 
91
92
  /**
@@ -101,6 +102,7 @@ class ObjectBrowserBody extends Component {
101
102
  selectableTypes: [],
102
103
  searchableTypes: null,
103
104
  maximumSelectionSize: null,
105
+ onlyFolderishSelectable: false,
104
106
  };
105
107
 
106
108
  /**
@@ -329,7 +331,17 @@ class ObjectBrowserBody extends Component {
329
331
  };
330
332
 
331
333
  isSelectable = (item) => {
332
- const { maximumSelectionSize, data, mode, selectableTypes } = this.props;
334
+ const {
335
+ maximumSelectionSize,
336
+ data,
337
+ mode,
338
+ selectableTypes,
339
+ onlyFolderishSelectable,
340
+ } = this.props;
341
+
342
+ if (onlyFolderishSelectable && !item.is_folderish) {
343
+ return false;
344
+ }
333
345
  if (
334
346
  maximumSelectionSize &&
335
347
  data &&
@@ -3,6 +3,7 @@ import { Button, Segment, Popup } from 'semantic-ui-react';
3
3
  import { useIntl, defineMessages } from 'react-intl';
4
4
  import cx from 'classnames';
5
5
  import Icon from '@plone/volto/components/theme/Icon/Icon';
6
+ import Image from '@plone/volto/components/theme/Image/Image';
6
7
  import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
7
8
  import { getContentIcon } from '@plone/volto/helpers/Content/Content';
8
9
  import config from '@plone/volto/registry';
@@ -69,7 +70,7 @@ const ObjectBrowserNav = ({
69
70
  }
70
71
  >
71
72
  {item['@type'] === 'Image' ? (
72
- <img
73
+ <Image
73
74
  src={`${item['@id']}/@@images/image/preview`}
74
75
  alt={item.title}
75
76
  style={{
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import { cleanup, render, screen } from '@testing-library/react';
3
+
4
+ import SidebarPortal from './SidebarPortal';
5
+
6
+ describe('SidebarPortal', () => {
7
+ let portalRoot: HTMLDivElement | null;
8
+
9
+ beforeEach(() => {
10
+ portalRoot = document.createElement('div');
11
+ portalRoot.setAttribute('id', 'sidebar-properties');
12
+ document.body.appendChild(portalRoot);
13
+ });
14
+
15
+ afterEach(() => {
16
+ cleanup();
17
+ portalRoot?.remove();
18
+ portalRoot = null;
19
+ });
20
+
21
+ test('renders the sidebar portal when the block is selected', async () => {
22
+ render(
23
+ <SidebarPortal selected={true}>
24
+ <p>Tested!</p>
25
+ </SidebarPortal>,
26
+ );
27
+
28
+ expect(await screen.findByText('Tested!')).toBeInTheDocument();
29
+ });
30
+
31
+ test('does not render the sidebar portal when the block is not selected', () => {
32
+ render(
33
+ <SidebarPortal selected={false}>
34
+ <p>Tested, but you should not see this!</p>
35
+ </SidebarPortal>,
36
+ );
37
+
38
+ expect(
39
+ screen.queryByText('Tested, but you should not see this!'),
40
+ ).not.toBeInTheDocument();
41
+ });
42
+ });