@evfrenkel/decap-cms-core 3.13.0-image-conversions.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 (306) hide show
  1. package/README.md +9 -0
  2. package/dist/20.decap-cms-core.js +2 -0
  3. package/dist/20.decap-cms-core.js.map +1 -0
  4. package/dist/3802306e7b58a11862fb.wasm +0 -0
  5. package/dist/@evfrenkel/20.decap-cms-core.js +2 -0
  6. package/dist/@evfrenkel/20.decap-cms-core.js.map +1 -0
  7. package/dist/@evfrenkel/decap-cms-core.js +44 -0
  8. package/dist/@evfrenkel/decap-cms-core.js.LICENSE.txt +126 -0
  9. package/dist/@evfrenkel/decap-cms-core.js.map +1 -0
  10. package/dist/decap-cms-core.js +47 -0
  11. package/dist/decap-cms-core.js.LICENSE.txt +126 -0
  12. package/dist/decap-cms-core.js.map +1 -0
  13. package/dist/esm/actions/auth.js +97 -0
  14. package/dist/esm/actions/collections.js +15 -0
  15. package/dist/esm/actions/config.js +503 -0
  16. package/dist/esm/actions/deploys.js +80 -0
  17. package/dist/esm/actions/editorialWorkflow.js +480 -0
  18. package/dist/esm/actions/entries.js +876 -0
  19. package/dist/esm/actions/media.js +147 -0
  20. package/dist/esm/actions/mediaLibrary.js +599 -0
  21. package/dist/esm/actions/notifications.js +21 -0
  22. package/dist/esm/actions/search.js +149 -0
  23. package/dist/esm/actions/status.js +74 -0
  24. package/dist/esm/actions/waitUntil.js +32 -0
  25. package/dist/esm/backend.js +1090 -0
  26. package/dist/esm/bootstrap.js +101 -0
  27. package/dist/esm/components/App/App.js +296 -0
  28. package/dist/esm/components/App/Header.js +172 -0
  29. package/dist/esm/components/App/NotFoundPage.js +19 -0
  30. package/dist/esm/components/Collection/Collection.js +198 -0
  31. package/dist/esm/components/Collection/CollectionControls.js +47 -0
  32. package/dist/esm/components/Collection/CollectionSearch.js +222 -0
  33. package/dist/esm/components/Collection/CollectionTop.js +68 -0
  34. package/dist/esm/components/Collection/ControlButton.js +17 -0
  35. package/dist/esm/components/Collection/Entries/Entries.js +73 -0
  36. package/dist/esm/components/Collection/Entries/EntriesCollection.js +241 -0
  37. package/dist/esm/components/Collection/Entries/EntriesSearch.js +113 -0
  38. package/dist/esm/components/Collection/Entries/EntryCard.js +192 -0
  39. package/dist/esm/components/Collection/Entries/EntryListing.js +143 -0
  40. package/dist/esm/components/Collection/FilterControl.js +33 -0
  41. package/dist/esm/components/Collection/GroupControl.js +33 -0
  42. package/dist/esm/components/Collection/NestedCollection.js +308 -0
  43. package/dist/esm/components/Collection/Sidebar.js +91 -0
  44. package/dist/esm/components/Collection/SortControl.js +59 -0
  45. package/dist/esm/components/Collection/ViewStyleControl.js +41 -0
  46. package/dist/esm/components/Editor/Editor.js +466 -0
  47. package/dist/esm/components/Editor/EditorControlPane/EditorControl.js +398 -0
  48. package/dist/esm/components/Editor/EditorControlPane/EditorControlPane.js +254 -0
  49. package/dist/esm/components/Editor/EditorControlPane/Widget.js +374 -0
  50. package/dist/esm/components/Editor/EditorInterface.js +386 -0
  51. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreview.js +47 -0
  52. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewContent.js +67 -0
  53. package/dist/esm/components/Editor/EditorPreviewPane/EditorPreviewPane.js +306 -0
  54. package/dist/esm/components/Editor/EditorPreviewPane/PreviewHOC.js +27 -0
  55. package/dist/esm/components/Editor/EditorToolbar.js +554 -0
  56. package/dist/esm/components/Editor/withWorkflow.js +56 -0
  57. package/dist/esm/components/EditorWidgets/Unknown/UnknownControl.js +18 -0
  58. package/dist/esm/components/EditorWidgets/Unknown/UnknownPreview.js +20 -0
  59. package/dist/esm/components/EditorWidgets/index.js +4 -0
  60. package/dist/esm/components/MediaLibrary/EmptyMessage.js +22 -0
  61. package/dist/esm/components/MediaLibrary/MediaLibrary.js +446 -0
  62. package/dist/esm/components/MediaLibrary/MediaLibraryButtons.js +92 -0
  63. package/dist/esm/components/MediaLibrary/MediaLibraryCard.js +99 -0
  64. package/dist/esm/components/MediaLibrary/MediaLibraryCardGrid.js +198 -0
  65. package/dist/esm/components/MediaLibrary/MediaLibraryHeader.js +34 -0
  66. package/dist/esm/components/MediaLibrary/MediaLibraryModal.js +156 -0
  67. package/dist/esm/components/MediaLibrary/MediaLibrarySearch.js +51 -0
  68. package/dist/esm/components/MediaLibrary/MediaLibraryTop.js +124 -0
  69. package/dist/esm/components/UI/DragDrop.js +67 -0
  70. package/dist/esm/components/UI/ErrorBoundary.js +170 -0
  71. package/dist/esm/components/UI/FileUploadButton.js +27 -0
  72. package/dist/esm/components/UI/Modal.js +104 -0
  73. package/dist/esm/components/UI/Notifications.js +62 -0
  74. package/dist/esm/components/UI/SettingsDropdown.js +107 -0
  75. package/dist/esm/components/UI/index.js +6 -0
  76. package/dist/esm/components/Workflow/Workflow.js +133 -0
  77. package/dist/esm/components/Workflow/WorkflowCard.js +128 -0
  78. package/dist/esm/components/Workflow/WorkflowList.js +204 -0
  79. package/dist/esm/constants/collectionTypes.js +2 -0
  80. package/dist/esm/constants/collectionViews.js +2 -0
  81. package/dist/esm/constants/commitProps.js +2 -0
  82. package/dist/esm/constants/configSchema.js +695 -0
  83. package/dist/esm/constants/fieldInference.js +57 -0
  84. package/dist/esm/constants/publishModes.js +18 -0
  85. package/dist/esm/constants/validationErrorTypes.js +6 -0
  86. package/dist/esm/formats/formats.js +83 -0
  87. package/dist/esm/formats/frontmatter.js +146 -0
  88. package/dist/esm/formats/helpers.js +12 -0
  89. package/dist/esm/formats/json.js +8 -0
  90. package/dist/esm/formats/toml.js +32 -0
  91. package/dist/esm/formats/yaml.js +60 -0
  92. package/dist/esm/index.js +7 -0
  93. package/dist/esm/integrations/index.js +28 -0
  94. package/dist/esm/integrations/providers/algolia/implementation.js +174 -0
  95. package/dist/esm/integrations/providers/assetStore/implementation.js +165 -0
  96. package/dist/esm/lib/consoleError.js +3 -0
  97. package/dist/esm/lib/formatters.js +201 -0
  98. package/dist/esm/lib/i18n.js +372 -0
  99. package/dist/esm/lib/imageTransformations.js +143 -0
  100. package/dist/esm/lib/phrases.js +6 -0
  101. package/dist/esm/lib/polyfill.js +8 -0
  102. package/dist/esm/lib/registry.js +332 -0
  103. package/dist/esm/lib/serializeEntryValues.js +67 -0
  104. package/dist/esm/lib/stega.js +142 -0
  105. package/dist/esm/lib/textHelper.js +9 -0
  106. package/dist/esm/lib/urlHelper.js +129 -0
  107. package/dist/esm/mediaLibrary.js +37 -0
  108. package/dist/esm/reducers/auth.js +27 -0
  109. package/dist/esm/reducers/collections.js +428 -0
  110. package/dist/esm/reducers/combinedReducer.js +8 -0
  111. package/dist/esm/reducers/config.js +29 -0
  112. package/dist/esm/reducers/cursors.js +31 -0
  113. package/dist/esm/reducers/deploys.js +50 -0
  114. package/dist/esm/reducers/editorialWorkflow.js +83 -0
  115. package/dist/esm/reducers/entries.js +568 -0
  116. package/dist/esm/reducers/entryDraft.js +211 -0
  117. package/dist/esm/reducers/globalUI.js +25 -0
  118. package/dist/esm/reducers/index.js +66 -0
  119. package/dist/esm/reducers/integrations.js +53 -0
  120. package/dist/esm/reducers/mediaLibrary.js +252 -0
  121. package/dist/esm/reducers/medias.js +68 -0
  122. package/dist/esm/reducers/notifications.js +23 -0
  123. package/dist/esm/reducers/search.js +92 -0
  124. package/dist/esm/reducers/status.js +30 -0
  125. package/dist/esm/redux/index.js +7 -0
  126. package/dist/esm/redux/middleware/waitUntilAction.js +48 -0
  127. package/dist/esm/routing/history.js +12 -0
  128. package/dist/esm/types/diacritics.d.js +0 -0
  129. package/dist/esm/types/global.d.js +1 -0
  130. package/dist/esm/types/immutable.js +7 -0
  131. package/dist/esm/types/redux.js +14 -0
  132. package/dist/esm/types/tomlify-j0.4.d.js +0 -0
  133. package/dist/esm/valueObjects/AssetProxy.js +44 -0
  134. package/dist/esm/valueObjects/EditorComponent.js +34 -0
  135. package/dist/esm/valueObjects/Entry.js +20 -0
  136. package/index.d.ts +662 -0
  137. package/package.json +100 -0
  138. package/src/__tests__/backend.spec.js +1223 -0
  139. package/src/actions/__tests__/config.spec.js +1023 -0
  140. package/src/actions/__tests__/editorialWorkflow.spec.js +216 -0
  141. package/src/actions/__tests__/entries.spec.js +610 -0
  142. package/src/actions/__tests__/media.spec.ts +171 -0
  143. package/src/actions/__tests__/mediaLibrary.spec.js +462 -0
  144. package/src/actions/__tests__/search.spec.js +209 -0
  145. package/src/actions/auth.ts +127 -0
  146. package/src/actions/collections.ts +18 -0
  147. package/src/actions/config.ts +574 -0
  148. package/src/actions/deploys.ts +105 -0
  149. package/src/actions/editorialWorkflow.ts +567 -0
  150. package/src/actions/entries.ts +1070 -0
  151. package/src/actions/media.ts +139 -0
  152. package/src/actions/mediaLibrary.ts +639 -0
  153. package/src/actions/notifications.ts +36 -0
  154. package/src/actions/search.ts +221 -0
  155. package/src/actions/status.ts +99 -0
  156. package/src/actions/waitUntil.ts +49 -0
  157. package/src/backend.ts +1411 -0
  158. package/src/bootstrap.js +104 -0
  159. package/src/components/App/App.js +295 -0
  160. package/src/components/App/Header.js +291 -0
  161. package/src/components/App/NotFoundPage.js +23 -0
  162. package/src/components/Collection/Collection.js +210 -0
  163. package/src/components/Collection/CollectionControls.js +58 -0
  164. package/src/components/Collection/CollectionSearch.js +243 -0
  165. package/src/components/Collection/CollectionTop.js +81 -0
  166. package/src/components/Collection/ControlButton.js +27 -0
  167. package/src/components/Collection/Entries/Entries.js +82 -0
  168. package/src/components/Collection/Entries/EntriesCollection.js +277 -0
  169. package/src/components/Collection/Entries/EntriesSearch.js +102 -0
  170. package/src/components/Collection/Entries/EntryCard.js +256 -0
  171. package/src/components/Collection/Entries/EntryListing.js +151 -0
  172. package/src/components/Collection/Entries/__tests__/EntriesCollection.spec.js +163 -0
  173. package/src/components/Collection/Entries/__tests__/__snapshots__/EntriesCollection.spec.js.snap +46 -0
  174. package/src/components/Collection/FilterControl.js +39 -0
  175. package/src/components/Collection/GroupControl.js +39 -0
  176. package/src/components/Collection/NestedCollection.js +330 -0
  177. package/src/components/Collection/Sidebar.js +136 -0
  178. package/src/components/Collection/SortControl.js +68 -0
  179. package/src/components/Collection/ViewStyleControl.js +52 -0
  180. package/src/components/Collection/__tests__/Collection.spec.js +75 -0
  181. package/src/components/Collection/__tests__/NestedCollection.spec.js +445 -0
  182. package/src/components/Collection/__tests__/Sidebar.spec.js +87 -0
  183. package/src/components/Collection/__tests__/__snapshots__/Collection.spec.js.snap +144 -0
  184. package/src/components/Collection/__tests__/__snapshots__/NestedCollection.spec.js.snap +550 -0
  185. package/src/components/Collection/__tests__/__snapshots__/Sidebar.spec.js.snap +312 -0
  186. package/src/components/Editor/Editor.js +497 -0
  187. package/src/components/Editor/EditorControlPane/EditorControl.js +453 -0
  188. package/src/components/Editor/EditorControlPane/EditorControlPane.js +269 -0
  189. package/src/components/Editor/EditorControlPane/Widget.js +384 -0
  190. package/src/components/Editor/EditorInterface.js +444 -0
  191. package/src/components/Editor/EditorPreviewPane/EditorPreview.js +40 -0
  192. package/src/components/Editor/EditorPreviewPane/EditorPreviewContent.js +75 -0
  193. package/src/components/Editor/EditorPreviewPane/EditorPreviewPane.js +337 -0
  194. package/src/components/Editor/EditorPreviewPane/PreviewHOC.js +33 -0
  195. package/src/components/Editor/EditorToolbar.js +728 -0
  196. package/src/components/Editor/__tests__/Editor.spec.js +221 -0
  197. package/src/components/Editor/__tests__/EditorToolbar.spec.js +166 -0
  198. package/src/components/Editor/__tests__/__snapshots__/Editor.spec.js.snap +45 -0
  199. package/src/components/Editor/__tests__/__snapshots__/EditorToolbar.spec.js.snap +4265 -0
  200. package/src/components/Editor/withWorkflow.js +61 -0
  201. package/src/components/EditorWidgets/Unknown/UnknownControl.js +17 -0
  202. package/src/components/EditorWidgets/Unknown/UnknownPreview.js +19 -0
  203. package/src/components/EditorWidgets/index.js +5 -0
  204. package/src/components/MediaLibrary/EmptyMessage.js +28 -0
  205. package/src/components/MediaLibrary/MediaLibrary.js +411 -0
  206. package/src/components/MediaLibrary/MediaLibraryButtons.js +135 -0
  207. package/src/components/MediaLibrary/MediaLibraryCard.js +128 -0
  208. package/src/components/MediaLibrary/MediaLibraryCardGrid.js +199 -0
  209. package/src/components/MediaLibrary/MediaLibraryHeader.js +48 -0
  210. package/src/components/MediaLibrary/MediaLibraryModal.js +200 -0
  211. package/src/components/MediaLibrary/MediaLibrarySearch.js +61 -0
  212. package/src/components/MediaLibrary/MediaLibraryTop.js +144 -0
  213. package/src/components/MediaLibrary/__tests__/MediaLibraryButtons.spec.js +45 -0
  214. package/src/components/MediaLibrary/__tests__/MediaLibraryCard.spec.js +49 -0
  215. package/src/components/MediaLibrary/__tests__/__snapshots__/MediaLibraryCard.spec.js.snap +264 -0
  216. package/src/components/UI/DragDrop.js +66 -0
  217. package/src/components/UI/ErrorBoundary.js +213 -0
  218. package/src/components/UI/FileUploadButton.js +24 -0
  219. package/src/components/UI/Modal.js +112 -0
  220. package/src/components/UI/Notifications.tsx +83 -0
  221. package/src/components/UI/SettingsDropdown.js +130 -0
  222. package/src/components/UI/__tests__/ErrorBoundary.spec.js +57 -0
  223. package/src/components/UI/index.js +6 -0
  224. package/src/components/Workflow/Workflow.js +169 -0
  225. package/src/components/Workflow/WorkflowCard.js +177 -0
  226. package/src/components/Workflow/WorkflowList.js +272 -0
  227. package/src/constants/__tests__/configSchema.spec.js +644 -0
  228. package/src/constants/collectionTypes.ts +2 -0
  229. package/src/constants/collectionViews.js +2 -0
  230. package/src/constants/commitProps.ts +2 -0
  231. package/src/constants/configSchema.js +489 -0
  232. package/src/constants/fieldInference.tsx +78 -0
  233. package/src/constants/publishModes.ts +22 -0
  234. package/src/constants/validationErrorTypes.js +6 -0
  235. package/src/formats/__tests__/formats.spec.js +87 -0
  236. package/src/formats/__tests__/frontmatter.spec.js +450 -0
  237. package/src/formats/__tests__/toml.spec.js +9 -0
  238. package/src/formats/__tests__/yaml.spec.js +189 -0
  239. package/src/formats/formats.ts +97 -0
  240. package/src/formats/frontmatter.ts +150 -0
  241. package/src/formats/helpers.ts +14 -0
  242. package/src/formats/json.ts +9 -0
  243. package/src/formats/toml.ts +33 -0
  244. package/src/formats/yaml.ts +73 -0
  245. package/src/index.js +8 -0
  246. package/src/integrations/index.js +35 -0
  247. package/src/integrations/providers/algolia/implementation.js +176 -0
  248. package/src/integrations/providers/assetStore/implementation.js +148 -0
  249. package/src/lib/__tests__/formatters.spec.js +844 -0
  250. package/src/lib/__tests__/i18n.spec.js +792 -0
  251. package/src/lib/__tests__/imageTransformations.spec.ts +97 -0
  252. package/src/lib/__tests__/phrases.spec.js +119 -0
  253. package/src/lib/__tests__/registry.spec.js +261 -0
  254. package/src/lib/__tests__/serializeEntryValues.spec.js +22 -0
  255. package/src/lib/__tests__/urlHelper.spec.js +145 -0
  256. package/src/lib/consoleError.js +7 -0
  257. package/src/lib/formatters.ts +297 -0
  258. package/src/lib/i18n.ts +462 -0
  259. package/src/lib/imageTransformations.ts +212 -0
  260. package/src/lib/phrases.js +8 -0
  261. package/src/lib/polyfill.js +9 -0
  262. package/src/lib/registry.js +315 -0
  263. package/src/lib/serializeEntryValues.js +75 -0
  264. package/src/lib/stega.ts +145 -0
  265. package/src/lib/textHelper.js +11 -0
  266. package/src/lib/urlHelper.ts +152 -0
  267. package/src/mediaLibrary.ts +51 -0
  268. package/src/reducers/__tests__/auth.spec.ts +38 -0
  269. package/src/reducers/__tests__/collections.spec.js +610 -0
  270. package/src/reducers/__tests__/config.spec.js +38 -0
  271. package/src/reducers/__tests__/deploys.spec.ts +111 -0
  272. package/src/reducers/__tests__/entries.spec.js +694 -0
  273. package/src/reducers/__tests__/entryDraft.spec.js +315 -0
  274. package/src/reducers/__tests__/globalUI.js +43 -0
  275. package/src/reducers/__tests__/integrations.spec.ts +76 -0
  276. package/src/reducers/__tests__/mediaLibrary.spec.js +154 -0
  277. package/src/reducers/__tests__/medias.spec.ts +49 -0
  278. package/src/reducers/auth.ts +46 -0
  279. package/src/reducers/collections.ts +535 -0
  280. package/src/reducers/combinedReducer.ts +11 -0
  281. package/src/reducers/config.ts +38 -0
  282. package/src/reducers/cursors.js +36 -0
  283. package/src/reducers/deploys.ts +54 -0
  284. package/src/reducers/editorialWorkflow.ts +163 -0
  285. package/src/reducers/entries.ts +819 -0
  286. package/src/reducers/entryDraft.js +259 -0
  287. package/src/reducers/globalUI.ts +45 -0
  288. package/src/reducers/index.ts +82 -0
  289. package/src/reducers/integrations.ts +59 -0
  290. package/src/reducers/mediaLibrary.ts +296 -0
  291. package/src/reducers/medias.ts +66 -0
  292. package/src/reducers/notifications.ts +52 -0
  293. package/src/reducers/search.ts +111 -0
  294. package/src/reducers/status.ts +40 -0
  295. package/src/redux/index.ts +18 -0
  296. package/src/redux/middleware/waitUntilAction.ts +64 -0
  297. package/src/routing/__tests__/history.spec.ts +49 -0
  298. package/src/routing/history.ts +17 -0
  299. package/src/types/diacritics.d.ts +1 -0
  300. package/src/types/global.d.ts +8 -0
  301. package/src/types/immutable.ts +49 -0
  302. package/src/types/redux.ts +875 -0
  303. package/src/types/tomlify-j0.4.d.ts +13 -0
  304. package/src/valueObjects/AssetProxy.ts +48 -0
  305. package/src/valueObjects/EditorComponent.js +38 -0
  306. package/src/valueObjects/Entry.ts +63 -0
