diff --git a/.env b/.env new file mode 100644 index 0000000..ef282fa --- /dev/null +++ b/.env @@ -0,0 +1,3 @@ +# Jest configuration variables +# - possible values: ON, OFF +JEST_USE_SETUP=OFF \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..0cbd65c --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,65 @@ +const fs = require('fs'); +const path = require('path'); +const projectRootPath = fs.realpathSync(__dirname + '/../../../'); + +let voltoPath = path.join(projectRootPath, 'node_modules/@plone/volto'); +let configFile; +if (fs.existsSync(`${projectRootPath}/tsconfig.json`)) + configFile = `${projectRootPath}/tsconfig.json`; +else if (fs.existsSync(`${projectRootPath}/jsconfig.json`)) + configFile = `${projectRootPath}/jsconfig.json`; + +if (configFile) { + const jsConfig = require(configFile).compilerOptions; + const pathsConfig = jsConfig.paths; + if (pathsConfig['@plone/volto']) + voltoPath = `./${jsConfig.baseUrl}/${pathsConfig['@plone/volto'][0]}`; +} + +const AddonConfigurationRegistry = require(`${voltoPath}/addon-registry.js`); +const reg = new AddonConfigurationRegistry(projectRootPath); + +// Extends ESlint configuration for adding the aliases to `src` directories in Volto addons +const addonAliases = Object.keys(reg.packages).map((o) => [ + o, + reg.packages[o].modulePath, +]); + +const addonExtenders = reg.getEslintExtenders().map((m) => require(m)); + +const defaultConfig = { + extends: `${voltoPath}/.eslintrc`, + settings: { + 'import/resolver': { + alias: { + map: [ + ['@plone/volto', '@plone/volto/src'], + ['@plone/volto-slate', '@plone/volto/packages/volto-slate/src'], + ...addonAliases, + ['@package', `${__dirname}/src`], + ['@root', `${__dirname}/src`], + ['~', `${__dirname}/src`], + ], + extensions: ['.js', '.jsx', '.json'], + }, + 'babel-plugin-root-import': { + rootPathSuffix: 'src', + }, + }, + }, + rules: { + 'react/jsx-no-target-blank': [ + 'error', + { + allowReferrer: true, + }, + ], + } +}; + +const config = addonExtenders.reduce( + (acc, extender) => extender.modify(acc), + defaultConfig, +); + +module.exports = config; diff --git a/.gitignore b/.gitignore index 53b9801..f1be4ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ .vscode/ .history -.eslintrc.js .nyc_output project coverage diff --git a/.project.eslintrc.js b/.project.eslintrc.js deleted file mode 100644 index 765070f..0000000 --- a/.project.eslintrc.js +++ /dev/null @@ -1,48 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -const projectRootPath = fs.existsSync('./project') - ? fs.realpathSync('./project') - : fs.realpathSync('./../../../'); -const packageJson = require(path.join(projectRootPath, 'package.json')); -const jsConfig = require(path.join(projectRootPath, 'jsconfig.json')).compilerOptions; - -const pathsConfig = jsConfig.paths; - -let voltoPath = path.join(projectRootPath, 'node_modules/@plone/volto'); - -Object.keys(pathsConfig).forEach(pkg => { - if (pkg === '@plone/volto') { - voltoPath = `./${jsConfig.baseUrl}/${pathsConfig[pkg][0]}`; - } -}); -const AddonConfigurationRegistry = require(`${voltoPath}/addon-registry.js`); -const reg = new AddonConfigurationRegistry(projectRootPath); - -// Extends ESlint configuration for adding the aliases to `src` directories in Volto addons -const addonAliases = Object.keys(reg.packages).map(o => [ - o, - reg.packages[o].modulePath, -]); - - -module.exports = { - extends: `${projectRootPath}/node_modules/@plone/volto/.eslintrc`, - settings: { - 'import/resolver': { - alias: { - map: [ - ['@plone/volto', '@plone/volto/src'], - ...addonAliases, - ['@package', `${__dirname}/src`], - ['~', `${__dirname}/src`], - ], - extensions: ['.js', '.jsx', '.json'], - }, - 'babel-plugin-root-import': { - rootPathSuffix: 'src', - }, - }, - }, -}; - diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bc9c1c..4f5e867 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ 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). +### [5.2.7](https://github.com/eea/volto-slate-zotero/compare/5.2.6...5.2.7) - 19 February 2024 + +#### :house: Internal changes + +- chore: package.json [Alin Voinea - [`e336d00`](https://github.com/eea/volto-slate-zotero/commit/e336d00d2aaad794908e835e6477a553d39e0802)] + +#### :hammer_and_wrench: Others + +- Add Sonarqube tag using insitu-frontend addons list [EEA Jenkins - [`ea159f3`](https://github.com/eea/volto-slate-zotero/commit/ea159f397d68d7a68695865f7d9c80f0089fd47c)] +- test: Update jest,Jenkinsfile,lint to volto-addons-template PR30 [valentinab25 - [`f721884`](https://github.com/eea/volto-slate-zotero/commit/f7218843ea0fbcb69ea76179a616436f0dcb5ad8)] ### [5.2.6](https://github.com/eea/volto-slate-zotero/compare/5.2.5...5.2.6) - 18 January 2024 #### :house: Internal changes diff --git a/Jenkinsfile b/Jenkinsfile index cc9ddb9..abd8cca 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,7 +9,7 @@ pipeline { environment { GIT_NAME = "volto-slate-zotero" NAMESPACE = "@eeacms" - SONARQUBE_TAGS = "volto.eea.europa.eu,www.eea.europa.eu-ims,climate-energy.eea.europa.eu,sustainability.eionet.europa.eu,forest.eea.europa.eu,biodiversity.europa.eu,clms.land.copernicus.eu,industry.eea.europa.eu,water.europa.eu-freshwater,demo-www.eea.europa.eu,clmsdemo.devel6cph.eea.europa.eu,water.europa.eu-marine,climate-adapt.eea.europa.eu,climate-advisory-board.devel4cph.eea.europa.eu,climate-advisory-board.europa.eu,www.eea.europa.eu-en" + SONARQUBE_TAGS = "volto.eea.europa.eu,www.eea.europa.eu-ims,climate-energy.eea.europa.eu,sustainability.eionet.europa.eu,forest.eea.europa.eu,biodiversity.europa.eu,clms.land.copernicus.eu,industry.eea.europa.eu,water.europa.eu-freshwater,demo-www.eea.europa.eu,clmsdemo.devel6cph.eea.europa.eu,water.europa.eu-marine,climate-adapt.eea.europa.eu,climate-advisory-board.devel4cph.eea.europa.eu,climate-advisory-board.europa.eu,www.eea.europa.eu-en,insitu-frontend.eionet.europa.eu" DEPENDENCIES = "" BACKEND_PROFILES = "eea.kitkat:testing" BACKEND_ADDONS = "" @@ -162,10 +162,16 @@ pipeline { script { try { sh '''docker run --pull always --rm -d --name="$IMAGE_NAME-plone" -e SITE="Plone" -e PROFILES="$BACKEND_PROFILES" -e ADDONS="$BACKEND_ADDONS" eeacms/plone-backend''' - sh '''docker run -d --shm-size=3g --link $IMAGE_NAME-plone:plone --name="$IMAGE_NAME-cypress" -e "RAZZLE_INTERNAL_API_PATH=http://plone:8080/Plone" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend start-ci''' + sh '''docker run -d --shm-size=4g --link $IMAGE_NAME-plone:plone --name="$IMAGE_NAME-cypress" -e "RAZZLE_INTERNAL_API_PATH=http://plone:8080/Plone" --entrypoint=make --workdir=/app/src/addons/$GIT_NAME $IMAGE_NAME-frontend start-ci''' + frontend = sh script:'''docker exec --workdir=/app/src/addons/${GIT_NAME} $IMAGE_NAME-cypress make check-ci''', returnStatus: true + if ( frontend != 0 ) { + sh '''docker logs $IMAGE_NAME-cypress; exit 1''' + } + sh '''timeout -s 9 1800 docker exec --workdir=/app/src/addons/${GIT_NAME} $IMAGE_NAME-cypress make cypress-ci''' } finally { try { + if ( frontend == 0 ) { sh '''rm -rf cypress-videos cypress-results cypress-coverage cypress-screenshots''' sh '''mkdir -p cypress-videos cypress-results cypress-coverage cypress-screenshots''' videos = sh script: '''docker cp $IMAGE_NAME-cypress:/app/src/addons/$GIT_NAME/cypress/videos cypress-videos/''', returnStatus: true @@ -189,6 +195,7 @@ pipeline { sh '''for file in $(find cypress-results -name *.xml); do if [ $(grep -E 'failures="[1-9].*"' $file | wc -l) -eq 0 ]; then testname=$(grep -E 'file=.*failures="0"' $file | sed 's#.* file=".*\\/\\(.*\\.[jsxt]\\+\\)" time.*#\\1#' ); rm -f cypress-videos/videos/$testname.mp4; fi; done''' archiveArtifacts artifacts: 'cypress-videos/**/*.mp4', fingerprint: true, allowEmptyArchive: true } + } } finally { catchError(buildResult: 'SUCCESS', stageResult: 'SUCCESS') { junit testResults: 'cypress-results/**/*.xml', allowEmptyResults: true diff --git a/Makefile b/Makefile index efbf2fb..c583f3f 100644 --- a/Makefile +++ b/Makefile @@ -86,7 +86,7 @@ cypress-open: ## Open cypress integration tests .PHONY: cypress-run cypress-run: ## Run cypress integration tests - CYPRESS_API_PATH="${RAZZLE_DEV_PROXY_API_PATH}" NODE_ENV=development $(NODE_MODULES)/cypress/bin/cypress run --browser chromium + CYPRESS_API_PATH="${RAZZLE_DEV_PROXY_API_PATH}" NODE_ENV=development $(NODE_MODULES)/cypress/bin/cypress run .PHONY: test test: ## Run jest tests @@ -155,8 +155,11 @@ start-ci: cd ../.. yarn start +.PHONY: check-ci +check-ci: + $(NODE_MODULES)/.bin/wait-on -t 240000 http://localhost:3000 + .PHONY: cypress-ci cypress-ci: $(NODE_MODULES)/.bin/wait-on -t 240000 http://localhost:3000 - NODE_ENV=development make cypress-run - + CYPRESS_API_PATH="${RAZZLE_DEV_PROXY_API_PATH}" NODE_ENV=development $(NODE_MODULES)/cypress/bin/cypress run --browser chromium diff --git a/jest-addon.config.js b/jest-addon.config.js index 3c86610..aba13bd 100644 --- a/jest-addon.config.js +++ b/jest-addon.config.js @@ -1,3 +1,5 @@ +require('dotenv').config({ path: __dirname + '/.env' }) + module.exports = { testMatch: ['**/src/addons/**/?(*.)+(spec|test).[jt]s?(x)'], collectCoverageFrom: [ @@ -9,16 +11,21 @@ module.exports = { '@plone/volto/cypress': '/node_modules/@plone/volto/cypress', '@plone/volto/babel': '/node_modules/@plone/volto/babel', '@plone/volto/(.*)$': '/node_modules/@plone/volto/src/$1', - '@package/(.*)$': '/src/$1', - '@root/(.*)$': '/src/$1', + '@package/(.*)$': '/node_modules/@plone/volto/src/$1', + '@root/(.*)$': '/node_modules/@plone/volto/src/$1', '@plone/volto-quanta/(.*)$': '/src/addons/volto-quanta/src/$1', '@eeacms/(.*?)/(.*)$': '/node_modules/@eeacms/$1/src/$2', - '@plone/volto-slate': + '@plone/volto-slate$': '/node_modules/@plone/volto/packages/volto-slate/src', + '@plone/volto-slate/(.*)$': + '/node_modules/@plone/volto/packages/volto-slate/src/$1', '~/(.*)$': '/src/$1', 'load-volto-addons': '/node_modules/@plone/volto/jest-addons-loader.js', }, + transformIgnorePatterns: [ + '/node_modules/(?!(@plone|@root|@package|@eeacms)/).*/', + ], transform: { '^.+\\.js(x)?$': 'babel-jest', '^.+\\.(png)$': 'jest-file', @@ -33,4 +40,9 @@ module.exports = { statements: 5, }, }, -}; + ...(process.env.JEST_USE_SETUP === 'ON' && { + setupFilesAfterEnv: [ + '/node_modules/@eeacms/volto-slate-zotero/jest.setup.js', + ], + }), +} diff --git a/jest.setup.js b/jest.setup.js new file mode 100644 index 0000000..85b16f7 --- /dev/null +++ b/jest.setup.js @@ -0,0 +1,65 @@ +import { jest } from '@jest/globals'; +import configureStore from 'redux-mock-store'; +import thunk from 'redux-thunk'; +import { blocksConfig } from '@plone/volto/config/Blocks'; +import installSlate from '@plone/volto-slate/index'; + +var mockSemanticComponents = jest.requireActual('semantic-ui-react'); +var mockComponents = jest.requireActual('@plone/volto/components'); +var config = jest.requireActual('@plone/volto/registry').default; + +config.blocks.blocksConfig = { + ...blocksConfig, + ...config.blocks.blocksConfig, +}; + +jest.doMock('semantic-ui-react', () => ({ + __esModule: true, + ...mockSemanticComponents, + Popup: ({ content, trigger }) => { + return ( +
+
{trigger}
+
{content}
+
+ ); + }, +})); + +jest.doMock('@plone/volto/components', () => { + return { + __esModule: true, + ...mockComponents, + SidebarPortal: ({ children }) => , + }; +}); + +jest.doMock('@plone/volto/registry', () => + [installSlate].reduce((acc, apply) => apply(acc), config), +); + +const mockStore = configureStore([thunk]); + +global.fetch = jest.fn(() => + Promise.resolve({ + json: () => Promise.resolve({}), + }), +); + +global.store = mockStore({ + intl: { + locale: 'en', + messages: {}, + formatMessage: jest.fn(), + }, + content: { + create: {}, + subrequests: [], + }, + connected_data_parameters: {}, + screen: { + page: { + width: 768, + }, + }, +}); diff --git a/package.json b/package.json index 3ab2015..61172d3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@eeacms/volto-slate-zotero", - "version": "5.2.6", + "version": "5.2.7", "description": "Zotero integration with Volto Slate Footnotes", "main": "src/index.js", "author": "European Environment Agency: IDM2 A-Team", @@ -31,6 +31,7 @@ "@cypress/code-coverage": "^3.10.0", "@plone/scripts": "*", "babel-plugin-transform-class-properties": "^6.24.1", + "dotenv": "^16.3.2", "husky": "^8.0.3", "lint-staged": "^14.0.1", "md5": "^2.3.0" diff --git a/src/plugins/zotero/editor/MasterDetailWidget.jsx b/src/plugins/zotero/editor/MasterDetailWidget.jsx index 45bfe15..dbcfc8e 100644 --- a/src/plugins/zotero/editor/MasterDetailWidget.jsx +++ b/src/plugins/zotero/editor/MasterDetailWidget.jsx @@ -94,7 +94,7 @@ const makeList = (props, resultsType, handleClick, activeIndex) => { DOI: {item.data.DOI} @@ -384,7 +384,7 @@ const MasterDetailWidget = (props) => { DOI: {item.data?.DOI}