@eeacms/volto-embed 9.1.0 → 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc.js ADDED
@@ -0,0 +1,65 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const projectRootPath = fs.realpathSync(__dirname + '/../../../');
4
+
5
+ let voltoPath = path.join(projectRootPath, 'node_modules/@plone/volto');
6
+ let configFile;
7
+ if (fs.existsSync(`${projectRootPath}/tsconfig.json`))
8
+ configFile = `${projectRootPath}/tsconfig.json`;
9
+ else if (fs.existsSync(`${projectRootPath}/jsconfig.json`))
10
+ configFile = `${projectRootPath}/jsconfig.json`;
11
+
12
+ if (configFile) {
13
+ const jsConfig = require(configFile).compilerOptions;
14
+ const pathsConfig = jsConfig.paths;
15
+ if (pathsConfig['@plone/volto'])
16
+ voltoPath = `./${jsConfig.baseUrl}/${pathsConfig['@plone/volto'][0]}`;
17
+ }
18
+
19
+ const AddonConfigurationRegistry = require(`${voltoPath}/addon-registry.js`);
20
+ const reg = new AddonConfigurationRegistry(projectRootPath);
21
+
22
+ // Extends ESlint configuration for adding the aliases to `src` directories in Volto addons
23
+ const addonAliases = Object.keys(reg.packages).map((o) => [
24
+ o,
25
+ reg.packages[o].modulePath,
26
+ ]);
27
+
28
+ const addonExtenders = reg.getEslintExtenders().map((m) => require(m));
29
+
30
+ const defaultConfig = {
31
+ extends: `${voltoPath}/.eslintrc`,
32
+ settings: {
33
+ 'import/resolver': {
34
+ alias: {
35
+ map: [
36
+ ['@plone/volto', '@plone/volto/src'],
37
+ ['@plone/volto-slate', '@plone/volto/packages/volto-slate/src'],
38
+ ...addonAliases,
39
+ ['@package', `${__dirname}/src`],
40
+ ['@root', `${__dirname}/src`],
41
+ ['~', `${__dirname}/src`],
42
+ ],
43
+ extensions: ['.js', '.jsx', '.json'],
44
+ },
45
+ 'babel-plugin-root-import': {
46
+ rootPathSuffix: 'src',
47
+ },
48
+ },
49
+ },
50
+ rules: {
51
+ 'react/jsx-no-target-blank': [
52
+ 'error',
53
+ {
54
+ allowReferrer: true,
55
+ },
56
+ ],
57
+ }
58
+ };
59
+
60
+ const config = addonExtenders.reduce(
61
+ (acc, extender) => extender.modify(acc),
62
+ defaultConfig,
63
+ );
64
+
65
+ module.exports = config;
package/CHANGELOG.md CHANGED
@@ -4,11 +4,19 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
- ### [9.1.0](https://github.com/eea/volto-embed/compare/9.0.7...9.1.0) - 17 January 2024
7
+ ### [10.0.0](https://github.com/eea/volto-embed/compare/9.1.1...10.0.0) - 23 April 2024
8
8
 
9
9
  #### :rocket: New Features
10
10
 
