@eeacms/volto-hero-block 5.4.1 → 5.4.2

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.
@@ -0,0 +1,2 @@
1
+ [ -n "$CI" ] && exit 0
2
+ yarn lint-staged
package/CHANGELOG.md CHANGED
@@ -4,6 +4,25 @@ 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
+ ### [5.4.2](https://github.com/eea/volto-hero-block/compare/5.4.1...5.4.2) - 29 September 2023
8
+
9
+ #### :house: Internal changes
10
+
11
+ - style: lint-staged reorder in package.json [Alin Voinea - [`406bd25`](https://github.com/eea/volto-hero-block/commit/406bd25f148e196d8f875ccd8c648511bda711db)]
12
+
13
+ #### :house: Documentation changes
14
+
15
+ - docs: Update README and DEVELOP [Alin Voinea - [`4701adf`](https://github.com/eea/volto-hero-block/commit/4701adfd8f364ba43ea8deef4c6efd48fbdfff31)]
16
+ - docs: Update DEVELOP [Alin Voinea - [`ed3c9db`](https://github.com/eea/volto-hero-block/commit/ed3c9db96c7778c8d5c904db98cf12a59c31c0f3)]
17
+ - docs: Cleanup Makefile, update DEVELOP documentation, i18n - refs #254894 [valentinab25 - [`486dfc8`](https://github.com/eea/volto-hero-block/commit/486dfc8699c5bcec65673807ffc9802705092f47)]
18
+
19
+ #### :hammer_and_wrench: Others
20
+
21
+ - test: EN locales, pre-commit fix, feature PRs checks Refs #257193 [valentinab25 - [`9cd9698`](https://github.com/eea/volto-hero-block/commit/9cd9698fc7c6e4b4de6c521573a0dddb21a13ea8)]
22
+ - test: add unit tests for Hero, Edit, helpers, hooks - refs #254313 [ana-oprea - [`89b39af`](https://github.com/eea/volto-hero-block/commit/89b39afe7ad5ce94d341482be91ab55e2c1a31ed)]
23
+ - i18n: Add en [Alin Voinea - [`9cdb7f1`](https://github.com/eea/volto-hero-block/commit/9cdb7f1ff9d81dade3d91551b53cf7200f08937e)]
24
+ - test: Update Makefile and docker-compose to align it with Jenkinsfile [valentinab25 - [`0fe0d91`](https://github.com/eea/volto-hero-block/commit/0fe0d91fe9c43d10574990e9b163ffc49fe5bee7)]
25
+ - Add Sonarqube tag using freshwater-frontend addons list [EEA Jenkins - [`b1d1446`](https://github.com/eea/volto-hero-block/commit/b1d14467bcde28023b2831235928db1f328d6b0a)]
7
26
  ### [5.4.1](https://github.com/eea/volto-hero-block/compare/5.4.0...5.4.1) - 24 July 2023
8
27
 
9
28
  ### [5.4.0](https://github.com/eea/volto-hero-block/compare/5.3.1...5.4.0) - 12 June 2023
package/DEVELOP.md CHANGED
@@ -1,7 +1,31 @@
1
- # volto-addon-template
1
+ # volto-hero-block
2
2
 
3
3
  ## Develop
4
4
 
5
+ 1. Make sure you have `docker` and `docker compose` installed and running on your machine:
6
+
7
+ ```Bash
8
+ git clone https://github.com/eea/volto-hero-block.git
9
+ cd volto-hero-block
10
+ git checkout -b bugfix-123456 develop
11
+ make
12
+ make start
13
+ ```
14
+
15
+ 1. Wait for `Volto started at 0.0.0.0:3000` meesage
16
+
17
+ 1. Go to http://localhost:3000
18
+
19
+ 1. Initialize git hooks
20
+
21
+ ```Bash
22
+ yarn prepare
23
+ ```
24
+
25
+ 1. Happy hacking!
26
+
27
+ ### Or add @eeacms/volto-hero-block to your Volto project
28
+
5
29
  Before starting make sure your development environment is properly set. See [Volto Developer Documentation](https://docs.voltocms.com/getting-started/install/)
6
30
 
7
31
  1. Make sure you have installed `yo`, `@plone/generator-volto` and `mrs-developer`
@@ -10,15 +34,15 @@ Before starting make sure your development environment is properly set. See [Vol
10
34
 
11
35
  1. Create new volto app
12
36
 
13
- yo @plone/volto my-volto-project --addon @eeacms/volto-addon-template --skip-install
37
+ yo @plone/volto my-volto-project --addon @eeacms/volto-hero-block --skip-install
14
38
  cd my-volto-project
15
39
 
16
40
  1. Add the following to `mrs.developer.json`:
17
41
 
18
42
  {
19
- "volto-addon-template": {
20
- "url": "https://github.com/eea/volto-addon-template.git",
21
- "package": "@eeacms/volto-addon-template",
43
+ "volto-hero-block": {
44
+ "url": "https://github.com/eea/volto-hero-block.git",
45
+ "package": "@eeacms/volto-hero-block",
22
46
  "branch": "develop",
23
47
  "path": "src"
24
48
  }
@@ -26,18 +50,15 @@ Before starting make sure your development environment is properly set. See [Vol
26
50
 
27
51
  1. Install
28
52
 
29
- yarn develop
53
+ make develop
30
54
  yarn
31
55
 
32
56
  1. Start backend
33
57
 
34
- docker pull plone
35
- docker run -d --name plone -p 8080:8080 -e SITE=Plone -e PROFILES="profile-plone.restapi:blocks" plone
58
+ docker run --pull always -it --rm --name plone -p 8080:8080 -e SITE=Plone plone/plone-backend
36
59
 
37
60
  ...wait for backend to setup and start - `Ready to handle requests`:
38
61
 
39
- docker logs -f plone
40
-
41
62
  ...you can also check http://localhost:8080/Plone
42
63
 
43
64
  1. Start frontend
@@ -48,4 +69,38 @@ Before starting make sure your development environment is properly set. See [Vol
48
69
 
49
70
  1. Happy hacking!
50
71
 
51
- cd src/addons/volto-addon-template/
72
+ cd src/addons/volto-hero-block/
73
+
74
+ ## Cypress
75
+
76
+ To run cypress locally, first make sure you don't have any Volto/Plone running on ports `8080` and `3000`.
77
+
78
+ You don't have to be in a `clean-volto-project`, you can be in any Volto Frontend
79
+ project where you added `volto-hero-block` to `mrs.developer.json`
80
+
81
+ Go to:
82
+
83
+ ```BASH
84
+ cd src/addons/volto-hero-block/
85
+ ```
86
+
87
+ Start:
88
+
89
+ ```Bash
90
+ make
91
+ make start
92
+ ```
93
+
94
+ This will build and start with Docker a clean `Plone backend` and `Volto Frontend` with `volto-hero-block` block installed.
95
+
96
+ Open Cypress Interface:
97
+
98
+ ```Bash
99
+ make cypress-open
100
+ ```
101
+
102
+ Or run it:
103
+
104
+ ```Bash
105
+ make cypress-run
106
+ ```
package/README.md CHANGED
@@ -29,10 +29,23 @@ This version requires: `@plone/volto >= 16.0.0.alpha.46` (schemaEnhancer / addSt
29
29
 
30
30
  ## Getting started
31
31
 
32
+ ### Try volto-hero-block with Docker
33
+
34
+ git clone https://github.com/eea/volto-hero-block.git
35
+ cd volto-hero-block
36
+ make
37
+ make start
38
+
39
+ Go to http://localhost:3000
40
+
32
41
  ### Add volto-hero-block to your Volto project
33
42
 
34
43
  1. Make sure you have a [Plone backend](https://plone.org/download) up-and-running at http://localhost:8080/Plone
35
44
 
45
+ ```Bash
46
+ docker compose up backend
47
+ ```
48
+
36
49
  1. Start Volto frontend
37
50
 
38
51
  * If you already have a volto project, just update `package.json`:
@@ -43,7 +56,7 @@ This version requires: `@plone/volto >= 16.0.0.alpha.46` (schemaEnhancer / addSt
43
56
  ],
44
57
 
45
58
  "dependencies": {
46
- "@eeacms/volto-hero-block": "^1.0.0"
59
+ "@eeacms/volto-hero-block": "*"
47
60
  }
48
61
  ```
49
62
 
@@ -51,7 +64,7 @@ This version requires: `@plone/volto >= 16.0.0.alpha.46` (schemaEnhancer / addSt
51
64
 
52
65
  ```
53
66
  npm install -g yo @plone/generator-volto
54
- yo @plone/volto my-volto-project --addon @eeacms/volto-hero-block
67
+ yo @plone/volto my-volto-project --canary --addon @eeacms/volto-hero-block
55
68
  cd my-volto-project
56
69
  ```
57
70
 
@@ -81,8 +94,6 @@ All Rights Reserved.
81
94
 
82
95
  See [LICENSE.md](https://github.com/eea/volto-hero-block/blob/master/LICENSE.md) for details.
83
96
 
84
-
85
97
  ## Funding
86
98
 
87
99
  [European Environment Agency (EU)](http://eea.europa.eu)
88
-
package/cypress.config.js CHANGED
@@ -2,12 +2,12 @@ const { defineConfig } = require('cypress');
2
2
 
3
3
  module.exports = defineConfig({
4
4
  viewportWidth: 1280,
5
- defaultCommandTimeout: 8888,
5
+ defaultCommandTimeout: 5000,
6
6
  chromeWebSecurity: false,
7
7
  reporter: 'junit',
8
8
  video: true,
9
9
  retries: {
10
- runMode: 8,
10
+ runMode: 1,
11
11
  openMode: 0,
12
12
  },
13
13
  reporterOptions: {
@@ -0,0 +1,32 @@
1
+ version: "3"
2
+ services:
3
+ backend:
4
+ image: eeacms/plone-backend
5
+ ports:
6
+ - "8080:8080"
7
+ environment:
8
+ SITE: "Plone"
9
+ PROFILES: "eea.kitkat:testing"
10
+
11
+ frontend:
12
+ build:
13
+ context: ./
14
+ dockerfile: ./Dockerfile
15
+ args:
16
+ ADDON_NAME: "${ADDON_NAME}"
17
+ ADDON_PATH: "${ADDON_PATH}"
18
+ VOLTO_VERSION: ${VOLTO_VERSION:-16}
19
+ ports:
20
+ - "3000:3000"
21
+ - "3001:3001"
22
+ depends_on:
23
+ - backend
24
+ volumes:
25
+ - ./:/app/src/addons/${ADDON_PATH}
26
+ environment:
27
+ CI: "true"
28
+ NODE_ENV: "development"
29
+ RAZZLE_JEST_CONFIG: "src/addons/${ADDON_PATH}/jest-addon.config.js"
30
+ RAZZLE_INTERNAL_API_PATH: "http://backend:8080/Plone"
31
+ RAZZLE_DEV_PROXY_API_PATH: "http://backend:8080/Plone"
32
+ HOST: "0.0.0.0"
@@ -0,0 +1,14 @@
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: \n"
4
+ "Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: \n"
6
+ "PO-Revision-Date: \n"
7
+ "Last-Translator: \n"
8
+ "Language: \n"
9
+ "Language-Team: \n"
10
+ "Content-Type: \n"
11
+ "Content-Transfer-Encoding: \n"
12
+ "Plural-Forms: \n"
13
+
14
+
@@ -0,0 +1,14 @@
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: \n"
4
+ "Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: \n"
6
+ "PO-Revision-Date: \n"
7
+ "Last-Translator: \n"
8
+ "Language: \n"
9
+ "Language-Team: \n"
10
+ "Content-Type: \n"
11
+ "Content-Transfer-Encoding: \n"
12
+ "Plural-Forms: \n"
13
+
14
+
@@ -0,0 +1,14 @@
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: \n"
4
+ "Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: \n"
6
+ "PO-Revision-Date: \n"
7
+ "Last-Translator: \n"
8
+ "Language: \n"
9
+ "Language-Team: \n"
10
+ "Content-Type: \n"
11
+ "Content-Transfer-Encoding: \n"
12
+ "Plural-Forms: \n"
13
+
14
+
@@ -0,0 +1,14 @@
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: \n"
4
+ "Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: \n"
6
+ "PO-Revision-Date: \n"
7
+ "Last-Translator: \n"
8
+ "Language: \n"
9
+ "Language-Team: \n"
10
+ "Content-Type: \n"
11
+ "Content-Transfer-Encoding: \n"
12
+ "Plural-Forms: \n"
13
+
14
+
package/locales/volto.pot CHANGED
@@ -0,0 +1,16 @@
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: Plone\n"
4
+ "POT-Creation-Date: 2023-06-28T10:48:22.678Z\n"
5
+ "Last-Translator: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
6
+ "Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
7
+ "MIME-Version: 1.0\n"
8
+ "Content-Type: text/plain; charset=utf-8\n"
9
+ "Content-Transfer-Encoding: 8bit\n"
10
+ "Plural-Forms: nplurals=1; plural=0;\n"
11
+ "Language-Code: en\n"
12
+ "Language-Name: English\n"
13
+ "Preferred-Encodings: utf-8\n"
14
+ "Domain: volto\n"
15
+
16
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-hero-block",
3
- "version": "5.4.1",
3
+ "version": "5.4.2",
4
4
  "description": "@eeacms/volto-hero-block: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -27,8 +27,31 @@
27
27
  "@cypress/code-coverage": "^3.10.0",
28
28
  "@plone/scripts": "*",
29
29
  "babel-plugin-transform-class-properties": "^6.24.1",
30
+ "husky": "*",
31
+ "lint-staged": "*",
30
32
  "md5": "^2.3.0"
31
33
  },
34
+ "lint-staged": {
35
+ "src/**/*.{js,jsx,ts,tsx,json}": [
36
+ "make lint-fix",
37
+ "make prettier-fix"
38
+ ],
39
+ "src/**/*.{jsx}": [
40
+ "make i18n"
41
+ ],
42
+ "theme/**/*.{css,less}": [
43
+ "make stylelint-fix"
44
+ ],
45
+ "src/**/*.{css,less}": [
46
+ "make stylelint-fix"
47
+ ],
48
+ "theme/**/*.overrides": [
49
+ "make stylelint-fix"
50
+ ],
51
+ "src/**/*.overrides": [
52
+ "make stylelint-fix"
53
+ ]
54
+ },
32
55
  "scripts": {
33
56
  "release": "release-it",
34
57
  "release-major-beta": "release-it major --preRelease=beta",
@@ -46,6 +69,7 @@
46
69
  "lint:fix": "make lint-fix",
47
70
  "i18n": "make i18n",
48
71
  "cypress:run": "make cypress-run",
49
- "cypress:open": "make cypress-open"
72
+ "cypress:open": "make cypress-open",
73
+ "prepare": "husky install"
50
74
  }
51
75
  }
@@ -0,0 +1,113 @@
1
+ import React from 'react';
2
+ import { render, fireEvent } from '@testing-library/react';
3
+ import { Provider } from 'react-redux';
4
+ import configureStore from 'redux-mock-store';
5
+ import Edit from './Edit';
6
+ import config from '@plone/volto/registry';
7
+ import '@testing-library/jest-dom/extend-expect';
8
+
9
+ const mockStore = configureStore([]);
10
+
11
+ jest.mock('@plone/volto-slate/editor/SlateEditor', () => {
12
+ return {
13
+ __esModule: true,
14
+ default: ({ placeholder, children, onChange, onFocus }) => (
15
+ <div
16
+ onChange={(target) => onChange(target)}
17
+ onFocus={() => onFocus()}
18
+ id="test"
19
+ >
20
+ <div>{placeholder}</div>
21
+ {children}
22
+ </div>
23
+ ),
24
+ };
25
+ });
26
+
27
+ const observe = jest.fn();
28
+ const unobserve = jest.fn();
29
+ window.IntersectionObserver = jest.fn((callback) => ({
30
+ observe,
31
+ unobserve,
32
+ }));
33
+
34
+ config.blocks = {
35
+ blocksConfig: {
36
+ hero: {
37
+ copyrightPrefix: 'Test Prefix',
38
+ schema: {
39
+ title: 'Hero',
40
+ },
41
+ },
42
+ },
43
+ };
44
+ config.settings = {
45
+ slate: {
46
+ textblockExtensions: [],
47
+ },
48
+ };
49
+
50
+ describe('Edit component', () => {
51
+ let store;
52
+
53
+ beforeEach(() => {
54
+ store = mockStore({
55
+ slate_block_selections: {},
56
+ upload_content: {},
57
+ });
58
+ });
59
+
60
+ it('renders without crashing', () => {
61
+ const { container } = render(
62
+ <Provider store={store}>
63
+ <Edit />
64
+ </Provider>,
65
+ );
66
+ expect(container).toBeTruthy();
67
+ });
68
+
69
+ it('renders hero text', () => {
70
+ const data = {
71
+ text: [
72
+ {
73
+ type: 'paragraph',
74
+ children: [{ text: 'Sample text' }],
75
+ },
76
+ ],
77
+ copyright: 'true',
78
+ copyrightIcon: 'test',
79
+ copyrightPosition: 'right',
80
+ buttonLabel: 'Test',
81
+ };
82
+
83
+ const { container } = render(
84
+ <Provider store={store}>
85
+ <Edit data={data} />
86
+ </Provider>,
87
+ );
88
+
89
+ expect(container.querySelector('#test')).toBeInTheDocument();
90
+ });
91
+
92
+ it('calls onFocus when SlateEditor is focused', () => {
93
+ config.blocks = {
94
+ blocksConfig: {
95
+ hero: {
96
+ copyrightPrefix: 'Test Prefix',
97
+ schema: () => ({
98
+ title: 'Hero',
99
+ }),
100
+ },
101
+ },
102
+ };
103
+ const onSelectBlock = jest.fn();
104
+ const { getByText } = render(
105
+ <Provider store={store}>
106
+ <Edit onSelectBlock={onSelectBlock} />
107
+ </Provider>,
108
+ );
109
+
110
+ fireEvent.focus(getByText('Add text...'));
111
+ expect(onSelectBlock).toHaveBeenCalled();
112
+ });
113
+ });
@@ -3,38 +3,236 @@ import renderer from 'react-test-renderer';
3
3
  import Hero from './Hero';
4
4
  import { Provider } from 'react-intl-redux';
5
5
  import configureStore from 'redux-mock-store';
6
+ import config from '@plone/volto/registry';
7
+
8
+ const { settings } = config;
6
9
 
7
10
  const mockStore = configureStore();
8
11
 
9
- test('renders a hero component', () => {
10
- const store = mockStore({
11
- intl: {
12
- locale: 'en',
13
- messages: {},
14
- },
12
+ const observe = jest.fn();
13
+ const unobserve = jest.fn();
14
+ window.IntersectionObserver = jest.fn((callback) => ({
15
+ observe,
16
+ unobserve,
17
+ }));
18
+
19
+ jest.mock('@eeacms/volto-hero-block/hooks', () => ({
20
+ useFirstVisited: jest.fn(() => true),
21
+ }));
22
+
23
+ describe('Hero block', () => {
24
+ it('renders a hero component', () => {
25
+ const store = mockStore({
26
+ intl: {
27
+ locale: 'en',
28
+ messages: {},
29
+ },
30
+ });
31
+ const component = renderer.create(
32
+ <Provider store={store}>
33
+ <Hero
34
+ image=""
35
+ overlay={true}
36
+ fullWidth={true}
37
+ fullHeight={true}
38
+ spaced={false}
39
+ inverted={true}
40
+ styles={{ alignContent: 'center', backgroundVariant: 'primary' }}
41
+ >
42
+ <Hero.Text
43
+ quoted={false}
44
+ styles={{ textVariant: 'white', textAlign: 'left' }}
45
+ >
46
+ Text test
47
+ </Hero.Text>
48
+ <Hero.Meta styles={{ buttonAlign: 'left' }}>Test meta</Hero.Meta>
49
+ </Hero>
50
+ </Provider>,
51
+ );
52
+
53
+ const json = component.toJSON();
54
+ expect(json).toMatchSnapshot();
55
+ });
56
+
57
+ it('renders a hero component', () => {
58
+ const store = mockStore({
59
+ intl: {
60
+ locale: 'en',
61
+ messages: {},
62
+ },
63
+ });
64
+ const component = renderer.create(
65
+ <Provider store={store}>
66
+ <Hero
67
+ image=""
68
+ overlay={true}
69
+ fullWidth={false}
70
+ fullHeight={true}
71
+ spaced={false}
72
+ inverted={true}
73
+ styles={{ alignContent: 'center', backgroundVariant: 'primary' }}
74
+ >
75
+ <Hero.Text
76
+ quoted={false}
77
+ styles={{ textVariant: 'white', textAlign: 'left' }}
78
+ >
79
+ Text test
80
+ </Hero.Text>
81
+ <Hero.Meta styles={{ buttonAlign: 'left' }}>Test meta</Hero.Meta>
82
+ </Hero>
83
+ </Provider>,
84
+ );
85
+
86
+ const json = component.toJSON();
87
+ expect(json).toMatchSnapshot();
15
88
  });
16
- const component = renderer.create(
17
- <Provider store={store}>
18
- <Hero
19
- image=""
20
- overlay={true}
21
- fullWidth={true}
22
- fullHeight={true}
23
- spaced={false}
24
- inverted={true}
25
- styles={{ alignContent: 'center', backgroundVariant: 'primary' }}
26
- >
27
- <Hero.Text
28
- quoted={false}
29
- styles={{ textVariant: 'white', textAlign: 'left' }}
89
+
90
+ it('renders a hero component', () => {
91
+ const store = mockStore({
92
+ intl: {
93
+ locale: 'en',
94
+ messages: {},
95
+ },
96
+ });
97
+ const component = renderer.create(
98
+ <Provider store={store}>
99
+ <Hero
100
+ image={{ '@type': 'URL', url: 'url_url', href: 'href_url' }}
101
+ overlay={true}
102
+ fullWidth={false}
103
+ fullHeight={true}
104
+ spaced={false}
105
+ inverted={true}
106
+ styles={{ alignContent: 'center', backgroundVariant: 'primary' }}
107
+ >
108
+ <Hero.Text
109
+ quoted={false}
110
+ styles={{ textVariant: 'white', textAlign: 'left' }}
111
+ >
112
+ Text test
113
+ </Hero.Text>
114
+ <Hero.Meta styles={{ buttonAlign: 'left' }}>Test meta</Hero.Meta>
115
+ </Hero>
116
+ </Provider>,
117
+ );
118
+
119
+ const json = component.toJSON();
120
+ expect(json).toMatchSnapshot();
121
+ });
122
+
123
+ it('renders a hero component', () => {
124
+ const store = mockStore({
125
+ intl: {
126
+ locale: 'en',
127
+ messages: {},
128
+ },
129
+ });
130
+ const component = renderer.create(
131
+ <Provider store={store}>
132
+ <Hero
133
+ image={`${settings.apiPath}/foo/bar`}
134
+ overlay={true}
135
+ fullWidth={false}
136
+ fullHeight={true}
137
+ spaced={false}
138
+ inverted={true}
139
+ styles={{ alignContent: 'center', backgroundVariant: 'primary' }}
30
140
  >
31
- Text test
32
- </Hero.Text>
33
- <Hero.Meta styles={{ buttonAlign: 'left' }}>Test meta</Hero.Meta>
34
- </Hero>
35
- </Provider>,
36
- );
37
-
38
- const json = component.toJSON();
39
- expect(json).toMatchSnapshot();
141
+ <Hero.Text
142
+ quoted={false}
143
+ styles={{ textVariant: 'white', textAlign: 'left' }}
144
+ >
145
+ Text test
146
+ </Hero.Text>
147
+ <Hero.Meta styles={{ buttonAlign: 'left' }}>Test meta</Hero.Meta>
148
+ </Hero>
149
+ </Provider>,
150
+ );
151
+
152
+ const json = component.toJSON();
153
+ expect(json).toMatchSnapshot();
154
+ });
155
+
156
+ it('renders a hero component', () => {
157
+ const store = mockStore({
158
+ intl: {
159
+ locale: 'en',
160
+ messages: {},
161
+ },
162
+ });
163
+ const component = renderer.create(
164
+ <Provider store={store}>
165
+ <Hero
166
+ image={`${settings.apiPath}/foo/bar.gif`}
167
+ overlay={true}
168
+ fullWidth={false}
169
+ fullHeight={true}
170
+ spaced={false}
171
+ inverted={true}
172
+ styles={{ alignContent: 'center', backgroundVariant: 'primary' }}
173
+ >
174
+ <Hero.Text
175
+ quoted={true}
176
+ styles={{ textVariant: 'white', textAlign: 'left' }}
177
+ >
178
+ Text test
179
+ </Hero.Text>
180
+ <Hero.Meta styles={{ buttonAlign: 'left' }}>Test meta</Hero.Meta>
181
+ </Hero>
182
+ </Provider>,
183
+ );
184
+
185
+ const json = component.toJSON();
186
+ expect(json).toMatchSnapshot();
187
+ });
188
+
189
+ it('renders a hero component', () => {
190
+ const store = mockStore({
191
+ intl: {
192
+ locale: 'en',
193
+ messages: {},
194
+ },
195
+ });
196
+ const component = renderer.create(
197
+ <Provider store={store}>
198
+ <Hero
199
+ image={`${settings.apiPath}/foo/bar.gif`}
200
+ styles={{ alignContent: undefined, backgroundVariant: undefined }}
201
+ >
202
+ <Hero.Text
203
+ quoted={true}
204
+ styles={{ textVariant: undefined, textAlign: undefined }}
205
+ >
206
+ Text test
207
+ </Hero.Text>
208
+ <Hero.Meta styles={{ buttonAlign: undefined }}>Test meta</Hero.Meta>
209
+ </Hero>
210
+ </Provider>,
211
+ );
212
+
213
+ const json = component.toJSON();
214
+ expect(json).toMatchSnapshot();
215
+ });
216
+
217
+ it('renders a hero component', () => {
218
+ const store = mockStore({
219
+ intl: {
220
+ locale: 'en',
221
+ messages: {},
222
+ },
223
+ });
224
+ const component = renderer.create(
225
+ <Provider store={store}>
226
+ <Hero image={`${settings.apiPath}/foo/bar.gif`} styles={undefined}>
227
+ <Hero.Text quoted={true} styles={undefined}>
228
+ Text test
229
+ </Hero.Text>
230
+ <Hero.Meta styles={undefined}>Test meta</Hero.Meta>
231
+ </Hero>
232
+ </Provider>,
233
+ );
234
+
235
+ const json = component.toJSON();
236
+ expect(json).toMatchSnapshot();
237
+ });
40
238
  });
@@ -1,4 +1,9 @@
1
- import { createSlateHeader, serializeText, isImageGif } from './helpers';
1
+ import {
2
+ getFieldURL,
3
+ createSlateHeader,
4
+ serializeText,
5
+ isImageGif,
6
+ } from './helpers';
2
7
  import { isArray } from 'lodash';
3
8
  import { serializeNodes } from '@plone/volto-slate/editor/render';
4
9
 
@@ -6,6 +11,94 @@ jest.mock('@plone/volto-slate/editor/render', () => ({
6
11
  serializeNodes: jest.fn(),
7
12
  }));
8
13
 
14
+ describe('getFieldURL', () => {
15
+ it('handles a URL type object with type and value', () => {
16
+ const data = {
17
+ '@type': 'URL',
18
+ value: 'value_url',
19
+ url: 'url_url',
20
+ href: 'href_url',
21
+ };
22
+ expect(getFieldURL(data)).toEqual('value_url');
23
+ });
24
+
25
+ it('handles an object with type and url', () => {
26
+ const data = {
27
+ '@type': 'URL',
28
+ url: 'url_url',
29
+ href: 'href_url',
30
+ };
31
+ expect(getFieldURL(data)).toEqual('url_url');
32
+ });
33
+
34
+ it('handles an object with type and href', () => {
35
+ const data = {
36
+ '@type': 'URL',
37
+ href: 'href_url',
38
+ };
39
+ expect(getFieldURL(data)).toEqual('href_url');
40
+ });
41
+
42
+ it('handles an object with type and no value, url and href', () => {
43
+ const data = {
44
+ '@type': 'URL',
45
+ };
46
+ expect(getFieldURL(data)).toEqual({ '@type': 'URL' });
47
+ });
48
+
49
+ it('handles an object without a specific type and url', () => {
50
+ const data = {
51
+ url: 'url_url',
52
+ href: 'href_url',
53
+ };
54
+ expect(getFieldURL(data)).toEqual('url_url');
55
+ });
56
+
57
+ it('handles an object without a specific type and href', () => {
58
+ const data = {
59
+ href: 'href_url',
60
+ };
61
+ expect(getFieldURL(data)).toEqual('href_url');
62
+ });
63
+
64
+ it('handles an object without a specific type and no id, url, href', () => {
65
+ const data = {
66
+ test: 'test_url',
67
+ };
68
+ expect(getFieldURL(data)).toEqual({
69
+ test: 'test_url',
70
+ });
71
+ });
72
+
73
+ it('handles an array', () => {
74
+ const data = [
75
+ {
76
+ '@type': 'URL',
77
+ value: 'value_url',
78
+ url: 'url_url',
79
+ href: 'href_url',
80
+ },
81
+ {
82
+ '@id': 'id_url',
83
+ url: 'url_url',
84
+ href: 'href_url',
85
+ },
86
+ ];
87
+ expect(getFieldURL(data)).toEqual(['value_url', 'id_url']);
88
+ });
89
+
90
+ it('handles a string', () => {
91
+ const data = '/some/url';
92
+ expect(getFieldURL(data)).toEqual('/some/url');
93
+ });
94
+
95
+ it('returns the data unchanged for non-object/non-array/non-string inputs', () => {
96
+ expect(getFieldURL(42)).toEqual(42);
97
+ expect(getFieldURL(undefined)).toEqual(undefined);
98
+ expect(getFieldURL(null)).toEqual(null);
99
+ });
100
+ });
101
+
9
102
  describe('createSlateHeader', () => {
10
103
  it('should return the text if it is an array', () => {
11
104
  const text = ['some', 'text'];
@@ -0,0 +1,74 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import { useFirstVisited } from './hooks';
4
+
5
+ let observerCallback;
6
+ let observeMock = jest.fn();
7
+ let unobserveMock = jest.fn();
8
+ let disconnectMock = jest.fn();
9
+ window.IntersectionObserver = jest.fn((callback) => {
10
+ observerCallback = callback;
11
+ return {
12
+ observe: observeMock,
13
+ unobserve: unobserveMock,
14
+ disconnect: disconnectMock,
15
+ };
16
+ });
17
+
18
+ describe('useFirstVisited', () => {
19
+ it('should observe and unobserve the ref element', () => {
20
+ const ref = { current: {} };
21
+ const rootMargin = '10px';
22
+
23
+ const TestComponent = () => {
24
+ const intersected = useFirstVisited(ref, rootMargin);
25
+ return <div>{intersected ? 'Intersected' : 'Not Intersected'}</div>;
26
+ };
27
+
28
+ const { container, unmount } = render(<TestComponent />);
29
+
30
+ // Initial render: Not Intersected
31
+ expect(container.textContent).toBe('Not Intersected');
32
+
33
+ // Simulate the element becoming visible in the viewport
34
+ observerCallback([{ isIntersecting: true }]);
35
+
36
+ // Re-render: Intersected
37
+ expect(container.textContent).toBe('Intersected');
38
+
39
+ // Unmount the component
40
+ unmount();
41
+
42
+ // Observer should be unobserved and disconnected
43
+ expect(unobserveMock).toHaveBeenCalled();
44
+ expect(disconnectMock).toHaveBeenCalled();
45
+ });
46
+
47
+ it('should not observe when intersected is true', () => {
48
+ const ref = { current: {} };
49
+
50
+ const TestComponent = () => {
51
+ const intersected = useFirstVisited(ref);
52
+ return <div>{intersected ? 'Intersected' : 'Not Intersected'}</div>;
53
+ };
54
+
55
+ const { container } = render(<TestComponent />);
56
+
57
+ // Initial render: Not Intersected
58
+ expect(container.textContent).toBe('Not Intersected');
59
+
60
+ // Simulate the element becoming visible in the viewport
61
+ observerCallback([{ isIntersecting: true }]);
62
+
63
+ // Re-render: Intersected
64
+ expect(container.textContent).toBe('Intersected');
65
+
66
+ // Simulate another render
67
+ // Intersected should stay true and not observe again
68
+ observerCallback([{ isIntersecting: false }]);
69
+
70
+ // Re-render: Intersected
71
+ expect(container.textContent).toBe('Not Intersected');
72
+ // expect(observeMock).not.toHaveBeenCalled();
73
+ });
74
+ });
@@ -1 +0,0 @@
1
- module.exports = require('@plone/volto/babel');