@payloadcms/ui 4.0.0-canary.35 → 4.0.0-canary.37

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 (237) hide show
  1. package/dist/css/app.css +1 -0
  2. package/dist/css/preflight.css +1 -0
  3. package/dist/css/spacing.css +3 -0
  4. package/dist/elements/AppHeader/index.css +3 -0
  5. package/dist/elements/Banner/index.css +4 -0
  6. package/dist/elements/Banner/index.d.ts.map +1 -1
  7. package/dist/elements/Banner/index.js +1 -0
  8. package/dist/elements/Banner/index.js.map +1 -1
  9. package/dist/elements/BulkUpload/ActionsBar/index.css +1 -0
  10. package/dist/elements/BulkUpload/AddingFilesView/index.css +2 -4
  11. package/dist/elements/BulkUpload/FileSidebar/index.css +1 -0
  12. package/dist/elements/BulkUpload/FormsManager/index.d.ts.map +1 -1
  13. package/dist/elements/BulkUpload/FormsManager/index.js +12 -7
  14. package/dist/elements/BulkUpload/FormsManager/index.js.map +1 -1
  15. package/dist/elements/BulkUpload/index.css +2 -0
  16. package/dist/elements/Collapsible/index.css +1 -0
  17. package/dist/elements/DatePicker/index.css +2 -0
  18. package/dist/elements/Dialog/index.css +1 -0
  19. package/dist/elements/DocumentControls/index.css +1 -0
  20. package/dist/elements/DocumentFields/index.css +2 -0
  21. package/dist/elements/DocumentHeader/Tabs/index.css +1 -0
  22. package/dist/elements/DocumentHeader/index.css +1 -0
  23. package/dist/elements/EditUpload/index.css +1 -1
  24. package/dist/elements/FieldDiffContainer/index.css +1 -0
  25. package/dist/elements/FieldDiffLabel/index.css +1 -0
  26. package/dist/elements/FileDetails/StaticFileDetails/index.css +2 -0
  27. package/dist/elements/HTMLDiff/index.css +1 -0
  28. package/dist/elements/ItemsDrawer/index.css +3 -0
  29. package/dist/elements/ListControls/index.css +1 -0
  30. package/dist/elements/ListControls/index.d.ts.map +1 -1
  31. package/dist/elements/ListControls/index.js +7 -1
  32. package/dist/elements/ListControls/index.js.map +1 -1
  33. package/dist/elements/ListControls/types.d.ts +3 -1
  34. package/dist/elements/ListControls/types.d.ts.map +1 -1
  35. package/dist/elements/ListControls/types.js.map +1 -1
  36. package/dist/elements/ListControlsBar/index.css +1 -0
  37. package/dist/elements/ListHeader/TitleActions/ListEmptyTrashButton.js +1 -1
  38. package/dist/elements/ListHeader/TitleActions/ListEmptyTrashButton.js.map +1 -1
  39. package/dist/elements/LivePreview/Window/index.css +1 -0
  40. package/dist/elements/Nav/getNavPrefs.d.ts.map +1 -1
  41. package/dist/elements/Nav/getNavPrefs.js +2 -0
  42. package/dist/elements/Nav/getNavPrefs.js.map +1 -1
  43. package/dist/elements/Nav/index.css +2 -0
  44. package/dist/elements/PageControls/index.css +1 -0
  45. package/dist/elements/PillSelector/index.css +1 -0
  46. package/dist/elements/PreviewSizes/index.css +2 -0
  47. package/dist/elements/PublishButton/index.css +1 -0
  48. package/dist/elements/PublishButton/index.d.ts.map +1 -1
  49. package/dist/elements/PublishButton/index.js +11 -25
  50. package/dist/elements/PublishButton/index.js.map +1 -1
  51. package/dist/elements/QueryPresets/fields/Heading/index.css +1 -0
  52. package/dist/elements/RenderTitle/index.css +1 -0
  53. package/dist/elements/Table/index.css +1 -0
  54. package/dist/elements/TableSection/index.css +1 -0
  55. package/dist/elements/Tabs/index.css +1 -0
  56. package/dist/elements/Thumbnail/index.css +1 -0
  57. package/dist/elements/TimezonePicker/index.css +1 -0
  58. package/dist/elements/Tooltip/index.css +7 -0
  59. package/dist/elements/WhereBuilder/Condition/index.css +1 -0
  60. package/dist/elements/WhereBuilder/index.css +2 -0
  61. package/dist/fields/Array/index.css +1 -0
  62. package/dist/fields/Blocks/index.css +1 -0
  63. package/dist/fields/Group/index.css +1 -0
  64. package/dist/fields/Row/index.css +2 -0
  65. package/dist/fields/Tabs/index.css +1 -0
  66. package/dist/forms/RenderFields/index.css +1 -0
  67. package/dist/hooks/useControllableState.js +3 -3
  68. package/dist/hooks/useControllableState.js.map +1 -1
  69. package/dist/layouts/Root/index.d.ts +3 -6
  70. package/dist/layouts/Root/index.d.ts.map +1 -1
  71. package/dist/layouts/Root/index.js +2 -4
  72. package/dist/layouts/Root/index.js.map +1 -1
  73. package/dist/providers/DocumentInfo/index.d.ts.map +1 -1
  74. package/dist/providers/DocumentInfo/index.js +30 -19
  75. package/dist/providers/DocumentInfo/index.js.map +1 -1
  76. package/dist/providers/Locale/index.d.ts.map +1 -1
  77. package/dist/providers/Locale/index.js +6 -7
  78. package/dist/providers/Locale/index.js.map +1 -1
  79. package/dist/styles.css +5 -1
  80. package/dist/templates/Default/Wrapper/index.css +2 -0
  81. package/dist/templates/Default/index.css +1 -0
  82. package/dist/utilities/getDocPreferences.d.ts.map +1 -1
  83. package/dist/utilities/getDocPreferences.js +1 -0
  84. package/dist/utilities/getDocPreferences.js.map +1 -1
  85. package/dist/utilities/getPreferences.d.ts.map +1 -1
  86. package/dist/utilities/getPreferences.js +1 -0
  87. package/dist/utilities/getPreferences.js.map +1 -1
  88. package/dist/utilities/getVersions.d.ts.map +1 -1
  89. package/dist/utilities/getVersions.js +8 -0
  90. package/dist/utilities/getVersions.js.map +1 -1
  91. package/dist/utilities/handleAuthRedirect.d.ts.map +1 -1
  92. package/dist/utilities/handleAuthRedirect.js +4 -1
  93. package/dist/utilities/handleAuthRedirect.js.map +1 -1
  94. package/dist/utilities/isPathMatchingRoute.d.ts.map +1 -1
  95. package/dist/utilities/isPathMatchingRoute.js +7 -5
  96. package/dist/utilities/isPathMatchingRoute.js.map +1 -1
  97. package/dist/utilities/schedulePublishHandler.d.ts.map +1 -1
  98. package/dist/utilities/schedulePublishHandler.js +2 -0
  99. package/dist/utilities/schedulePublishHandler.js.map +1 -1
  100. package/dist/utilities/upsertPreferences.d.ts.map +1 -1
  101. package/dist/utilities/upsertPreferences.js +3 -0
  102. package/dist/utilities/upsertPreferences.js.map +1 -1
  103. package/dist/views/API/index.css +1 -0
  104. package/dist/views/Dashboard/Default/ModularDashboard/index.css +2 -0
  105. package/dist/views/Document/handleServerFunction.d.ts.map +1 -1
  106. package/dist/views/Document/handleServerFunction.js +1 -0
  107. package/dist/views/Document/handleServerFunction.js.map +1 -1
  108. package/dist/views/Edit/index.css +1 -0
  109. package/dist/views/HierarchyList/HierarchyTable/SlotTable.css +1 -0
  110. package/dist/views/HierarchyList/index.css +1 -0
  111. package/dist/views/List/ListHeader/index.css +1 -0
  112. package/dist/views/List/ListHeader/index.d.ts +0 -1
  113. package/dist/views/List/ListHeader/index.d.ts.map +1 -1
  114. package/dist/views/List/ListHeader/index.js +2 -6
  115. package/dist/views/List/ListHeader/index.js.map +1 -1
  116. package/dist/views/List/enrichDocsWithVersionStatus.d.ts.map +1 -1
  117. package/dist/views/List/enrichDocsWithVersionStatus.js +1 -0
  118. package/dist/views/List/enrichDocsWithVersionStatus.js.map +1 -1
  119. package/dist/views/List/handleServerFunction.d.ts.map +1 -1
  120. package/dist/views/List/handleServerFunction.js +1 -0
  121. package/dist/views/List/handleServerFunction.js.map +1 -1
  122. package/dist/views/List/index.client.d.ts.map +1 -1
  123. package/dist/views/List/index.client.js +3 -2
  124. package/dist/views/List/index.client.js.map +1 -1
  125. package/dist/views/List/index.css +2 -0
  126. package/dist/views/NotFound/client.d.ts +2 -0
  127. package/dist/views/NotFound/client.d.ts.map +1 -0
  128. package/dist/views/NotFound/client.js +4 -0
  129. package/dist/views/NotFound/client.js.map +1 -0
  130. package/dist/views/Root/index.d.ts.map +1 -1
  131. package/dist/views/Root/index.js +26 -19
  132. package/dist/views/Root/index.js.map +1 -1
  133. package/dist/views/Version/Default/index.css +2 -0
  134. package/dist/views/Version/RenderFieldsToDiff/fields/Date/index.css +8 -0
  135. package/dist/views/Version/RenderFieldsToDiff/fields/Relationship/generateLabelFromValue.d.ts.map +1 -1
  136. package/dist/views/Version/RenderFieldsToDiff/fields/Relationship/generateLabelFromValue.js +1 -0
  137. package/dist/views/Version/RenderFieldsToDiff/fields/Relationship/generateLabelFromValue.js.map +1 -1
  138. package/dist/views/Version/RenderFieldsToDiff/fields/Relationship/index.css +1 -0
  139. package/dist/views/Version/RenderFieldsToDiff/fields/Upload/index.css +1 -0
  140. package/dist/views/Version/RenderFieldsToDiff/index.css +2 -0
  141. package/dist/views/Version/Restore/index.d.ts.map +1 -1
  142. package/dist/views/Version/Restore/index.js +9 -6
  143. package/dist/views/Version/Restore/index.js.map +1 -1
  144. package/dist/views/Versions/VersionPillLabel/index.css +1 -0
  145. package/dist/views/Versions/index.css +1 -0
  146. package/dist/widgets/CollectionCards/index.css +4 -0
  147. package/package.json +11 -6
  148. package/dist/elements/ClipboardAction/clipboardUtilities.spec.js +0 -120
  149. package/dist/elements/ClipboardAction/clipboardUtilities.spec.js.map +0 -1
  150. package/dist/elements/ClipboardAction/isClipboardDataValid.spec.js +0 -144
  151. package/dist/elements/ClipboardAction/isClipboardDataValid.spec.js.map +0 -1
  152. package/dist/elements/ClipboardAction/mergeFormStateFromClipboard.spec.js +0 -885
  153. package/dist/elements/ClipboardAction/mergeFormStateFromClipboard.spec.js.map +0 -1
  154. package/dist/elements/ColumnSelection/matchesColumnSearch.spec.js +0 -87
  155. package/dist/elements/ColumnSelection/matchesColumnSearch.spec.js.map +0 -1
  156. package/dist/elements/CommandPalette/buildActions.spec.js +0 -158
  157. package/dist/elements/CommandPalette/buildActions.spec.js.map +0 -1
  158. package/dist/elements/CommandPalette/highlightLabel.spec.js +0 -78
  159. package/dist/elements/CommandPalette/highlightLabel.spec.js.map +0 -1
  160. package/dist/elements/FieldSelect/reduceFieldOptions.spec.js +0 -143
  161. package/dist/elements/FieldSelect/reduceFieldOptions.spec.js.map +0 -1
  162. package/dist/elements/Toasts/fieldErrors.spec.js +0 -46
  163. package/dist/elements/Toasts/fieldErrors.spec.js.map +0 -1
  164. package/dist/elements/WhereBuilder/Condition/Relationship/optionsReducer.spec.js +0 -152
  165. package/dist/elements/WhereBuilder/Condition/Relationship/optionsReducer.spec.js.map +0 -1
  166. package/dist/elements/WhereBuilder/conditionValue.spec.js +0 -65
  167. package/dist/elements/WhereBuilder/conditionValue.spec.js.map +0 -1
  168. package/dist/fields/Upload/Input.spec.js +0 -242
  169. package/dist/fields/Upload/Input.spec.js.map +0 -1
  170. package/dist/forms/fieldSchemasToFormState/fieldSchemasToFormState.spec.d.ts +0 -2
  171. package/dist/forms/fieldSchemasToFormState/fieldSchemasToFormState.spec.d.ts.map +0 -1
  172. package/dist/forms/fieldSchemasToFormState/fieldSchemasToFormState.spec.js +0 -67
  173. package/dist/forms/fieldSchemasToFormState/fieldSchemasToFormState.spec.js.map +0 -1
  174. package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.spec.js +0 -150
  175. package/dist/forms/fieldSchemasToFormState/serverFunctions/renderFieldServerFn.spec.js.map +0 -1
  176. package/dist/layouts/Root/index.spec.js +0 -20
  177. package/dist/layouts/Root/index.spec.js.map +0 -1
  178. package/dist/providers/Auth/authSessionRequests.spec.js +0 -121
  179. package/dist/providers/Auth/authSessionRequests.spec.js.map +0 -1
  180. package/dist/providers/Auth/sessionActivity.spec.js +0 -44
  181. package/dist/providers/Auth/sessionActivity.spec.js.map +0 -1
  182. package/dist/providers/Auth/tabSessionSync/index.spec.js +0 -463
  183. package/dist/providers/Auth/tabSessionSync/index.spec.js.map +0 -1
  184. package/dist/providers/Auth/useAuthSessionTimers.spec.js +0 -311
  185. package/dist/providers/Auth/useAuthSessionTimers.spec.js.map +0 -1
  186. package/dist/providers/RouteTransition/ProgressBar/index.spec.js +0 -44
  187. package/dist/providers/RouteTransition/ProgressBar/index.spec.js.map +0 -1
  188. package/dist/providers/TableColumns/buildColumnState/index.spec.js +0 -40
  189. package/dist/providers/TableColumns/buildColumnState/index.spec.js.map +0 -1
  190. package/dist/utilities/appendCacheTag.spec.js +0 -34
  191. package/dist/utilities/appendCacheTag.spec.js.map +0 -1
  192. package/dist/utilities/formatAbsoluteURL.spec.js +0 -27
  193. package/dist/utilities/formatAbsoluteURL.spec.js.map +0 -1
  194. package/dist/utilities/formatMetadata.spec.js +0 -83
  195. package/dist/utilities/formatMetadata.spec.js.map +0 -1
  196. package/dist/utilities/fuzzyMatch.spec.js +0 -38
  197. package/dist/utilities/fuzzyMatch.spec.js.map +0 -1
  198. package/dist/utilities/getRequestLocale.d.ts +0 -7
  199. package/dist/utilities/getRequestLocale.d.ts.map +0 -1
  200. package/dist/utilities/getRequestLocale.js +0 -20
  201. package/dist/utilities/getRequestLocale.js.map +0 -1
  202. package/dist/utilities/initReq.d.ts +0 -16
  203. package/dist/utilities/initReq.d.ts.map +0 -1
  204. package/dist/utilities/initReq.js +0 -146
  205. package/dist/utilities/initReq.js.map +0 -1
  206. package/dist/utilities/initReq.spec.js +0 -226
  207. package/dist/utilities/initReq.spec.js.map +0 -1
  208. package/dist/utilities/isAbsoluteURL.spec.js +0 -11
  209. package/dist/utilities/isAbsoluteURL.spec.js.map +0 -1
  210. package/dist/utilities/isCustomAdminView.spec.js +0 -90
  211. package/dist/utilities/isCustomAdminView.spec.js.map +0 -1
  212. package/dist/utilities/isHttpURL.spec.js +0 -25
  213. package/dist/utilities/isHttpURL.spec.js.map +0 -1
  214. package/dist/utilities/isPathMatchingRoute.spec.js +0 -178
  215. package/dist/utilities/isPathMatchingRoute.spec.js.map +0 -1
  216. package/dist/utilities/isPublicAdminRoute.spec.js +0 -34
  217. package/dist/utilities/isPublicAdminRoute.spec.js.map +0 -1
  218. package/dist/utilities/normalizeRelationshipValue.spec.js +0 -373
  219. package/dist/utilities/normalizeRelationshipValue.spec.js.map +0 -1
  220. package/dist/utilities/recentlyViewed.spec.js +0 -92
  221. package/dist/utilities/recentlyViewed.spec.js.map +0 -1
  222. package/dist/utilities/selectiveCache.d.ts +0 -12
  223. package/dist/utilities/selectiveCache.d.ts.map +0 -1
  224. package/dist/utilities/selectiveCache.js +0 -37
  225. package/dist/utilities/selectiveCache.js.map +0 -1
  226. package/dist/views/Root/getCustomCollectionViewByRoute.spec.js +0 -168
  227. package/dist/views/Root/getCustomCollectionViewByRoute.spec.js.map +0 -1
  228. package/dist/views/Version/RenderFieldsToDiff/buildVersionFields.spec.js +0 -258
  229. package/dist/views/Version/RenderFieldsToDiff/buildVersionFields.spec.js.map +0 -1
  230. package/dist/views/Version/RenderFieldsToDiff/utilities/countChangedFields.spec.js +0 -915
  231. package/dist/views/Version/RenderFieldsToDiff/utilities/countChangedFields.spec.js.map +0 -1
  232. package/dist/views/Version/RenderFieldsToDiff/utilities/fieldHasChanges.spec.js +0 -47
  233. package/dist/views/Version/RenderFieldsToDiff/utilities/fieldHasChanges.spec.js.map +0 -1
  234. package/dist/views/Version/RenderFieldsToDiff/utilities/getFieldsForRowComparison.spec.js +0 -125
  235. package/dist/views/Version/RenderFieldsToDiff/utilities/getFieldsForRowComparison.spec.js.map +0 -1
  236. package/dist/widgets/CollectionQuery/getCollectionFieldPaths.spec.js +0 -100
  237. package/dist/widgets/CollectionQuery/getCollectionFieldPaths.spec.js.map +0 -1
