@plone/volto 19.0.0-alpha.0 → 19.0.0-alpha.1

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 (148) hide show
  1. package/.eslintignore +1 -0
  2. package/.eslintrc +2 -0
  3. package/CHANGELOG.md +46 -2
  4. package/package.json +14 -7
  5. package/src/actions/actions/actions.test.js +3 -3
  6. package/src/actions/addons/addons.test.js +15 -12
  7. package/src/actions/aliases/aliases.test.js +1 -1
  8. package/src/actions/querystring/querystring.test.js +2 -2
  9. package/src/actions/types/types.test.js +1 -1
  10. package/src/components/manage/Actions/Actions.test.jsx +5 -1
  11. package/src/components/manage/Add/Add.jsx +22 -20
  12. package/src/components/manage/Add/Add.test.jsx +6 -3
  13. package/src/components/manage/Aliases/Aliases.test.jsx +7 -7
  14. package/src/components/manage/Blocks/Block/BlocksForm.jsx +1 -0
  15. package/src/components/manage/Blocks/Block/BlocksForm.test.jsx +48 -16
  16. package/src/components/manage/Blocks/Block/Edit.jsx +2 -1
  17. package/src/components/manage/Blocks/Block/Settings.test.jsx +5 -1
  18. package/src/components/manage/Blocks/Block/StyleWrapper.jsx +11 -3
  19. package/src/components/manage/Blocks/Description/View.test.jsx +1 -1
  20. package/src/components/manage/Blocks/HTML/Edit.test.jsx +12 -5
  21. package/src/components/manage/Blocks/HTML/View.test.jsx +1 -1
  22. package/src/components/manage/Blocks/Image/ImageSidebar.test.jsx +6 -2
  23. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.test.jsx +8 -1
  24. package/src/components/manage/Blocks/Listing/View.test.jsx +3 -1
  25. package/src/components/manage/Blocks/Maps/MapsSidebar.test.jsx +5 -1
  26. package/src/components/manage/Blocks/Search/components/DateRangeFacet.test.jsx +13 -7
  27. package/src/components/manage/Blocks/Search/components/SelectFacet.test.jsx +12 -6
  28. package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.test.jsx +11 -1
  29. package/src/components/manage/Blocks/Video/VideoSidebar.test.jsx +5 -1
  30. package/src/components/manage/ConditionalLink/ConditionalLink.test.tsx +109 -0
  31. package/src/components/manage/ConditionalLink/ConditionalLink.tsx +36 -0
  32. package/src/components/manage/Contents/Contents.test.jsx +29 -13
  33. package/src/components/manage/Contents/ContentsPropertiesModal.test.jsx +5 -1
  34. package/src/components/manage/Contents/ContentsRenameModal.test.jsx +5 -1
  35. package/src/components/manage/Contents/ContentsTagsModal.test.jsx +5 -1
  36. package/src/components/manage/Contents/ContentsWorkflowModal.test.jsx +5 -1
  37. package/src/components/manage/Contents/__mocks__/index.tsx +16 -0
  38. package/src/components/manage/Contents/__mocks__/index.vitest.tsx +5 -0
  39. package/src/components/manage/Controlpanels/AddonsControlpanel.test.jsx +28 -3
  40. package/src/components/manage/Controlpanels/Aliases.test.jsx +35 -3
  41. package/src/components/manage/Controlpanels/ContentType.test.jsx +29 -3
  42. package/src/components/manage/Controlpanels/ContentTypeLayout.test.jsx +4 -2
  43. package/src/components/manage/Controlpanels/ContentTypes.test.jsx +25 -2
  44. package/src/components/manage/Controlpanels/Controlpanel.test.jsx +37 -6
  45. package/src/components/manage/Controlpanels/Controlpanels.test.jsx +47 -3
  46. package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.test.jsx +15 -9
  47. package/src/components/manage/Controlpanels/ModerateComments.test.jsx +31 -5
  48. package/src/components/manage/Controlpanels/Rules/AddRule.test.jsx +13 -4
  49. package/src/components/manage/Controlpanels/Rules/ConfigureRule.test.jsx +9 -5
  50. package/src/components/manage/Controlpanels/Rules/EditRule.test.jsx +12 -4
  51. package/src/components/manage/Controlpanels/Rules/Rules.test.jsx +7 -3
  52. package/src/components/manage/Controlpanels/UndoControlpanel.test.jsx +33 -4
  53. package/src/components/manage/Controlpanels/Users/UserGroupMembershipControlPanel.test.jsx +3 -1
  54. package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +15 -9
  55. package/src/components/manage/Delete/Delete.test.jsx +45 -4
  56. package/src/components/manage/Diff/Diff.test.jsx +15 -6
  57. package/src/components/manage/Diff/DiffField.test.jsx +12 -6
  58. package/src/components/manage/Display/Display.test.jsx +17 -6
  59. package/src/components/manage/Edit/Edit.test.jsx +11 -3
  60. package/src/components/manage/Form/BlockDataForm.test.jsx +5 -1
  61. package/src/components/manage/Form/Form.test.jsx +5 -1
  62. package/src/components/manage/Form/InlineForm.test.jsx +5 -1
  63. package/src/components/manage/Form/ModalForm.test.jsx +5 -1
  64. package/src/components/manage/Form/__mocks__/index.tsx +17 -0
  65. package/src/components/manage/Form/__mocks__/index.vitest.tsx +73 -0
  66. package/src/components/manage/History/History.test.jsx +3 -1
  67. package/src/components/manage/LinksToItem/LinksToItem.test.jsx +6 -4
  68. package/src/components/manage/MaybeWrap/MaybeWrap.tsx +15 -0
  69. package/src/components/manage/Multilingual/ManageTranslations.test.jsx +3 -2
  70. package/src/components/manage/Preferences/ChangePassword.test.jsx +9 -2
  71. package/src/components/manage/Preferences/PersonalInformation.test.jsx +3 -1
  72. package/src/components/manage/Preferences/PersonalPreferences.test.jsx +20 -7
  73. package/src/components/manage/Rules/Rules.test.jsx +6 -3
  74. package/src/components/manage/Sharing/Sharing.test.jsx +3 -1
  75. package/src/components/manage/Sidebar/ObjectBrowserNav.test.jsx +3 -3
  76. package/src/components/manage/Toolbar/More.test.jsx +6 -7
  77. package/src/components/manage/UniversalLink/UniversalLink.test.jsx +196 -14
  78. package/src/components/manage/UniversalLink/UniversalLink.tsx +214 -0
  79. package/src/components/manage/Widgets/ArrayWidget.test.jsx +22 -5
  80. package/src/components/manage/Widgets/CheckboxGroupWidget.test.jsx +12 -5
  81. package/src/components/manage/Widgets/DatetimeWidget.test.jsx +21 -6
  82. package/src/components/manage/Widgets/ImageWidget.jsx +5 -2
  83. package/src/components/manage/Widgets/NumberWidget.test.jsx +8 -7
  84. package/src/components/manage/Widgets/ObjectListWidget.jsx +11 -1
  85. package/src/components/manage/Widgets/ObjectListWidget.test.jsx +18 -8
  86. package/src/components/manage/Widgets/ObjectWidget.test.jsx +5 -1
  87. package/src/components/manage/Widgets/RadioGroupWidget.test.jsx +12 -5
  88. package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.test.jsx +12 -6
  89. package/src/components/manage/Widgets/RegistryImageWidget.test.jsx +43 -41
  90. package/src/components/manage/Widgets/SchemaWidget.test.jsx +12 -5
  91. package/src/components/manage/Widgets/SchemaWidgetFieldset.test.jsx +12 -5
  92. package/src/components/manage/Widgets/SelectAutoComplete.test.jsx +12 -6
  93. package/src/components/manage/Widgets/SelectWidget.test.jsx +12 -6
  94. package/src/components/manage/Widgets/TimeWidget.test.jsx +13 -5
  95. package/src/components/manage/Widgets/TokenWidget.test.jsx +12 -6
  96. package/src/components/manage/Widgets/VocabularyTermsWidget.test.jsx +18 -9
  97. package/src/components/manage/Widgets/__mocks__/index.tsx +16 -0
  98. package/src/components/manage/Widgets/__mocks__/index.vitest.tsx +41 -0
  99. package/src/components/manage/Workflow/Workflow.test.jsx +17 -7
  100. package/src/components/theme/App/App.test.jsx +21 -17
  101. package/src/components/theme/AppExtras/AppExtras.test.jsx +6 -6
  102. package/src/components/theme/Comments/CommentEditModal.test.jsx +5 -1
  103. package/src/components/theme/Comments/Comments.test.jsx +29 -12
  104. package/src/components/theme/ContactForm/ContactForm.test.jsx +8 -4
  105. package/src/components/theme/Header/Header.test.jsx +19 -13
  106. package/src/components/theme/Logout/Logout.test.jsx +1 -1
  107. package/src/components/theme/PasswordReset/PasswordReset.test.jsx +10 -1
  108. package/src/components/theme/PasswordReset/RequestPasswordReset.test.jsx +5 -1
  109. package/src/components/theme/Register/Register.test.jsx +5 -1
  110. package/src/components/theme/Search/Search.test.jsx +6 -4
  111. package/src/components/theme/TsTest/TsTest.test.tsx +0 -1
  112. package/src/components/theme/View/EventDatesInfo.test.jsx +12 -5
  113. package/src/components/theme/View/EventView.test.jsx +12 -5
  114. package/src/components/theme/View/ListingView.test.jsx +2 -0
  115. package/src/components/theme/View/SummaryView.test.jsx +10 -0
  116. package/src/components/theme/View/TabularView.test.jsx +1 -0
  117. package/src/components/theme/View/View.test.jsx +42 -23
  118. package/src/helpers/Api/Api.plone.rest.test.js +11 -9
  119. package/src/helpers/Api/Api.test.js +11 -14
  120. package/src/helpers/AsyncConnect/AsyncConnect.test.jsx +145 -189
  121. package/src/helpers/AuthToken/AuthToken.test.js +60 -22
  122. package/src/helpers/Blocks/Blocks.test.js +1 -1
  123. package/src/helpers/Html/Html.test.jsx +32 -28
  124. package/src/helpers/Loadable/__mocks__/Loadable.jsx +16 -1
  125. package/src/helpers/Loadable/__mocks__/Loadable.vitest.jsx +39 -0
  126. package/src/middleware/Api.test.js +47 -0
  127. package/src/middleware/api.js +1 -1
  128. package/src/middleware/storeProtectLoadUtils.test.js +90 -78
  129. package/test-setup-globals-vitest.js +46 -0
  130. package/tsconfig.declarations.json +12 -1
  131. package/tsconfig.json +2 -1
  132. package/types/components/manage/ConditionalLink/ConditionalLink.d.ts +11 -15
  133. package/types/components/manage/Contents/__mocks__/index.vitest.d.ts +2 -0
  134. package/types/components/manage/Form/__mocks__/index.vitest.d.ts +8 -0
  135. package/types/components/manage/MaybeWrap/MaybeWrap.d.ts +7 -5
  136. package/types/components/manage/UniversalLink/UniversalLink.d.ts +54 -20
  137. package/types/components/manage/Widgets/__mocks__/index.vitest.d.ts +33 -0
  138. package/types/helpers/Loadable/__mocks__/Loadable.vitest.d.ts +3 -0
  139. package/types/react-router-hash-link.d.ts +12 -0
  140. package/types/routes.d.ts +4 -0
  141. package/types/server.d.ts +1 -1
  142. package/vite-plugins/svg.mjs +81 -0
  143. package/vitest.config.mjs +77 -0
  144. package/src/components/manage/ConditionalLink/ConditionalLink.jsx +0 -27
  145. package/src/components/manage/ConditionalLink/ConditionalLink.test.jsx +0 -30
  146. package/src/components/manage/MaybeWrap/MaybeWrap.jsx +0 -9
  147. package/src/components/manage/UniversalLink/UniversalLink.jsx +0 -154
  148. package/src/components/manage/Widgets/FileWidget.test.jsx +0 -91
