From 94b58f7c0390bfcac24adbfbea61577137c91e2b Mon Sep 17 00:00:00 2001 From: valentinab25 Date: Mon, 31 Jul 2023 07:31:34 +0300 Subject: [PATCH 1/4] docs: Cleanup Makefile, update DEVELOP documentation, i18n - refs #254894 --- .i18n.babel.config.js | 1 - DEVELOP.md | 56 ++++++++++++ Dockerfile | 14 +++ Jenkinsfile | 25 +++++ Makefile | 156 +++++++++++++++++++------------- README.md | 4 + docker-compose.yml | 28 ++++++ locales/de/LC_MESSAGES/volto.po | 14 +++ locales/it/LC_MESSAGES/volto.po | 14 +++ locales/ro/LC_MESSAGES/volto.po | 14 +++ locales/volto.pot | 16 ++++ 11 files changed, 277 insertions(+), 65 deletions(-) delete mode 100644 .i18n.babel.config.js create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 locales/de/LC_MESSAGES/volto.po create mode 100644 locales/it/LC_MESSAGES/volto.po create mode 100644 locales/ro/LC_MESSAGES/volto.po diff --git a/.i18n.babel.config.js b/.i18n.babel.config.js deleted file mode 100644 index a900a75..0000000 --- a/.i18n.babel.config.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('@plone/volto/babel'); diff --git a/DEVELOP.md b/DEVELOP.md index a1d2550..39347dd 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -2,6 +2,28 @@ ## Develop +1. Make sure you have `docker` and `docker compose` installed and running on your machine: + + ```Bash + git clone https://github.com/eea/volto-group-block.git + cd volto-group-block + git checkout -b bugfix-123456 develop + make + make start + ``` + +1. Wait for `Volto started at 0.0.0.0:3000` meesage + +1. Go to http://localhost:3000 + +1. Happy hacking! + + ```Bash + cd src/addons/volto-group-block/ + ``` + +### Or add @eeacms/volto-group-block to your Volto project + Before starting make sure your development environment is properly set. See [Volto Developer Documentation](https://docs.voltocms.com/getting-started/install/) 1. Make sure you have installed `yo`, `@plone/generator-volto` and `mrs-developer` @@ -48,3 +70,37 @@ Before starting make sure your development environment is properly set. See [Vol 1. Happy hacking! cd src/addons/volto-group-block/ + +## Cypress + +To run cypress locally, first make sure you don't have any Volto/Plone running on ports `8080` and `3000`. + +You don't have to be in a `clean-volto-project`, you can be in any Volto Frontend +project where you added `volto-group-block` to `mrs.developer.json` + +Go to: + + ```BASH + cd src/addons/volto-group-block/ + ``` + +Start: + + ```Bash + make + make start + ``` + +This will build and start with Docker a clean `Plone backend` and `Volto Frontend` with `volto-group-block` block installed. + +Open Cypress Interface: + + ```Bash + make cypress-open + ``` + +Or run it: + + ```Bash + make cypress-run + ``` diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bd8e10d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +# syntax=docker/dockerfile:1 +ARG VOLTO_VERSION +FROM plone/frontend-builder:${VOLTO_VERSION} + +ARG ADDON_NAME +ARG ADDON_PATH + +COPY --chown=node:node ./ /app/src/addons/${ADDON_PATH}/ + +RUN /setupAddon +RUN yarn install + +ENTRYPOINT ["yarn"] +CMD ["start"] diff --git a/Jenkinsfile b/Jenkinsfile index 0770aa5..5e1feff 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -197,6 +197,31 @@ pipeline { } } + stage('SonarQube compare to master') { + when { + allOf { + environment name: 'CHANGE_ID', value: '' + branch 'develop' + not { changelog '.*^Automated release [0-9\\.]+$' } + } + } + steps { + node(label: 'docker') { + script { + sh '''docker pull eeacms/gitflow''' + sh '''echo "Error" > checkresult.txt''' + catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { + sh '''set -o pipefail; docker run -i --rm --name="$BUILD_TAG-gitflow-sn" -e GIT_BRANCH="$BRANCH_NAME" -e GIT_NAME="$GIT_NAME" eeacms/gitflow /checkSonarqubemaster.sh | grep -v "Found script" | tee checkresult.txt''' + } + + publishChecks name: 'SonarQube', title: 'Sonarqube Code Quality Check', summary: "Quality check on the SonarQube metrics from branch develop, comparing it with the ones from master branch. No bugs are allowed", + text: readFile(file: 'checkresult.txt'), conclusion: "${currentBuild.currentResult}", + detailsURL: "${env.BUILD_URL}display/redirect" + } + } + } + } + stage('Pull Request') { when { not { diff --git a/Makefile b/Makefile index ad3ef9a..13481d3 100644 --- a/Makefile +++ b/Makefile @@ -1,62 +1,93 @@ -SHELL=/bin/bash +############################################################################## +# Run: +# make +# make start +# +# Go to: +# +# http://localhost:3000 +# +# Cypress: +# +# make cypress-open +# +############################################################################## +# SETUP MAKE +# +## Defensive settings for make: https://tech.davis-hansson.com/p/make/ +SHELL:=bash +.ONESHELL: +# for Makefile debugging purposes add -x to the .SHELLFLAGS +.SHELLFLAGS:=-eu -o pipefail -O inherit_errexit -c +.SILENT: +.DELETE_ON_ERROR: +MAKEFLAGS+=--warn-undefined-variables +MAKEFLAGS+=--no-builtin-rules + +# Colors +# OK=Green, warn=yellow, error=red +ifeq ($(TERM),) +# no colors if not in terminal + MARK_COLOR= + OK_COLOR= + WARN_COLOR= + ERROR_COLOR= + NO_COLOR= +else + MARK_COLOR=`tput setaf 6` + OK_COLOR=`tput setaf 2` + WARN_COLOR=`tput setaf 3` + ERROR_COLOR=`tput setaf 1` + NO_COLOR=`tput sgr0` +endif +############################################################################## +# SETTINGS AND VARIABLE DIR=$(shell basename $$(pwd)) -ADDON ?= "@eeacms/volto-group-block" - -# We like colors -# From: https://coderwall.com/p/izxssa/colored-makefile-for-golang-projects -RED=`tput setaf 1` -GREEN=`tput setaf 2` -RESET=`tput sgr0` -YELLOW=`tput setaf 3` - -project: - npm install -g yo - npm install -g @plone/generator-volto - npm install -g mrs-developer - yo @plone/volto project --addon ${ADDON} --workspace "src/addons/${DIR}" --no-interactive - ln -sf $$(pwd) project/src/addons/ - cp .project.eslintrc.js .eslintrc.js - cd project && yarn - @echo "-------------------" - @echo "$(GREEN)Volto project is ready!$(RESET)" - @echo "$(RED)Now run: cd project && yarn start$(RESET)" - -all: project - -.PHONY: start-test-backend -start-test-backend: ## Start Test Plone Backend - @echo "$(GREEN)==> Start Test Plone Backend$(RESET)" - docker run -i --rm -e ZSERVER_HOST=0.0.0.0 -e ZSERVER_PORT=55001 -p 55001:55001 -e SITE=plone -e APPLY_PROFILES=plone.app.contenttypes:plone-content,plone.restapi:default,kitconcept.volto:default-homepage -e CONFIGURE_PACKAGES=plone.app.contenttypes,plone.restapi,kitconcept.volto,kitconcept.volto.cors -e ADDONS='plone.app.robotframework plone.app.contenttypes plone.restapi kitconcept.volto' plone ./bin/robot-server plone.app.robotframework.testing.PLONE_ROBOT_TESTING - -.PHONY: start-backend-docker -start-backend-docker: ## Starts a Docker-based backend - @echo "$(GREEN)==> Start Docker-based Plone Backend$(RESET)" - docker run -it --rm --name=plone -p 8080:8080 -e SITE=Plone -e ADDONS="kitconcept.volto" -e ZCML="kitconcept.volto.cors" plone +NODE_MODULES?="../../../node_modules" +PLONE_VERSION?=6 +VOLTO_VERSION?=16 +ADDON_PATH="${DIR}" +ADDON_NAME="@eeacms/${ADDON_PATH}" +DOCKER_COMPOSE=PLONE_VERSION=${PLONE_VERSION} VOLTO_VERSION=${VOLTO_VERSION} ADDON_NAME=${ADDON_NAME} ADDON_PATH=${ADDON_PATH} docker compose + +# Top-level targets +.PHONY: all +all: clean install + +.PHONY: clean +clean: ## Cleanup development environment + ${DOCKER_COMPOSE} down --volumes --remove-orphans + +.PHONY: install +install: ## Build and install development environment + echo "Running: ${DOCKER_COMPOSE} build" + ${DOCKER_COMPOSE} pull + ${DOCKER_COMPOSE} build + +.PHONY: start +start: ## Start development environment + echo "Running: ${DOCKER_COMPOSE} up" + ${DOCKER_COMPOSE} up -.PHONY: test -test: - docker pull plone/volto-addon-ci:alpha - docker run -it --rm -e NAMESPACE="@eeacms" -e GIT_NAME="${DIR}" -e RAZZLE_JEST_CONFIG=jest-addon.config.js -v "$$(pwd):/opt/frontend/my-volto-project/src/addons/${DIR}" -e CI="true" plone/volto-addon-ci:alpha - -.PHONY: test-update -test-update: - docker pull plone/volto-addon-ci:alpha - docker run -it --rm -e NAMESPACE="@eeacms" -e GIT_NAME="${DIR}" -e RAZZLE_JEST_CONFIG=jest-addon.config.js -v "$$(pwd):/opt/frontend/my-volto-project/src/addons/${DIR}" -e CI="true" plone/volto-addon-ci:alpha yarn test src/addons/${DIR}/src --watchAll=false -u +.PHONY: cypress-open +cypress-open: ## Open cypress integration tests + NODE_ENV=development $(NODE_MODULES)/cypress/bin/cypress open -.PHONY: help -help: ## Show this help. - @echo -e "$$(grep -hE '^\S+:.*##' $(MAKEFILE_LIST) | sed -e 's/:.*##\s*/:/' -e 's/^\(.\+\):\(.*\)/\\x1b[36m\1\\x1b[m:\2/' | column -c2 -t -s :)" +.PHONY: cypress-run +cypress-run: ## Run cypress integration tests + NODE_ENV=development $(NODE_MODULES)/cypress/bin/cypress run +.PHONY: test +test: ## Run jest tests + ${DOCKER_COMPOSE} run -e CI=1 frontend test -ifeq ($(wildcard ./project),) - NODE_MODULES = "../../../node_modules" -else - NODE_MODULES = "./project/node_modules" -endif +.PHONY: test-update +test-update: ## Update jest tests snapshots + ${DOCKER_COMPOSE} run -e CI=1 frontend test -u .PHONY: stylelint -stylelint: +stylelint: ## Stylelint $(NODE_MODULES)/stylelint/bin/stylelint.js --allow-empty-input 'src/**/*.{css,less}' .PHONY: stylelint-overrides @@ -64,35 +95,32 @@ stylelint-overrides: $(NODE_MODULES)/.bin/stylelint --syntax less --allow-empty-input 'theme/**/*.overrides' 'src/**/*.overrides' .PHONY: stylelint-fix -stylelint-fix: +stylelint-fix: ## Fix stylelint $(NODE_MODULES)/stylelint/bin/stylelint.js --allow-empty-input 'src/**/*.{css,less}' --fix $(NODE_MODULES)/.bin/stylelint --syntax less --allow-empty-input 'theme/**/*.overrides' 'src/**/*.overrides' --fix .PHONY: prettier -prettier: +prettier: ## Prettier $(NODE_MODULES)/.bin/prettier --single-quote --check 'src/**/*.{js,jsx,json,css,less,md}' .PHONY: prettier-fix -prettier-fix: +prettier-fix: ## Fix prettier $(NODE_MODULES)/.bin/prettier --single-quote --write 'src/**/*.{js,jsx,json,css,less,md}' .PHONY: lint -lint: +lint: ## ES Lint $(NODE_MODULES)/eslint/bin/eslint.js --max-warnings=0 'src/**/*.{js,jsx}' .PHONY: lint-fix -lint-fix: +lint-fix: ## Fix ES Lint $(NODE_MODULES)/eslint/bin/eslint.js --fix 'src/**/*.{js,jsx}' .PHONY: i18n -i18n: +i18n: ## i18n rm -rf build/messages NODE_ENV=development $(NODE_MODULES)/.bin/i18n --addon -.PHONY: cypress-run -cypress-run: - NODE_ENV=development $(NODE_MODULES)/cypress/bin/cypress run - -.PHONY: cypress-open -cypress-open: - NODE_ENV=development $(NODE_MODULES)/cypress/bin/cypress open +.PHONY: help +help: ## Show this help. + @echo -e "$$(grep -hE '^\S+:.*##' $(MAKEFILE_LIST) | sed -e 's/:.*##\s*/:/' -e 's/^\(.\+\):\(.*\)/\\x1b[36m\1\\x1b[m:\2/' | column -c2 -t -s :)" + head -n 14 Makefile diff --git a/README.md b/README.md index bacfdfd..883d053 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,10 @@ 1. Make sure you have a [Plone backend](https://plone.org/download) up-and-running at http://localhost:8080/Plone + ```Bash + docker compose up backend + ``` + 1. Start Volto frontend - If you already have a volto project, just update `package.json`: diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..c6f4862 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,28 @@ +version: "3" +services: + backend: + image: plone/plone-backend:${PLONE_VERSION:-6} + ports: + - "8080:8080" + environment: + SITE: "Plone" + + frontend: + build: + context: ./ + dockerfile: ./Dockerfile + args: + ADDON_NAME: "${ADDON_NAME}" + ADDON_PATH: "${ADDON_PATH}" + VOLTO_VERSION: ${VOLTO_VERSION:-16} + ports: + - "3000:3000" + - "3001:3001" + depends_on: + - backend + volumes: + - ./:/app/src/addons/${ADDON_PATH} + environment: + RAZZLE_INTERNAL_API_PATH: "http://backend:8080/Plone" + RAZZLE_DEV_PROXY_API_PATH: "http://backend:8080/Plone" + HOST: "0.0.0.0" diff --git a/locales/de/LC_MESSAGES/volto.po b/locales/de/LC_MESSAGES/volto.po new file mode 100644 index 0000000..12b9a47 --- /dev/null +++ b/locales/de/LC_MESSAGES/volto.po @@ -0,0 +1,14 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language: \n" +"Language-Team: \n" +"Content-Type: \n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + + diff --git a/locales/it/LC_MESSAGES/volto.po b/locales/it/LC_MESSAGES/volto.po new file mode 100644 index 0000000..12b9a47 --- /dev/null +++ b/locales/it/LC_MESSAGES/volto.po @@ -0,0 +1,14 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language: \n" +"Language-Team: \n" +"Content-Type: \n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + + diff --git a/locales/ro/LC_MESSAGES/volto.po b/locales/ro/LC_MESSAGES/volto.po new file mode 100644 index 0000000..12b9a47 --- /dev/null +++ b/locales/ro/LC_MESSAGES/volto.po @@ -0,0 +1,14 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language: \n" +"Language-Team: \n" +"Content-Type: \n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + + diff --git a/locales/volto.pot b/locales/volto.pot index e69de29..93c2825 100644 --- a/locales/volto.pot +++ b/locales/volto.pot @@ -0,0 +1,16 @@ +msgid "" +msgstr "" +"Project-Id-Version: Plone\n" +"POT-Creation-Date: 2023-06-28T10:48:22.678Z\n" +"Last-Translator: Plone i18n \n" +"Language-Team: Plone i18n \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"Language-Code: en\n" +"Language-Name: English\n" +"Preferred-Encodings: utf-8\n" +"Domain: volto\n" + + From 5facadec2f866a066ca836f8247a5e58ea44d176 Mon Sep 17 00:00:00 2001 From: ana-oprea <80201759+ana-oprea@users.noreply.github.com> Date: Mon, 14 Aug 2023 14:55:06 +0300 Subject: [PATCH 2/4] test: increase test coverage - refs #254313 --- cypress/e2e/01-block-group.cy.js | 84 +++++++ .../Blocks/Group/CounterComponent.test.jsx | 234 ++++++++++++++++++ .../manage/Blocks/Group/Edit.test.jsx | 107 ++++++++ src/index.test.js | 101 ++++++++ 4 files changed, 526 insertions(+) create mode 100644 src/components/manage/Blocks/Group/CounterComponent.test.jsx create mode 100644 src/index.test.js diff --git a/cypress/e2e/01-block-group.cy.js b/cypress/e2e/01-block-group.cy.js index 7b578c9..48409f2 100644 --- a/cypress/e2e/01-block-group.cy.js +++ b/cypress/e2e/01-block-group.cy.js @@ -20,6 +20,8 @@ describe('Blocks Tests', () => { .contains('Section (Group)') .click({ force: true }); + cy.contains('Block').click(); + cy.get('.block-editor-group [contenteditable=true]') .focus() .click() @@ -49,4 +51,86 @@ describe('Blocks Tests', () => { cy.contains('My Add-on Page'); cy.contains('test2'); }); + + it('Add Block: Make content type and add group block to layout', () => { + cy.clearSlateTitle(); + cy.getSlateTitle().type('My Add-on Page'); + + cy.get('.documentFirstHeading').contains('My Add-on Page'); + + cy.get('#toolbar-save').click(); + cy.get('.user').click(); + cy.get('a[href="/controlpanel"]').click(); + cy.get('a[href="/controlpanel/dexterity-types"]').click(); + + // add the content type + cy.get('#toolbar-add').click(); + cy.get('#field-title').click().type('Test Content Type'); + cy.get('.actions button[aria-label="Save"]').click(); + + // change the layout + cy.get('.ui.dropdown.actions-test_content_type').click(); + cy.get('.item.layout-test_content_type').click(); + cy.contains('Enable editable Blocks').click(); + cy.getSlate().click(); + + // Add block + cy.get('.ui.basic.icon.button.block-add-button').first().click(); + cy.get('.blocks-chooser .title').contains('Common').click(); + cy.get('.content.active.common .button.group') + .contains('Section (Group)') + .click({ force: true }); + cy.contains('Section').click(); + + cy.get('.sidebar-container #field-placeholder') + .click() + .type('Test Helper Text'); + cy.get( + '.sidebar-container .field-wrapper-instructions div[role="textbox"] p', + ) + .click() + .type('Description Blocks'); + cy.get( + '.sidebar-container .field-wrapper-allowedBlocks .react-select__value-container', + ).click(); + cy.get('.react-select__option') + .contains('Description') + .click({ force: true }); + cy.get('.field-wrapper-ignoreSpaces input').click({ force: true }); + cy.get('.field-wrapper-required input').click({ force: true }); + + cy.get('#toolbar-save').click(); + cy.get('.ui.button.cancel').click(); + cy.get('a[href="/controlpanel').click(); + cy.contains('Home').click(); + cy.get('#toolbar-add').click(); + cy.get('#toolbar-add-test_content_type').click(); + cy.get('#field-title').click().type('Test Content Type'); + cy.get('.block-editor-group div[role="textbox"]') + .click() + .type('/description{enter}'); + cy.get('.block-editor-group .block-editor-slate').click(); + cy.get( + '.block-editor-slate .block-toolbar button[title="Add block"]', + ).click(); + cy.get('.blocks-chooser .field.searchbox div.ui.transparent.input input') + .click() + .focus() + .type('Description{enter}'); + cy.get( + '.blocks-chooser .accordion div[aria-label="Unfold Text blocks"]', + ).click(); + cy.get('.ui.basic.icon.button.description').click(); + cy.get('button[title="Remove block"]').click(); + + // delete the content type + cy.get('#toolbar-save').click(); + cy.get('.user').click(); + cy.get('a[href="/controlpanel"]').click(); + cy.get('a[href="/controlpanel/dexterity-types"]').click(); + + cy.get('.ui.dropdown.actions-test_content_type').click(); + cy.get('.item.delete-test_content_type').click(); + cy.get('button.ui.primary.button').should('contain', 'Yes').click(); + }); }); diff --git a/src/components/manage/Blocks/Group/CounterComponent.test.jsx b/src/components/manage/Blocks/Group/CounterComponent.test.jsx new file mode 100644 index 0000000..3c34a86 --- /dev/null +++ b/src/components/manage/Blocks/Group/CounterComponent.test.jsx @@ -0,0 +1,234 @@ +import React from 'react'; +import { render } from '@testing-library/react'; +import CounterComponent from './CounterComponent'; +import '@testing-library/jest-dom/extend-expect'; + +jest.mock('@plone/volto/registry', () => ({ + blocks: { + blocksConfig: { + group: { + countTextIn: ['text'], + }, + }, + }, +})); + +jest.mock('@plone/volto-slate/editor/render', () => ({ + serializeNodesToText: jest.fn((nodes) => + nodes.map((node) => node.text).join(' '), + ), +})); + +describe('CounterComponent', () => { + const setSidebarTab = jest.fn(); + const setSelectedBlock = jest.fn(); + + it('should render info class when character count is less than 95% of maxChars', () => { + const { container, getByText } = render( + , + ); + expect(getByText('96 characters remaining out of 100')).toBeInTheDocument(); + expect(container.querySelector('.counter.info')).toBeInTheDocument(); + }); + + it('should render warning class when character count is between 95% and 100% of maxChars', () => { + const { container, getByText } = render( + , + ); + expect(getByText('4 characters remaining out of 100')).toBeInTheDocument(); + expect(container.querySelector('.counter.warning')).toBeInTheDocument(); + }); + + it('should render warning class when character count is over the maxChars', () => { + const { container, getByText } = render( + , + ); + expect(getByText('4 characters over the limit')).toBeInTheDocument(); + expect(container.querySelector('.counter.danger')).toBeInTheDocument(); + }); + + it('should handle click event', () => { + const { container } = render( + , + ); + container.querySelector('.counter').click(); + expect(setSidebarTab).toHaveBeenCalledWith(1); + expect(setSelectedBlock).toHaveBeenCalled(); + }); + + it('should handle click event with maxChar undefined', () => { + const { container } = render( + , + ); + container.querySelector('.counter').click(); + expect(setSidebarTab).toHaveBeenCalledWith(1); + expect(setSelectedBlock).toHaveBeenCalled(); + }); + + it('should handle click event with data undefined', () => { + const { container } = render( + , + ); + container.querySelector('.counter').click(); + expect(setSidebarTab).toHaveBeenCalledWith(1); + expect(setSelectedBlock).toHaveBeenCalled(); + }); + + it('should handle click event with plaintext undefined, but values present', () => { + const { container } = render( + , + ); + container.querySelector('.counter').click(); + expect(setSidebarTab).toHaveBeenCalledWith(1); + expect(setSelectedBlock).toHaveBeenCalled(); + }); + + it('should handle click event with plaintext undefined and values is not an array and the type is in countTextIn', () => { + const { container } = render( + , + ); + container.querySelector('.counter').click(); + expect(setSidebarTab).toHaveBeenCalledWith(1); + expect(setSelectedBlock).toHaveBeenCalled(); + }); + + it('should handle click event with plaintext undefined and values is not an array and the type is not in countTextIn', () => { + const { container } = render( + , + ); + container.querySelector('.counter').click(); + expect(setSidebarTab).toHaveBeenCalledWith(1); + expect(setSelectedBlock).toHaveBeenCalled(); + }); +}); diff --git a/src/components/manage/Blocks/Group/Edit.test.jsx b/src/components/manage/Blocks/Group/Edit.test.jsx index 48da9de..6c772f2 100644 --- a/src/components/manage/Blocks/Group/Edit.test.jsx +++ b/src/components/manage/Blocks/Group/Edit.test.jsx @@ -76,4 +76,111 @@ describe('Edit', () => { ); fireEvent.keyDown(getByRole('presentation'), { key: 'ArrowUp', code: 38 }); }); + + it('should call ArrowUp keydown', () => { + const props = { + block: 'testBlock', + data: { + instructions: 'test', + data: { + blocks: { + block1: { + type: 'test', + data: { + value: 'Test', + }, + }, + }, + blocks_layout: { + items: [undefined], + }, + }, + }, + onChangeBlock, + onChangeField, + pathname: '/', + selected: true, + manage: true, + }; + const mockOnFocusPreviousBlock = jest.fn(); + const mockOnFocusNextBlock = jest.fn(); + const mockOnAddBlock = jest.fn(); + const mockSidebarTab = jest.fn(); + + const { container } = render( + + + , + ); + + fireEvent.keyDown(container.querySelector('.section-block'), { + key: 'ArrowUp', + code: 38, + }); + fireEvent.keyDown(container.querySelector('.section-block'), { + key: 'ArrowDown', + code: 40, + }); + fireEvent.keyDown(container.querySelector('.section-block'), { + key: 'Enter', + code: 13, + }); + + fireEvent.click(container.querySelector('.blocks-form'), { + shiftKey: true, + }); + fireEvent.click(container.querySelector('.section-block legend')); + }); + + it('should call ArrowUp keydown', () => { + const props = { + block: 'testBlock', + data: { + instructions: 'test', + data: { + blocks: { + block1: { + type: 'test', + data: { + value: 'Test', + }, + }, + }, + blocks_layout: { + items: [undefined], + }, + }, + }, + onChangeBlock, + onChangeField, + pathname: '/', + selected: true, + manage: true, + }; + const mockOnFocusPreviousBlock = jest.fn(); + const mockOnFocusNextBlock = jest.fn(); + const mockOnAddBlock = jest.fn(); + const mockSidebarTab = jest.fn(); + const { container } = render( + + + , + ); + + fireEvent.click(container.querySelector('.section-block legend')); + }); }); diff --git a/src/index.test.js b/src/index.test.js new file mode 100644 index 0000000..fff5824 --- /dev/null +++ b/src/index.test.js @@ -0,0 +1,101 @@ +import applyConfig from './index'; + +describe('applyConfig', () => { + it('should add group block configuration', () => { + const config = { + blocks: { + blocksConfig: { + text: { title: 'Text', restricted: false }, + image: { title: 'Image', restricted: true }, + }, + }, + }; + + const newConfig = applyConfig(config); + + expect(newConfig.blocks.blocksConfig.group).toBeDefined(); + expect(newConfig.blocks.blocksConfig.group.id).toEqual('group'); + expect(newConfig.blocks.blocksConfig.group.title).toEqual( + 'Section (Group)', + ); + expect(newConfig.blocks.blocksConfig.group.icon).toBeDefined(); + expect(newConfig.blocks.blocksConfig.group.view).toBeDefined(); + expect(newConfig.blocks.blocksConfig.group.edit).toBeDefined(); + expect(newConfig.blocks.blocksConfig.group.schema).toBeDefined(); + expect(newConfig.blocks.blocksConfig.group.restricted).toEqual(false); + }); + + it('should include allowed blocks in schema', () => { + const config = { + blocks: { + blocksConfig: { + text: { title: 'Text', restricted: false }, + image: { restricted: false }, + image_test: { title: 'Image', restricted: true }, + }, + }, + }; + + const newConfig = applyConfig(config); + + expect( + newConfig.blocks.blocksConfig.group.schema.properties.allowedBlocks.items + .choices, + ).toEqual([ + ['text', 'Text'], + ['image', 'image'], + ['group', 'Group'], + ]); + }); + + it('should generate tocEntries correctly', () => { + const config = { + blocks: { + blocksConfig: {}, + }, + }; + + const block = { + data: { + blocks: { + block1: { value: [{ type: 'h1' }], plaintext: 'Heading 1' }, + block2: { value: [{ type: 'h2' }], plaintext: 'Heading 2' }, + block3: { value: [{ type: 'h3' }], plaintext: 'Heading 3' }, // This should be ignored + }, + blocks_layout: { + items: ['block1', 'block2', 'block3'], + }, + }, + }; + const tocData = { + levels: ['h1', 'h2'], + }; + const newConfig = applyConfig(config); + const entries = newConfig.blocks.blocksConfig.group.tocEntries( + block, + tocData, + ); + expect(entries).toEqual([ + [1, 'Heading 1', 'block1'], + [2, 'Heading 2', 'block2'], + ]); + }); + + it('should generate no entries', () => { + const config = { + blocks: { + blocksConfig: {}, + }, + }; + const block = undefined; + const tocData = { + levels: undefined, + }; + const newConfig = applyConfig(config); + const entries = newConfig.blocks.blocksConfig.group.tocEntries( + block, + tocData, + ); + expect(entries).toEqual([]); + }); +}); From 8d1ad2cfdf972b88f02f9efc4b7ef55b1e4b3592 Mon Sep 17 00:00:00 2001 From: rexalex Date: Fri, 18 Aug 2023 17:40:15 +0300 Subject: [PATCH 3/4] fix: ignoreSpaces on char counter - refs #256525 --- .../manage/Blocks/Group/CounterComponent.jsx | 71 ++++++++++--------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/src/components/manage/Blocks/Group/CounterComponent.jsx b/src/components/manage/Blocks/Group/CounterComponent.jsx index 7279f6c..8693df9 100644 --- a/src/components/manage/Blocks/Group/CounterComponent.jsx +++ b/src/components/manage/Blocks/Group/CounterComponent.jsx @@ -8,46 +8,53 @@ import { serializeNodesToText } from '@plone/volto-slate/editor/render'; import delightedSVG from '@plone/volto/icons/delighted.svg'; import dissatisfiedSVG from '@plone/volto/icons/dissatisfied.svg'; -const CounterComponent = ({ data, setSidebarTab, setSelectedBlock }) => { - const { maxChars } = data; - let charCount = 0; - - const countCharsWithoutSpaces = (paragraph) => { - const regex = /[^\s\\]/g; +const countCharsWithoutSpaces = (paragraph) => { + const regex = /[^\s\\]/g; + return (paragraph.match(regex) || []).length; +}; - return (paragraph.match(regex) || []).length; - }; +const countCharsWithSpaces = (paragraph) => { + return paragraph?.length || 0; +}; - const countCharsWithSpaces = (paragraph) => { - return paragraph?.length || 0; - }; +const countTextInEachBlock = (countTextIn, ignoreSpaces, groupCharCount) => ([ + id, + blockData, +]) => { + const foundText = + blockData && countTextIn?.includes(blockData?.['@type']) + ? isString(blockData?.plaintext) + ? blockData?.plaintext + : isArray(blockData?.value) && blockData?.value !== null + ? serializeNodesToText(blockData?.value) + : '' + : ''; - const countTextInBlocks = (blocksObject) => { - const { countTextIn } = config.blocks?.blocksConfig?.group; - let groupCharCount = 0; - if (!maxChars) { - return groupCharCount; - } - if (!blocksObject) return groupCharCount; + groupCharCount.value += ignoreSpaces + ? countCharsWithoutSpaces(foundText) + : countCharsWithSpaces(foundText); +}; - visitBlocks(blocksObject, ([id, data]) => { - let foundText; - if (data && countTextIn?.includes(data?.['@type'])) { - if (isString(data?.plaintext)) foundText = data?.plaintext; - else if (isArray(data?.value) && data?.value !== null) - foundText = serializeNodesToText(data?.value); - } else foundText = ''; +const countTextInBlocks = (blocksObject, ignoreSpaces, maxChars) => { + const { countTextIn } = config.blocks?.blocksConfig?.group; + // use obj ref to update value - if you send number it will not be updated + const groupCharCount = { value: 0 }; - groupCharCount += data?.ignoreSpaces - ? countCharsWithoutSpaces(foundText) - : countCharsWithSpaces(foundText); - }); + if (!maxChars || !blocksObject) { + return groupCharCount.value; + } - return groupCharCount; - }; + visitBlocks( + blocksObject, + countTextInEachBlock(countTextIn, ignoreSpaces, groupCharCount), + ); - charCount = countTextInBlocks(data?.data); + return groupCharCount.value; +}; +const CounterComponent = ({ data, setSidebarTab, setSelectedBlock }) => { + const { maxChars, ignoreSpaces } = data; + const charCount = countTextInBlocks(data?.data, ignoreSpaces, maxChars); const counterClass = charCount < Math.ceil(maxChars / 1.05) ? 'info' From c900817e8dc5c85c7a12beb96df540f09eabdad5 Mon Sep 17 00:00:00 2001 From: EEA Jenkins <@users.noreply.github.com> Date: Fri, 18 Aug 2023 14:53:38 +0000 Subject: [PATCH 4/4] Automated release 6.2.1 --- CHANGELOG.md | 36 ++++++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db18b71..63ab48e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). +### [6.2.1](https://github.com/eea/volto-group-block/compare/6.2.0...6.2.1) - 18 August 2023 + +#### :bug: Bug Fixes + +- fix: ignoreSpaces on char counter - refs #256525 [rexalex - [`8d1ad2c`](https://github.com/eea/volto-group-block/commit/8d1ad2cfdf972b88f02f9efc4b7ef55b1e4b3592)] + +#### :house: Documentation changes + +- docs: Cleanup Makefile, update DEVELOP documentation, i18n - refs #254894 [valentinab25 - [`94b58f7`](https://github.com/eea/volto-group-block/commit/94b58f7c0390bfcac24adbfbea61577137c91e2b)] + +#### :hammer_and_wrench: Others + +- test: increase test coverage - refs #254313 [ana-oprea - [`5facade`](https://github.com/eea/volto-group-block/commit/5facadec2f866a066ca836f8247a5e58ea44d176)] ### [6.2.0](https://github.com/eea/volto-group-block/compare/6.1.2...6.2.0) - 20 July 2023 #### :nail_care: Enhancements @@ -17,6 +30,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). #### :house: Internal changes +- chore: [JENKINS] Deprecate circularity website [valentinab25 - [`ad30e83`](https://github.com/eea/volto-group-block/commit/ad30e832bb869b67dc4e64ed99590b51cb80ab75)] #### :hammer_and_wrench: Others @@ -33,12 +47,19 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). #### :hammer_and_wrench: Others +- Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`37ffae5`](https://github.com/eea/volto-group-block/commit/37ffae512967b36af22cbed208a3ec9e1ddc392b)] ## [6.0.0](https://github.com/eea/volto-group-block/compare/5.0.1...6.0.0) - 24 March 2023 #### :hammer_and_wrench: Others - (feat): Possibility to copy/cut/paste blocks within section group block - refs #157469 [dobri1408 - [`e9fc098`](https://github.com/eea/volto-group-block/commit/e9fc09825ba2ae258feb77864491d97d94c585b4)] +- Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`db4b09a`](https://github.com/eea/volto-group-block/commit/db4b09a6c14a8b271dec0c766886ffbcc3fe205e)] +- Add Sonarqube tag using advisory-board-frontend addons list [EEA Jenkins - [`b8c2bf4`](https://github.com/eea/volto-group-block/commit/b8c2bf471868bb0394b2dbbf75ccb7917a9ef0bf)] +- Add Sonarqube tag using advisory-board-frontend addons list [EEA Jenkins - [`b343119`](https://github.com/eea/volto-group-block/commit/b3431196931fd568476fa8bf6fbc508e086229ae)] - test(Jenkins): Run tests and cypress with latest canary @plone/volto [Alin Voinea - [`2f42e7c`](https://github.com/eea/volto-group-block/commit/2f42e7c19a1da5a9c6a883cb4f101e8fa224ff94)] +- Add Sonarqube tag using cca-frontend addons list [EEA Jenkins - [`73afcc2`](https://github.com/eea/volto-group-block/commit/73afcc2f417797cedaa78cceefb007001d6c2406)] +- yarn 3 [Alin Voinea - [`3c00ccc`](https://github.com/eea/volto-group-block/commit/3c00ccc7110bbf12a4d268182313418fb46b1a5d)] +- Add Sonarqube tag using demo-kitkat-frontend addons list [EEA Jenkins - [`9b9662b`](https://github.com/eea/volto-group-block/commit/9b9662bda1da70ba0c3a7b4b05cebf130ed89e9e)] ### [5.0.1](https://github.com/eea/volto-group-block/compare/5.0.0...5.0.1) - 16 November 2022 #### :nail_care: Enhancements @@ -55,6 +76,8 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Prepare 5.0.0 release [Miu Razvan - [`88c0ddd`](https://github.com/eea/volto-group-block/commit/88c0ddd569aeda7ee34d1eadea6a087f4e7dc257)] - Update dependencies [Alin Voinea - [`c8405af`](https://github.com/eea/volto-group-block/commit/c8405afb830cdf62e7877bf30b619933519e1d71)] +- Add Sonarqube tag using marine-frontend addons list [EEA Jenkins - [`18e26c6`](https://github.com/eea/volto-group-block/commit/18e26c6939706d572ab8574e9b1826b9abc76314)] +- Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`8ed6d21`](https://github.com/eea/volto-group-block/commit/8ed6d21d8489911cc4cb471e3f8823c35f4adc50)] ### [4.3.8](https://github.com/eea/volto-group-block/compare/4.3.7...4.3.8) - 26 August 2022 ### [4.3.7](https://github.com/eea/volto-group-block/compare/4.3.6...4.3.7) - 22 August 2022 @@ -67,6 +90,9 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). #### :hammer_and_wrench: Others +- Add Sonarqube tag using circularity-frontend addons list [EEA Jenkins - [`4e73f8b`](https://github.com/eea/volto-group-block/commit/4e73f8be3c73559557efadc410cb56abc055d82d)] +- Add Sonarqube tag using clms-frontend addons list [EEA Jenkins - [`3040335`](https://github.com/eea/volto-group-block/commit/3040335002c63b50208c95918413bc958150e7a9)] +- Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`386f730`](https://github.com/eea/volto-group-block/commit/386f730ed65f73fe1468b9b77351c97fb70edcc5)] ### [4.3.5](https://github.com/eea/volto-group-block/compare/4.3.4...4.3.5) - 4 January 2022 ### [4.3.4](https://github.com/eea/volto-group-block/compare/4.3.3...4.3.4) - 3 January 2022 @@ -75,15 +101,23 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). #### :hammer_and_wrench: Others +- Add Sonarqube tag using freshwater-frontend addons list [EEA Jenkins - [`3e62d79`](https://github.com/eea/volto-group-block/commit/3e62d79a7ed37d10d623bc845d43e1144f8080f7)] ### [4.3.2](https://github.com/eea/volto-group-block/compare/4.3.1...4.3.2) - 10 December 2021 #### :hammer_and_wrench: Others - Refs #142010 - Optimize Volto-addons gitflow pipelines [valentinab25 - [`bc36cf5`](https://github.com/eea/volto-group-block/commit/bc36cf58c39e2b43c2fbf5189df6ddefc1260857)] +- Add Sonarqube tag using industry-frontend addons list [EEA Jenkins - [`8038e78`](https://github.com/eea/volto-group-block/commit/8038e783c1e8ddd71e21f72070fdfa8e7e098993)] +- Add Sonarqube tag using clms-frontend addons list [EEA Jenkins - [`daccdbc`](https://github.com/eea/volto-group-block/commit/daccdbc733e47be7d6536eb67f8f2eea038dc94b)] ### [4.3.1](https://github.com/eea/volto-group-block/compare/4.3.0...4.3.1) - 11 October 2021 #### :hammer_and_wrench: Others +- Add Sonarqube tag using bise-frontend addons list [EEA Jenkins - [`b0092e4`](https://github.com/eea/volto-group-block/commit/b0092e4f78a1a0184e22e32bb9806cd57417dfb2)] +- Add Sonarqube tag using sustainability-frontend addons list [EEA Jenkins - [`ff8889c`](https://github.com/eea/volto-group-block/commit/ff8889cb7b0761b1df43b201984ce40b14e1561b)] +- Add Sonarqube tag using climate-energy-frontend addons list [EEA Jenkins - [`0375c28`](https://github.com/eea/volto-group-block/commit/0375c28ed1ffe9186a4790b454795c0ca8039f72)] +- Add Sonarqube tag using ims-frontend addons list [EEA Jenkins - [`c392190`](https://github.com/eea/volto-group-block/commit/c392190f044f5d9397bd2fb8c3d6a357f84960d0)] +- Add Sonarqube tag using frontend addons list [EEA Jenkins - [`9694501`](https://github.com/eea/volto-group-block/commit/9694501141e6780eba89464d36406e3c93629fd8)] ### [4.3.0](https://github.com/eea/volto-group-block/compare/4.2.3...4.3.0) - 24 June 2021 #### :hammer_and_wrench: Others @@ -199,6 +233,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Release 1.0.0 [Alin Voinea - [`b6ef873`](https://github.com/eea/volto-group-block/commit/b6ef873cb6f61e17db66fdd4de1d9d4902a66fc6)] - Update package meta info [Alin Voinea - [`143b7d4`](https://github.com/eea/volto-group-block/commit/143b7d44438d7afa5e346a9d21a85352df4e925f)] - Add Jenkinkins pipeline [Alin Voinea - [`866a4e1`](https://github.com/eea/volto-group-block/commit/866a4e14ea1eb8f5adb01222e576e5ab6dc73a70)] +- yarn prettier [Alin Voinea - [`e3fe0a3`](https://github.com/eea/volto-group-block/commit/e3fe0a36b89878769341b45198d6c9e2f2584d15)] ### [0.1.3](https://github.com/eea/volto-group-block/compare/0.1.2...0.1.3) - 9 November 2020 #### :hammer_and_wrench: Others @@ -238,4 +273,5 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). - Render meta block [Alin Voinea - [`0d44560`](https://github.com/eea/volto-group-block/commit/0d4456011ca56454068a54c610250b02df4ccb3b)] - Implement meta block allowedBlocks settings [Alin Voinea - [`f24feb1`](https://github.com/eea/volto-group-block/commit/f24feb1a1751f04841c21c7cd52a517fb02074ba)] - Edit meta block [Alin Voinea - [`236d291`](https://github.com/eea/volto-group-block/commit/236d29156fa835a7aa54eecdb4f120de0d64b271)] +- yarn bootstrap [Alin Voinea - [`e009dfb`](https://github.com/eea/volto-group-block/commit/e009dfb6b9b74d101a6722f0982a5359fc522b6b)] - Initial commit [Alin Voinea - [`6a7b0de`](https://github.com/eea/volto-group-block/commit/6a7b0deb8f873d1462fd6a9c61edfc1562b3aace)] diff --git a/package.json b/package.json index d02e61f..c667229 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@eeacms/volto-group-block", - "version": "6.2.0", + "version": "6.2.1", "description": "volto-group-block: Volto block to be used to group other blocks", "main": "src/index.js", "author": "European Environment Agency: IDM2 A-Team",