@@ -0,0 +1,610 @@
1
+ import { fromJS, List, Map } from 'immutable';
2
+ import configureMockStore from 'redux-mock-store';
3
+ import thunk from 'redux-thunk';
4
+
5
+ import {
6
+ createEmptyDraft,
7
+ createEmptyDraftData,
8
+ retrieveLocalBackup,
9
+ persistLocalBackup,
10
+ getMediaAssets,
11
+ validateMetaField,
12
+ } from '../entries';
13
+ import AssetProxy from '../../valueObjects/AssetProxy';
14
+
15
+ jest.mock('../../backend');
16
+ jest.mock('decap-cms-lib-util');
17
+ jest.mock('../mediaLibrary');
18
+ jest.mock('../../reducers/entries');
19
+ jest.mock('../../reducers/entryDraft');
20
+
21
+ const middlewares = [thunk];
22
+ const mockStore = configureMockStore(middlewares);
23
+
24
+ describe('entries', () => {
25
+ describe('createEmptyDraft', () => {
26
+ const { currentBackend } = require('../../backend');
27
+ const backend = {
28
+ processEntry: jest.fn((_state, _collection, entry) => Promise.resolve(entry)),
29
+ };
30
+
31
+ currentBackend.mockReturnValue(backend);
32
+
33
+ beforeEach(() => {
34
+ jest.clearAllMocks();
35
+ });
36
+ it('should dispatch draft created action', () => {
37
+ const store = mockStore({ mediaLibrary: fromJS({ files: [] }) });
38
+
39
+ const collection = fromJS({
40
+ fields: [{ name: 'title' }],
41
+ });
42
+
43
+ return store.dispatch(createEmptyDraft(collection, '')).then(() => {
44
+ const actions = store.getActions();
45
+ expect(actions).toHaveLength(1);
46
+
47
+ expect(actions[0]).toEqual({
48
+ payload: {
49
+ author: '',
50
+ collection: undefined,
51
+ data: {},
52
+ meta: {},
53
+ i18n: {},
54
+ isModification: null,
55
+ label: null,
56
+ mediaFiles: [],
57
+ partial: false,
58
+ path: '',
59
+ raw: '',
60
+ slug: '',
61
+ status: '',
62
+ updatedOn: '',
63
+ },
64
+ type: 'DRAFT_CREATE_EMPTY',
65
+ });
66
+ });
67
+ });
68
+
69
+ it('should populate draft entry from URL param', () => {
70
+ const store = mockStore({ mediaLibrary: fromJS({ files: [] }) });
71
+
72
+ const collection = fromJS({
73
+ fields: [{ name: 'title' }, { name: 'boolean' }],
74
+ });
75
+
76
+ return store.dispatch(createEmptyDraft(collection, '?title=title&boolean=True')).then(() => {
77
+ const actions = store.getActions();
78
+ expect(actions).toHaveLength(1);
79
+
80
+ expect(actions[0]).toEqual({
81
+ payload: {
82
+ author: '',
83
+ collection: undefined,
84
+ data: { title: 'title', boolean: true },
85
+ meta: {},
86
+ i18n: {},
87
+ isModification: null,
88
+ label: null,
89
+ mediaFiles: [],
90
+ partial: false,
91
+ path: '',
92
+ raw: '',
93
+ slug: '',
94
+ status: '',
95
+ updatedOn: '',
96
+ },
97
+ type: 'DRAFT_CREATE_EMPTY',
98
+ });
99
+ });
100
+ });
101
+
102
+ it('should populate draft entry from repeated URL param', () => {
103
+ const store = mockStore({ mediaLibrary: fromJS({ files: [] }) });
104
+
105
+ const collection = fromJS({
106
+ fields: [{ name: 'post', multiple: true }],
107
+ });
108
+
109
+ return store
110
+ .dispatch(createEmptyDraft(collection, '?post=2026-05-07-test&post=2026-05-08-test'))
111
+ .then(() => {
112
+ const actions = store.getActions();
113
+ expect(actions).toHaveLength(1);
114
+
115
+ expect(actions[0]).toEqual({
116
+ payload: {
117
+ author: '',
118
+ collection: undefined,
119
+ data: { post: List(['2026-05-07-test', '2026-05-08-test']) },
120
+ meta: {},
121
+ i18n: {},
122
+ isModification: null,
123
+ label: null,
124
+ mediaFiles: [],
125
+ partial: false,
126
+ path: '',
127
+ raw: '',
128
+ slug: '',
129
+ status: '',
130
+ updatedOn: '',
131
+ },
132
+ type: 'DRAFT_CREATE_EMPTY',
133
+ });
134
+ });
135
+ });
136
+
137
+ it('should html escape URL params', () => {
138
+ const store = mockStore({ mediaLibrary: fromJS({ files: [] }) });
139
+
140
+ const collection = fromJS({
141
+ fields: [{ name: 'title' }],
142
+ });
143
+
144
+ return store
145
+ .dispatch(createEmptyDraft(collection, "?title=<script>alert('hello')</script>"))
146
+ .then(() => {
147
+ const actions = store.getActions();
148
+ expect(actions).toHaveLength(1);
149
+
150
+ expect(actions[0]).toEqual({
151
+ payload: {
152
+ author: '',
153
+ collection: undefined,
154
+ data: { title: '&lt;script&gt;alert(&#039;hello&#039;)&lt;/script&gt;' },
155
+ meta: {},
156
+ i18n: {},
157
+ isModification: null,
158
+ label: null,
159
+ mediaFiles: [],
160
+ partial: false,
161
+ path: '',
162
+ raw: '',
163
+ slug: '',
164
+ status: '',
165
+ updatedOn: '',
166
+ },
167
+ type: 'DRAFT_CREATE_EMPTY',
168
+ });
169
+ });
170
+ });
171
+ });
172
+ describe('createEmptyDraftData', () => {
173
+ it('should allow an empty array as list default for a single field list', () => {
174
+ const fields = fromJS([
175
+ {
176
+ name: 'images',
177
+ widget: 'list',
178
+ default: [],
179
+ field: { name: 'url', widget: 'text' },
180
+ },
181
+ ]);
182
+ expect(createEmptyDraftData(fields)).toEqual({ images: fromJS([]) });
183
+ });
184
+
185
+ it('should allow a complex array as list default for a single field list', () => {
186
+ const fields = fromJS([
187
+ {
188
+ name: 'images',
189
+ widget: 'list',
190
+ default: [
191
+ {
192
+ url: 'https://image.png',
193
+ },
194
+ ],
195
+ field: { name: 'url', widget: 'text' },
196
+ },
197
+ ]);
198
+ expect(createEmptyDraftData(fields)).toEqual({
199
+ images: fromJS([
200
+ {
201
+ url: 'https://image.png',
202
+ },
203
+ ]),
204
+ });
205
+ });
206
+
207
+ it('should allow an empty array as list default for a fields list', () => {
208
+ const fields = fromJS([
209
+ {
210
+ name: 'images',
211
+ widget: 'list',
212
+ default: [],
213
+ fields: [
214
+ { name: 'title', widget: 'text' },
215
+ { name: 'url', widget: 'text' },
216
+ ],
217
+ },
218
+ ]);
219
+ expect(createEmptyDraftData(fields)).toEqual({ images: fromJS([]) });
220
+ });
221
+
222
+ it('should allow a complex array as list default for a fields list', () => {
223
+ const fields = fromJS([
224
+ {
225
+ name: 'images',
226
+ widget: 'list',
227
+ default: [
228
+ {
229
+ title: 'default image',
230
+ url: 'https://image.png',
231
+ },
232
+ ],
233
+ fields: [
234
+ { name: 'title', widget: 'text' },
235
+ { name: 'url', widget: 'text' },
236
+ ],
237
+ },
238
+ ]);
239
+ expect(createEmptyDraftData(fields)).toEqual({
240
+ images: fromJS([
241
+ {
242
+ title: 'default image',
243
+ url: 'https://image.png',
244
+ },
245
+ ]),
246
+ });
247
+ });
248
+
249
+ it('should use field default when no list default is provided', () => {
250
+ const fields = fromJS([
251
+ {
252
+ name: 'images',
253
+ widget: 'list',
254
+ field: { name: 'url', widget: 'text', default: 'https://image.png' },
255
+ },
256
+ ]);
257
+ expect(createEmptyDraftData(fields)).toEqual({ images: [{ url: 'https://image.png' }] });
258
+ });
259
+
260
+ it('should use fields default when no list default is provided', () => {
261
+ const fields = fromJS([
262
+ {
263
+ name: 'images',
264
+ widget: 'list',
265
+ fields: [
266
+ { name: 'title', widget: 'text', default: 'default image' },
267
+ { name: 'url', widget: 'text', default: 'https://image.png' },
268
+ ],
269
+ },
270
+ ]);
271
+ expect(createEmptyDraftData(fields)).toEqual({
272
+ images: [{ title: 'default image', url: 'https://image.png' }],
273
+ });
274
+ });
275
+
276
+ it('should not set empty value for list fields widget', () => {
277
+ const fields = fromJS([
278
+ {
279
+ name: 'images',
280
+ widget: 'list',
281
+ fields: [
282
+ { name: 'title', widget: 'text' },
283
+ { name: 'url', widget: 'text' },
284
+ ],
285
+ },
286
+ ]);
287
+ expect(createEmptyDraftData(fields)).toEqual({});
288
+ });
289
+
290
+ it('should set default value for object field widget', () => {
291
+ const fields = fromJS([
292
+ {
293
+ name: 'post',
294
+ widget: 'object',
295
+ field: { name: 'image', widget: 'text', default: 'https://image.png' },
296
+ },
297
+ ]);
298
+ expect(createEmptyDraftData(fields)).toEqual({ post: { image: 'https://image.png' } });
299
+ });
300
+
301
+ it('should set default values for object fields widget', () => {
302
+ const fields = fromJS([
303
+ {
304
+ name: 'post',
305
+ widget: 'object',
306
+ fields: [
307
+ { name: 'title', widget: 'text', default: 'default title' },
308
+ { name: 'url', widget: 'text', default: 'https://image.png' },
309
+ ],
310
+ },
311
+ ]);
312
+ expect(createEmptyDraftData(fields)).toEqual({
313
+ post: { title: 'default title', url: 'https://image.png' },
314
+ });
315
+ });
316
+
317
+ it('should not set empty value for object fields widget', () => {
318
+ const fields = fromJS([
319
+ {
320
+ name: 'post',
321
+ widget: 'object',
322
+ fields: [
323
+ { name: 'title', widget: 'text' },
324
+ { name: 'url', widget: 'text' },
325
+ ],
326
+ },
327
+ ]);
328
+ expect(createEmptyDraftData(fields)).toEqual({});
329
+ });
330
+
331
+ it('should populate nested fields', () => {
332
+ const fields = fromJS([
333
+ {
334
+ name: 'names',
335
+ widget: 'list',
336
+ field: {
337
+ name: 'object',
338
+ widget: 'object',
339
+ fields: [
340
+ { name: 'first', widget: 'string', default: 'first' },
341
+ { name: 'second', widget: 'string', default: 'second' },
342
+ ],
343
+ },
344
+ },
345
+ ]);
346
+ expect(createEmptyDraftData(fields)).toEqual({
347
+ names: [{ object: { first: 'first', second: 'second' } }],
348
+ });
349
+ });
350
+ });
351
+
352
+ describe('persistLocalBackup', () => {
353
+ beforeEach(() => {
354
+ jest.clearAllMocks();
355
+ });
356
+
357
+ it('should persist local backup with media files', () => {
358
+ const { currentBackend } = require('../../backend');
359
+
360
+ const backend = {
361
+ persistLocalDraftBackup: jest.fn(() => Promise.resolve()),
362
+ };
363
+
364
+ const store = mockStore({
365
+ config: Map(),
366
+ });
367
+
368
+ currentBackend.mockReturnValue(backend);
369
+
370
+ const collection = Map();
371
+ const mediaFiles = [{ path: 'static/media/image.png' }];
372
+ const entry = fromJS({ mediaFiles });
373
+
374
+ return store.dispatch(persistLocalBackup(entry, collection)).then(() => {
375
+ const actions = store.getActions();
376
+ expect(actions).toHaveLength(0);
377
+
378
+ expect(backend.persistLocalDraftBackup).toHaveBeenCalledTimes(1);
379
+ expect(backend.persistLocalDraftBackup).toHaveBeenCalledWith(entry, collection);
380
+ });
381
+ });
382
+ });
383
+
384
+ describe('retrieveLocalBackup', () => {
385
+ beforeEach(() => {
386
+ jest.clearAllMocks();
387
+ });
388
+
389
+ it('should retrieve media files with local backup', () => {
390
+ const { currentBackend } = require('../../backend');
391
+ const { createAssetProxy } = require('../../valueObjects/AssetProxy');
392
+
393
+ const backend = {
394
+ getLocalDraftBackup: jest.fn((...args) => args),
395
+ };
396
+
397
+ const store = mockStore({
398
+ config: Map(),
399
+ });
400
+
401
+ currentBackend.mockReturnValue(backend);
402
+
403
+ const collection = Map({
404
+ name: 'collection',
405
+ });
406
+ const slug = 'slug';
407
+
408
+ const file = new File([], 'image.png');
409
+ const mediaFiles = [{ path: 'static/media/image.png', url: 'url', file }];
410
+ const asset = createAssetProxy(mediaFiles[0]);
411
+ const entry = { mediaFiles };
412
+
413
+ backend.getLocalDraftBackup.mockReturnValue({ entry });
414
+
415
+ return store.dispatch(retrieveLocalBackup(collection, slug)).then(() => {
416
+ const actions = store.getActions();
417
+
418
+ expect(actions).toHaveLength(2);
419
+
420
+ expect(actions[0]).toEqual({
421
+ type: 'ADD_ASSETS',
422
+ payload: [asset],
423
+ });
424
+ expect(actions[1]).toEqual({
425
+ type: 'DRAFT_LOCAL_BACKUP_RETRIEVED',
426
+ payload: { entry },
427
+ });
428
+ });
429
+ });
430
+ });
431
+
432
+ describe('getMediaAssets', () => {
433
+ beforeEach(() => {
434
+ jest.clearAllMocks();
435
+ });
436
+
437
+ it('should map mediaFiles to assets', () => {
438
+ const mediaFiles = fromJS([{ path: 'path1' }, { path: 'path2', draft: true }]);
439
+
440
+ const entry = Map({ mediaFiles });
441
+ expect(getMediaAssets({ entry })).toEqual([new AssetProxy({ path: 'path2' })]);
442
+ });
443
+ });
444
+
445
+ describe('validateMetaField', () => {
446
+ const state = {
447
+ config: {
448
+ slug: {
449
+ encoding: 'unicode',
450
+ clean_accents: false,
451
+ sanitize_replacement: '-',
452
+ },
453
+ },
454
+ entries: fromJS([]),
455
+ };
456
+ const collection = fromJS({
457
+ folder: 'folder',
458
+ type: 'folder_based_collection',
459
+ name: 'name',
460
+ });
461
+ const t = jest.fn((key, args) => ({ key, args }));
462
+
463
+ const { selectCustomPath } = require('../../reducers/entryDraft');
464
+ const { selectEntryByPath } = require('../../reducers/entries');
465
+
466
+ beforeEach(() => {
467
+ jest.clearAllMocks();
468
+ });
469
+
470
+ it('should not return error on non meta field', () => {
471
+ expect(validateMetaField(null, null, fromJS({}), null, t)).toEqual({ error: false });
472
+ });
473
+
474
+ it('should not return error on meta path field', () => {
475
+ expect(validateMetaField(null, null, fromJS({ meta: true, name: 'other' }), null, t)).toEqual(
476
+ { error: false },
477
+ );
478
+ });
479
+
480
+ it('should return error on empty path', () => {
481
+ expect(validateMetaField(null, null, fromJS({ meta: true, name: 'path' }), null, t)).toEqual({
482
+ error: {
483
+ message: {
484
+ key: 'editor.editorControlPane.widget.invalidPath',
485
+ args: { path: null },
486
+ },
487
+ type: 'CUSTOM',
488
+ },
489
+ });
490
+
491
+ expect(
492
+ validateMetaField(null, null, fromJS({ meta: true, name: 'path' }), undefined, t),
493
+ ).toEqual({
494
+ error: {
495
+ message: {
496
+ key: 'editor.editorControlPane.widget.invalidPath',
497
+ args: { path: undefined },
498
+ },
499
+ type: 'CUSTOM',
500
+ },
501
+ });
502
+
503
+ expect(validateMetaField(null, null, fromJS({ meta: true, name: 'path' }), '', t)).toEqual({
504
+ error: {
505
+ message: {
506
+ key: 'editor.editorControlPane.widget.invalidPath',
507
+ args: { path: '' },
508
+ },
509
+ type: 'CUSTOM',
510
+ },
511
+ });
512
+ });
513
+
514
+ it('should return error on invalid path', () => {
515
+ expect(
516
+ validateMetaField(state, null, fromJS({ meta: true, name: 'path' }), 'invalid path', t),
517
+ ).toEqual({
518
+ error: {
519
+ message: {
520
+ key: 'editor.editorControlPane.widget.invalidPath',
521
+ args: { path: 'invalid path' },
522
+ },
523
+ type: 'CUSTOM',
524
+ },
525
+ });
526
+ });
527
+
528
+ it('should return error on existing path', () => {
529
+ selectCustomPath.mockReturnValue('existing-path');
530
+ selectEntryByPath.mockReturnValue(fromJS({ path: 'existing-path' }));
531
+ expect(
532
+ validateMetaField(
533
+ {
534
+ ...state,
535
+ entryDraft: fromJS({
536
+ entry: {},
537
+ }),
538
+ },
539
+ collection,
540
+ fromJS({ meta: true, name: 'path' }),
541
+ 'existing-path',
542
+ t,
543
+ ),
544
+ ).toEqual({
545
+ error: {
546
+ message: {
547
+ key: 'editor.editorControlPane.widget.pathExists',
548
+ args: { path: 'existing-path' },
549
+ },
550
+ type: 'CUSTOM',
551
+ },
552
+ });
553
+
554
+ expect(selectCustomPath).toHaveBeenCalledTimes(1);
555
+ expect(selectCustomPath).toHaveBeenCalledWith(
556
+ collection,
557
+ fromJS({ entry: { meta: { path: 'existing-path' } } }),
558
+ );
559
+
560
+ expect(selectEntryByPath).toHaveBeenCalledTimes(1);
561
+ expect(selectEntryByPath).toHaveBeenCalledWith(
562
+ state.entries,
563
+ collection.get('name'),
564
+ 'existing-path',
565
+ );
566
+ });
567
+
568
+ it('should not return error on non existing path for new entry', () => {
569
+ selectCustomPath.mockReturnValue('non-existing-path');
570
+ selectEntryByPath.mockReturnValue(undefined);
571
+ expect(
572
+ validateMetaField(
573
+ {
574
+ ...state,
575
+ entryDraft: fromJS({
576
+ entry: {},
577
+ }),
578
+ },
579
+ collection,
580
+ fromJS({ meta: true, name: 'path' }),
581
+ 'non-existing-path',
582
+ t,
583
+ ),
584
+ ).toEqual({
585
+ error: false,
586
+ });
587
+ });
588
+
589
+ it('should not return error when for existing entry', () => {
590
+ selectCustomPath.mockReturnValue('existing-path');
591
+ selectEntryByPath.mockReturnValue(fromJS({ path: 'existing-path' }));
592
+ expect(
593
+ validateMetaField(
594
+ {
595
+ ...state,
596
+ entryDraft: fromJS({
597
+ entry: { path: 'existing-path' },
598
+ }),
599
+ },
600
+ collection,
601
+ fromJS({ meta: true, name: 'path' }),
602
+ 'existing-path',
603
+ t,
604
+ ),
605
+ ).toEqual({
606
+ error: false,
607
+ });
608
+ });
609
+ });
610
+ });