@@ -1,311 +0,0 @@
1
- // @vitest-environment jsdom
2
- import React, { act } from 'react';
3
- import { createRoot } from 'react-dom/client';
4
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
5
- import { getAuthSessionTiming } from './sessionTiming.js';
6
- import { useAuthSessionTimers } from './useAuthSessionTimers.js';
7
- const timerCleanups = [];
8
- beforeEach(() => {
9
- vi.useFakeTimers();
10
- vi.setSystemTime(new Date('2026-01-01T00:00:00.000Z'));
11
- });
12
- afterEach(() => {
13
- for (const cleanup of timerCleanups.splice(0)) {
14
- cleanup();
15
- }
16
- vi.useRealTimers();
17
- });
18
- describe('useAuthSessionTimers', () => {
19
- it('should scale session timing for tokens shorter than two minutes', () => {
20
- const nowMs = Date.now();
21
- const expirationMs = nowMs + 30_000;
22
- expect(getAuthSessionTiming({
23
- expirationMs,
24
- nowMs
25
- })).toEqual({
26
- activityTrackingStartsAt: nowMs,
27
- expiresAt: expirationMs,
28
- refreshStartsAt: nowMs,
29
- reminderStartsAt: nowMs + 15_000
30
- });
31
- });
32
- it('should return the lifecycle timing when setting an expiration', () => {
33
- const timers = renderAuthSessionTimers();
34
- const expirationMs = Date.now() + 300_000;
35
- expect(timers.setExpiration(expirationMs)).toEqual({
36
- activityTrackingStartsAt: expirationMs - 240_000,
37
- expiresAt: expirationMs,
38
- refreshStartsAt: expirationMs - 120_000,
39
- reminderStartsAt: expirationMs - 60_000
40
- });
41
- });
42
- it('should refresh at the checkpoint when activity occurred in the tracking window', () => {
43
- const onActivity = vi.fn();
44
- const onActivityRefresh = vi.fn();
45
- const timers = renderAuthSessionTimers({
46
- onActivity,
47
- onActivityRefresh
48
- });
49
- timers.setExpiration(Date.now() + 300_000);
50
- act(() => {
51
- vi.advanceTimersByTime(120_000);
52
- window.dispatchEvent(new MouseEvent('mousemove'));
53
- vi.advanceTimersByTime(1_000);
54
- window.dispatchEvent(new KeyboardEvent('keydown'));
55
- vi.advanceTimersByTime(59_000);
56
- vi.advanceTimersByTime(1_000);
57
- });
58
- expect(onActivity).toHaveBeenCalledOnce();
59
- expect(onActivityRefresh).toHaveBeenCalledTimes(1);
60
- });
61
- it('should ignore activity once the expiration reminder opens', () => {
62
- const onActivityRefresh = vi.fn();
63
- const timers = renderAuthSessionTimers({
64
- onActivityRefresh
65
- });
66
- const sessionStartedAt = Date.now();
67
- timers.setExpiration(sessionStartedAt + 300_000);
68
- act(() => {
69
- vi.advanceTimersByTime(60_000);
70
- });
71
- vi.setSystemTime(sessionStartedAt + 240_000);
72
- expect(timers.recordActivity('route')).toBe(false);
73
- expect(onActivityRefresh).not.toHaveBeenCalled();
74
- });
75
- it('should clear timers and listeners on logout', () => {
76
- const onActivityRefresh = vi.fn();
77
- const onExpire = vi.fn();
78
- const timers = renderAuthSessionTimers({
79
- onActivityRefresh,
80
- onExpire
81
- });
82
- timers.setExpiration(Date.now() + 300_000);
83
- timers.clear();
84
- act(() => {
85
- window.dispatchEvent(new MouseEvent('mousemove'));
86
- vi.advanceTimersByTime(300_000);
87
- });
88
- expect(onActivityRefresh).not.toHaveBeenCalled();
89
- expect(onExpire).not.toHaveBeenCalled();
90
- });
91
- it('should schedule the reminder and expiration from the current expiration', () => {
92
- const onExpire = vi.fn();
93
- const onReminder = vi.fn();
94
- const timers = renderAuthSessionTimers({
95
- onExpire,
96
- onReminder
97
- });
98
- const expirationMs = Date.now() + 300_000;
99
- timers.setExpiration(expirationMs);
100
- act(() => {
101
- vi.advanceTimersByTime(240_000);
102
- });
103
- expect(onReminder).toHaveBeenCalledTimes(1);
104
- expect(onExpire).not.toHaveBeenCalled();
105
- act(() => {
106
- vi.advanceTimersByTime(60_000);
107
- });
108
- expect(onExpire).toHaveBeenCalledWith(expirationMs);
109
- });
110
- it('should respect expirations beyond the maximum browser timeout', () => {
111
- const onExpire = vi.fn();
112
- const timers = renderAuthSessionTimers({
113
- onExpire
114
- });
115
- const thirtyDaysMs = 2_592_000_000;
116
- const maximumBrowserTimeoutMs = 2_147_483_647;
117
- const expirationMs = Date.now() + thirtyDaysMs;
118
- timers.setExpiration(expirationMs);
119
- act(() => {
120
- vi.advanceTimersByTime(maximumBrowserTimeoutMs);
121
- });
122
- expect(onExpire).not.toHaveBeenCalled();
123
- act(() => {
124
- vi.advanceTimersByTime(thirtyDaysMs - maximumBrowserTimeoutMs - 1);
125
- });
126
- expect(onExpire).not.toHaveBeenCalled();
127
- act(() => {
128
- vi.advanceTimersByTime(1);
129
- });
130
- expect(onExpire).toHaveBeenCalledOnce();
131
- expect(onExpire).toHaveBeenCalledWith(expirationMs);
132
- });
133
- it('should schedule expiration when the token expires exactly now', () => {
134
- const onActivityRefresh = vi.fn();
135
- const onExpire = vi.fn();
136
- const onReminder = vi.fn();
137
- const timers = renderAuthSessionTimers({
138
- isAuthenticated: false,
139
- onActivityRefresh,
140
- onExpire,
141
- onReminder
142
- });
143
- const expirationMs = Date.now();
144
- timers.setExpiration(expirationMs);
145
- expect(onExpire).not.toHaveBeenCalled();
146
- act(() => {
147
- vi.advanceTimersByTime(0);
148
- });
149
- expect(onExpire).toHaveBeenCalledOnce();
150
- expect(onExpire).toHaveBeenCalledWith(expirationMs);
151
- expect(onActivityRefresh).not.toHaveBeenCalled();
152
- expect(onReminder).not.toHaveBeenCalled();
153
- });
154
- it('should schedule expiration when the token is already past', () => {
155
- const onActivityRefresh = vi.fn();
156
- const onExpire = vi.fn();
157
- const onReminder = vi.fn();
158
- const timers = renderAuthSessionTimers({
159
- isAuthenticated: false,
160
- onActivityRefresh,
161
- onExpire,
162
- onReminder
163
- });
164
- const expirationMs = Date.now() - 1;
165
- timers.setExpiration(expirationMs);
166
- act(() => {
167
- vi.advanceTimersByTime(0);
168
- });
169
- expect(onExpire).toHaveBeenCalledOnce();
170
- expect(onExpire).toHaveBeenCalledWith(expirationMs);
171
- expect(onActivityRefresh).not.toHaveBeenCalled();
172
- expect(onReminder).not.toHaveBeenCalled();
173
- });
174
- it('should reject a non-finite expiration without activating the session', () => {
175
- const onActivityRefresh = vi.fn();
176
- const onExpire = vi.fn();
177
- const timers = renderAuthSessionTimers({
178
- isAuthenticated: false,
179
- onActivityRefresh,
180
- onExpire
181
- });
182
- timers.setExpiration(Number.NaN);
183
- timers.scheduleRefresh(true);
184
- act(() => {
185
- vi.advanceTimersByTime(1_000);
186
- });
187
- expect(timers.getCurrentExpirationMs()).toBeUndefined();
188
- expect(onActivityRefresh).not.toHaveBeenCalled();
189
- expect(onExpire).not.toHaveBeenCalled();
190
- });
191
- it('should synchronously activate on apply and deactivate on clear', () => {
192
- const onActivityRefresh = vi.fn();
193
- const timers = renderAuthSessionTimers({
194
- isAuthenticated: false,
195
- onActivityRefresh
196
- });
197
- timers.clear();
198
- timers.setExpiration(Date.now() + 300_000);
199
- timers.scheduleRefresh(true);
200
- act(() => {
201
- vi.advanceTimersByTime(1_000);
202
- });
203
- expect(onActivityRefresh).toHaveBeenCalledOnce();
204
- timers.clear();
205
- timers.scheduleRefresh(true);
206
- act(() => {
207
- vi.advanceTimersByTime(1_000);
208
- });
209
- expect(onActivityRefresh).toHaveBeenCalledOnce();
210
- });
211
- it('should reset tracked activity when replacing the expiration', () => {
212
- const onActivity = vi.fn();
213
- const onActivityRefresh = vi.fn();
214
- const timers = renderAuthSessionTimers({
215
- onActivity,
216
- onActivityRefresh
217
- });
218
- const expirationMs = Date.now() + 300_000;
219
- timers.setExpiration(expirationMs);
220
- act(() => {
221
- vi.advanceTimersByTime(60_000);
222
- });
223
- expect(timers.recordActivity('route')).toBe(true);
224
- expect(onActivity).toHaveBeenCalledOnce();
225
- timers.setExpiration(expirationMs);
226
- expect(timers.recordActivity('route')).toBe(true);
227
- expect(onActivity).toHaveBeenCalledTimes(2);
228
- act(() => {
229
- vi.advanceTimersByTime(120_000);
230
- vi.advanceTimersByTime(1_000);
231
- });
232
- expect(onActivityRefresh).toHaveBeenCalledOnce();
233
- });
234
- it('should keep its controller and activity throttle across rerenders', () => {
235
- const onActivityRefresh = vi.fn();
236
- const timers = renderAuthSessionTimers({
237
- onActivityRefresh
238
- });
239
- const initialController = timers.getController();
240
- timers.setExpiration(Date.now() + 300_000);
241
- act(() => {
242
- vi.advanceTimersByTime(238_000);
243
- window.dispatchEvent(new MouseEvent('mousemove'));
244
- });
245
- timers.rerender();
246
- expect(timers.getController()).toBe(initialController);
247
- act(() => {
248
- vi.advanceTimersByTime(1);
249
- window.dispatchEvent(new MouseEvent('mousemove'));
250
- vi.advanceTimersByTime(999);
251
- });
252
- expect(onActivityRefresh).toHaveBeenCalledTimes(1);
253
- });
254
- it('should synchronously replace the current expiration', () => {
255
- const timers = renderAuthSessionTimers();
256
- const firstExpirationMs = Date.now() + 300_000;
257
- const replacementExpirationMs = Date.now() + 600_000;
258
- timers.setExpiration(firstExpirationMs);
259
- timers.setExpiration(replacementExpirationMs);
260
- expect(timers.getCurrentExpirationMs()).toBe(replacementExpirationMs);
261
- });
262
- });
263
- function renderAuthSessionTimers({
264
- isAuthenticated = true,
265
- onActivity = vi.fn(),
266
- onActivityRefresh = vi.fn(),
267
- onExpire = vi.fn(),
268
- onReminder = vi.fn()
269
- } = {}) {
270
- let controller;
271
- const container = document.createElement('div');
272
- const root = createRoot(container);
273
- function SessionTimers() {
274
- controller = useAuthSessionTimers({
275
- isAuthenticated,
276
- onActivity,
277
- onActivityRefresh,
278
- onExpire,
279
- onReminder
280
- });
281
- return null;
282
- }
283
- act(() => {
284
- root.render(React.createElement(SessionTimers));
285
- });
286
- timerCleanups.push(() => {
287
- act(() => {
288
- root.unmount();
289
- });
290
- });
291
- const getController = () => {
292
- if (!controller) {
293
- throw new Error('Expected auth session timers.');
294
- }
295
- return controller;
296
- };
297
- return {
298
- clear: () => getController().clear(),
299
- getController,
300
- getCurrentExpirationMs: () => getController().getCurrentExpirationMs(),
301
- rerender: () => {
302
- act(() => {
303
- root.render(React.createElement(SessionTimers));
304
- });
305
- },
306
- recordActivity: source => getController().recordActivity(source),
307
- scheduleRefresh: forceRefresh => getController().scheduleRefresh(forceRefresh),
308
- setExpiration: expirationMs => getController().setExpiration(expirationMs)
309
- };
310
- }
311
- //# sourceMappingURL=useAuthSessionTimers.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useAuthSessionTimers.spec.js","names":["React","act","createRoot","afterEach","beforeEach","describe","expect","it","vi","getAuthSessionTiming","useAuthSessionTimers","timerCleanups","useFakeTimers","setSystemTime","Date","cleanup","splice","useRealTimers","nowMs","now","expirationMs","toEqual","activityTrackingStartsAt","expiresAt","refreshStartsAt","reminderStartsAt","timers","renderAuthSessionTimers","setExpiration","onActivity","fn","onActivityRefresh","advanceTimersByTime","window","dispatchEvent","MouseEvent","KeyboardEvent","toHaveBeenCalledOnce","toHaveBeenCalledTimes","sessionStartedAt","recordActivity","toBe","not","toHaveBeenCalled","onExpire","clear","onReminder","toHaveBeenCalledWith","thirtyDaysMs","maximumBrowserTimeoutMs","isAuthenticated","Number","NaN","scheduleRefresh","getCurrentExpirationMs","toBeUndefined","initialController","getController","rerender","firstExpirationMs","replacementExpirationMs","controller","container","document","createElement","root","SessionTimers","render","push","unmount","Error","source","forceRefresh"],"sources":["../../../src/providers/Auth/useAuthSessionTimers.spec.ts"],"sourcesContent":["// @vitest-environment jsdom\nimport React, { act } from 'react'\nimport { createRoot } from 'react-dom/client'\nimport { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport type { AuthSessionTimers } from './useAuthSessionTimers.js'\n\nimport { getAuthSessionTiming } from './sessionTiming.js'\nimport { useAuthSessionTimers } from './useAuthSessionTimers.js'\n\nconst timerCleanups: Array<() => void> = []\n\nbeforeEach(() => {\n vi.useFakeTimers()\n vi.setSystemTime(new Date('2026-01-01T00:00:00.000Z'))\n})\n\nafterEach(() => {\n for (const cleanup of timerCleanups.splice(0)) {\n cleanup()\n }\n\n vi.useRealTimers()\n})\n\ndescribe('useAuthSessionTimers', () => {\n it('should scale session timing for tokens shorter than two minutes', () => {\n const nowMs = Date.now()\n const expirationMs = nowMs + 30_000\n\n expect(getAuthSessionTiming({ expirationMs, nowMs })).toEqual({\n activityTrackingStartsAt: nowMs,\n expiresAt: expirationMs,\n refreshStartsAt: nowMs,\n reminderStartsAt: nowMs + 15_000,\n })\n })\n\n it('should return the lifecycle timing when setting an expiration', () => {\n const timers = renderAuthSessionTimers()\n const expirationMs = Date.now() + 300_000\n\n expect(timers.setExpiration(expirationMs)).toEqual({\n activityTrackingStartsAt: expirationMs - 240_000,\n expiresAt: expirationMs,\n refreshStartsAt: expirationMs - 120_000,\n reminderStartsAt: expirationMs - 60_000,\n })\n })\n\n it('should refresh at the checkpoint when activity occurred in the tracking window', () => {\n const onActivity = vi.fn()\n const onActivityRefresh = vi.fn()\n const timers = renderAuthSessionTimers({ onActivity, onActivityRefresh })\n\n timers.setExpiration(Date.now() + 300_000)\n act(() => {\n vi.advanceTimersByTime(120_000)\n window.dispatchEvent(new MouseEvent('mousemove'))\n vi.advanceTimersByTime(1_000)\n window.dispatchEvent(new KeyboardEvent('keydown'))\n vi.advanceTimersByTime(59_000)\n vi.advanceTimersByTime(1_000)\n })\n\n expect(onActivity).toHaveBeenCalledOnce()\n expect(onActivityRefresh).toHaveBeenCalledTimes(1)\n })\n\n it('should ignore activity once the expiration reminder opens', () => {\n const onActivityRefresh = vi.fn()\n const timers = renderAuthSessionTimers({ onActivityRefresh })\n const sessionStartedAt = Date.now()\n\n timers.setExpiration(sessionStartedAt + 300_000)\n act(() => {\n vi.advanceTimersByTime(60_000)\n })\n vi.setSystemTime(sessionStartedAt + 240_000)\n\n expect(timers.recordActivity('route')).toBe(false)\n expect(onActivityRefresh).not.toHaveBeenCalled()\n })\n\n it('should clear timers and listeners on logout', () => {\n const onActivityRefresh = vi.fn()\n const onExpire = vi.fn()\n const timers = renderAuthSessionTimers({ onActivityRefresh, onExpire })\n\n timers.setExpiration(Date.now() + 300_000)\n timers.clear()\n act(() => {\n window.dispatchEvent(new MouseEvent('mousemove'))\n vi.advanceTimersByTime(300_000)\n })\n\n expect(onActivityRefresh).not.toHaveBeenCalled()\n expect(onExpire).not.toHaveBeenCalled()\n })\n\n it('should schedule the reminder and expiration from the current expiration', () => {\n const onExpire = vi.fn()\n const onReminder = vi.fn()\n const timers = renderAuthSessionTimers({ onExpire, onReminder })\n const expirationMs = Date.now() + 300_000\n\n timers.setExpiration(expirationMs)\n act(() => {\n vi.advanceTimersByTime(240_000)\n })\n\n expect(onReminder).toHaveBeenCalledTimes(1)\n expect(onExpire).not.toHaveBeenCalled()\n\n act(() => {\n vi.advanceTimersByTime(60_000)\n })\n\n expect(onExpire).toHaveBeenCalledWith(expirationMs)\n })\n\n it('should respect expirations beyond the maximum browser timeout', () => {\n const onExpire = vi.fn()\n const timers = renderAuthSessionTimers({ onExpire })\n const thirtyDaysMs = 2_592_000_000\n const maximumBrowserTimeoutMs = 2_147_483_647\n const expirationMs = Date.now() + thirtyDaysMs\n\n timers.setExpiration(expirationMs)\n\n act(() => {\n vi.advanceTimersByTime(maximumBrowserTimeoutMs)\n })\n\n expect(onExpire).not.toHaveBeenCalled()\n\n act(() => {\n vi.advanceTimersByTime(thirtyDaysMs - maximumBrowserTimeoutMs - 1)\n })\n\n expect(onExpire).not.toHaveBeenCalled()\n\n act(() => {\n vi.advanceTimersByTime(1)\n })\n\n expect(onExpire).toHaveBeenCalledOnce()\n expect(onExpire).toHaveBeenCalledWith(expirationMs)\n })\n\n it('should schedule expiration when the token expires exactly now', () => {\n const onActivityRefresh = vi.fn()\n const onExpire = vi.fn()\n const onReminder = vi.fn()\n const timers = renderAuthSessionTimers({\n isAuthenticated: false,\n onActivityRefresh,\n onExpire,\n onReminder,\n })\n const expirationMs = Date.now()\n\n timers.setExpiration(expirationMs)\n\n expect(onExpire).not.toHaveBeenCalled()\n\n act(() => {\n vi.advanceTimersByTime(0)\n })\n\n expect(onExpire).toHaveBeenCalledOnce()\n expect(onExpire).toHaveBeenCalledWith(expirationMs)\n expect(onActivityRefresh).not.toHaveBeenCalled()\n expect(onReminder).not.toHaveBeenCalled()\n })\n\n it('should schedule expiration when the token is already past', () => {\n const onActivityRefresh = vi.fn()\n const onExpire = vi.fn()\n const onReminder = vi.fn()\n const timers = renderAuthSessionTimers({\n isAuthenticated: false,\n onActivityRefresh,\n onExpire,\n onReminder,\n })\n const expirationMs = Date.now() - 1\n\n timers.setExpiration(expirationMs)\n\n act(() => {\n vi.advanceTimersByTime(0)\n })\n\n expect(onExpire).toHaveBeenCalledOnce()\n expect(onExpire).toHaveBeenCalledWith(expirationMs)\n expect(onActivityRefresh).not.toHaveBeenCalled()\n expect(onReminder).not.toHaveBeenCalled()\n })\n\n it('should reject a non-finite expiration without activating the session', () => {\n const onActivityRefresh = vi.fn()\n const onExpire = vi.fn()\n const timers = renderAuthSessionTimers({\n isAuthenticated: false,\n onActivityRefresh,\n onExpire,\n })\n\n timers.setExpiration(Number.NaN)\n timers.scheduleRefresh(true)\n act(() => {\n vi.advanceTimersByTime(1_000)\n })\n\n expect(timers.getCurrentExpirationMs()).toBeUndefined()\n expect(onActivityRefresh).not.toHaveBeenCalled()\n expect(onExpire).not.toHaveBeenCalled()\n })\n\n it('should synchronously activate on apply and deactivate on clear', () => {\n const onActivityRefresh = vi.fn()\n const timers = renderAuthSessionTimers({ isAuthenticated: false, onActivityRefresh })\n\n timers.clear()\n timers.setExpiration(Date.now() + 300_000)\n timers.scheduleRefresh(true)\n act(() => {\n vi.advanceTimersByTime(1_000)\n })\n\n expect(onActivityRefresh).toHaveBeenCalledOnce()\n\n timers.clear()\n timers.scheduleRefresh(true)\n act(() => {\n vi.advanceTimersByTime(1_000)\n })\n\n expect(onActivityRefresh).toHaveBeenCalledOnce()\n })\n\n it('should reset tracked activity when replacing the expiration', () => {\n const onActivity = vi.fn()\n const onActivityRefresh = vi.fn()\n const timers = renderAuthSessionTimers({ onActivity, onActivityRefresh })\n const expirationMs = Date.now() + 300_000\n\n timers.setExpiration(expirationMs)\n act(() => {\n vi.advanceTimersByTime(60_000)\n })\n expect(timers.recordActivity('route')).toBe(true)\n expect(onActivity).toHaveBeenCalledOnce()\n\n timers.setExpiration(expirationMs)\n\n expect(timers.recordActivity('route')).toBe(true)\n expect(onActivity).toHaveBeenCalledTimes(2)\n\n act(() => {\n vi.advanceTimersByTime(120_000)\n vi.advanceTimersByTime(1_000)\n })\n\n expect(onActivityRefresh).toHaveBeenCalledOnce()\n })\n\n it('should keep its controller and activity throttle across rerenders', () => {\n const onActivityRefresh = vi.fn()\n const timers = renderAuthSessionTimers({ onActivityRefresh })\n const initialController = timers.getController()\n\n timers.setExpiration(Date.now() + 300_000)\n act(() => {\n vi.advanceTimersByTime(238_000)\n window.dispatchEvent(new MouseEvent('mousemove'))\n })\n timers.rerender()\n\n expect(timers.getController()).toBe(initialController)\n\n act(() => {\n vi.advanceTimersByTime(1)\n window.dispatchEvent(new MouseEvent('mousemove'))\n vi.advanceTimersByTime(999)\n })\n\n expect(onActivityRefresh).toHaveBeenCalledTimes(1)\n })\n\n it('should synchronously replace the current expiration', () => {\n const timers = renderAuthSessionTimers()\n const firstExpirationMs = Date.now() + 300_000\n const replacementExpirationMs = Date.now() + 600_000\n\n timers.setExpiration(firstExpirationMs)\n timers.setExpiration(replacementExpirationMs)\n\n expect(timers.getCurrentExpirationMs()).toBe(replacementExpirationMs)\n })\n})\n\nfunction renderAuthSessionTimers({\n isAuthenticated = true,\n onActivity = vi.fn(),\n onActivityRefresh = vi.fn(),\n onExpire = vi.fn(),\n onReminder = vi.fn(),\n}: {\n isAuthenticated?: boolean\n onActivity?: () => void\n onActivityRefresh?: () => void\n onExpire?: (expirationMs: number) => void\n onReminder?: () => void\n} = {}): RenderedAuthSessionTimers {\n let controller: AuthSessionTimers | undefined\n const container = document.createElement('div')\n const root = createRoot(container)\n\n function SessionTimers() {\n controller = useAuthSessionTimers({\n isAuthenticated,\n onActivity,\n onActivityRefresh,\n onExpire,\n onReminder,\n })\n\n return null\n }\n\n act(() => {\n root.render(React.createElement(SessionTimers))\n })\n\n timerCleanups.push(() => {\n act(() => {\n root.unmount()\n })\n })\n\n const getController = (): AuthSessionTimers => {\n if (!controller) {\n throw new Error('Expected auth session timers.')\n }\n\n return controller\n }\n\n return {\n clear: () => getController().clear(),\n getController,\n getCurrentExpirationMs: () => getController().getCurrentExpirationMs(),\n rerender: () => {\n act(() => {\n root.render(React.createElement(SessionTimers))\n })\n },\n recordActivity: (source) => getController().recordActivity(source),\n scheduleRefresh: (forceRefresh) => getController().scheduleRefresh(forceRefresh),\n setExpiration: (expirationMs) => getController().setExpiration(expirationMs),\n }\n}\n\ntype RenderedAuthSessionTimers = AuthSessionTimers & {\n getController: () => AuthSessionTimers\n recordActivity: (source: 'focus' | 'keydown' | 'mousemove' | 'route') => boolean\n rerender: () => void\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,44 +0,0 @@
1
- // @vitest-environment happy-dom
2
- import { act, createElement, useEffect } from 'react';
3
- import { createRoot } from 'react-dom/client';
4
- import { afterEach, beforeEach, expect, test, vi } from 'vitest';
5
- import { RouteTransitionProvider, useRouteTransition } from '../index.js';
6
- import { ProgressBar } from './index.js';
7
- let container;
8
- let root;
9
- beforeEach(() => {
10
- globalThis.IS_REACT_ACT_ENVIRONMENT = true;
11
- container = document.createElement('div');
12
- document.body.appendChild(container);
13
- root = createRoot(container);
14
- });
15
- afterEach(() => {
16
- act(() => root.unmount());
17
- container.remove();
18
- vi.useRealTimers();
19
- });
20
- test('does not show progress for transitions that finish before the initial delay', async () => {
21
- vi.useFakeTimers();
22
- const FastTransition = () => {
23
- const {
24
- holdRouteTransition
25
- } = useRouteTransition();
26
- useEffect(() => {
27
- const releaseRouteTransition = holdRouteTransition();
28
- const timeout = setTimeout(releaseRouteTransition, 50);
29
- return () => {
30
- clearTimeout(timeout);
31
- releaseRouteTransition();
32
- };
33
- }, [holdRouteTransition]);
34
- return null;
35
- };
36
- await act(async () => {
37
- root.render(createElement(RouteTransitionProvider, null, createElement(ProgressBar), createElement(FastTransition)));
38
- });
39
- await act(async () => {
40
- await vi.advanceTimersByTimeAsync(50);
41
- });
42
- expect(container.querySelector('.progress-bar')).toBeNull();
43
- });
44
- //# sourceMappingURL=index.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.spec.js","names":["act","createElement","useEffect","createRoot","afterEach","beforeEach","expect","test","vi","RouteTransitionProvider","useRouteTransition","ProgressBar","container","root","globalThis","IS_REACT_ACT_ENVIRONMENT","document","body","appendChild","unmount","remove","useRealTimers","useFakeTimers","FastTransition","holdRouteTransition","releaseRouteTransition","timeout","setTimeout","clearTimeout","render","advanceTimersByTimeAsync","querySelector","toBeNull"],"sources":["../../../../src/providers/RouteTransition/ProgressBar/index.spec.ts"],"sourcesContent":["// @vitest-environment happy-dom\n\nimport { act, createElement, useEffect } from 'react'\nimport { createRoot, type Root } from 'react-dom/client'\nimport { afterEach, beforeEach, expect, test, vi } from 'vitest'\n\nimport { RouteTransitionProvider, useRouteTransition } from '../index.js'\nimport { ProgressBar } from './index.js'\n\nlet container: HTMLDivElement\nlet root: Root\n\nbeforeEach(() => {\n globalThis.IS_REACT_ACT_ENVIRONMENT = true\n container = document.createElement('div')\n document.body.appendChild(container)\n root = createRoot(container)\n})\n\nafterEach(() => {\n act(() => root.unmount())\n container.remove()\n vi.useRealTimers()\n})\n\ntest('does not show progress for transitions that finish before the initial delay', async () => {\n vi.useFakeTimers()\n\n const FastTransition = () => {\n const { holdRouteTransition } = useRouteTransition()\n\n useEffect(() => {\n const releaseRouteTransition = holdRouteTransition()\n const timeout = setTimeout(releaseRouteTransition, 50)\n\n return () => {\n clearTimeout(timeout)\n releaseRouteTransition()\n }\n }, [holdRouteTransition])\n\n return null\n }\n\n await act(async () => {\n root.render(\n createElement(\n RouteTransitionProvider,\n null,\n createElement(ProgressBar),\n createElement(FastTransition),\n ),\n )\n })\n\n await act(async () => {\n await vi.advanceTimersByTimeAsync(50)\n })\n\n expect(container.querySelector('.progress-bar')).toBeNull()\n})\n"],"mappings":"AAAA;AAEA,SAASA,GAAG,EAAEC,aAAa,EAAEC,SAAS,QAAQ;AAC9C,SAASC,UAAU,QAAmB;AACtC,SAASC,SAAS,EAAEC,UAAU,EAAEC,MAAM,EAAEC,IAAI,EAAEC,EAAE,QAAQ;AAExD,SAASC,uBAAuB,EAAEC,kBAAkB,QAAQ;AAC5D,SAASC,WAAW,QAAQ;AAE5B,IAAIC,SAAA;AACJ,IAAIC,IAAA;AAEJR,UAAA,CAAW;EACTS,UAAA,CAAWC,wBAAwB,GAAG;EACtCH,SAAA,GAAYI,QAAA,CAASf,aAAa,CAAC;EACnCe,QAAA,CAASC,IAAI,CAACC,WAAW,CAACN,SAAA;EAC1BC,IAAA,GAAOV,UAAA,CAAWS,SAAA;AACpB;AAEAR,SAAA,CAAU;EACRJ,GAAA,CAAI,MAAMa,IAAA,CAAKM,OAAO;EACtBP,SAAA,CAAUQ,MAAM;EAChBZ,EAAA,CAAGa,aAAa;AAClB;AAEAd,IAAA,CAAK,+EAA+E;EAClFC,EAAA,CAAGc,aAAa;EAEhB,MAAMC,cAAA,GAAiBA,CAAA;IACrB,MAAM;MAAEC;IAAmB,CAAE,GAAGd,kBAAA;IAEhCR,SAAA,CAAU;MACR,MAAMuB,sBAAA,GAAyBD,mBAAA;MAC/B,MAAME,OAAA,GAAUC,UAAA,CAAWF,sBAAA,EAAwB;MAEnD,OAAO;QACLG,YAAA,CAAaF,OAAA;QACbD,sBAAA;MACF;IACF,GAAG,CAACD,mBAAA,CAAoB;IAExB,OAAO;EACT;EAEA,MAAMxB,GAAA,CAAI;IACRa,IAAA,CAAKgB,MAAM,CACT5B,aAAA,CACEQ,uBAAA,EACA,MACAR,aAAA,CAAcU,WAAA,GACdV,aAAA,CAAcsB,cAAA;EAGpB;EAEA,MAAMvB,GAAA,CAAI;IACR,MAAMQ,EAAA,CAAGsB,wBAAwB,CAAC;EACpC;EAEAxB,MAAA,CAAOM,SAAA,CAAUmB,aAAa,CAAC,kBAAkBC,QAAQ;AAC3D","ignoreList":[]}
@@ -1,40 +0,0 @@
1
- import { describe, expect, it, vi } from 'vitest';
2
- import { buildColumnState } from './index.js';
3
- vi.mock('../../../exports/client/index.js', () => ({
4
- SortColumn: () => null
5
- }));
6
- describe('buildColumnState', () => {
7
- it('should handle fields with admin components explicitly set to undefined', () => {
8
- const clientField = {
9
- name: 'title',
10
- type: 'text'
11
- };
12
- const serverField = {
13
- name: 'title',
14
- type: 'text',
15
- admin: {
16
- components: undefined
17
- }
18
- };
19
- const columns = buildColumnState({
20
- clientFields: [clientField],
21
- collectionSlug: 'posts',
22
- customCellProps: {},
23
- dataType: 'monomorphic',
24
- docs: [],
25
- enableRowSelections: false,
26
- fieldPermissions: true,
27
- i18n: {
28
- t: vi.fn()
29
- },
30
- payload: {
31
- importMap: {}
32
- },
33
- serverFields: [serverField],
34
- useAsTitle: 'title'
35
- });
36
- expect(columns).toHaveLength(1);
37
- expect(columns[0].CustomLabel).toBeUndefined();
38
- });
39
- });
40
- //# sourceMappingURL=index.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.spec.js","names":["describe","expect","it","vi","buildColumnState","mock","SortColumn","clientField","name","type","serverField","admin","components","undefined","columns","clientFields","collectionSlug","customCellProps","dataType","docs","enableRowSelections","fieldPermissions","i18n","t","fn","payload","importMap","serverFields","useAsTitle","toHaveLength","CustomLabel","toBeUndefined"],"sources":["../../../../src/providers/TableColumns/buildColumnState/index.spec.ts"],"sourcesContent":["import type { I18nClient } from '@payloadcms/translations'\nimport type { ClientField, Field, Payload } from 'payload'\n\nimport { describe, expect, it, vi } from 'vitest'\n\nimport { buildColumnState } from './index.js'\n\nvi.mock('../../../exports/client/index.js', () => ({\n SortColumn: () => null,\n}))\n\ndescribe('buildColumnState', () => {\n it('should handle fields with admin components explicitly set to undefined', () => {\n const clientField: ClientField = {\n name: 'title',\n type: 'text',\n }\n const serverField: Field = {\n name: 'title',\n type: 'text',\n admin: {\n components: undefined,\n },\n }\n\n const columns = buildColumnState({\n clientFields: [clientField],\n collectionSlug: 'posts',\n customCellProps: {},\n dataType: 'monomorphic',\n docs: [],\n enableRowSelections: false,\n fieldPermissions: true,\n i18n: {\n t: vi.fn(),\n } as unknown as I18nClient,\n payload: {\n importMap: {},\n } as unknown as Payload,\n serverFields: [serverField],\n useAsTitle: 'title',\n })\n\n expect(columns).toHaveLength(1)\n expect(columns[0].CustomLabel).toBeUndefined()\n })\n})\n"],"mappings":"AAGA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ;AAEzC,SAASC,gBAAgB,QAAQ;AAEjCD,EAAA,CAAGE,IAAI,CAAC,oCAAoC,OAAO;EACjDC,UAAA,EAAYA,CAAA,KAAM;AACpB;AAEAN,QAAA,CAAS,oBAAoB;EAC3BE,EAAA,CAAG,0EAA0E;IAC3E,MAAMK,WAAA,GAA2B;MAC/BC,IAAA,EAAM;MACNC,IAAA,EAAM;IACR;IACA,MAAMC,WAAA,GAAqB;MACzBF,IAAA,EAAM;MACNC,IAAA,EAAM;MACNE,KAAA,EAAO;QACLC,UAAA,EAAYC;MACd;IACF;IAEA,MAAMC,OAAA,GAAUV,gBAAA,CAAiB;MAC/BW,YAAA,EAAc,CAACR,WAAA,CAAY;MAC3BS,cAAA,EAAgB;MAChBC,eAAA,EAAiB,CAAC;MAClBC,QAAA,EAAU;MACVC,IAAA,EAAM,EAAE;MACRC,mBAAA,EAAqB;MACrBC,gBAAA,EAAkB;MAClBC,IAAA,EAAM;QACJC,CAAA,EAAGpB,EAAA,CAAGqB,EAAE;MACV;MACAC,OAAA,EAAS;QACPC,SAAA,EAAW,CAAC;MACd;MACAC,YAAA,EAAc,CAACjB,WAAA,CAAY;MAC3BkB,UAAA,EAAY;IACd;IAEA3B,MAAA,CAAOa,OAAA,EAASe,YAAY,CAAC;IAC7B5B,MAAA,CAAOa,OAAO,CAAC,EAAE,CAACgB,WAAW,EAAEC,aAAa;EAC9C;AACF","ignoreList":[]}
@@ -1,34 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { appendCacheTag } from './appendCacheTag.js';
3
- describe('appendCacheTag', () => {
4
- it('should return the url unchanged when cacheTag is undefined', () => {
5
- expect(appendCacheTag('https://example.com/image.jpg', undefined)).toBe('https://example.com/image.jpg');
6
- });
7
- it('should return the url unchanged when cacheTag is false', () => {
8
- expect(appendCacheTag('https://example.com/image.jpg', false)).toBe('https://example.com/image.jpg');
9
- });
10
- it('should return the url unchanged when cacheTag is empty string', () => {
11
- expect(appendCacheTag('https://example.com/image.jpg', '')).toBe('https://example.com/image.jpg');
12
- });
13
- it('should append the cache tag with ? when the url has no query string', () => {
14
- const result = appendCacheTag('https://example.com/image.jpg', '2024-01-01T00:00:00.000Z');
15
- expect(result).toBe('https://example.com/image.jpg?2024-01-01T00%3A00%3A00.000Z');
16
- });
17
- it('should append the cache tag with & when the url already has a query string', () => {
18
- const result = appendCacheTag('https://example.com/image.jpg?w=800&q=75', '2024-01-01T00:00:00.000Z');
19
- expect(result).toBe('https://example.com/image.jpg?w=800&q=75&2024-01-01T00%3A00%3A00.000Z');
20
- });
21
- it('should URI-encode the cache tag value', () => {
22
- const result = appendCacheTag('/image.jpg', '2024-06-15T12:30:00.000Z');
23
- expect(result).toBe('/image.jpg?2024-06-15T12%3A30%3A00.000Z');
24
- });
25
- it('should work with relative urls', () => {
26
- const result = appendCacheTag('/uploads/photo.png', '2024-01-01T00:00:00.000Z');
27
- expect(result).toBe('/uploads/photo.png?2024-01-01T00%3A00%3A00.000Z');
28
- });
29
- it('should work with relative urls that already have a query string', () => {
30
- const result = appendCacheTag('/uploads/photo.png?size=large', '2024-01-01T00:00:00.000Z');
31
- expect(result).toBe('/uploads/photo.png?size=large&2024-01-01T00%3A00%3A00.000Z');
32
- });
33
- });
34
- //# sourceMappingURL=appendCacheTag.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"appendCacheTag.spec.js","names":["describe","expect","it","appendCacheTag","undefined","toBe","result"],"sources":["../../src/utilities/appendCacheTag.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { appendCacheTag } from './appendCacheTag.js'\n\ndescribe('appendCacheTag', () => {\n it('should return the url unchanged when cacheTag is undefined', () => {\n expect(appendCacheTag('https://example.com/image.jpg', undefined)).toBe(\n 'https://example.com/image.jpg',\n )\n })\n\n it('should return the url unchanged when cacheTag is false', () => {\n expect(appendCacheTag('https://example.com/image.jpg', false)).toBe(\n 'https://example.com/image.jpg',\n )\n })\n\n it('should return the url unchanged when cacheTag is empty string', () => {\n expect(appendCacheTag('https://example.com/image.jpg', '')).toBe(\n 'https://example.com/image.jpg',\n )\n })\n\n it('should append the cache tag with ? when the url has no query string', () => {\n const result = appendCacheTag('https://example.com/image.jpg', '2024-01-01T00:00:00.000Z')\n expect(result).toBe('https://example.com/image.jpg?2024-01-01T00%3A00%3A00.000Z')\n })\n\n it('should append the cache tag with & when the url already has a query string', () => {\n const result = appendCacheTag(\n 'https://example.com/image.jpg?w=800&q=75',\n '2024-01-01T00:00:00.000Z',\n )\n expect(result).toBe('https://example.com/image.jpg?w=800&q=75&2024-01-01T00%3A00%3A00.000Z')\n })\n\n it('should URI-encode the cache tag value', () => {\n const result = appendCacheTag('/image.jpg', '2024-06-15T12:30:00.000Z')\n expect(result).toBe('/image.jpg?2024-06-15T12%3A30%3A00.000Z')\n })\n\n it('should work with relative urls', () => {\n const result = appendCacheTag('/uploads/photo.png', '2024-01-01T00:00:00.000Z')\n expect(result).toBe('/uploads/photo.png?2024-01-01T00%3A00%3A00.000Z')\n })\n\n it('should work with relative urls that already have a query string', () => {\n const result = appendCacheTag('/uploads/photo.png?size=large', '2024-01-01T00:00:00.000Z')\n expect(result).toBe('/uploads/photo.png?size=large&2024-01-01T00%3A00%3A00.000Z')\n })\n})\n"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ;AAErC,SAASC,cAAc,QAAQ;AAE/BH,QAAA,CAAS,kBAAkB;EACzBE,EAAA,CAAG,8DAA8D;IAC/DD,MAAA,CAAOE,cAAA,CAAe,iCAAiCC,SAAA,GAAYC,IAAI,CACrE;EAEJ;EAEAH,EAAA,CAAG,0DAA0D;IAC3DD,MAAA,CAAOE,cAAA,CAAe,iCAAiC,QAAQE,IAAI,CACjE;EAEJ;EAEAH,EAAA,CAAG,iEAAiE;IAClED,MAAA,CAAOE,cAAA,CAAe,iCAAiC,KAAKE,IAAI,CAC9D;EAEJ;EAEAH,EAAA,CAAG,uEAAuE;IACxE,MAAMI,MAAA,GAASH,cAAA,CAAe,iCAAiC;IAC/DF,MAAA,CAAOK,MAAA,EAAQD,IAAI,CAAC;EACtB;EAEAH,EAAA,CAAG,8EAA8E;IAC/E,MAAMI,MAAA,GAASH,cAAA,CACb,4CACA;IAEFF,MAAA,CAAOK,MAAA,EAAQD,IAAI,CAAC;EACtB;EAEAH,EAAA,CAAG,yCAAyC;IAC1C,MAAMI,MAAA,GAASH,cAAA,CAAe,cAAc;IAC5CF,MAAA,CAAOK,MAAA,EAAQD,IAAI,CAAC;EACtB;EAEAH,EAAA,CAAG,kCAAkC;IACnC,MAAMI,MAAA,GAASH,cAAA,CAAe,sBAAsB;IACpDF,MAAA,CAAOK,MAAA,EAAQD,IAAI,CAAC;EACtB;EAEAH,EAAA,CAAG,mEAAmE;IACpE,MAAMI,MAAA,GAASH,cAAA,CAAe,iCAAiC;IAC/DF,MAAA,CAAOK,MAAA,EAAQD,IAAI,CAAC;EACtB;AACF","ignoreList":[]}
@@ -1,27 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
- import { formatAbsoluteURL } from './formatAbsoluteURL.js';
3
- describe('formatAbsoluteURL', () => {
4
- beforeEach(() => {
5
- vi.stubGlobal('window', {
6
- location: {
7
- origin: 'https://admin.example.com'
8
- }
9
- });
10
- });
11
- afterEach(() => {
12
- vi.unstubAllGlobals();
13
- });
14
- it.each([['/preview', 'https://admin.example.com/preview'], ['preview?draft=true', 'https://admin.example.com/preview?draft=true'], ['../preview', 'https://admin.example.com/preview'], ['?draft=true', 'https://admin.example.com/?draft=true'], ['#preview', 'https://admin.example.com/#preview'], ['//preview.example.com/page', 'https://preview.example.com/page'], ['', 'https://admin.example.com/']])('should resolve relative URL %s against the admin origin', (input, expected) => {
15
- expect(formatAbsoluteURL(input)).toBe(expected);
16
- });
17
- it.each(['http://preview.example.com', 'https://preview.example.com', 'https://preview.example.com:443/one/../two?draft=true#preview'])('should preserve absolute HTTP(S) URL %s', input => {
18
- expect(formatAbsoluteURL(input)).toBe(input);
19
- });
20
- it.each(['mailto:editor@example.com', 'file:///preview.html'])('should return undefined for unsupported URL %s', input => {
21
- expect(formatAbsoluteURL(input)).toBeUndefined();
22
- });
23
- it.each(['http://', 'https://', 'https://[invalid'])('should return undefined for invalid URL %s', input => {
24
- expect(formatAbsoluteURL(input)).toBeUndefined();
25
- });
26
- });
27
- //# sourceMappingURL=formatAbsoluteURL.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"formatAbsoluteURL.spec.js","names":["afterEach","beforeEach","describe","expect","it","vi","formatAbsoluteURL","stubGlobal","location","origin","unstubAllGlobals","each","input","expected","toBe","toBeUndefined"],"sources":["../../src/utilities/formatAbsoluteURL.spec.ts"],"sourcesContent":["import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'\n\nimport { formatAbsoluteURL } from './formatAbsoluteURL.js'\n\ndescribe('formatAbsoluteURL', () => {\n beforeEach(() => {\n vi.stubGlobal('window', {\n location: { origin: 'https://admin.example.com' },\n })\n })\n\n afterEach(() => {\n vi.unstubAllGlobals()\n })\n\n it.each([\n ['/preview', 'https://admin.example.com/preview'],\n ['preview?draft=true', 'https://admin.example.com/preview?draft=true'],\n ['../preview', 'https://admin.example.com/preview'],\n ['?draft=true', 'https://admin.example.com/?draft=true'],\n ['#preview', 'https://admin.example.com/#preview'],\n ['//preview.example.com/page', 'https://preview.example.com/page'],\n ['', 'https://admin.example.com/'],\n ])('should resolve relative URL %s against the admin origin', (input, expected) => {\n expect(formatAbsoluteURL(input)).toBe(expected)\n })\n\n it.each([\n 'http://preview.example.com',\n 'https://preview.example.com',\n 'https://preview.example.com:443/one/../two?draft=true#preview',\n ])('should preserve absolute HTTP(S) URL %s', (input) => {\n expect(formatAbsoluteURL(input)).toBe(input)\n })\n\n it.each(['mailto:editor@example.com', 'file:///preview.html'])(\n 'should return undefined for unsupported URL %s',\n (input) => {\n expect(formatAbsoluteURL(input)).toBeUndefined()\n },\n )\n\n it.each(['http://', 'https://', 'https://[invalid'])(\n 'should return undefined for invalid URL %s',\n (input) => {\n expect(formatAbsoluteURL(input)).toBeUndefined()\n },\n )\n})\n"],"mappings":"AAAA,SAASA,SAAS,EAAEC,UAAU,EAAEC,QAAQ,EAAEC,MAAM,EAAEC,EAAE,EAAEC,EAAE,QAAQ;AAEhE,SAASC,iBAAiB,QAAQ;AAElCJ,QAAA,CAAS,qBAAqB;EAC5BD,UAAA,CAAW;IACTI,EAAA,CAAGE,UAAU,CAAC,UAAU;MACtBC,QAAA,EAAU;QAAEC,MAAA,EAAQ;MAA4B;IAClD;EACF;EAEAT,SAAA,CAAU;IACRK,EAAA,CAAGK,gBAAgB;EACrB;EAEAN,EAAA,CAAGO,IAAI,CAAC,CACN,CAAC,YAAY,oCAAoC,EACjD,CAAC,sBAAsB,+CAA+C,EACtE,CAAC,cAAc,oCAAoC,EACnD,CAAC,eAAe,wCAAwC,EACxD,CAAC,YAAY,qCAAqC,EAClD,CAAC,8BAA8B,mCAAmC,EAClE,CAAC,IAAI,6BAA6B,CACnC,EAAE,2DAA2D,CAACC,KAAA,EAAOC,QAAA;IACpEV,MAAA,CAAOG,iBAAA,CAAkBM,KAAA,GAAQE,IAAI,CAACD,QAAA;EACxC;EAEAT,EAAA,CAAGO,IAAI,CAAC,CACN,8BACA,+BACA,gEACD,EAAE,2CAA4CC,KAAA;IAC7CT,MAAA,CAAOG,iBAAA,CAAkBM,KAAA,GAAQE,IAAI,CAACF,KAAA;EACxC;EAEAR,EAAA,CAAGO,IAAI,CAAC,CAAC,6BAA6B,uBAAuB,EAC3D,kDACCC,KAAA;IACCT,MAAA,CAAOG,iBAAA,CAAkBM,KAAA,GAAQG,aAAa;EAChD;EAGFX,EAAA,CAAGO,IAAI,CAAC,CAAC,WAAW,YAAY,mBAAmB,EACjD,8CACCC,KAAA;IACCT,MAAA,CAAOG,iBAAA,CAAkBM,KAAA,GAAQG,aAAa;EAChD;AAEJ","ignoreList":[]}
@@ -1,83 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { formatMetadata } from './formatMetadata.js';
3
- describe('formatMetadata', () => {
4
- it('should handle a string title with titleSuffix', async () => {
5
- const result = await formatMetadata({
6
- serverURL: 'http://localhost:3000',
7
- title: 'Dashboard',
8
- titleSuffix: '- My CMS'
9
- });
10
- expect(result.title).toBe('Dashboard - My CMS');
11
- });
12
- it('should apply titleSuffix to default and template fields of a TemplateString title object', async () => {
13
- const result = await formatMetadata({
14
- serverURL: 'http://localhost:3000',
15
- title: {
16
- default: 'Dashboard',
17
- template: '%s | Dashboard'
18
- },
19
- titleSuffix: '- My CMS'
20
- });
21
- expect(typeof result.title).toBe('object');
22
- expect(result.title.default).toBe('Dashboard - My CMS');
23
- expect(result.title.template).toBe('%s | Dashboard - My CMS');
24
- });
25
- it('should use the TemplateString default for ogTitle when title is a TemplateString object', async () => {
26
- const result = await formatMetadata({
27
- serverURL: 'http://localhost:3000',
28
- title: {
29
- default: 'My CMS',
30
- template: '%s | My CMS'
31
- },
32
- titleSuffix: '- Payload'
33
- });
34
- // OG title must be a plain string — extract from TemplateString.default and append titleSuffix
35
- expect(result.openGraph?.title).toBe('My CMS - Payload');
36
- });
37
- it('should use the TemplateString absolute for ogTitle when title has absolute property', async () => {
38
- const result = await formatMetadata({
39
- serverURL: 'http://localhost:3000',
40
- title: {
41
- absolute: 'My CMS Absolute'
42
- },
43
- titleSuffix: '- Payload'
44
- });
45
- expect(result.openGraph?.title).toBe('My CMS Absolute - Payload');
46
- });
47
- it('should apply titleSuffix to the absolute field of a TemplateString title object', async () => {
48
- const result = await formatMetadata({
49
- serverURL: 'http://localhost:3000',
50
- title: {
51
- absolute: 'My CMS Absolute'
52
- },
53
- titleSuffix: '- Payload'
54
- });
55
- expect(typeof result.title).toBe('object');
56
- expect(result.title.absolute).toBe('My CMS Absolute - Payload');
57
- });
58
- it('should use openGraph.title string over incomingMetadata.title for ogTitle', async () => {
59
- const result = await formatMetadata({
60
- serverURL: 'http://localhost:3000',
61
- title: 'My CMS',
62
- titleSuffix: '- Payload',
63
- openGraph: {
64
- title: 'Custom OG Title'
65
- }
66
- });
67
- expect(result.openGraph?.title).toBe('Custom OG Title');
68
- });
69
- it('should return undefined for metaTitle when no title and no titleSuffix are set', async () => {
70
- const result = await formatMetadata({
71
- serverURL: 'http://localhost:3000'
72
- });
73
- expect(result.title).toBeUndefined();
74
- });
75
- it('should return just the title when no titleSuffix is set', async () => {
76
- const result = await formatMetadata({
77
- serverURL: 'http://localhost:3000',
78
- title: 'My CMS'
79
- });
80
- expect(result.title).toBe('My CMS');
81
- });
82
- });
83
- //# sourceMappingURL=formatMetadata.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"formatMetadata.spec.js","names":["describe","expect","it","formatMetadata","result","serverURL","title","titleSuffix","toBe","default","template","openGraph","absolute","toBeUndefined"],"sources":["../../src/utilities/formatMetadata.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport { formatMetadata } from './formatMetadata.js'\n\ndescribe('formatMetadata', () => {\n it('should handle a string title with titleSuffix', async () => {\n const result = await formatMetadata({\n serverURL: 'http://localhost:3000',\n title: 'Dashboard',\n titleSuffix: '- My CMS',\n })\n\n expect(result.title).toBe('Dashboard - My CMS')\n })\n\n it('should apply titleSuffix to default and template fields of a TemplateString title object', async () => {\n const result = await formatMetadata({\n serverURL: 'http://localhost:3000',\n title: { default: 'Dashboard', template: '%s | Dashboard' },\n titleSuffix: '- My CMS',\n })\n\n expect(typeof result.title).toBe('object')\n expect((result.title as { default: string; template: string }).default).toBe(\n 'Dashboard - My CMS',\n )\n expect((result.title as { default: string; template: string }).template).toBe(\n '%s | Dashboard - My CMS',\n )\n })\n\n it('should use the TemplateString default for ogTitle when title is a TemplateString object', async () => {\n const result = await formatMetadata({\n serverURL: 'http://localhost:3000',\n title: { default: 'My CMS', template: '%s | My CMS' },\n titleSuffix: '- Payload',\n })\n\n // OG title must be a plain string — extract from TemplateString.default and append titleSuffix\n expect(result.openGraph?.title).toBe('My CMS - Payload')\n })\n\n it('should use the TemplateString absolute for ogTitle when title has absolute property', async () => {\n const result = await formatMetadata({\n serverURL: 'http://localhost:3000',\n title: { absolute: 'My CMS Absolute' },\n titleSuffix: '- Payload',\n })\n\n expect(result.openGraph?.title).toBe('My CMS Absolute - Payload')\n })\n\n it('should apply titleSuffix to the absolute field of a TemplateString title object', async () => {\n const result = await formatMetadata({\n serverURL: 'http://localhost:3000',\n title: { absolute: 'My CMS Absolute' },\n titleSuffix: '- Payload',\n })\n\n expect(typeof result.title).toBe('object')\n expect((result.title as { absolute: string }).absolute).toBe('My CMS Absolute - Payload')\n })\n\n it('should use openGraph.title string over incomingMetadata.title for ogTitle', async () => {\n const result = await formatMetadata({\n serverURL: 'http://localhost:3000',\n title: 'My CMS',\n titleSuffix: '- Payload',\n openGraph: { title: 'Custom OG Title' },\n })\n\n expect(result.openGraph?.title).toBe('Custom OG Title')\n })\n\n it('should return undefined for metaTitle when no title and no titleSuffix are set', async () => {\n const result = await formatMetadata({\n serverURL: 'http://localhost:3000',\n })\n\n expect(result.title).toBeUndefined()\n })\n\n it('should return just the title when no titleSuffix is set', async () => {\n const result = await formatMetadata({\n serverURL: 'http://localhost:3000',\n title: 'My CMS',\n })\n\n expect(result.title).toBe('My CMS')\n })\n})\n"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ;AAErC,SAASC,cAAc,QAAQ;AAE/BH,QAAA,CAAS,kBAAkB;EACzBE,EAAA,CAAG,iDAAiD;IAClD,MAAME,MAAA,GAAS,MAAMD,cAAA,CAAe;MAClCE,SAAA,EAAW;MACXC,KAAA,EAAO;MACPC,WAAA,EAAa;IACf;IAEAN,MAAA,CAAOG,MAAA,CAAOE,KAAK,EAAEE,IAAI,CAAC;EAC5B;EAEAN,EAAA,CAAG,4FAA4F;IAC7F,MAAME,MAAA,GAAS,MAAMD,cAAA,CAAe;MAClCE,SAAA,EAAW;MACXC,KAAA,EAAO;QAAEG,OAAA,EAAS;QAAaC,QAAA,EAAU;MAAiB;MAC1DH,WAAA,EAAa;IACf;IAEAN,MAAA,CAAO,OAAOG,MAAA,CAAOE,KAAK,EAAEE,IAAI,CAAC;IACjCP,MAAA,CAAOG,MAAC,CAAOE,KAAK,CAA2CG,OAAO,EAAED,IAAI,CAC1E;IAEFP,MAAA,CAAOG,MAAC,CAAOE,KAAK,CAA2CI,QAAQ,EAAEF,IAAI,CAC3E;EAEJ;EAEAN,EAAA,CAAG,2FAA2F;IAC5F,MAAME,MAAA,GAAS,MAAMD,cAAA,CAAe;MAClCE,SAAA,EAAW;MACXC,KAAA,EAAO;QAAEG,OAAA,EAAS;QAAUC,QAAA,EAAU;MAAc;MACpDH,WAAA,EAAa;IACf;IAEA;IACAN,MAAA,CAAOG,MAAA,CAAOO,SAAS,EAAEL,KAAA,EAAOE,IAAI,CAAC;EACvC;EAEAN,EAAA,CAAG,uFAAuF;IACxF,MAAME,MAAA,GAAS,MAAMD,cAAA,CAAe;MAClCE,SAAA,EAAW;MACXC,KAAA,EAAO;QAAEM,QAAA,EAAU;MAAkB;MACrCL,WAAA,EAAa;IACf;IAEAN,MAAA,CAAOG,MAAA,CAAOO,SAAS,EAAEL,KAAA,EAAOE,IAAI,CAAC;EACvC;EAEAN,EAAA,CAAG,mFAAmF;IACpF,MAAME,MAAA,GAAS,MAAMD,cAAA,CAAe;MAClCE,SAAA,EAAW;MACXC,KAAA,EAAO;QAAEM,QAAA,EAAU;MAAkB;MACrCL,WAAA,EAAa;IACf;IAEAN,MAAA,CAAO,OAAOG,MAAA,CAAOE,KAAK,EAAEE,IAAI,CAAC;IACjCP,MAAA,CAAOG,MAAC,CAAOE,KAAK,CAA0BM,QAAQ,EAAEJ,IAAI,CAAC;EAC/D;EAEAN,EAAA,CAAG,6EAA6E;IAC9E,MAAME,MAAA,GAAS,MAAMD,cAAA,CAAe;MAClCE,SAAA,EAAW;MACXC,KAAA,EAAO;MACPC,WAAA,EAAa;MACbI,SAAA,EAAW;QAAEL,KAAA,EAAO;MAAkB;IACxC;IAEAL,MAAA,CAAOG,MAAA,CAAOO,SAAS,EAAEL,KAAA,EAAOE,IAAI,CAAC;EACvC;EAEAN,EAAA,CAAG,kFAAkF;IACnF,MAAME,MAAA,GAAS,MAAMD,cAAA,CAAe;MAClCE,SAAA,EAAW;IACb;IAEAJ,MAAA,CAAOG,MAAA,CAAOE,KAAK,EAAEO,aAAa;EACpC;EAEAX,EAAA,CAAG,2DAA2D;IAC5D,MAAME,MAAA,GAAS,MAAMD,cAAA,CAAe;MAClCE,SAAA,EAAW;MACXC,KAAA,EAAO;IACT;IAEAL,MAAA,CAAOG,MAAA,CAAOE,KAAK,EAAEE,IAAI,CAAC;EAC5B;AACF","ignoreList":[]}