11
- - feat: show embed error + always show sources [Razvan - [`105d620`](https://github.com/eea/volto-embed/commit/105d6207b244df85eea6d6b9b3bd8e03da0a439b)]
11
+ - feat: Release 10.0.0 - Volto 17 support [alin - [`bea6fba`](https://github.com/eea/volto-embed/commit/bea6fba260bf0551ac17f7c2e30ddd5717756733)]
12
+ - feat: Volto 17 support - refs #264527 [EEA Jenkins - [`fd4b412`](https://github.com/eea/volto-embed/commit/fd4b412405a32abfb680383c2769013974184371)]
13
+
14
+ ### [9.1.1](https://github.com/eea/volto-embed/compare/9.1.0...9.1.1) - 6 February 2024
15
+
16
+ #### :hammer_and_wrench: Others
17
+
18
+ - fallbacks [Razvan - [`53441ff`](https://github.com/eea/volto-embed/commit/53441ffa005800032ceb7577d20b6f29c30905dd)]
19
+ ### [9.1.0](https://github.com/eea/volto-embed/compare/9.0.7...9.1.0) - 17 January 2024
12
20
 
13
21
  #### :hammer_and_wrench: Others
14
22
 
@@ -1,3 +1,5 @@
1
+ require('dotenv').config({ path: __dirname + '/.env' })
2
+
1
3
  module.exports = {
2
4
  testMatch: ['**/src/addons/**/?(*.)+(spec|test).[jt]s?(x)'],
3
5
  collectCoverageFrom: [
@@ -9,25 +11,30 @@ module.exports = {
9
11
  '@plone/volto/cypress': '<rootDir>/node_modules/@plone/volto/cypress',
10
12
  '@plone/volto/babel': '<rootDir>/node_modules/@plone/volto/babel',
11
13
  '@plone/volto/(.*)$': '<rootDir>/node_modules/@plone/volto/src/$1',
12
- '@package/(.*)$': '<rootDir>/src/$1',
13
- '@root/(.*)$': '<rootDir>/src/$1',
14
+ '@package/(.*)$': '<rootDir>/node_modules/@plone/volto/src/$1',
15
+ '@root/(.*)$': '<rootDir>/node_modules/@plone/volto/src/$1',
14
16
  '@plone/volto-quanta/(.*)$': '<rootDir>/src/addons/volto-quanta/src/$1',
17
+ '@eeacms/search/(.*)$': '<rootDir>/src/addons/volto-searchlib/searchlib/$1',
18
+ '@eeacms/search': '<rootDir>/src/addons/volto-searchlib/searchlib',
15
19
  '@eeacms/(.*?)/(.*)$': '<rootDir>/node_modules/@eeacms/$1/src/$2',
16
- '@plone/volto-slate':
20
+ '@plone/volto-slate$':
17
21
  '<rootDir>/node_modules/@plone/volto/packages/volto-slate/src',
22
+ '@plone/volto-slate/(.*)$':
23
+ '<rootDir>/node_modules/@plone/volto/packages/volto-slate/src/$1',
18
24
  '~/(.*)$': '<rootDir>/src/$1',
19
25
  'load-volto-addons':
20
26
  '<rootDir>/node_modules/@plone/volto/jest-addons-loader.js',
21
27
  },
28
+ transformIgnorePatterns: [
29
+ '/node_modules/(?!(@plone|@root|@package|@eeacms)/).*/',
30
+ ],
22
31
  transform: {
23
32
  '^.+\\.js(x)?$': 'babel-jest',
33
+ '^.+\\.ts(x)?$': 'babel-jest',
24
34
  '^.+\\.(png)$': 'jest-file',
25
35
  '^.+\\.(jpg)$': 'jest-file',
26
36
  '^.+\\.(svg)$': './node_modules/@plone/volto/jest-svgsystem-transform.js',
27
37
  },
28
- transformIgnorePatterns: [
29
- 'node_modules/(?!@eeacms)/volto-datablocks/helpers',
30
- ],
31
38
  coverageThreshold: {
32
39
  global: {
33
40
  branches: 5,
@@ -36,7 +43,9 @@ module.exports = {
36
43
  statements: 5,
37
44
  },
38
45
  },
39
- setupFilesAfterEnv: [
40
- '<rootDir>/node_modules/@eeacms/volto-embed/jest.setup.js',
41
- ],
42
- };
46
+ ...(process.env.JEST_USE_SETUP === 'ON' && {
47
+ setupFilesAfterEnv: [
48
+ '<rootDir>/node_modules/@eeacms/volto-embed/jest.setup.js',
49
+ ],
50
+ }),
51
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-embed",
3
- "version": "9.1.0",
3
+ "version": "10.0.0",
4
4
  "description": "Embed external content",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -27,6 +27,7 @@
27
27
  "@plone/scripts": "*",
28
28
  "babel-plugin-transform-class-properties": "^6.24.1",
29
29
  "cypress-fail-fast": "^5.0.1",
30
+ "dotenv": "^16.3.2",
30
31
  "husky": "^8.0.3",
31
32
  "lint-staged": "^14.0.1",
32
33
  "md5": "^2.3.0"
@@ -1,51 +1,122 @@
1
1
  import React from 'react';
2
- import renderer from 'react-test-renderer';
2
+ import { render, fireEvent } from '@testing-library/react';
3
3
  import { Provider } from 'react-intl-redux';
4
4
  import config from '@plone/volto/registry';
5
5
 
6
6
  import Edit from './Edit';
7
7
  import installEmbedMaps from '.';
8
+ import '@testing-library/jest-dom/extend-expect';
8
9
 
9
10
  installEmbedMaps(config);
10
11
 
11
- test('renders an edit embed map block component', () => {
12
- const component = renderer.create(
13
- <Provider store={global.store}>
14
- <Edit
15
- id="my-map"
16
- data={{
17
- '@type': 'embed_maps',
18
- with_notes: false,
19
- with_sources: false,
20
- with_more_info: true,
21
- with_share: true,
22
- with_enlarge: true,
23
- url: '/path/to/map',
24
- maps: {
25
- '@id': '/path/to/map',
26
- title: 'My map',
27
- url:
28
- 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166',
29
- },
30
- dataprotection: {
31
- enabled: false,
32
- },
33
- useVisibilitySensor: false,
34
- }}
35
- pathname="/news"
36
- selected={true}
37
- block="1234"
38
- index={1}
39
- onChangeBlock={() => {}}
40
- onSelectBlock={() => {}}
41
- onDeleteBlock={() => {}}
42
- onFocusPreviousBlock={() => {}}
43
- onFocusNextBlock={() => {}}
44
- handleKeyDown={() => {}}
45
- content={{}}
46
- />
47
- </Provider>,
48
- );
49
- const json = component.toJSON();
50
- expect(json).toMatchSnapshot();
12
+ jest.mock('@plone/volto/components', () => ({
13
+ SidebarPortal: ({ children }) => (
14
+ <div data-testid="sidebar-portal">{children}</div>
15
+ ),
16
+ UniversalLink: ({ children, href }) => <a href={href}>{children}</a>,
17
+ }));
18
+
19
+ jest.mock(
20
+ '@plone/volto/components/manage/Form/BlockDataForm',
21
+ () => (props) => (
22
+ <div data-testid="block-data-form">
23
+ <p>Mocked BlockDataForm</p>
24
+ <input data-testid="block-data-input" onChange={props.onChangeField} />
25
+ </div>
26
+ ),
27
+ );
28
+
29
+ jest.mock('./View', () =>
30
+ jest.fn((props) => (
31
+ <div>
32
+ <div data-testid="view-component" mode={props.mode}>
33
+ Mocked View Component
34
+ </div>
35
+ {props.children}
36
+ </div>
37
+ )),
38
+ );
39
+
40
+ describe('Edit component', () => {
41
+ const mockOnChangeBlock = jest.fn();
42
+ const props = {
43
+ id: 'my-map',
44
+ data: {
45
+ '@type': 'embed_maps',
46
+ with_notes: false,
47
+ with_sources: false,
48
+ with_more_info: true,
49
+ with_share: true,
50
+ with_enlarge: true,
51
+ url: '/path/to/map',
52
+ maps: {
53
+ '@id': '/path/to/map',
54
+ title: 'My map',
55
+ url: 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166',
56
+ },
57
+ dataprotection: {
58
+ enabled: false,
59
+ },
60
+ useVisibilitySensor: false,
61
+ },
62
+ pathname: '/news',
63
+ selected: true,
64
+ block: '1234',
65
+ index: 1,
66
+ onChangeBlock: jest.fn(),
67
+ onSelectBlock: jest.fn(),
68
+ onDeleteBlock: jest.fn(),
69
+ onFocusPreviousBlock: jest.fn(),
70
+ onFocusNextBlock: jest.fn(),
71
+ handleKeyDown: jest.fn(),
72
+ content: {},
73
+ };
74
+
75
+ it('should render View component with mode set to edit', () => {
76
+ const { getByTestId } = render(
77
+ <Provider store={global.store}>
78
+ <Edit {...props} />
79
+ </Provider>,
80
+ );
81
+
82
+ const viewComponent = getByTestId('view-component');
83
+ expect(viewComponent).toBeInTheDocument();
84
+ expect(viewComponent).toHaveAttribute('mode', 'edit');
85
+ });
86
+
87
+ it('should render SidebarPortal when selected is true', () => {
88
+ const { getByTestId } = render(
89
+ <Provider store={global.store}>
90
+ <Edit {...props} />
91
+ </Provider>,
92
+ );
93
+ const sidebarPortal = getByTestId('sidebar-portal');
94
+ expect(sidebarPortal).toBeInTheDocument();
95
+ });
96
+
97
+ it('should render SidebarPortal and BlockDataForm', () => {
98
+ const { getByTestId } = render(
99
+ <Provider store={global.store}>
100
+ <Edit {...props} />
101
+ </Provider>,
102
+ );
103
+
104
+ const sidebarPortal = getByTestId('sidebar-portal');
105
+ const blockDataForm = getByTestId('block-data-form');
106
+ expect(sidebarPortal).toBeInTheDocument();
107
+ expect(blockDataForm).toBeInTheDocument();
108
+ });
109
+
110
+ it('should call onChangeBlock when onChangeField is triggered', () => {
111
+ const { getByTestId } = render(
112
+ <Provider store={global.store}>
113
+ <Edit {...props} onChangeBlock={mockOnChangeBlock} />
114
+ </Provider>,
115
+ );
116
+
117
+ const inputField = getByTestId('block-data-input');
118
+ fireEvent.change(inputField, { target: { value: 'new value' } });
119
+
120
+ expect(mockOnChangeBlock).toHaveBeenCalled();
121
+ });
51
122
  });
@@ -1,71 +1,118 @@
1
1
  import React from 'react';
2
- import renderer from 'react-test-renderer';
3
2
  import { Provider } from 'react-intl-redux';
4
3
  import config from '@plone/volto/registry';
4
+ import { render, screen, fireEvent } from '@testing-library/react';
5
+ import '@testing-library/jest-dom/extend-expect';
5
6
 
6
7
  import View from './View';
7
8
  import installEmbedMaps from '.';
8
9
 
9
10
  installEmbedMaps(config);
10
11
 
11
- test('renders a view embed map block component', () => {
12
- const component = renderer.create(
13
- <Provider store={global.store}>
14
- <View
15
- id="my-map"
16
- data={{
17
- '@type': 'embed_maps',
18
- with_notes: false,
19
- with_sources: false,
20
- with_more_info: true,
21
- with_share: true,
22
- with_enlarge: true,
23
- url: '/path/to/map',
24
- maps: {
25
- '@id': '/path/to/map',
26
- title: 'My map',
27
- url:
28
- 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166',
29
- },
30
- dataprotection: {
31
- enabled: false,
32
- },
33
- useVisibilitySensor: false,
34
- parameters: {
35
- '@id': '647e4a0f-d4a0-4b8a-9965-0a016f017ebd',
36
- field: 'zoomtocountry',
37
- value: 'RO',
38
- },
39
- height: '800',
40
- }}
41
- data_query={[
42
- {
43
- i: 'Country',
44
- o: 'plone.app.querystring.operation.selection.is',
45
- v: ['RO'],
46
- },
47
- ]}
48
- />
49
- </Provider>,
50
- );
51
- const json = component.toJSON();
52
- expect(json).toMatchSnapshot();
53
- });
12
+ describe('EmbedMaps Block View', () => {
13
+ it('renders a view embed map block component', () => {
14
+ render(
15
+ <Provider store={global.store}>
16
+ <View
17
+ id="my-map"
18
+ data={{
19
+ '@type': 'embed_maps',
20
+ with_notes: false,
21
+ with_sources: false,
22
+ with_more_info: true,
23
+ with_share: true,
24
+ with_enlarge: true,
25
+ url: '/path/to/map',
26
+ maps: {
27
+ '@id': '/path/to/map',
28
+ title: 'My map',
29
+ url: 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166',
30
+ },
31
+ dataprotection: {
32
+ enabled: false,
33
+ },
34
+ useVisibilitySensor: false,
35
+ parameters: {
36
+ '@id': '647e4a0f-d4a0-4b8a-9965-0a016f017ebd',
37
+ field: 'zoomtocountry',
38
+ value: 'RO',
39
+ },
40
+ height: '800',
41
+ }}
42
+ data_query={[
43
+ {
44
+ i: 'Country',
45
+ o: 'plone.app.querystring.operation.selection.is',
46
+ v: ['RO'],
47
+ },
48
+ ]}
49
+ />
50
+ </Provider>,
51
+ );
52
+ expect(screen.getByTitle('Embeded ESRI Maps')).toBeInTheDocument();
53
+ expect(screen.getByText('Sources')).toBeInTheDocument();
54
+ expect(screen.getByText('More info')).toBeInTheDocument();
55
+ expect(screen.getByText('Share')).toBeInTheDocument();
56
+ expect(screen.getByText('Enlarge')).toBeInTheDocument();
57
+ });
58
+
59
+ it('renders an edit view embed map block component', () => {
60
+ render(
61
+ <Provider store={global.store}>
62
+ <View
63
+ id="my-map"
64
+ mode="edit"
65
+ data={{
66
+ '@type': 'embed_maps',
67
+ url: '',
68
+ maps: {},
69
+ }}
70
+ />
71
+ </Provider>,
72
+ );
73
+ expect(
74
+ screen.getByText('Please select a map from block editor.'),
75
+ ).toBeInTheDocument();
76
+ });
77
+
78
+ it('handles map error', () => {
79
+ render(
80
+ <Provider store={global.store}>
81
+ <View
82
+ id="my-map"
83
+ data={{
84
+ '@type': 'embed_maps',
85
+ maps: {
86
+ error: 'Error message',
87
+ },
88
+ }}
89
+ />
90
+ </Provider>,
91
+ );
92
+
93
+ expect(screen.getByText('Error message')).toBeInTheDocument();
94
+ });
95
+
96
+ it('handles share button click', () => {
97
+ render(
98
+ <Provider store={global.store}>
99
+ <View
100
+ id="my-map"
101
+ data={{
102
+ '@type': 'embed_maps',
103
+ with_share: true,
104
+ url: '/path/to/map',
105
+ maps: {
106
+ '@id': '/path/to/map',
107
+ title: 'My map',
108
+ url: 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166',
109
+ },
110
+ }}
111
+ />
112
+ </Provider>,
113
+ );
54
114
 
55
- test('renders an edit view embed map block component', () => {
56
- const component = renderer.create(
57
- <Provider store={global.store}>
58
- <View
59
- id="my-map"
60
- mode="edit"
61
- data={{
62
- '@type': 'embed_maps',
63
- url: '',
64
- maps: {},
65
- }}
66
- />
67
- </Provider>,
68
- );
69
- const json = component.toJSON();
70
- expect(json).toMatchSnapshot();
115
+ fireEvent.click(screen.getByText('Share'));
116
+ expect(screen.getByDisplayValue('/path/to/map')).toBeInTheDocument();
117
+ });
71
118
  });
@@ -27,7 +27,7 @@ const parameters = {
27
27
  required: [],
28
28
  };
29
29
 
30
- export default (props) => {
30
+ const getSchema = (props) => {
31
31
  return {
32
32
  title: 'Embed interactive Map',
33
33
  fieldsets: [
@@ -101,3 +101,5 @@ export default (props) => {
101
101
  required: [],
102
102
  };
103
103
  };
104
+
105
+ export default getSchema;
@@ -145,11 +145,17 @@ class Edit extends Component {
145
145
  * @returns {undefined}
146
146
  */
147
147
  onSubmitUrl() {
148
- this.props.onChangeBlock(this.props.block, {
149
- ...this.props.data,
150
- url: this.getSrc(this.state.url),
151
- privacy_notification: this.state.privacy_notification,
152
- });
148
+ try {
149
+ const url = this.getSrc(this.state.url);
150
+ new URL(url);
151
+ this.props.onChangeBlock(this.props.block, {
152
+ ...this.props.data,
153
+ url: this.getSrc(this.state.url),
154
+ privacy_notification: this.state.privacy_notification,
155
+ });
156
+ } catch {
157
+ this.setState({ error: true });
158
+ }
153
159
  }
154
160
 
155
161
  /**
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
- import renderer from 'react-test-renderer';
2
+ import { render, screen, fireEvent } from '@testing-library/react';
3
3
  import { Provider } from 'react-intl-redux';
4
4
  import config from '@plone/volto/registry';
5
+ import '@testing-library/jest-dom/extend-expect';
5
6
 
6
7
  import Edit from './Edit';
7
8
 
@@ -26,8 +27,7 @@ describe('Test Maps Block editing', () => {
26
27
 
27
28
  const data = {
28
29
  '@type': 'maps',
29
- url:
30
- '<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d11255.043736345397!2d24.6862147!3d45.15143895!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x474d3248f30cd7b5%3A0x307c5acf21ded9e3!2sHotel%20Posada!5e0!3m2!1sro!2sro!4v1701254795494!5m2!1sro!2sro" width="600" height="450" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>',
30
+ url: '<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d11255.043736345397!2d24.6862147!3d45.15143895!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x474d3248f30cd7b5%3A0x307c5acf21ded9e3!2sHotel%20Posada!5e0!3m2!1sro!2sro!4v1701254795494!5m2!1sro!2sro" width="600" height="450" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>',
31
31
  dataprotection: {
32
32
  enabled: false,
33
33
  privacy_statement: 'This is a privacy statement',
@@ -35,8 +35,8 @@ describe('Test Maps Block editing', () => {
35
35
  useVisibilitySensor: false,
36
36
  };
37
37
 
38
- test('test-1', () => {
39
- const component = renderer.create(
38
+ it('renders the edit form with a map', () => {
39
+ const { container } = render(
40
40
  <Provider store={global.store}>
41
41
  <Edit
42
42
  data={data}
@@ -54,15 +54,18 @@ describe('Test Maps Block editing', () => {
54
54
  />
55
55
  </Provider>,
56
56
  );
57
- const json = component.toJSON();
58
- expect(json).toMatchSnapshot();
57
+ expect(screen.getByTitle('ESRI Maps Embedded Block')).toBeInTheDocument();
58
+ expect(container.querySelector('iframe')).toBeInTheDocument();
59
59
  });
60
60
 
61
- test('test-2', () => {
62
- const component = renderer.create(
61
+ it('renders the edit form without a map', () => {
62
+ render(
63
63
  <Provider store={global.store}>
64
64
  <Edit
65
- data={data}
65
+ data={{
66
+ '@type': 'maps',
67
+ url: '',
68
+ }}
66
69
  pathname="/news"
67
70
  selected={true}
68
71
  block="1234"
@@ -77,12 +80,15 @@ describe('Test Maps Block editing', () => {
77
80
  />
78
81
  </Provider>,
79
82
  );
80
- const json = component.toJSON();
81
- expect(json).toMatchSnapshot();
83
+ expect(
84
+ screen.getByText(
85
+ 'Please enter the embed code or URL for the ESRI webmap.',
86
+ ),
87
+ ).toBeInTheDocument();
82
88
  });
83
89
 
84
- test('test-3', () => {
85
- const component = renderer.create(
90
+ it('handles URL input', () => {
91
+ const { container } = render(
86
92
  <Provider store={global.store}>
87
93
  <Edit
88
94
  data={{
@@ -93,17 +99,22 @@ describe('Test Maps Block editing', () => {
93
99
  selected={true}
94
100
  block="1234"
95
101
  index={1}
96
- onChangeBlock={() => {}}
97
- onSelectBlock={() => {}}
98
- onDeleteBlock={() => {}}
99
- onFocusPreviousBlock={() => {}}
100
- onFocusNextBlock={() => {}}
101
- handleKeyDown={() => {}}
102
- content={{}}
102
+ onChangeBlock={jest.fn()}
103
+ onSelectBlock={jest.fn()}
104
+ onDeleteBlock={jest.fn()}
105
+ onFocusPreviousBlock={jest.fn()}
106
+ onFocusNextBlock={jest.fn()}
107
+ handleKeyDown={jest.fn()}
103
108
  />
104
109
  </Provider>,
105
110
  );
106
- const json = component.toJSON();
107
- expect(json).toMatchSnapshot();
111
+
112
+ const input = screen.getByPlaceholderText('Enter map Embed Code');
113
+ fireEvent.change(input, { target: { value: 'https://example.com/map' } });
114
+ fireEvent.click(container.querySelector('button.primary.button'));
115
+
116
+ expect(
117
+ screen.getByDisplayValue('https://example.com/map'),
118
+ ).toBeInTheDocument();
108
119
  });
109
120
  });
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
- import { render } from '@testing-library/react';
3
- import renderer from 'react-test-renderer';
2
+ import { render, screen } from '@testing-library/react';
4
3
  import { Provider } from 'react-intl-redux';
5
4
  import config from '@plone/volto/registry';
5
+ import '@testing-library/jest-dom/extend-expect';
6
6
 
7
7
  import View from './View';
8
8
  import installEmbedMaps from '.';
@@ -32,29 +32,32 @@ config.blocks.blocksConfig = {
32
32
  },
33
33
  };
34
34
 
35
- describe('Test Maps Block rendering', () => {
35
+ describe('Maps Block View', () => {
36
36
  const data = {
37
37
  '@type': 'maps',
38
- url:
39
- 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166',
38
+ url: 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166',
40
39
  useVisibilitySensor: false,
41
40
  dataprotection: {
42
41
  enabled: false,
43
42
  },
44
43
  };
45
44
 
46
- test('test-1', () => {
47
- const component = renderer.create(
45
+ it('test-1', () => {
46
+ const { container } = render(
48
47
  <Provider store={global.store}>
49
48
  <View data={data} />
50
49
  </Provider>,
51
50
  );
52
- const json = component.toJSON();
53
- expect(json).toMatchSnapshot();
51
+
52
+ expect(screen.getByTitle('Embeded ESRI Maps')).toBeInTheDocument();
53
+ expect(container.querySelector('iframe')).toHaveAttribute(
54
+ 'src',
55
+ 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166',
56
+ );
54
57
  });
55
58
 
56
- test('test-2', () => {
57
- const component = renderer.create(
59
+ it('test-2', () => {
60
+ const { container } = render(
58
61
  <Provider store={global.store}>
59
62
  <View
60
63
  data={{
@@ -64,11 +67,14 @@ describe('Test Maps Block rendering', () => {
64
67
  />
65
68
  </Provider>,
66
69
  );
67
- const json = component.toJSON();
68
- expect(json).toMatchSnapshot();
70
+
71
+ expect(container.querySelector('iframe')).toHaveAttribute(
72
+ 'style',
73
+ 'height: 100vh;',
74
+ );
69
75
  });
70
76
 
71
- test('test-3', () => {
77
+ it('test-3', () => {
72
78
  const Component = (props) => (
73
79
  <Provider store={global.store}>
74
80
  <View
@@ -86,11 +92,8 @@ describe('Test Maps Block rendering', () => {
86
92
  );
87
93
  const { container, rerender } = render(<Component />);
88
94
 
89
- expect(container).toMatchSnapshot();
90
-
91
95
  container.querySelector('.privacy-button button').click();
92
96
 
93
97
  rerender(<Component />);
94
- expect(container).toMatchSnapshot();
95
98
  });
96
99
  });
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
- import renderer from 'react-test-renderer';
2
+ import { render, screen } from '@testing-library/react';
3
3
  import { Provider } from 'react-intl-redux';
4
4
  import config from '@plone/volto/registry';
5
+ import '@testing-library/jest-dom/extend-expect';
5
6
 
6
7
  import EmbedMap from './EmbedMap';
7
8
 
@@ -23,28 +24,65 @@ config.blocks.blocksConfig = {
23
24
  },
24
25
  };
25
26
 
26
- test('renders map component', () => {
27
- const component = renderer.create(
28
- <Provider store={global.store}>
29
- <EmbedMap
30
- id="my-map"
31
- data={{
32
- with_notes: false,
33
- with_sources: false,
34
- with_more_info: true,
35
- with_share: true,
36
- with_enlarge: true,
37
- url:
38
- 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166',
39
- useVisibilitySensor: false,
40
- parameters: {
41
- Country: 'RO',
42
- zoomtocountry: 'RO',
43
- },
44
- }}
45
- />
46
- </Provider>,
47
- );
48
- const json = component.toJSON();
49
- expect(json).toMatchSnapshot();
27
+ describe('EmbedMap', () => {
28
+ it('renders map component', () => {
29
+ const { container } = render(
30
+ <Provider store={global.store}>
31
+ <EmbedMap
32
+ id="my-map"
33
+ data={{
34
+ with_notes: false,
35
+ with_sources: false,
36
+ with_more_info: true,
37
+ with_share: true,
38
+ with_enlarge: true,
39
+ url: 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166',
40
+ useVisibilitySensor: false,
41
+ parameters: {
42
+ Country: 'RO',
43
+ zoomtocountry: 'RO',
44
+ },
45
+ }}
46
+ />
47
+ </Provider>,
48
+ );
49
+ expect(screen.getByTitle('Embeded ESRI Maps')).toBeInTheDocument();
50
+ expect(container.querySelector('iframe')).toHaveAttribute(
51
+ 'src',
52
+ 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166&Country=RO&zoomtocountry=RO',
53
+ );
54
+ expect(screen.getByText('More info')).toBeInTheDocument();
55
+ expect(screen.getByText('Share')).toBeInTheDocument();
56
+ expect(screen.getByText('Enlarge')).toBeInTheDocument();
57
+ });
58
+
59
+ it('handles mobile view', () => {
60
+ const { container } = render(
61
+ <Provider store={global.store}>
62
+ <EmbedMap
63
+ id="my-map"
64
+ data={{
65
+ with_notes: false,
66
+ with_sources: false,
67
+ with_more_info: true,
68
+ with_share: true,
69
+ with_enlarge: true,
70
+ url: 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166',
71
+ useVisibilitySensor: false,
72
+ parameters: {
73
+ Country: 'RO',
74
+ zoomtocountry: 'RO',
75
+ },
76
+ }}
77
+ intl={{ formatMessage: (message) => message.defaultMessage }}
78
+ screen={{ width: 400 }}
79
+ />
80
+ </Provider>,
81
+ );
82
+
83
+ expect(container.querySelector('iframe')).toHaveClass('google-map');
84
+ expect(container.querySelector('.visualization-toolbar')).toHaveClass(
85
+ 'mobile',
86
+ );
87
+ });
50
88
  });
@@ -24,8 +24,7 @@ export const ProtectionSchema = () => ({
24
24
  {
25
25
  children: [
26
26
  {
27
- text:
28
- 'This map is hosted by a third party, Environmental Systems Research Institute. By showing the external content you accept the terms and conditions of ',
27
+ text: 'This map is hosted by a third party, Environmental Systems Research Institute. By showing the external content you accept the terms and conditions of ',
29
28
  },
30
29
  {
31
30
  type: 'a',
@@ -37,8 +36,7 @@ export const ProtectionSchema = () => ({
37
36
  ],
38
37
  },
39
38
  {
40
- text:
41
- '. This includes their cookie policies, which we have no control over.',
39
+ text: '. This includes their cookie policies, which we have no control over.',
42
40
  },
43
41
  ],
44
42
  },
@@ -19,9 +19,9 @@
19
19
  .wrapped {
20
20
  width: 300px;
21
21
  padding: 1.4rem;
22
+ border-radius: 5px;
22
23
  margin: 0 auto;
23
24
  background: white;
24
- border-radius: 5px;
25
25
  opacity: 1;
26
26
  }
27
27
 
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
- import renderer from 'react-test-renderer';
2
+ import { render, screen } from '@testing-library/react';
3
3
  import { Provider } from 'react-intl-redux';
4
4
  import config from '@plone/volto/registry';
5
+ import '@testing-library/jest-dom/extend-expect';
5
6
 
6
7
  import { Enlarge, FigureNote, MoreInfo, Share, Sources } from '.';
7
8
 
@@ -24,7 +25,7 @@ config.blocks.blocksConfig = {
24
25
  };
25
26
 
26
27
  test('renders toolbar components', () => {
27
- const component = renderer.create(
28
+ const { container } = render(
28
29
  <Provider store={global.store}>
29
30
  <div className="visualization-toolbar">
30
31
  <div className="left-col">
@@ -43,6 +44,37 @@ test('renders toolbar components', () => {
43
44
  </div>
44
45
  </Provider>,
45
46
  );
46
- const json = component.toJSON();
47
- expect(json).toMatchSnapshot();
47
+
48
+ expect(screen.getByText('Note')).toBeInTheDocument();
49
+ expect(screen.getByText('Sources')).toBeInTheDocument();
50
+ expect(screen.getByText('More info')).toBeInTheDocument();
51
+ expect(screen.getByText('Share')).toBeInTheDocument();
52
+ expect(screen.getByText('Enlarge')).toBeInTheDocument();
53
+ expect(
54
+ screen.getByDisplayValue('/path/to/embeded/content'),
55
+ ).toBeInTheDocument();
56
+ expect(screen.getByText('Copy')).toBeInTheDocument();
57
+ expect(container.querySelector('.figure-note')).toBeInTheDocument();
58
+ expect(container.querySelector('.sources')).toBeInTheDocument();
59
+ expect(container.querySelector('.more-info')).toBeInTheDocument();
60
+ expect(container.querySelector('.enlarge')).toBeInTheDocument();
61
+ expect(container.querySelector('.share')).toBeInTheDocument();
62
+ expect(container.querySelector('p')).toHaveTextContent('This is a note');
63
+ expect(
64
+ screen.getByText('Data provenance is not set for this visualization.'),
65
+ ).toBeInTheDocument();
66
+ expect(container.querySelector('a')).toHaveAttribute(
67
+ 'href',
68
+ '/path/to/embeded/content',
69
+ );
70
+ expect(
71
+ container.querySelector('i.ri-external-link-line'),
72
+ ).toBeInTheDocument();
73
+ expect(container.querySelector('i.ri-fullscreen-line')).toBeInTheDocument();
74
+ expect(container.querySelector('i.ri-share-fill')).toBeInTheDocument();
75
+ expect(container.querySelector('input')).toHaveAttribute(
76
+ 'value',
77
+ '/path/to/embeded/content',
78
+ );
79
+ expect(container.querySelector('button.copy-button')).toBeInTheDocument();
48
80
  });
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
- import renderer from 'react-test-renderer';
2
+ import { render, screen } from '@testing-library/react';
3
3
  import { Provider } from 'react-intl-redux';
4
4
  import config from '@plone/volto/registry';
5
+ import '@testing-library/jest-dom/extend-expect';
5
6
 
6
7
  import MapView from './MapView';
7
8
 
@@ -29,7 +30,7 @@ config.blocks.blocksConfig = {
29
30
  };
30
31
 
31
32
  test('renders map component', () => {
32
- const component = renderer.create(
33
+ const { container } = render(
33
34
  <Provider store={global.store}>
34
35
  <MapView
35
36
  content={{
@@ -40,14 +41,33 @@ test('renders map component', () => {
40
41
  with_more_info: true,
41
42
  with_share: true,
42
43
  with_enlarge: true,
43
- url:
44
- 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166',
44
+ url: 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166',
45
45
  useVisibilitySensor: false,
46
46
  },
47
47
  }}
48
48
  />
49
49
  </Provider>,
50
50
  );
51
- const json = component.toJSON();
52
- expect(json).toMatchSnapshot();
51
+
52
+ expect(screen.getByTitle('Embeded ESRI Maps')).toBeInTheDocument();
53
+ expect(container.querySelector('iframe')).toHaveAttribute(
54
+ 'src',
55
+ 'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166',
56
+ );
57
+ expect(container.querySelector('.more-info')).toBeInTheDocument();
58
+ expect(container.querySelector('.more-info a')).toHaveAttribute(
59
+ 'href',
60
+ '/path/to/map',
61
+ );
62
+ expect(container.querySelector('.share')).toBeInTheDocument();
63
+ expect(container.querySelector('.share button')).toBeInTheDocument();
64
+ expect(container.querySelector('.enlarge')).toBeInTheDocument();
65
+ expect(container.querySelector('.enlarge button')).toBeInTheDocument();
66
+ expect(container.querySelector('.ui.input.share-link input')).toHaveAttribute(
67
+ 'value',
68
+ '/path/to/map',
69
+ );
70
+ expect(
71
+ container.querySelector('.ui.primary.button.copy-button'),
72
+ ).toBeInTheDocument();
53
73
  });
@@ -21,8 +21,8 @@ const messages = defineMessages({
21
21
 
22
22
  function MapEditorModal({ id, onClose, onChange, ...rest }) {
23
23
  const intl = useIntl();
24
- const [value, setValue] = useState(rest.value);
25
- const [url, setUrl] = useState(rest.value.url);
24
+ const [value, setValue] = useState(rest.value || {});
25
+ const [url, setUrl] = useState(rest.value?.url || '');
26
26
  const [error, setError] = useState(false);
27
27
 
28
28
  const schema = useMemo(
@@ -213,11 +213,11 @@ export default function MapsWidget(props) {
213
213
  </Button>
214
214
  </div>
215
215
  {description && <p className="help">{description}</p>}
216
- {value.url && <EmbedMap {...props} data={value} />}
216
+ {value?.url && <EmbedMap {...props} data={value} />}
217
217
  {mapEditor && (
218
218
  <MapEditorModal
219
219
  id={id}
220
- value={value}
220
+ value={value || {}}
221
221
  onChange={onChange}
222
222
  onClose={() => setMapEditor(false)}
223
223
  />
@@ -1,48 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
-
4
- const projectRootPath = fs.existsSync('./project')
5
- ? fs.realpathSync('./project')
6
- : fs.realpathSync('./../../../');
7
- const packageJson = require(path.join(projectRootPath, 'package.json'));
8
- const jsConfig = require(path.join(projectRootPath, 'jsconfig.json')).compilerOptions;
9
-
10
- const pathsConfig = jsConfig.paths;
11
-
12
- let voltoPath = path.join(projectRootPath, 'node_modules/@plone/volto');
13
-
14
- Object.keys(pathsConfig).forEach(pkg => {
15
- if (pkg === '@plone/volto') {
16
- voltoPath = `./${jsConfig.baseUrl}/${pathsConfig[pkg][0]}`;
17
- }
18
- });
19
- const AddonConfigurationRegistry = require(`${voltoPath}/addon-registry.js`);
20
- const reg = new AddonConfigurationRegistry(projectRootPath);
21
-
22
- // Extends ESlint configuration for adding the aliases to `src` directories in Volto addons
23
- const addonAliases = Object.keys(reg.packages).map(o => [
24
- o,
25
- reg.packages[o].modulePath,
26
- ]);
27
-
28
-
29
- module.exports = {
30
- extends: `${projectRootPath}/node_modules/@plone/volto/.eslintrc`,
31
- settings: {
32
- 'import/resolver': {
33
- alias: {
34
- map: [
35
- ['@plone/volto', '@plone/volto/src'],
36
- ...addonAliases,
37
- ['@package', `${__dirname}/src`],
38
- ['~', `${__dirname}/src`],
39
- ],
40
- extensions: ['.js', '.jsx', '.json'],
41
- },
42
- 'babel-plugin-root-import': {
43
- rootPathSuffix: 'src',
44
- },
45
- },
46
- },
47
- };
48
-