@@ -1,15 +1,11 @@
1
- export default ConditionalLink;
2
- declare function ConditionalLink({ condition, to, item, ...props }: {
3
- [x: string]: any;
4
- condition: any;
5
- to: any;
6
- item: any;
7
- }): import("react/jsx-runtime").JSX.Element;
8
- declare namespace ConditionalLink {
9
- namespace propTypes {
10
- let condition: any;
11
- let to: any;
12
- let item: any;
13
- let children: any;
14
- }
15
- }
1
+ import React from 'react';
2
+ import type { UniversalLinkProps } from '@plone/volto/components/manage/UniversalLink/UniversalLink';
3
+ declare const _default: React.MemoExoticComponent<React.ForwardRefExoticComponent<{
4
+ condition?: boolean;
5
+ to?: string;
6
+ children: React.ReactNode;
7
+ } & Omit<UniversalLinkProps, "href" | "item"> & {
8
+ href?: string;
9
+ item?: UniversalLinkProps["item"];
10
+ } & React.RefAttributes<HTMLAnchorElement | HTMLDivElement>>>;
11
+ export default _default;
@@ -0,0 +1,2 @@
1
+ export declare const Contents: any;
2
+ export declare const ContentsRenameModal: any;
@@ -0,0 +1,8 @@
1
+ export declare const Field: any;
2
+ export declare const InlineForm: any;
3
+ export declare const ModalForm: any;
4
+ export declare const UndoToolbar: any;
5
+ export declare const BlocksToolbar: any;
6
+ export declare const BlockDataForm: any;
7
+ export declare const BlocksForm: any;
8
+ export declare const Form: any;
@@ -1,5 +1,7 @@
1
- export default function MaybeWrap({ condition, as: Component, ...props }: {
2
- [x: string]: any;
3
- condition: any;
4
- as?: string;
5
- }): any;
1
+ import React, { ComponentPropsWithoutRef } from 'react';
2
+ type MaybeWrapProps<T extends React.ElementType> = {
3
+ condition: boolean;
4
+ as: T;
5
+ } & ComponentPropsWithoutRef<React.ElementType extends T ? 'div' : T>;
6
+ declare function MaybeWrap<T extends React.ElementType = 'div'>(props: MaybeWrapProps<T>): any;
7
+ export default MaybeWrap;
@@ -1,22 +1,56 @@
1
- export default UniversalLink;
2
- declare function UniversalLink({ href, item, openLinkInNewTab, download, children, className, title, ...props }: {
3
- [x: string]: any;
4
- href: any;
5
- item?: any;
6
- openLinkInNewTab: any;
1
+ import React from 'react';
2
+ import type { ObjectBrowserItem } from '@plone/types';
3
+ type BaseProps = {
4
+ openLinkInNewTab?: boolean;
7
5
  download?: boolean;
8
- children: any;
9
- className?: any;
10
- title?: any;
11
- }): import("react/jsx-runtime").JSX.Element;
12
- declare namespace UniversalLink {
13
- namespace propTypes {
14
- let href: any;
15
- let openLinkInNewTab: any;
16
- let download: any;
17
- let className: any;
18
- let title: any;
19
- let item: any;
20
- let children: any;
21
- }
6
+ children: React.ReactNode;
7
+ className?: string;
8
+ title?: string;
9
+ smooth?: boolean;
10
+ onClick?: (e: React.MouseEvent) => void;
11
+ onKeyDown?: (e: React.KeyboardEvent) => void;
12
+ };
13
+ type HrefOnly = {
14
+ href: string;
15
+ item?: never;
16
+ } & BaseProps;
17
+ type ItemOnly = {
18
+ href?: never;
19
+ item: Partial<ObjectBrowserItem> & {
20
+ remoteUrl?: string;
21
+ };
22
+ } & BaseProps;
23
+ export type UniversalLinkProps = HrefOnly | ItemOnly;
24
+ export interface AppState {
25
+ content: {
26
+ data?: {
27
+ '@components'?: {
28
+ translations?: {
29
+ items?: {
30
+ language: string;
31
+ '@id': string;
32
+ }[];
33
+ };
34
+ };
35
+ };
36
+ };
37
+ navroot: {
38
+ data: {
39
+ navroot: {
40
+ id: string;
41
+ };
42
+ };
43
+ };
44
+ intl: {
45
+ locale: string;
46
+ };
47
+ userSession: {
48
+ token: string | null;
49
+ };
22
50
  }
51
+ export declare const __test: {
52
+ renderCounter: () => void;
53
+ };
54
+ export declare function getUrl(props: UniversalLinkProps, token: string | null, item: UniversalLinkProps['item'], children: React.ReactNode): string;
55
+ declare const UniversalLink: React.MemoExoticComponent<React.ForwardRefExoticComponent<UniversalLinkProps & React.RefAttributes<HTMLAnchorElement | HTMLDivElement>>>;
56
+ export default UniversalLink;
@@ -0,0 +1,33 @@
1
+ export declare const AlignWidget: any;
2
+ export declare const ButtonsWidget: any;
3
+ export declare const ArrayWidget: any;
4
+ export declare const CheckboxWidget: any;
5
+ export declare const FileWidget: any;
6
+ export declare const IdWidget: any;
7
+ export declare const PasswordWidget: any;
8
+ export declare const QueryWidget: any;
9
+ export declare const QuerySortOnWidget: any;
10
+ export declare const QuerystringWidget: any;
11
+ export declare const SchemaWidget: any;
12
+ export declare const SelectWidget: any;
13
+ export declare const TextareaWidget: any;
14
+ export declare const TextWidget: any;
15
+ export declare const TokenWidget: any;
16
+ export declare const WysiwygWidget: any;
17
+ export declare const UrlWidget: any;
18
+ export declare const InternalUrlWidget: any;
19
+ export declare const EmailWidget: any;
20
+ export declare const NumberWidget: any;
21
+ export declare const ImageSizeWidget: any;
22
+ export declare const RegistryImageWidget: any;
23
+ export declare const ReferenceWidget: any;
24
+ export declare const ObjectBrowserWidget: any;
25
+ export declare const ObjectWidget: any;
26
+ export declare const ObjectListWidget: any;
27
+ export declare const VocabularyTermsWidget: any;
28
+ export declare const SelectMetadataWidget: any;
29
+ export declare const SelectAutoComplete: any;
30
+ export declare const ColorPickerWidget: any;
31
+ export declare const DatetimeWidget: any;
32
+ export declare const RecurrenceWidget: any;
33
+ export declare const FormFieldWrapper: any;
@@ -0,0 +1,3 @@
1
+ export function __setLoadables(): Promise<void>;
2
+ export const injectLazyLibs: any;
3
+ export const preloadLazyLibs: any;
@@ -0,0 +1,12 @@
1
+ declare module 'react-router-hash-link' {
2
+ import { ComponentType } from 'react';
3
+ import { NavLinkProps } from 'react-router-dom';
4
+
5
+ interface HashLinkProps extends NavLinkProps {
6
+ smooth?: boolean;
7
+ scroll?: (element: HTMLElement) => void;
8
+ }
9
+
10
+ export const HashLink: ComponentType<HashLinkProps>;
11
+ export const NavHashLink: ComponentType<HashLinkProps>;
12
+ }
package/types/routes.d.ts CHANGED
@@ -39,6 +39,10 @@ declare const routes: {
39
39
  path: string;
40
40
  component: any;
41
41
  routes: ({
42
+ path: string;
43
+ component: React.ComponentType;
44
+ exact?: boolean;
45
+ } | {
42
46
  path: string;
43
47
  component: any;
44
48
  exact?: undefined;
package/types/server.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export function defaultReadCriticalCss(): any;
1
+ export function defaultReadCriticalCss(): string;
2
2
  export default server;
3
3
  declare const server: any;
@@ -0,0 +1,81 @@
1
+ import { promises as fs } from 'fs';
2
+ import { optimize as optimizeSvg } from 'svgo';
3
+ import _debug from 'debug';
4
+
5
+ const debug = _debug('volto-vite-svg-loader');
6
+
7
+ export function svgLoader(options = {}) {
8
+ const { svgoConfig, svgo, defaultImport } = options;
9
+
10
+ const svgRegex = /icons\/.*\.svg(\?(raw|skipsvgo))?$/;
11
+
12
+ return {
13
+ name: 'svg-loader',
14
+ enforce: 'pre',
15
+
16
+ async load(id) {
17
+ if (!id.match(svgRegex)) {
18
+ return;
19
+ }
20
+
21
+ debug('\n', `Processing: ${id}.`);
22
+
23
+ const [path, query] = id.split('?', 2);
24
+ const importType = query || defaultImport;
25
+
26
+ if (importType === 'url') {
27
+ return; // Use default svg loader
28
+ }
29
+
30
+ let content;
31
+ try {
32
+ content = await fs.readFile(path, 'utf-8');
33
+ } catch (ex) {
34
+ debug(
35
+ '\n',
36
+ `${id} couldn't be loaded by vite-svg-loader, fallback to default loader`,
37
+ );
38
+
39
+ return;
40
+ }
41
+
42
+ if (importType === 'raw') {
43
+ return `export default ${JSON.stringify(content)}`;
44
+ }
45
+
46
+ if (svgo !== false && query !== 'skipsvgo') {
47
+ content = optimizeSvg(content, {
48
+ ...svgoConfig,
49
+ path,
50
+ }).data;
51
+ }
52
+
53
+ const match = content.match(/<svg([^>]+)+>([\s\S]+)<\/svg>/i);
54
+ let attrs = {};
55
+
56
+ if (match) {
57
+ attrs = match[1];
58
+ if (attrs) {
59
+ attrs = attrs
60
+ .match(/([\w-:]+)(=)?("[^<>"]*"|'[^<>']*'|[\w-:]+)/g)
61
+ .reduce(function (obj, attr) {
62
+ var split = attr.split('=');
63
+ var name = split[0];
64
+ var value = true;
65
+ if (split && split[1]) {
66
+ value = split[1].replace(/['"]/g, '');
67
+ }
68
+ obj[name] = value;
69
+ return obj;
70
+ }, {});
71
+ }
72
+
73
+ content = match[2] || '';
74
+ }
75
+
76
+ content = content.replace(/\n/g, ' ').trim();
77
+
78
+ return `export default ${JSON.stringify({ attributes: attrs, content: content })}`;
79
+ },
80
+ };
81
+ }
@@ -0,0 +1,77 @@
1
+ import { defineConfig } from 'vitest/config';
2
+ import react from '@vitejs/plugin-react';
3
+ import path from 'path';
4
+ import { svgLoader } from './vite-plugins/svg.mjs';
5
+ import { fileURLToPath } from 'url';
6
+ import { createRequire } from 'module';
7
+
8
+ const require = createRequire(import.meta.url);
9
+
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = path.dirname(__filename);
12
+
13
+ const projectRoot = path.resolve(__dirname);
14
+
15
+ export default defineConfig({
16
+ plugins: [
17
+ react(),
18
+ svgLoader({
19
+ svgoConfig: {
20
+ plugins: [
21
+ {
22
+ name: 'preset-default',
23
+ params: {
24
+ overrides: {
25
+ convertPathData: false,
26
+ removeViewBox: false,
27
+ },
28
+ },
29
+ },
30
+ 'removeTitle',
31
+ 'removeUselessStrokeAndFill',
32
+ ],
33
+ },
34
+ }),
35
+ ],
36
+ resolve: {
37
+ alias: {
38
+ '@plone/volto': path.resolve(__dirname, 'src'),
39
+ '@plone/volto-slate': path.resolve(__dirname, '../volto-slate/src'),
40
+ '@root': path.resolve(__dirname, 'src'),
41
+ 'promise-file-reader': require.resolve('promise-file-reader'),
42
+ 'react-dropzone': require.resolve('react-dropzone'),
43
+ 'prop-types': require.resolve('prop-types'),
44
+ },
45
+ },
46
+ test: {
47
+ isolate: true,
48
+ deps: {
49
+ moduleDirectories: ['node_modules'],
50
+ },
51
+ snapshotFormat: { printBasicPrototype: false },
52
+ globals: true,
53
+ environment: 'jsdom',
54
+ setupFiles: [
55
+ `${projectRoot}/test-setup-globals-vitest.js`,
56
+ `${projectRoot}/test-setup-config.jsx`,
57
+ `${projectRoot}/jest-setup-afterenv.js`,
58
+ `${projectRoot}/jest-addons-loader.js`,
59
+ ],
60
+ globalSetup: `${projectRoot}/global-test-setup.js`,
61
+ coverage: {
62
+ provider: 'v8',
63
+ reporter: ['text', 'json', 'html'],
64
+ include: [
65
+ 'src/**/*.{test,spec}.{js,ts,jsx,tsx}',
66
+ '__test__/**/*.{test,spec}.{js,ts,jsx,tsx}',
67
+ ],
68
+ exclude: [
69
+ 'node_modules/**',
70
+ '**/dist/**',
71
+ '**/*.config.{js,ts}',
72
+ '**/jest-*.js',
73
+ ],
74
+ },
75
+ css: true,
76
+ },
77
+ });
@@ -1,27 +0,0 @@
1
- import React from 'react';
2
- import UniversalLink from '@plone/volto/components/manage/UniversalLink/UniversalLink';
3
- import PropTypes from 'prop-types';
4
-
5
- const ConditionalLink = ({ condition, to, item, ...props }) => {
6
- if (condition) {
7
- return (
8
- <UniversalLink href={to} item={item} {...props}>
9
- {props.children}
10
- </UniversalLink>
11
- );
12
- } else {
13
- return <>{props.children}</>;
14
- }
15
- };
16
-
17
- ConditionalLink.propTypes = {
18
- condition: PropTypes.bool,
19
- to: PropTypes.string,
20
- item: PropTypes.shape({
21
- '@id': PropTypes.string,
22
- remoteUrl: PropTypes.string, //of plone @type 'Link'
23
- }),
24
- children: PropTypes.node,
25
- };
26
-
27
- export default ConditionalLink;
@@ -1,30 +0,0 @@
1
- import React from 'react';
2
- import renderer from 'react-test-renderer';
3
- import { MemoryRouter } from 'react-router-dom';
4
-
5
- import ConditionalLink from './ConditionalLink';
6
-
7
- describe('ConditionalLink', () => {
8
- it('renders a ConditionalLink component not link', () => {
9
- const component = renderer.create(
10
- <MemoryRouter>
11
- <ConditionalLink>
12
- <h1>Title</h1>
13
- </ConditionalLink>
14
- </MemoryRouter>,
15
- );
16
- const json = component.toJSON();
17
- expect(json).toMatchSnapshot();
18
- });
19
- it('renders a ConditionalLink component with link', () => {
20
- const component = renderer.create(
21
- <MemoryRouter>
22
- <ConditionalLink isLink>
23
- <h1>Title</h1>
24
- </ConditionalLink>
25
- </MemoryRouter>,
26
- );
27
- const json = component.toJSON();
28
- expect(json).toMatchSnapshot();
29
- });
30
- });
@@ -1,9 +0,0 @@
1
- import React from 'react';
2
-
3
- export default function MaybeWrap({
4
- condition,
5
- as: Component = 'div',
6
- ...props
7
- }) {
8
- return condition ? <Component {...props} /> : props.children;
9
- }
@@ -1,154 +0,0 @@
1
- /*
2
- * UniversalLink
3
- * @module components/UniversalLink
4
- */
5
-
6
- import React from 'react';
7
- import PropTypes from 'prop-types';
8
- import { HashLink as Link } from 'react-router-hash-link';
9
- import { useSelector } from 'react-redux';
10
- import {
11
- flattenToAppURL,
12
- isInternalURL,
13
- URLUtils,
14
- } from '@plone/volto/helpers/Url/Url';
15
-
16
- import config from '@plone/volto/registry';
17
- import cx from 'classnames';
18
-
19
- const UniversalLink = ({
20
- href,
21
- item = null,
22
- openLinkInNewTab,
23
- download = false,
24
- children,
25
- className = null,
26
- title = null,
27
- ...props
28
- }) => {
29
- const token = useSelector((state) => state.userSession?.token);
30
-
31
- let url = href;
32
- if (!href && item) {
33
- if (item['@id'] === '') {
34
- url = config.settings.publicURL;
35
- } else if (!item['@id']) {
36
- // eslint-disable-next-line no-console
37
- console.error(
38
- 'Invalid item passed to UniversalLink',
39
- item,
40
- props,
41
- children,
42
- );
43
- url = '#';
44
- } else {
45
- //case: generic item
46
- url = flattenToAppURL(item['@id']);
47
-
48
- //case: item like a Link
49
- let remoteUrl = item.remoteUrl || item.getRemoteUrl;
50
- if (!token && remoteUrl) {
51
- url = remoteUrl;
52
- }
53
-
54
- //case: item of type 'File'
55
- if (
56
- !token &&
57
- config.settings.downloadableObjects.includes(item['@type'])
58
- ) {
59
- url = `${url}/@@download/file`;
60
- }
61
-
62
- if (
63
- !token &&
64
- config.settings.viewableInBrowserObjects.includes(item['@type'])
65
- ) {
66
- url = `${url}/@@display-file/file`;
67
- }
68
- }
69
- }
70
-
71
- const isExternal = !isInternalURL(url);
72
-
73
- const isDownload = (!isExternal && url.includes('@@download')) || download;
74
- const isDisplayFile =
75
- (!isExternal && url.includes('@@display-file')) || false;
76
-
77
- const checkedURL = URLUtils.checkAndNormalizeUrl(url);
78
-
79
- url = checkedURL.url;
80
- let tag = (
81
- <Link
82
- to={flattenToAppURL(url)}
83
- target={openLinkInNewTab ?? false ? '_blank' : null}
84
- title={title}
85
- className={className}
86
- smooth={config.settings.hashLinkSmoothScroll}
87
- {...props}
88
- >
89
- {children}
90
- </Link>
91
- );
92
-
93
- if (isExternal) {
94
- const isTelephoneOrMail = checkedURL.isMail || checkedURL.isTelephone;
95
- tag = (
96
- <a
97
- href={url}
98
- title={title}
99
- target={
100
- !isTelephoneOrMail && !(openLinkInNewTab === false) ? '_blank' : null
101
- }
102
- rel="noopener noreferrer"
103
- className={cx({ external: !isTelephoneOrMail }, className)}
104
- {...props}
105
- >
106
- {children}
107
- </a>
108
- );
109
- } else if (isDownload) {
110
- tag = (
111
- <a
112
- href={flattenToAppURL(url)}
113
- download
114
- title={title}
115
- className={className}
116
- {...props}
117
- >
118
- {children}
119
- </a>
120
- );
121
- } else if (isDisplayFile) {
122
- tag = (
123
- <a
124
- href={flattenToAppURL(url)}
125
- title={title}
126
- target="_blank"
127
- rel="noopener noreferrer"
128
- className={className}
129
- {...props}
130
- >
131
- {children}
132
- </a>
133
- );
134
- }
135
- return tag;
136
- };
137
-
138
- UniversalLink.propTypes = {
139
- href: PropTypes.string,
140
- openLinkInNewTab: PropTypes.bool,
141
- download: PropTypes.bool,
142
- className: PropTypes.string,
143
- title: PropTypes.string,
144
- item: PropTypes.shape({
145
- '@id': PropTypes.string.isRequired,
146
- remoteUrl: PropTypes.string, //of plone @type 'Link'
147
- }),
148
- children: PropTypes.oneOfType([
149
- PropTypes.arrayOf(PropTypes.node),
150
- PropTypes.node,
151
- ]),
152
- };
153
-
154
- export default UniversalLink;
@@ -1,91 +0,0 @@
1
- import React from 'react';
2
- import { Provider } from 'react-intl-redux';
3
- import { render, waitFor } from '@testing-library/react';
4
- import configureStore from 'redux-mock-store';
5
-
6
- import FileWidget from './FileWidget';
7
-
8
- jest.spyOn(global.Date, 'now').mockImplementation(() => '0');
9
-
10
- const mockStore = configureStore();
11
-
12
- describe('FileWidget', () => {
13
- test('renders an empty file widget component', async () => {
14
- const store = mockStore({
15
- intl: {
16
- locale: 'en',
17
- messages: {},
18
- },
19
- });
20
-
21
- const { container } = render(
22
- <Provider store={store}>
23
- <FileWidget
24
- id="my-field"
25
- title="My field"
26
- fieldSet="default"
27
- onChange={() => {}}
28
- />
29
- </Provider>,
30
- );
31
-
32
- await waitFor(() => {});
33
- expect(container).toMatchSnapshot();
34
- });
35
- test('renders a file widget component with value', async () => {
36
- const store = mockStore({
37
- intl: {
38
- locale: 'en',
39
- messages: {},
40
- },
41
- });
42
-
43
- const { container } = render(
44
- <Provider store={store}>
45
- <FileWidget
46
- id="my-field"
47
- title="My field"
48
- fieldSet="default"
49
- onChange={() => {}}
50
- value={{
51
- download: 'http://myfile',
52
- 'content-type': 'image/png',
53
- filename: 'myfile',
54
- encoding: '',
55
- }}
56
- />
57
- </Provider>,
58
- );
59
-
60
- await waitFor(() => {});
61
- expect(container).toMatchSnapshot();
62
- });
63
- test('renders a file widget component with value in raw data', async () => {
64
- const store = mockStore({
65
- intl: {
66
- locale: 'en',
67
- messages: {},
68
- },
69
- });
70
-
71
- const { container } = render(
72
- <Provider store={store}>
73
- <FileWidget
74
- id="my-field"
75
- title="My field"
76
- fieldSet="default"
77
- onChange={() => {}}
78
- value={{
79
- data: 'oiweurtksdgfjaslfqw9523563456',
80
- 'content-type': 'image/png',
81
- filename: 'myfile',
82
- encoding: 'base64',
83
- }}
84
- />
85
- </Provider>,
86
- );
87
-
88
- await waitFor(() => {});
89
- expect(container).toMatchSnapshot();
90
- });
91
- });