diff --git a/cypress.config.js b/cypress.config.js index 57c32a3d7c9..86edfbe5024 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -28,7 +28,6 @@ module.exports = defineConfig({ supportFile: 'test/cypress/support/index.js', }, retries: { - runMode: 2, // number of retries when running `cypress run` - openMode: 2, // number of retries when running `cypress open` + runMode: 2, }, }) diff --git a/package-lock.json b/package-lock.json index 6ea5e28c6b0..8b34426dbe0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,9 +13,9 @@ "@nivo/tooltip": "^0.88.0", "@redux-devtools/extension": "^3.3.0", "@reduxjs/toolkit": "^2.5.0", - "@sentry/browser": "^8.47.0", - "@sentry/node": "^8.45.1", - "@sentry/react": "^8.45.1", + "@sentry/browser": "^8.50.0", + "@sentry/node": "^8.50.0", + "@sentry/react": "^8.50.0", "autoprefixer": "^10.4.20", "axios": "^1.7.9", "basic-auth": "^2.0.1", @@ -33,7 +33,7 @@ "date-fns": "^4.1.0", "del-cli": "^6.0.0", "dotenv": "^16.4.7", - "elastic-apm-node": "^4.9.0", + "elastic-apm-node": "^4.11.0", "element-closest": "^3.0.2", "express": "^4.21.2", "express-minify-html-2": "^2.0.0", @@ -43,7 +43,7 @@ "get-form-data": "^3.0.0", "govuk_frontend_toolkit": "^9.0.1", "govuk-elements-sass": "^3.1.3", - "govuk-frontend": "^5.7.1", + "govuk-frontend": "^5.8.0", "govuk-react": "^0.10.7", "hawk": "^9.0.2", "history": "^5.3.0", @@ -61,17 +61,17 @@ "postcss-loader": "^8.1.0", "prop-types": "^15.8.1", "pure-uuid": "^1.8.1", - "qs": "^6.13.1", + "qs": "^6.14.0", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-error-boundary": "^4.1.2", + "react-error-boundary": "^5.0.0", "react-icons": "^5.4.0", "react-lines-ellipsis": "^0.15.4", "react-markdown": "^9.0.1", "react-redux": "^9.2.0", - "react-router-dom": "^7.1.0", + "react-router-dom": "^7.1.1", "react-string-replace": "^1.1.1", - "react-to-print": "^3.0.2", + "react-to-print": "^3.0.4", "react-use": "^17.6.0", "redis": "4.7.0", "redux": "^5.0.1", @@ -81,7 +81,7 @@ "request-promise": "^4.2.6", "resolve-url-loader": "^5.0.0", "sass": "^1.83.0", - "sass-loader": "^16.0.3", + "sass-loader": "^16.0.4", "serve-favicon": "^2.5.0", "sniffr": "^1.3.1", "style-loader": "^4.0.0", @@ -92,7 +92,7 @@ }, "devDependencies": { "@babel/core": "^7.26.0", - "@babel/eslint-parser": "^7.25.9", + "@babel/eslint-parser": "^7.26.5", "@babel/helper-call-delegate": "^7.12.13", "@babel/plugin-syntax-import-assertions": "^7.25.6", "@babel/plugin-transform-class-properties": "^7.25.4", @@ -104,16 +104,16 @@ "@babel/preset-typescript": "^7.26.0", "@babel/register": "^7.25.9", "@babel/runtime": "^7.26.0", - "@chromatic-com/storybook": "^3.2.2", - "@cypress/code-coverage": "^3.13.9", + "@chromatic-com/storybook": "^3.2.3", + "@cypress/code-coverage": "^3.13.10", "@faker-js/faker": "^9.3.0", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.15", - "@storybook/addon-a11y": "^8.4.7", - "@storybook/addon-essentials": "^8.4.7", - "@storybook/addon-webpack5-compiler-babel": "^3.0.3", - "@storybook/manager-api": "^8.4.7", - "@storybook/react": "^8.4.7", - "@storybook/react-webpack5": "^8.4.7", + "@storybook/addon-a11y": "^8.5.0", + "@storybook/addon-essentials": "^8.5.0", + "@storybook/addon-webpack5-compiler-babel": "^3.0.5", + "@storybook/manager-api": "^8.5.0", + "@storybook/react": "^8.5.0", + "@storybook/react-webpack5": "^8.5.0", "babel-loader": "^9.2.1", "babel-plugin-istanbul": "7.0.0", "chai": "^4.5.0", @@ -121,26 +121,26 @@ "cypress": "^13.17.0", "cypress-axe": "^1.5.0", "eslint": "^8.57.0", - "eslint-config-prettier": "^9.1.0", + "eslint-config-prettier": "^10.0.1", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-mocha": "^10.5.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-promise": "^7.2.1", - "eslint-plugin-react": "^7.37.2", + "eslint-plugin-react": "^7.37.4", "eslint-plugin-react-hooks": "^5.1.0", "git-directory-deploy": "^1.5.1", "html": "^1.0.0", "http-server": "^14.1.1", - "image-minimizer-webpack-plugin": "^4.1.1", + "image-minimizer-webpack-plugin": "^4.1.3", "js-beautify": "^1.14.11", "js-cookie": "^3.0.5", "jsdom": "^25.0.1", "jsdom-global": "^3.0.2", "json-schema-faker": "^0.5.8", - "lint-staged": "^15.2.11", - "mocha": "^11.0.1", + "lint-staged": "^15.4.3", + "mocha": "^11.1.0", "mocha-junit-reporter": "^2.2.1", "mochapack": "^2.1.4", "nock": "^13.5.6", @@ -157,9 +157,9 @@ "sinon": "^19.0.2", "sinon-chai": "^3.7.0", "std-mocks": "^2.0.0", - "storybook": "^8.4.7", + "storybook": "^8.5.0", "supertest": "^7.0.0", - "webpack": "^5.96.1", + "webpack": "^5.97.1", "webpack-assets-manifest": "^5.1.0", "webpack-cli": "^6.0.1", "webpack-dev-server": "^5.2.0", @@ -169,6 +169,12 @@ "node": "20.11.0" } }, + "node_modules/@adobe/css-tools": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.1.tgz", + "integrity": "sha512-12WGKBQzjUAI4ayyF4IAtfw2QR/IDoqk6jTddXDhtYTJF9ASmoE1zst7cVtP0aL/F1jUJL5r+JxKXKEgHNbEUQ==", + "dev": true + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -232,9 +238,9 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.9.tgz", - "integrity": "sha512-5UXfgpK0j0Xr/xIdgdLEhOFxaDZ0bRPWJJchRpqOSur/3rZoPbqqki5mm0p4NE2cs28krBEiSM2MB7//afRSQQ==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.26.5.tgz", + "integrity": "sha512-Kkm8C8uxI842AwQADxl0GbcG1rupELYLShazYEZO/2DYjhyWXJIOUVOE3tBYm6JXzUCNJOZEzqc4rCW/jsEQYQ==", "dev": true, "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", @@ -1957,9 +1963,9 @@ } }, "node_modules/@chromatic-com/storybook": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-3.2.2.tgz", - "integrity": "sha512-xmXt/GW0hAPbzNTrxYuVo43Adrtjue4DeVrsoIIEeJdGaPNNeNf+DHMlJKOBdlHmCnFUoe9R/0mLM9zUp5bKWw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@chromatic-com/storybook/-/storybook-3.2.3.tgz", + "integrity": "sha512-3+hfANx79kIjP1qrOSLxpoAXOiYUA0S7A0WI0A24kASrv7USFNNW8etR5TjUilMb0LmqKUn3wDwUK2h6aceQ9g==", "dev": true, "dependencies": { "chromatic": "^11.15.0", @@ -1987,10 +1993,11 @@ } }, "node_modules/@cypress/code-coverage": { - "version": "3.13.9", - "resolved": "https://registry.npmjs.org/@cypress/code-coverage/-/code-coverage-3.13.9.tgz", - "integrity": "sha512-VnsBLmhRLE3xgeX5hdN7aWCU3l8UHttUCMO7b+2OrRvs+R3kpBwjejfSC0/H7ErXz5o6r99biClIaS5bqo60uQ==", + "version": "3.13.10", + "resolved": "https://registry.npmjs.org/@cypress/code-coverage/-/code-coverage-3.13.10.tgz", + "integrity": "sha512-Bcj24zr82HNd6XGLvt9i00YYPscZwKiXBoyNM5iloJeo1cOqJRN7qkS/SIfX9Ab6lTvuNBDdZat48vyuZAuJBA==", "dev": true, + "license": "MIT", "dependencies": { "@cypress/webpack-preprocessor": "^6.0.0", "chalk": "4.1.2", @@ -2154,15 +2161,6 @@ "node": ">=8" } }, - "node_modules/@cypress/code-coverage/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@cypress/code-coverage/node_modules/istanbul-lib-instrument": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", @@ -2510,9 +2508,9 @@ "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", - "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", + "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", "cpu": [ "ppc64" ], @@ -2526,9 +2524,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", - "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", + "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", "cpu": [ "arm" ], @@ -2542,9 +2540,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", - "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", + "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", "cpu": [ "arm64" ], @@ -2558,9 +2556,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", - "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", + "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", "cpu": [ "x64" ], @@ -2574,9 +2572,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", - "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", + "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", "cpu": [ "arm64" ], @@ -2590,9 +2588,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", - "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", + "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", "cpu": [ "x64" ], @@ -2606,9 +2604,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", - "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", + "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", "cpu": [ "arm64" ], @@ -2622,9 +2620,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", - "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", + "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", "cpu": [ "x64" ], @@ -2638,9 +2636,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", - "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", + "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", "cpu": [ "arm" ], @@ -2654,9 +2652,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", - "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", + "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", "cpu": [ "arm64" ], @@ -2670,9 +2668,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", - "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", + "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", "cpu": [ "ia32" ], @@ -2686,9 +2684,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", - "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", + "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", "cpu": [ "loong64" ], @@ -2702,9 +2700,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", - "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", + "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", "cpu": [ "mips64el" ], @@ -2718,9 +2716,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", - "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", + "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", "cpu": [ "ppc64" ], @@ -2734,9 +2732,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", - "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", + "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", "cpu": [ "riscv64" ], @@ -2750,9 +2748,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", - "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", + "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", "cpu": [ "s390x" ], @@ -2766,9 +2764,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", - "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", + "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", "cpu": [ "x64" ], @@ -2781,10 +2779,26 @@ "node": ">=18" } }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", + "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", - "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", + "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", "cpu": [ "x64" ], @@ -2798,9 +2812,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", - "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", + "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", "cpu": [ "arm64" ], @@ -2814,9 +2828,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", - "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", + "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", "cpu": [ "x64" ], @@ -2830,9 +2844,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", - "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", + "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", "cpu": [ "x64" ], @@ -2846,9 +2860,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", - "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", + "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", "cpu": [ "arm64" ], @@ -2862,9 +2876,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", - "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", + "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", "cpu": [ "ia32" ], @@ -2878,9 +2892,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", - "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", + "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", "cpu": [ "x64" ], @@ -4805,7 +4819,6 @@ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", "dev": true, - "license": "MIT", "dependencies": { "@types/mdx": "^2.0.0" }, @@ -5499,13 +5512,12 @@ } }, "node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.29.0.tgz", - "integrity": "sha512-hEOpAYLKXF3wGJpXOtWsxEtqBgde0SCv+w+jvr3/UusR4ll3QrENEGnSl1WDCyRrpqOQ5NCNOvZch9UFVa7MnQ==", - "license": "Apache-2.0", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz", + "integrity": "sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg==", "dependencies": { - "@opentelemetry/core": "1.29.0", - "@opentelemetry/resources": "1.29.0", + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1", "@opentelemetry/semantic-conventions": "1.28.0" }, "engines": { @@ -5516,10 +5528,9 @@ } }, "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/core": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.29.0.tgz", - "integrity": "sha512-gmT7vAreXl0DTHD2rVZcw3+l2g84+5XiHIqdBUxXbExymPCvSsGOpiwMmn8nkiJur28STV31wnhIDrzWDPzjfA==", - "license": "Apache-2.0", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", + "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", "dependencies": { "@opentelemetry/semantic-conventions": "1.28.0" }, @@ -5531,12 +5542,11 @@ } }, "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/resources": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.29.0.tgz", - "integrity": "sha512-s7mLXuHZE7RQr1wwweGcaRp3Q4UJJ0wazeGlc/N5/XSe6UyXfsh1UQGMADYeg7YwD+cEdMtU1yJAUXdnFzYzyQ==", - "license": "Apache-2.0", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", + "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", "dependencies": { - "@opentelemetry/core": "1.29.0", + "@opentelemetry/core": "1.30.1", "@opentelemetry/semantic-conventions": "1.28.0" }, "engines": { @@ -5550,7 +5560,6 @@ "version": "1.28.0", "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", - "license": "Apache-2.0", "engines": { "node": ">=14" } @@ -5922,19 +5931,19 @@ } }, "node_modules/@prisma/instrumentation": { - "version": "5.19.1", - "resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-5.19.1.tgz", - "integrity": "sha512-VLnzMQq7CWroL5AeaW0Py2huiNKeoMfCH3SUxstdzPrlWQi6UQ9UrfcbUkNHlVFqOMacqy8X/8YtE0kuKDpD9w==", + "version": "5.22.0", + "resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-5.22.0.tgz", + "integrity": "sha512-LxccF392NN37ISGxIurUljZSh1YWnphO34V5a0+T7FVQG2u9bhAXRTJpgmQ3483woVhkraQZFF7cbRrpbw/F4Q==", "dependencies": { "@opentelemetry/api": "^1.8", - "@opentelemetry/instrumentation": "^0.49 || ^0.50 || ^0.51 || ^0.52.0", + "@opentelemetry/instrumentation": "^0.49 || ^0.50 || ^0.51 || ^0.52.0 || ^0.53.0", "@opentelemetry/sdk-trace-base": "^1.22" } }, "node_modules/@prisma/instrumentation/node_modules/@opentelemetry/api-logs": { - "version": "0.52.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.52.1.tgz", - "integrity": "sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.53.0.tgz", + "integrity": "sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==", "dependencies": { "@opentelemetry/api": "^1.0.0" }, @@ -5943,12 +5952,12 @@ } }, "node_modules/@prisma/instrumentation/node_modules/@opentelemetry/instrumentation": { - "version": "0.52.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.52.1.tgz", - "integrity": "sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==", + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.53.0.tgz", + "integrity": "sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==", "dependencies": { - "@opentelemetry/api-logs": "0.52.1", - "@types/shimmer": "^1.0.2", + "@opentelemetry/api-logs": "0.53.0", + "@types/shimmer": "^1.2.0", "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1", "semver": "^7.5.2", @@ -6170,6 +6179,272 @@ } } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.31.0.tgz", + "integrity": "sha512-9NrR4033uCbUBRgvLcBrJofa2KY9DzxL2UKZ1/4xA/mnTNyhZCWBuD8X3tPm1n4KxcgaraOYgrFKSgwjASfmlA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.31.0.tgz", + "integrity": "sha512-iBbODqT86YBFHajxxF8ebj2hwKm1k8PTBQSojSt3d1FFt1gN+xf4CowE47iN0vOSdnd+5ierMHBbu/rHc7nq5g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.31.0.tgz", + "integrity": "sha512-WHIZfXgVBX30SWuTMhlHPXTyN20AXrLH4TEeH/D0Bolvx9PjgZnn4H677PlSGvU6MKNsjCQJYczkpvBbrBnG6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.31.0.tgz", + "integrity": "sha512-hrWL7uQacTEF8gdrQAqcDy9xllQ0w0zuL1wk1HV8wKGSGbKPVjVUv/DEwT2+Asabf8Dh/As+IvfdU+H8hhzrQQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.31.0.tgz", + "integrity": "sha512-S2oCsZ4hJviG1QjPY1h6sVJLBI6ekBeAEssYKad1soRFv3SocsQCzX6cwnk6fID6UQQACTjeIMB+hyYrFacRew==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "peer": true + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.31.0.tgz", + "integrity": "sha512-pCANqpynRS4Jirn4IKZH4tnm2+2CqCNLKD7gAdEjzdLGbH1iO0zouHz4mxqg0uEMpO030ejJ0aA6e1PJo2xrPA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.31.0.tgz", + "integrity": "sha512-0O8ViX+QcBd3ZmGlcFTnYXZKGbFu09EhgD27tgTdGnkcYXLat4KIsBBQeKLR2xZDCXdIBAlWLkiXE1+rJpCxFw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.31.0.tgz", + "integrity": "sha512-w5IzG0wTVv7B0/SwDnMYmbr2uERQp999q8FMkKG1I+j8hpPX2BYFjWe69xbhbP6J9h2gId/7ogesl9hwblFwwg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.31.0.tgz", + "integrity": "sha512-JyFFshbN5xwy6fulZ8B/8qOqENRmDdEkcIMF0Zz+RsfamEW+Zabl5jAb0IozP/8UKnJ7g2FtZZPEUIAlUSX8cA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.31.0.tgz", + "integrity": "sha512-kpQXQ0UPFeMPmPYksiBL9WS/BDiQEjRGMfklVIsA0Sng347H8W2iexch+IEwaR7OVSKtr2ZFxggt11zVIlZ25g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.31.0.tgz", + "integrity": "sha512-pMlxLjt60iQTzt9iBb3jZphFIl55a70wexvo8p+vVFK+7ifTRookdoXX3bOsRdmfD+OKnMozKO6XM4zR0sHRrQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.31.0.tgz", + "integrity": "sha512-D7TXT7I/uKEuWiRkEFbed1UUYZwcJDU4vZQdPTcepK7ecPhzKOYk4Er2YR4uHKme4qDeIh6N3XrLfpuM7vzRWQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.31.0.tgz", + "integrity": "sha512-wal2Tc8O5lMBtoePLBYRKj2CImUCJ4UNGJlLwspx7QApYny7K1cUYlzQ/4IGQBLmm+y0RS7dwc3TDO/pmcneTw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.31.0.tgz", + "integrity": "sha512-O1o5EUI0+RRMkK9wiTVpk2tyzXdXefHtRTIjBbmFREmNMy7pFeYXCFGbhKFwISA3UOExlo5GGUuuj3oMKdK6JQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.31.0.tgz", + "integrity": "sha512-zSoHl356vKnNxwOWnLd60ixHNPRBglxpv2g7q0Cd3Pmr561gf0HiAcUBRL3S1vPqRC17Zo2CX/9cPkqTIiai1g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.31.0.tgz", + "integrity": "sha512-ypB/HMtcSGhKUQNiFwqgdclWNRrAYDH8iMYH4etw/ZlGwiTVxBz2tDrGRrPlfZu6QjXwtd+C3Zib5pFqID97ZA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.31.0.tgz", + "integrity": "sha512-JuhN2xdI/m8Hr+aVO3vspO7OQfUFO6bKLIRTAy0U15vmWjnZDLrEgCZ2s6+scAYaQVpYSh9tZtRijApw9IXyMw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.31.0.tgz", + "integrity": "sha512-U1xZZXYkvdf5MIWmftU8wrM5PPXzyaY1nGCI4KI4BFfoZxHamsIe+BtnPLIvvPykvQWlVbqUXdLa4aJUuilwLQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.31.0.tgz", + "integrity": "sha512-ul8rnCsUumNln5YWwz0ted2ZHFhzhRRnkpBZ+YRuHoRAlUji9KChpOUOndY7uykrPEPXVbHLlsdo6v5yXo/TXw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -6177,120 +6452,78 @@ "dev": true }, "node_modules/@sentry-internal/browser-utils": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.47.0.tgz", - "integrity": "sha512-vOXzYzHTKkahTLDzWWIA4EiVCQ+Gk+7xGWUlNcR2ZiEPBqYZVb5MjsUozAcc7syrSUy6WicyFjcomZ3rlCVQhg==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.50.0.tgz", + "integrity": "sha512-hZm6ngWTEzZhaMHpLIKB4wWp0Od1MdCZdvR5FRdIThUMLa1P8rXeolovTRfOE81NE755EiwJHzj4O7rq3EjA+A==", "dependencies": { - "@sentry/core": "8.47.0" + "@sentry/core": "8.50.0" }, "engines": { "node": ">=14.18" } }, - "node_modules/@sentry-internal/browser-utils/node_modules/@sentry/core": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.47.0.tgz", - "integrity": "sha512-iSEJZMe3DOcqBFZQAqgA3NB2lCWBc4Gv5x/SCri/TVg96wAlss4VrUunSI2Mp0J4jJ5nJcJ2ChqHSBAU48k3FA==", - "engines": { - "node": ">=14.18" - } - }, "node_modules/@sentry-internal/feedback": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.47.0.tgz", - "integrity": "sha512-IAiIemTQIalxAOYhUENs9bZ8pMNgJnX3uQSuY7v0gknEqClOGpGkG04X/cxCmtJUj1acZ9ShTGDxoh55a+ggAQ==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.50.0.tgz", + "integrity": "sha512-79WlvSJYCXL/D0PBC8AIT4JbyS44AE3h6lP05IESXMqzTZl3KeSqCx317rwJw1KaxzeFd/JQwkFq95jaKAcLhg==", "dependencies": { - "@sentry/core": "8.47.0" + "@sentry/core": "8.50.0" }, "engines": { "node": ">=14.18" } }, - "node_modules/@sentry-internal/feedback/node_modules/@sentry/core": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.47.0.tgz", - "integrity": "sha512-iSEJZMe3DOcqBFZQAqgA3NB2lCWBc4Gv5x/SCri/TVg96wAlss4VrUunSI2Mp0J4jJ5nJcJ2ChqHSBAU48k3FA==", - "engines": { - "node": ">=14.18" - } - }, "node_modules/@sentry-internal/replay": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.47.0.tgz", - "integrity": "sha512-G/S40ZBORj0HSMLw/uVC6YDEPN/dqVk901vf4VYfml686DEhJrZesfAfp5SydJumQ0NKZQrdtvny+BWnlI5H1w==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.50.0.tgz", + "integrity": "sha512-mhRPujzO6n+mb6ZR+wQNkSpjqIqDriR0hZEvdzHQdyXu9zVdCHUJ3sINkzpT1XwiypQVCEfxB6Oh9y/NmcQfGg==", "dependencies": { - "@sentry-internal/browser-utils": "8.47.0", - "@sentry/core": "8.47.0" + "@sentry-internal/browser-utils": "8.50.0", + "@sentry/core": "8.50.0" }, "engines": { "node": ">=14.18" } }, "node_modules/@sentry-internal/replay-canvas": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.47.0.tgz", - "integrity": "sha512-M4W9UGouEeELbGbP3QsXLDVtGiQSZoWJlKwqMWyqdQgZuLoKw0S33+60t6teLVMhuQZR0UI9VJTF5coiXysnnA==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.50.0.tgz", + "integrity": "sha512-Hv1bBaPpe62xFPLpuaUxVBUHd/Ed9bnGndeqN4hueeEGDT9T6NyVokgm35O5xE9/op6Yodm/3NfUkEg8oE++Aw==", "dependencies": { - "@sentry-internal/replay": "8.47.0", - "@sentry/core": "8.47.0" + "@sentry-internal/replay": "8.50.0", + "@sentry/core": "8.50.0" }, "engines": { "node": ">=14.18" } }, - "node_modules/@sentry-internal/replay-canvas/node_modules/@sentry/core": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.47.0.tgz", - "integrity": "sha512-iSEJZMe3DOcqBFZQAqgA3NB2lCWBc4Gv5x/SCri/TVg96wAlss4VrUunSI2Mp0J4jJ5nJcJ2ChqHSBAU48k3FA==", - "engines": { - "node": ">=14.18" - } - }, - "node_modules/@sentry-internal/replay/node_modules/@sentry/core": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.47.0.tgz", - "integrity": "sha512-iSEJZMe3DOcqBFZQAqgA3NB2lCWBc4Gv5x/SCri/TVg96wAlss4VrUunSI2Mp0J4jJ5nJcJ2ChqHSBAU48k3FA==", - "engines": { - "node": ">=14.18" - } - }, "node_modules/@sentry/browser": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.47.0.tgz", - "integrity": "sha512-K6BzHisykmbFy/wORtGyfsAlw7ShevLALzu3ReZZZ18dVubO1bjSNjkZQU9MJD5Jcb9oLwkq89n3N9XIBfvdRA==", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.50.0.tgz", + "integrity": "sha512-aGJSpuKiHVKkLvd1VklJSZ2oCsl4wcKUVxKIa8dhJC8KjDY0vREQCywrlWuS5KYP0xFy4k28pg6PPR3HKkUlNw==", "dependencies": { - "@sentry-internal/browser-utils": "8.47.0", - "@sentry-internal/feedback": "8.47.0", - "@sentry-internal/replay": "8.47.0", - "@sentry-internal/replay-canvas": "8.47.0", - "@sentry/core": "8.47.0" + "@sentry-internal/browser-utils": "8.50.0", + "@sentry-internal/feedback": "8.50.0", + "@sentry-internal/replay": "8.50.0", + "@sentry-internal/replay-canvas": "8.50.0", + "@sentry/core": "8.50.0" }, "engines": { "node": ">=14.18" } }, - "node_modules/@sentry/browser/node_modules/@sentry/core": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.47.0.tgz", - "integrity": "sha512-iSEJZMe3DOcqBFZQAqgA3NB2lCWBc4Gv5x/SCri/TVg96wAlss4VrUunSI2Mp0J4jJ5nJcJ2ChqHSBAU48k3FA==", - "engines": { - "node": ">=14.18" - } - }, "node_modules/@sentry/core": { - "version": "8.45.1", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.45.1.tgz", - "integrity": "sha512-1fGmkr0paZshh38mD29c4CfkRkgFoYDaAGyDLoGYfTbEph/lU8RHB2HWzN93McqNdMEhl1DRRyqIasUZoPlqSA==", - "license": "MIT", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.50.0.tgz", + "integrity": "sha512-q71m8Ha9YGwqn4Gd7sWvcFTRgbHXxEfU4QeIFtwMBpwHfq2Q+9koiF8DOoOHqIEOsnlvZWRQgGggIOdHzajnVw==", "engines": { "node": ">=14.18" } }, "node_modules/@sentry/node": { - "version": "8.45.1", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-8.45.1.tgz", - "integrity": "sha512-xvlXifM/FSOQdLAqQBuo04SiOh7RP8rRRr+c5G/YbBtgJA867Pve0X8JZK2BJpDZ3OrGvzXV1Ubnt9ao4rBfYA==", - "license": "MIT", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-8.50.0.tgz", + "integrity": "sha512-I9eGIdcoWKVy4O8a1f2t0jGVTdN1z9McxbGW8aWwDE5Vd9gpuNjFh9qGapmBEPzysWBX8rjsemDdSa3TcijJMw==", "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.29.0", @@ -6323,9 +6556,9 @@ "@opentelemetry/resources": "^1.29.0", "@opentelemetry/sdk-trace-base": "^1.29.0", "@opentelemetry/semantic-conventions": "^1.28.0", - "@prisma/instrumentation": "5.19.1", - "@sentry/core": "8.45.1", - "@sentry/opentelemetry": "8.45.1", + "@prisma/instrumentation": "5.22.0", + "@sentry/core": "8.50.0", + "@sentry/opentelemetry": "8.50.0", "import-in-the-middle": "^1.11.2" }, "engines": { @@ -6373,12 +6606,11 @@ } }, "node_modules/@sentry/node/node_modules/@sentry/opentelemetry": { - "version": "8.45.1", - "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-8.45.1.tgz", - "integrity": "sha512-khnR5TS21ksITTXmXnpniRN7brlZS5RNNQuMZ9n3MYi/L1/s9LT73skNh1gder28OV6ZxGUgrTZ+1dtKqn9tig==", - "license": "MIT", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-8.50.0.tgz", + "integrity": "sha512-uAZjAMPAulFHL88ThK2k+XPx2QzvZ/I7e7sP1In28Tb/yLH0mi+51AUH+zcnLELIPC86m1aDYl8uwYcP6tV4dA==", "dependencies": { - "@sentry/core": "8.45.1" + "@sentry/core": "8.50.0" }, "engines": { "node": ">=14.18" @@ -6392,13 +6624,12 @@ } }, "node_modules/@sentry/react": { - "version": "8.45.1", - "resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.45.1.tgz", - "integrity": "sha512-ooMR2Lt4YSc5CMJklBKiL/mb+uidcZMpflxUvVUbtWMif+PqTUkfPRyICv6vs7muxK9i84Rr4iCkyZ4ns4H27A==", - "license": "MIT", + "version": "8.50.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-8.50.0.tgz", + "integrity": "sha512-qkDW5dieROPDf0uk1usXib/SLZTEveN5jvKgBFd+HKWz5JNu+M7L53t9KdZ7ryn4T68utI/LWs4qR3QhmXzUbQ==", "dependencies": { - "@sentry/browser": "8.45.1", - "@sentry/core": "8.45.1", + "@sentry/browser": "8.50.0", + "@sentry/core": "8.50.0", "hoist-non-react-statics": "^3.3.2" }, "engines": { @@ -6408,67 +6639,6 @@ "react": "^16.14.0 || 17.x || 18.x || 19.x" } }, - "node_modules/@sentry/react/node_modules/@sentry-internal/browser-utils": { - "version": "8.45.1", - "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-8.45.1.tgz", - "integrity": "sha512-sZwtP3zAzDsjUS7WkMW5VGbvSl7hGKTMc8gAJbpEsrybMxllIP13zzMRwpeFF11RnnvbrZ/FtAeX58Mvj0jahA==", - "dependencies": { - "@sentry/core": "8.45.1" - }, - "engines": { - "node": ">=14.18" - } - }, - "node_modules/@sentry/react/node_modules/@sentry-internal/feedback": { - "version": "8.45.1", - "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-8.45.1.tgz", - "integrity": "sha512-zCKptzki4SLnG+s8je8dgnppOKFjiiO4GVBc4fh7uL8zjNPBnxW8wK4SrPfAEKVYaHUzkKc5vixwUqcpmfLLGw==", - "dependencies": { - "@sentry/core": "8.45.1" - }, - "engines": { - "node": ">=14.18" - } - }, - "node_modules/@sentry/react/node_modules/@sentry-internal/replay": { - "version": "8.45.1", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-8.45.1.tgz", - "integrity": "sha512-cOA9CodNSR9+hmICDaGIDUvWiwxQxeMHk/esbjB8uAW8HG4CYTG3CTYTZmlmou7DuysfMd4JNuFmDFBj+YU5/A==", - "dependencies": { - "@sentry-internal/browser-utils": "8.45.1", - "@sentry/core": "8.45.1" - }, - "engines": { - "node": ">=14.18" - } - }, - "node_modules/@sentry/react/node_modules/@sentry-internal/replay-canvas": { - "version": "8.45.1", - "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-8.45.1.tgz", - "integrity": "sha512-qiPg6XwOwkiMMe/8Qf3EhXCqkSlSnWLlorYngIbdkV2klbWjd7vKnqkFJF4PnaS0g7kkZr7nh+MdzpyLyuj2Mw==", - "dependencies": { - "@sentry-internal/replay": "8.45.1", - "@sentry/core": "8.45.1" - }, - "engines": { - "node": ">=14.18" - } - }, - "node_modules/@sentry/react/node_modules/@sentry/browser": { - "version": "8.45.1", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-8.45.1.tgz", - "integrity": "sha512-/KvYhQSRg8m9kotG8h9FrfXCWRlebrvdfXKjj1oE9SyZ2LmR8Ze9AcEw1qzsBsa1F1D/a5FQbUJahSoLBkaQPA==", - "dependencies": { - "@sentry-internal/browser-utils": "8.45.1", - "@sentry-internal/feedback": "8.45.1", - "@sentry-internal/replay": "8.45.1", - "@sentry-internal/replay-canvas": "8.45.1", - "@sentry/core": "8.45.1" - }, - "engines": { - "node": ">=14.18" - } - }, "node_modules/@sideway/address": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", @@ -6582,29 +6752,29 @@ "dev": true }, "node_modules/@storybook/addon-a11y": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-8.4.7.tgz", - "integrity": "sha512-GpUvXp6n25U1ZSv+hmDC+05BEqxWdlWjQTb/GaboRXZQeMBlze6zckpVb66spjmmtQAIISo0eZxX1+mGcVR7lA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-8.5.0.tgz", + "integrity": "sha512-dTKlnhOaDsAXxkmHz7m6/qb98IENoaXTCG3fXo2iwJ1xT27fZF+i8fz8oQprLAN5r7xlnz66ARJvEIKJ+Lxjgw==", "dev": true, - "license": "MIT", "dependencies": { - "@storybook/addon-highlight": "8.4.7", - "axe-core": "^4.2.0" + "@storybook/addon-highlight": "8.5.0", + "@storybook/test": "8.5.0", + "axe-core": "^4.2.0", + "vitest-axe": "^0.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.4.7" + "storybook": "^8.5.0" } }, "node_modules/@storybook/addon-actions": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.4.7.tgz", - "integrity": "sha512-mjtD5JxcPuW74T6h7nqMxWTvDneFtokg88p6kQ5OnC1M259iAXb//yiSZgu/quunMHPCXSiqn4FNOSgASTSbsA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.5.0.tgz", + "integrity": "sha512-6CW9+17rk5eNx6I8EKqCxRKtsJFTR/lHL+xiJ6/iBWApIm8sg63vhXvUTJ58UixmIkT5oLh0+ESNPh+x10D8fw==", "dev": true, - "license": "MIT", "dependencies": { "@storybook/global": "^5.0.0", "@types/uuid": "^9.0.1", @@ -6617,7 +6787,7 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.4.7" + "storybook": "^8.5.0" } }, "node_modules/@storybook/addon-actions/node_modules/uuid": { @@ -6629,17 +6799,15 @@ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], - "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/@storybook/addon-backgrounds": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.4.7.tgz", - "integrity": "sha512-I4/aErqtFiazcoWyKafOAm3bLpxTj6eQuH/woSbk1Yx+EzN+Dbrgx1Updy8//bsNtKkcrXETITreqHC+a57DHQ==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.5.0.tgz", + "integrity": "sha512-lzyFLs7niNsqlhH5kdUrp7htLiMIcjY50VLWe0PaeJ6T6GZ7X9qhQzROAUV6cGqzyd8A6y/LzIUntDPMVEm/6g==", "dev": true, - "license": "MIT", "dependencies": { "@storybook/global": "^5.0.0", "memoizerific": "^1.11.3", @@ -6650,15 +6818,14 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.4.7" + "storybook": "^8.5.0" } }, "node_modules/@storybook/addon-controls": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.4.7.tgz", - "integrity": "sha512-377uo5IsJgXLnQLJixa47+11V+7Wn9KcDEw+96aGCBCfLbWNH8S08tJHHnSu+jXg9zoqCAC23MetntVp6LetHA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.5.0.tgz", + "integrity": "sha512-1fivx77A/ahObrPl0L66o9i9MUNfqXxsrpekne5gjMNXw9XJFIRNUe/ddL4CMmwu7SgVbj2QV+q5E5mlnZNTJw==", "dev": true, - "license": "MIT", "dependencies": { "@storybook/global": "^5.0.0", "dequal": "^2.0.2", @@ -6669,20 +6836,19 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.4.7" + "storybook": "^8.5.0" } }, "node_modules/@storybook/addon-docs": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.4.7.tgz", - "integrity": "sha512-NwWaiTDT5puCBSUOVuf6ME7Zsbwz7Y79WF5tMZBx/sLQ60vpmJVQsap6NSjvK1Ravhc21EsIXqemAcBjAWu80w==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.5.0.tgz", + "integrity": "sha512-REwLSr1VgOVNJZwP3y3mldhOjBHlM5fqTvq/tC8NaYpAzx9O4rZdoUSZxW3tYtoNoYrHpB8kzRTeZl8WSdKllw==", "dev": true, - "license": "MIT", "dependencies": { "@mdx-js/react": "^3.0.0", - "@storybook/blocks": "8.4.7", - "@storybook/csf-plugin": "8.4.7", - "@storybook/react-dom-shim": "8.4.7", + "@storybook/blocks": "8.5.0", + "@storybook/csf-plugin": "8.5.0", + "@storybook/react-dom-shim": "8.5.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", "ts-dedent": "^2.0.0" @@ -6692,25 +6858,24 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.4.7" + "storybook": "^8.5.0" } }, "node_modules/@storybook/addon-essentials": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.4.7.tgz", - "integrity": "sha512-+BtZHCBrYtQKILtejKxh0CDRGIgTl9PumfBOKRaihYb4FX1IjSAxoV/oo/IfEjlkF5f87vouShWsRa8EUauFDw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@storybook/addon-actions": "8.4.7", - "@storybook/addon-backgrounds": "8.4.7", - "@storybook/addon-controls": "8.4.7", - "@storybook/addon-docs": "8.4.7", - "@storybook/addon-highlight": "8.4.7", - "@storybook/addon-measure": "8.4.7", - "@storybook/addon-outline": "8.4.7", - "@storybook/addon-toolbars": "8.4.7", - "@storybook/addon-viewport": "8.4.7", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.5.0.tgz", + "integrity": "sha512-RrHRdaw2j3ugZiYQ6OHt3Ff08ID4hwAvipqULEsbEnEw3VlXOaW/MT5e2M7kW3MHskQ3iJ6XAD1Y1rNm432Pzw==", + "dev": true, + "dependencies": { + "@storybook/addon-actions": "8.5.0", + "@storybook/addon-backgrounds": "8.5.0", + "@storybook/addon-controls": "8.5.0", + "@storybook/addon-docs": "8.5.0", + "@storybook/addon-highlight": "8.5.0", + "@storybook/addon-measure": "8.5.0", + "@storybook/addon-outline": "8.5.0", + "@storybook/addon-toolbars": "8.5.0", + "@storybook/addon-viewport": "8.5.0", "ts-dedent": "^2.0.0" }, "funding": { @@ -6718,15 +6883,14 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.4.7" + "storybook": "^8.5.0" } }, "node_modules/@storybook/addon-highlight": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.4.7.tgz", - "integrity": "sha512-whQIDBd3PfVwcUCrRXvCUHWClXe9mQ7XkTPCdPo4B/tZ6Z9c6zD8JUHT76ddyHivixFLowMnA8PxMU6kCMAiNw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.5.0.tgz", + "integrity": "sha512-/JxYzMK5aJSYs0K/0eAEFyER2dMoxqwM891MdnkNwLFdyrM58lzHee00F9oEX6zeQoRUNQPRepq0ui2PvbTMGw==", "dev": true, - "license": "MIT", "dependencies": { "@storybook/global": "^5.0.0" }, @@ -6735,15 +6899,14 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.4.7" + "storybook": "^8.5.0" } }, "node_modules/@storybook/addon-measure": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.4.7.tgz", - "integrity": "sha512-QfvqYWDSI5F68mKvafEmZic3SMiK7zZM8VA0kTXx55hF/+vx61Mm0HccApUT96xCXIgmwQwDvn9gS4TkX81Dmw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.5.0.tgz", + "integrity": "sha512-e8pJy2sICyj0Ff0W1PFc6HPE6PqcjnnHtfuDaO3M9uSKJLYkpTWJ8i1VSP178f8seq44r5/PdQCHqs5q5l3zgw==", "dev": true, - "license": "MIT", "dependencies": { "@storybook/global": "^5.0.0", "tiny-invariant": "^1.3.1" @@ -6753,15 +6916,14 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.4.7" + "storybook": "^8.5.0" } }, "node_modules/@storybook/addon-outline": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.4.7.tgz", - "integrity": "sha512-6LYRqUZxSodmAIl8icr585Oi8pmzbZ90aloZJIpve+dBAzo7ydYrSQxxoQEVltXbKf3VeVcrs64ouAYqjisMYA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.5.0.tgz", + "integrity": "sha512-r12sk1b38Ph6NroWAOTfjbJ/V+gDobm7tKQQlbSDf6fgX7cqyPHmKjfNDCOCQpXouZm/Jm+41zd758PW+Yt4ng==", "dev": true, - "license": "MIT", "dependencies": { "@storybook/global": "^5.0.0", "ts-dedent": "^2.0.0" @@ -6771,29 +6933,27 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.4.7" + "storybook": "^8.5.0" } }, "node_modules/@storybook/addon-toolbars": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.4.7.tgz", - "integrity": "sha512-OSfdv5UZs+NdGB+nZmbafGUWimiweJ/56gShlw8Neo/4jOJl1R3rnRqqY7MYx8E4GwoX+i3GF5C3iWFNQqlDcw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.5.0.tgz", + "integrity": "sha512-q3yYYO2WX8K2DYNM++FzixGDjzYaeREincgsl2WXYXrcuGb5hkOoOgRiAQL8Nz9NQ1Eo+B/yZxrhG/5VoVhUUQ==", "dev": true, - "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.4.7" + "storybook": "^8.5.0" } }, "node_modules/@storybook/addon-viewport": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.4.7.tgz", - "integrity": "sha512-hvczh/jjuXXcOogih09a663sRDDSATXwbE866al1DXgbDFraYD/LxX/QDb38W9hdjU9+Qhx8VFIcNWoMQns5HQ==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.5.0.tgz", + "integrity": "sha512-MlhVELImk9YzjEgGR2ciLC8d5tUSGcO7my4kWIClN0VyTRcvG4ZfwrsEC+jN3/l52nrgjLmKrDX5UAGZm6w5mQ==", "dev": true, - "license": "MIT", "dependencies": { "memoizerific": "^1.11.3" }, @@ -6802,31 +6962,29 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.4.7" + "storybook": "^8.5.0" } }, "node_modules/@storybook/addon-webpack5-compiler-babel": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-babel/-/addon-webpack5-compiler-babel-3.0.3.tgz", - "integrity": "sha512-rVQTTw+oxJltbVKaejIWSHwVKOBJs3au21f/pYXhV0aiNgNhxEa3vr79t/j0j8ox8uJtzM8XYOb7FlkvGfHlwQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@storybook/addon-webpack5-compiler-babel/-/addon-webpack5-compiler-babel-3.0.5.tgz", + "integrity": "sha512-9dlc5PrehEFUHqkgj8x+aKtOY9XH9Zk6WBbtpgY/JCQ7waJ2VvhyDnrgJeXfek+WYlSkJElnta6SlqP+XRG0PQ==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/core": "^7.23.7", - "babel-loader": "^9.1.3" + "@babel/core": "^7.26.0", + "babel-loader": "^9.2.1" }, "engines": { "node": ">=18" } }, "node_modules/@storybook/blocks": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.4.7.tgz", - "integrity": "sha512-+QH7+JwXXXIyP3fRCxz/7E2VZepAanXJM7G8nbR3wWsqWgrRp4Wra6MvybxAYCxU7aNfJX5c+RW84SNikFpcIA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.5.0.tgz", + "integrity": "sha512-2sTOgjH/JFOgWnpqkKjpKVvKAgUaC9ZBjH1gnCoA5dne/SDafYaCAYfv6yZn7g2Xm1sTxWCAmMIUkYSALeWr+w==", "dev": true, - "license": "MIT", "dependencies": { - "@storybook/csf": "^0.1.11", + "@storybook/csf": "0.1.12", "@storybook/icons": "^1.2.12", "ts-dedent": "^2.0.0" }, @@ -6837,7 +6995,7 @@ "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.4.7" + "storybook": "^8.5.0" }, "peerDependenciesMeta": { "react": { @@ -6849,14 +7007,12 @@ } }, "node_modules/@storybook/builder-webpack5": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.4.7.tgz", - "integrity": "sha512-O8LpsQ+4g2x5kh7rI9+jEUdX8k1a5egBQU1lbudmHchqsV0IKiVqBD9LL5Gj3wpit4vB8coSW4ZWTFBw8FQb4Q==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-8.5.0.tgz", + "integrity": "sha512-MyCj11cktyN2HeK8NsLv+L0Km36qAz2UGqu6j1VKJUgPelgpCCi4StCW/KaSBeOFAwGD52xjAdNu+c1h/vfiMg==", "dev": true, - "license": "MIT", "dependencies": { - "@storybook/core-webpack": "8.4.7", - "@types/node": "^22.0.0", + "@storybook/core-webpack": "8.5.0", "@types/semver": "^7.3.4", "browser-assert": "^1.2.1", "case-sensitive-paths-webpack-plugin": "^2.4.0", @@ -6886,7 +7042,7 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.4.7" + "storybook": "^8.5.0" }, "peerDependenciesMeta": { "typescript": { @@ -6899,7 +7055,6 @@ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", "dev": true, - "license": "MIT", "dependencies": { "icss-utils": "^5.1.0", "postcss": "^8.4.33", @@ -6935,7 +7090,6 @@ "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", "dev": true, - "license": "MIT", "engines": { "node": ">= 12.13.0" }, @@ -6948,9 +7102,9 @@ } }, "node_modules/@storybook/components": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-8.4.7.tgz", - "integrity": "sha512-uyJIcoyeMWKAvjrG9tJBUCKxr2WZk+PomgrgrUwejkIfXMO76i6jw9BwLa0NZjYdlthDv30r9FfbYZyeNPmF0g==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-8.5.0.tgz", + "integrity": "sha512-DhaHtwfEcfWYj3ih/5RBSDHe3Idxyf+oHw2/DmaLKJX6MluhdK3ZqigjRcTmA9Gj/SbR4CkHEEtDzAvBlW0BYw==", "dev": true, "funding": { "type": "opencollective", @@ -6961,12 +7115,12 @@ } }, "node_modules/@storybook/core": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.4.7.tgz", - "integrity": "sha512-7Z8Z0A+1YnhrrSXoKKwFFI4gnsLbWzr8fnDCU6+6HlDukFYh8GHRcZ9zKfqmy6U3hw2h8H5DrHsxWfyaYUUOoA==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.5.0.tgz", + "integrity": "sha512-apborO6ynns7SeydBSqE9o0zT6JSU+VY4gLFPJROGcconvSW4bS5xtJCsgjlulceyWVxepFHGXl4jEZw+SktXA==", "dev": true, "dependencies": { - "@storybook/csf": "^0.1.11", + "@storybook/csf": "0.1.12", "better-opn": "^3.0.2", "browser-assert": "^1.2.1", "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0", @@ -6992,13 +7146,11 @@ } }, "node_modules/@storybook/core-webpack": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.4.7.tgz", - "integrity": "sha512-Tj+CjQLpFyBJxhhMms+vbPT3+gTRAiQlrhY3L1IEVwBa3wtRMS0qjozH26d1hK4G6mUIEdwu13L54HMU/w33Sg==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-8.5.0.tgz", + "integrity": "sha512-bJAcF9TwNO2qNa7Jef4h5U9ka4399HDiHiQec1AxdqUIy/2zfbetgV6+2Fr5mtejPqJgbs7kXNGErI+fFByLGg==", "dev": true, - "license": "MIT", "dependencies": { - "@types/node": "^22.0.0", "ts-dedent": "^2.0.0" }, "funding": { @@ -7006,24 +7158,23 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.4.7" + "storybook": "^8.5.0" } }, "node_modules/@storybook/csf": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.11.tgz", - "integrity": "sha512-dHYFQH3mA+EtnCkHXzicbLgsvzYjcDJ1JWsogbItZogkPHgSJM/Wr71uMkcvw8v9mmCyP4NpXJuu6bPoVsOnzg==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.12.tgz", + "integrity": "sha512-9/exVhabisyIVL0VxTCxo01Tdm8wefIXKXfltAPTSr8cbLn5JAxGQ6QV3mjdecLGEOucfoVhAKtJfVHxEK1iqw==", "dev": true, "dependencies": { "type-fest": "^2.19.0" } }, "node_modules/@storybook/csf-plugin": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.4.7.tgz", - "integrity": "sha512-Fgogplu4HImgC+AYDcdGm1rmL6OR1rVdNX1Be9C/NEXwOCpbbBwi0BxTf/2ZxHRk9fCeaPEcOdP5S8QHfltc1g==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.5.0.tgz", + "integrity": "sha512-cs6ogviNyLG1h9J8Sb47U3DqIrQmn2EHm4ta3fpCeV3ABbrMgbzYyxtmybz4g/AwlDgjAZAt6PPcXkfCJ6p2CQ==", "dev": true, - "license": "MIT", "dependencies": { "unplugin": "^1.3.1" }, @@ -7032,7 +7183,7 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "storybook": "^8.4.7" + "storybook": "^8.5.0" } }, "node_modules/@storybook/global": { @@ -7046,7 +7197,6 @@ "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.3.0.tgz", "integrity": "sha512-Nz/UzeYQdUZUhacrPyfkiiysSjydyjgg/p0P9HxB4p/WaJUUjMAcaoaLgy3EXx61zZJ3iD36WPuDkZs5QYrA0A==", "dev": true, - "license": "MIT", "engines": { "node": ">=14.0.0" }, @@ -7055,12 +7205,28 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" } }, + "node_modules/@storybook/instrumenter": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.5.0.tgz", + "integrity": "sha512-eZ/UY6w4U2vay+wX7QVwKiRoyMzZscuv6v4k4r8BlmHPFWbhiZDO9S2GsG16UkyKnrQrYk432he70n7hn1Xvmg==", + "dev": true, + "dependencies": { + "@storybook/global": "^5.0.0", + "@vitest/utils": "^2.1.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.5.0" + } + }, "node_modules/@storybook/manager-api": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.4.7.tgz", - "integrity": "sha512-ELqemTviCxAsZ5tqUz39sDmQkvhVAvAgiplYy9Uf15kO0SP2+HKsCMzlrm2ue2FfkUNyqbDayCPPCB0Cdn/mpQ==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.5.0.tgz", + "integrity": "sha512-Ildriueo3eif4M+gMlMxu/mrBIbAnz8+oesmQJKdzZfe/U9eQTI9OUqJsxx/IVBmdzQ3ySsgNmzj5VweRkse4A==", "dev": true, - "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" @@ -7070,16 +7236,14 @@ } }, "node_modules/@storybook/preset-react-webpack": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.4.7.tgz", - "integrity": "sha512-geTSBKyrBagVihil5MF7LkVFynbfHhCinvnbCZZqXW7M1vgcxvatunUENB+iV8eWg/0EJ+8O7scZL+BAxQ/2qg==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-8.5.0.tgz", + "integrity": "sha512-KJwVcQVYQWuMT5QUF06be60UuBfazBIO+90erfoYoIx0UwOxKMVnQz0HfG2JMc4EIoNLIl0/cm5mb2k4BWyhbA==", "dev": true, - "license": "MIT", "dependencies": { - "@storybook/core-webpack": "8.4.7", - "@storybook/react": "8.4.7", + "@storybook/core-webpack": "8.5.0", + "@storybook/react": "8.5.0", "@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.0c3f3b7.0", - "@types/node": "^22.0.0", "@types/semver": "^7.3.4", "find-up": "^5.0.0", "magic-string": "^0.30.5", @@ -7099,7 +7263,7 @@ "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.4.7" + "storybook": "^8.5.0" }, "peerDependenciesMeta": { "typescript": { @@ -7108,9 +7272,9 @@ } }, "node_modules/@storybook/preview-api": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.4.7.tgz", - "integrity": "sha512-0QVQwHw+OyZGHAJEXo6Knx+6/4er7n2rTDE5RYJ9F2E2Lg42E19pfdLlq2Jhoods2Xrclo3wj6GWR//Ahi39Eg==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.5.0.tgz", + "integrity": "sha512-g0XbD54zMUkl6bpuA7qEBCE9rW1QV6KKmwkO4bkxMOJcMke3x9l00JTaYn7Un8wItjXiS3BIG15B6mnfBG7fng==", "dev": true, "funding": { "type": "opencollective", @@ -7121,18 +7285,17 @@ } }, "node_modules/@storybook/react": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/react/-/react-8.4.7.tgz", - "integrity": "sha512-nQ0/7i2DkaCb7dy0NaT95llRVNYWQiPIVuhNfjr1mVhEP7XD090p0g7eqUmsx8vfdHh2BzWEo6CoBFRd3+EXxw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/react/-/react-8.5.0.tgz", + "integrity": "sha512-/jbkmGGc95N7KduIennL/k8grNTP5ye/YBnkcS4TbF7uDWBtKy3/Wqvx5BIlFXq3qeUnZJ8YtZc0lPIYeCY8XQ==", "dev": true, - "license": "MIT", "dependencies": { - "@storybook/components": "8.4.7", + "@storybook/components": "8.5.0", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "8.4.7", - "@storybook/preview-api": "8.4.7", - "@storybook/react-dom-shim": "8.4.7", - "@storybook/theming": "8.4.7" + "@storybook/manager-api": "8.5.0", + "@storybook/preview-api": "8.5.0", + "@storybook/react-dom-shim": "8.5.0", + "@storybook/theming": "8.5.0" }, "engines": { "node": ">=18.0.0" @@ -7142,10 +7305,10 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "@storybook/test": "8.4.7", + "@storybook/test": "8.5.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.4.7", + "storybook": "^8.5.0", "typescript": ">= 4.2.x" }, "peerDependenciesMeta": { @@ -7162,7 +7325,6 @@ "resolved": "https://registry.npmjs.org/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.6--canary.9.0c3f3b7.0.tgz", "integrity": "sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^4.1.1", "endent": "^2.0.1", @@ -7178,11 +7340,10 @@ } }, "node_modules/@storybook/react-dom-shim": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.4.7.tgz", - "integrity": "sha512-6bkG2jvKTmWrmVzCgwpTxwIugd7Lu+2btsLAqhQSzDyIj2/uhMNp8xIMr/NBDtLgq3nomt9gefNa9xxLwk/OMg==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.5.0.tgz", + "integrity": "sha512-7P8xg4FiuFpM6kQOzZynno+0zyLVs8NgsmRK58t3JRZXbda1tzlxTXzvqx4hUevvbPJGjmrB0F3xTFH+8Otnvw==", "dev": true, - "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" @@ -7190,20 +7351,18 @@ "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.4.7" + "storybook": "^8.5.0" } }, "node_modules/@storybook/react-webpack5": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/react-webpack5/-/react-webpack5-8.4.7.tgz", - "integrity": "sha512-T9GLqlsP4It4El7cC8rSkBPRWvORAsTDULeWlO36RST2TrYnmBOUytsi22mk7cAAAVhhD6rTrs1YdqWRMpfa1w==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/react-webpack5/-/react-webpack5-8.5.0.tgz", + "integrity": "sha512-L2KIR458Q2+5VOOh0wf84vla3gSsuq9C/266GmHZovlDClVlnaQTg8lc8ug52K2+rOChdz8MQqZjGO+Bg0OvLw==", "dev": true, - "license": "MIT", "dependencies": { - "@storybook/builder-webpack5": "8.4.7", - "@storybook/preset-react-webpack": "8.4.7", - "@storybook/react": "8.4.7", - "@types/node": "^22.0.0" + "@storybook/builder-webpack5": "8.5.0", + "@storybook/preset-react-webpack": "8.5.0", + "@storybook/react": "8.5.0" }, "engines": { "node": ">=18.0.0" @@ -7215,7 +7374,7 @@ "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", - "storybook": "^8.4.7", + "storybook": "^8.5.0", "typescript": ">= 4.2.x" }, "peerDependenciesMeta": { @@ -7224,10 +7383,33 @@ } } }, + "node_modules/@storybook/test": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/test/-/test-8.5.0.tgz", + "integrity": "sha512-M/DdPlI6gwL7NGkK5o7GYjdEBp95AsFEUtW29zQfnVIAngYugzi3nIuM/XkQHunidVdAZCYjw2s2Yhhsx/m9sw==", + "dev": true, + "dependencies": { + "@storybook/csf": "0.1.12", + "@storybook/global": "^5.0.0", + "@storybook/instrumenter": "8.5.0", + "@testing-library/dom": "10.4.0", + "@testing-library/jest-dom": "6.5.0", + "@testing-library/user-event": "14.5.2", + "@vitest/expect": "2.0.5", + "@vitest/spy": "2.0.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.5.0" + } + }, "node_modules/@storybook/theming": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.4.7.tgz", - "integrity": "sha512-99rgLEjf7iwfSEmdqlHkSG3AyLcK0sfExcr0jnc6rLiAkBhzuIsvcHjjUwkR210SOCgXqBPW0ZA6uhnuyppHLw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.5.0.tgz", + "integrity": "sha512-591LbOj/HMmHYUfLgrMerxhF1A9mY61HWKxcRpB6xxalc1Xw1kRtQ49DcwuTXnUu9ktBB3nuOzPNPQPFSh/7PQ==", "dev": true, "funding": { "type": "opencollective", @@ -7237,12 +7419,185 @@ "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, + "node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/@testing-library/dom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@testing-library/dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.5.0.tgz", + "integrity": "sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA==", + "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + }, + "node_modules/@testing-library/jest-dom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/user-event": { + "version": "14.5.2", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", + "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", + "dev": true, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, - "license": "MIT", "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", @@ -7256,7 +7611,6 @@ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.0.0" } @@ -7266,7 +7620,6 @@ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, - "license": "MIT", "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" @@ -7277,7 +7630,6 @@ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.20.7" } @@ -7372,8 +7724,7 @@ "version": "0.0.9", "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.9.tgz", "integrity": "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/eslint": { "version": "9.6.1", @@ -7452,8 +7803,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/http-errors": { "version": "2.0.4", @@ -7497,8 +7847,7 @@ "version": "2.0.13", "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/mime": { "version": "1.3.5", @@ -7547,8 +7896,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/pg": { "version": "8.6.1", @@ -7601,8 +7949,7 @@ "version": "1.20.6", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", "integrity": "sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/retry": { "version": "0.12.2", @@ -7614,8 +7961,7 @@ "version": "7.5.8", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/send": { "version": "0.17.4", @@ -7701,8 +8047,7 @@ "version": "9.0.8", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@types/ws": { "version": "8.5.12", @@ -7728,134 +8073,430 @@ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, - "node_modules/@webassemblyjs/ast": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", - "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", + "node_modules/@vitest/expect": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.0.5.tgz", + "integrity": "sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==", + "dev": true, "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + "@vitest/spy": "2.0.5", + "@vitest/utils": "2.0.5", + "chai": "^5.1.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", - "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "node_modules/@vitest/expect/node_modules/@vitest/pretty-format": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.0.5.tgz", + "integrity": "sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==", + "dev": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.6", - "@webassemblyjs/helper-api-error": "1.11.6", - "@xtuc/long": "4.2.2" + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", - "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", + "node_modules/@vitest/expect/node_modules/@vitest/utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.0.5.tgz", + "integrity": "sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==", + "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/wasm-gen": "1.12.1" - } + "@vitest/pretty-format": "2.0.5", + "estree-walker": "^3.0.3", + "loupe": "^3.1.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/expect/node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@vitest/expect/node_modules/chai": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", + "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", + "dev": true, + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@vitest/expect/node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "engines": { + "node": ">= 16" + } + }, + "node_modules/@vitest/expect/node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@vitest/expect/node_modules/loupe": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", + "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "dev": true + }, + "node_modules/@vitest/expect/node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "dev": true, + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.2.tgz", + "integrity": "sha512-Hr09FoBf0jlwwSyzIF4Xw31OntpO3XtZjkccpcBf8FeVW3tpiyKlkeUzxS/txzHqpUCNIX157NaTySxedyZLvA==", + "dev": true, + "peer": true, + "dependencies": { + "@vitest/spy": "3.0.2", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/@vitest/spy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.2.tgz", + "integrity": "sha512-8mI2iUn+PJFMT44e3ISA1R+K6ALVs47W6eriDTfXe6lFqlflID05MB4+rIFhmDSLBj8iBsZkzBYlgSkinxLzSQ==", + "dev": true, + "peer": true, + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.8.tgz", + "integrity": "sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==", + "dev": true, + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.2.tgz", + "integrity": "sha512-GHEsWoncrGxWuW8s405fVoDfSLk6RF2LCXp6XhevbtDjdDme1WV/eNmUueDfpY1IX3MJaCRelVCEXsT9cArfEg==", + "dev": true, + "peer": true, + "dependencies": { + "@vitest/utils": "3.0.2", + "pathe": "^2.0.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/@vitest/pretty-format": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.2.tgz", + "integrity": "sha512-yBohcBw/T/p0/JRgYD+IYcjCmuHzjC3WLAKsVE4/LwiubzZkE8N49/xIQ/KGQwDRA8PaviF8IRO8JMWMngdVVQ==", + "dev": true, + "peer": true, + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/@vitest/utils": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.2.tgz", + "integrity": "sha512-Qu01ZYZlgHvDP02JnMBRpX43nRaZtNpIzw3C1clDXmn8eakgX6iQVGzTQ/NjkIr64WD8ioqOjkaYRVvHQI5qiw==", + "dev": true, + "peer": true, + "dependencies": { + "@vitest/pretty-format": "3.0.2", + "loupe": "^3.1.2", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/loupe": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", + "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "dev": true, + "peer": true + }, + "node_modules/@vitest/runner/node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.2.tgz", + "integrity": "sha512-h9s67yD4+g+JoYG0zPCo/cLTabpDqzqNdzMawmNPzDStTiwxwkyYM1v5lWE8gmGv3SVJ2DcxA2NpQJZJv9ym3g==", + "dev": true, + "peer": true, + "dependencies": { + "@vitest/pretty-format": "3.0.2", + "magic-string": "^0.30.17", + "pathe": "^2.0.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot/node_modules/@vitest/pretty-format": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.2.tgz", + "integrity": "sha512-yBohcBw/T/p0/JRgYD+IYcjCmuHzjC3WLAKsVE4/LwiubzZkE8N49/xIQ/KGQwDRA8PaviF8IRO8JMWMngdVVQ==", + "dev": true, + "peer": true, + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot/node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@vitest/spy": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.0.5.tgz", + "integrity": "sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==", + "dev": true, + "dependencies": { + "tinyspy": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.8.tgz", + "integrity": "sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==", + "dev": true, + "dependencies": { + "@vitest/pretty-format": "2.1.8", + "loupe": "^3.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils/node_modules/loupe": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", + "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "dev": true + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", - "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "license": "MIT", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", - "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "license": "Apache-2.0", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", - "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/helper-wasm-section": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-opt": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1", - "@webassemblyjs/wast-printer": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", - "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", - "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-buffer": "1.12.1", - "@webassemblyjs/wasm-gen": "1.12.1", - "@webassemblyjs/wasm-parser": "1.12.1" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", - "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", - "@webassemblyjs/helper-api-error": "1.11.6", - "@webassemblyjs/helper-wasm-bytecode": "1.11.6", - "@webassemblyjs/ieee754": "1.11.6", - "@webassemblyjs/leb128": "1.11.6", - "@webassemblyjs/utf8": "1.11.6" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", - "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "license": "MIT", "dependencies": { - "@webassemblyjs/ast": "1.12.1", + "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, @@ -7911,12 +8552,14 @@ "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "license": "BSD-3-Clause" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "license": "Apache-2.0" }, "node_modules/a-sync-waterfall": { "version": "1.0.1", @@ -8237,13 +8880,14 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, "engines": { "node": ">= 0.4" @@ -8351,15 +8995,16 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -8385,19 +9030,19 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, + "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { "node": ">= 0.4" @@ -8468,6 +9113,16 @@ "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/async-value": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/async-value/-/async-value-1.2.2.tgz", @@ -8973,8 +9628,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true, - "license": "ISC" + "dev": true }, "node_modules/brace-expansion": { "version": "1.1.11", @@ -9109,6 +9763,16 @@ "node": ">= 0.8" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, "node_modules/cachedir": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", @@ -9134,15 +9798,15 @@ } }, "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" }, "engines": { "node": ">= 0.4" @@ -9151,26 +9815,84 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", - "dev": true - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "license": "MIT", "dependencies": { - "pascal-case": "^3.1.2", + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "dev": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dependencies": { + "pascal-case": "^3.1.2", "tslib": "^2.0.3" } }, @@ -9223,7 +9945,6 @@ "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -9502,21 +10223,24 @@ } }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/cliui/node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -9525,7 +10249,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -9540,7 +10264,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -9552,7 +10276,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -9905,8 +10629,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/constate": { "version": "3.3.2", @@ -10051,7 +10774,6 @@ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, - "license": "MIT", "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -10154,7 +10876,6 @@ "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.0.1", @@ -10201,7 +10922,6 @@ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">= 6" }, @@ -10209,6 +10929,12 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -10623,14 +11349,15 @@ } }, "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10640,29 +11367,31 @@ } }, "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/inspect-js" } }, "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" }, @@ -10726,8 +11455,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/deep-eql": { "version": "4.1.4", @@ -11034,12 +11762,17 @@ "node": ">=6.0.0" } }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, "node_modules/dom-converter": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", "dev": true, - "license": "MIT", "dependencies": { "utila": "~0.4" } @@ -11058,7 +11791,6 @@ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "dev": true, - "license": "MIT", "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", @@ -11073,7 +11805,6 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", "dev": true, - "license": "BSD-2-Clause", "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -11094,7 +11825,6 @@ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "domelementtype": "^2.2.0" }, @@ -11110,7 +11840,6 @@ "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", @@ -11140,6 +11869,20 @@ "url": "https://dotenvx.com" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -11212,9 +11955,10 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/elastic-apm-node": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/elastic-apm-node/-/elastic-apm-node-4.9.0.tgz", - "integrity": "sha512-VUbrahqHmqpfwGHtUysWJ7aeCIUm61hAw8tSu0gE9AYdriVSPod4Ki11X4K8sBri0bIc/FTHxOrg7kudhGoqHQ==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/elastic-apm-node/-/elastic-apm-node-4.11.0.tgz", + "integrity": "sha512-QXYjOysgjjASJewDK40iUq8W4fdn/QsJtvl4wsxbSncRfcJCSYPaqfWbxN6YAMpOU0vLp5kBj6tdWPBMTaYrMg==", + "license": "BSD-2-Clause", "dependencies": { "@elastic/ecs-pino-format": "^1.5.0", "@opentelemetry/api": "^1.4.1", @@ -11234,7 +11978,7 @@ "fast-safe-stringify": "^2.0.7", "fast-stream-to-buffer": "^1.0.0", "http-headers": "^3.0.2", - "import-in-the-middle": "1.11.3", + "import-in-the-middle": "1.12.0", "json-bigint": "^1.0.0", "lru-cache": "10.2.0", "measured-reporting": "^1.51.1", @@ -11364,7 +12108,6 @@ "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", "integrity": "sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==", "dev": true, - "license": "MIT", "dependencies": { "dedent": "^0.7.0", "fast-json-parse": "^1.0.3", @@ -11497,57 +12240,63 @@ } }, "node_modules/es-abstract": { - "version": "1.23.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.5.tgz", - "integrity": "sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==", + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", "dev": true, + "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", + "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", - "gopd": "^1.0.1", + "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", + "is-data-view": "^1.0.2", + "is-regex": "^1.2.1", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.3", "object-keys": "^1.1.1", - "object.assign": "^4.1.5", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.3", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" }, "engines": { "node": ">= 0.4" @@ -11557,12 +12306,10 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -11576,35 +12323,37 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz", - "integrity": "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", + "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", + "get-intrinsic": "^1.2.6", "globalthis": "^1.0.4", - "gopd": "^1.0.1", + "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.3", - "safe-array-concat": "^1.1.2" + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-module-lexer": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", + "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==" }, "node_modules/es-object-atoms": { "version": "1.0.0", @@ -11618,14 +12367,16 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -11641,14 +12392,15 @@ } }, "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -11664,9 +12416,9 @@ "dev": true }, "node_modules/esbuild": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", - "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", + "version": "0.24.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", + "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", "dev": true, "hasInstallScript": true, "bin": { @@ -11676,30 +12428,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.0", - "@esbuild/android-arm": "0.24.0", - "@esbuild/android-arm64": "0.24.0", - "@esbuild/android-x64": "0.24.0", - "@esbuild/darwin-arm64": "0.24.0", - "@esbuild/darwin-x64": "0.24.0", - "@esbuild/freebsd-arm64": "0.24.0", - "@esbuild/freebsd-x64": "0.24.0", - "@esbuild/linux-arm": "0.24.0", - "@esbuild/linux-arm64": "0.24.0", - "@esbuild/linux-ia32": "0.24.0", - "@esbuild/linux-loong64": "0.24.0", - "@esbuild/linux-mips64el": "0.24.0", - "@esbuild/linux-ppc64": "0.24.0", - "@esbuild/linux-riscv64": "0.24.0", - "@esbuild/linux-s390x": "0.24.0", - "@esbuild/linux-x64": "0.24.0", - "@esbuild/netbsd-x64": "0.24.0", - "@esbuild/openbsd-arm64": "0.24.0", - "@esbuild/openbsd-x64": "0.24.0", - "@esbuild/sunos-x64": "0.24.0", - "@esbuild/win32-arm64": "0.24.0", - "@esbuild/win32-ia32": "0.24.0", - "@esbuild/win32-x64": "0.24.0" + "@esbuild/aix-ppc64": "0.24.2", + "@esbuild/android-arm": "0.24.2", + "@esbuild/android-arm64": "0.24.2", + "@esbuild/android-x64": "0.24.2", + "@esbuild/darwin-arm64": "0.24.2", + "@esbuild/darwin-x64": "0.24.2", + "@esbuild/freebsd-arm64": "0.24.2", + "@esbuild/freebsd-x64": "0.24.2", + "@esbuild/linux-arm": "0.24.2", + "@esbuild/linux-arm64": "0.24.2", + "@esbuild/linux-ia32": "0.24.2", + "@esbuild/linux-loong64": "0.24.2", + "@esbuild/linux-mips64el": "0.24.2", + "@esbuild/linux-ppc64": "0.24.2", + "@esbuild/linux-riscv64": "0.24.2", + "@esbuild/linux-s390x": "0.24.2", + "@esbuild/linux-x64": "0.24.2", + "@esbuild/netbsd-arm64": "0.24.2", + "@esbuild/netbsd-x64": "0.24.2", + "@esbuild/openbsd-arm64": "0.24.2", + "@esbuild/openbsd-x64": "0.24.2", + "@esbuild/sunos-x64": "0.24.2", + "@esbuild/win32-arm64": "0.24.2", + "@esbuild/win32-ia32": "0.24.2", + "@esbuild/win32-x64": "0.24.2" } }, "node_modules/esbuild-register": { @@ -11792,12 +12545,12 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.0.1.tgz", + "integrity": "sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw==", "dev": true, "bin": { - "eslint-config-prettier": "bin/cli.js" + "eslint-config-prettier": "build/bin/cli.js" }, "peerDependencies": { "eslint": ">=7.0.0" @@ -12145,28 +12898,29 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.37.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", - "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", + "version": "7.37.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", + "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", "dev": true, + "license": "MIT", "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.2", + "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.1.0", + "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.8", "object.fromentries": "^2.0.8", - "object.values": "^1.2.0", + "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.11", + "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "engines": { @@ -12507,6 +13261,15 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -12586,6 +13349,16 @@ "node": ">=4" } }, + "node_modules/expect-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz", + "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/express": { "version": "4.21.2", "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", @@ -12831,8 +13604,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", @@ -13150,7 +13922,6 @@ "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-8.0.0.tgz", "integrity": "sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==", "dev": true, - "license": "MIT", "dependencies": { "@babel/code-frame": "^7.16.7", "chalk": "^4.1.2", @@ -13179,7 +13950,6 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -13195,7 +13965,6 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -13212,7 +13981,6 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -13227,7 +13995,6 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -13237,7 +14004,6 @@ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, - "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -13256,7 +14022,6 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -13367,8 +14132,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", - "dev": true, - "license": "Unlicense" + "dev": true }, "node_modules/fs.realpath": { "version": "1.0.0", @@ -13398,15 +14162,18 @@ } }, "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { "node": ">= 0.4" @@ -13481,15 +14248,21 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -13507,6 +14280,19 @@ "node": ">=8.0.0" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stdin": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", @@ -13534,14 +14320,15 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -13710,11 +14497,12 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13747,9 +14535,9 @@ "integrity": "sha512-BlJsYnC0HJomBNCiBm2oQCqgbvP7vaA06XyJ2NocpWM4vFcK/AxAC/7gAU6iCjP3LVhyobR+o2MTFFGozPIE6A==" }, "node_modules/govuk-frontend": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-5.7.1.tgz", - "integrity": "sha512-jF1cq5rn57kxZmJRprUZhTQ31zaBBK4b5AyeJaPX3Yhg22lk90Mx/dQLvOk/ycV3wM7e0y+s4IPvb2fFaPlCGg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/govuk-frontend/-/govuk-frontend-5.8.0.tgz", + "integrity": "sha512-6l3f/YhDUCWjpmSW3CL95Hg8B+ZLzTf2WYo25ZtCs2Lb8UIzxxxFI8LxG7Ey/z04UuPhUunqFhTwSkQyJ69XbQ==", "engines": { "node": ">= 4.2.0" } @@ -13860,10 +14648,14 @@ } }, "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13888,9 +14680,14 @@ } }, "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -13899,9 +14696,10 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -14261,7 +15059,6 @@ "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz", "integrity": "sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==", "dev": true, - "license": "MIT", "dependencies": { "@types/html-minifier-terser": "^6.0.0", "html-minifier-terser": "^6.0.2", @@ -14294,7 +15091,6 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "dev": true, - "license": "MIT", "engines": { "node": ">= 12" } @@ -14304,7 +15100,6 @@ "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", "dev": true, - "license": "MIT", "dependencies": { "camel-case": "^4.1.2", "clean-css": "^5.2.2", @@ -14333,7 +15128,6 @@ "url": "https://github.com/sponsors/fb55" } ], - "license": "MIT", "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.0.0", @@ -14346,7 +15140,6 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", "dev": true, - "license": "BSD-2-Clause", "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } @@ -14624,9 +15417,9 @@ "dev": true }, "node_modules/image-minimizer-webpack-plugin": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/image-minimizer-webpack-plugin/-/image-minimizer-webpack-plugin-4.1.1.tgz", - "integrity": "sha512-SKOcRpciu2diRH71k+YW9o3Sih8lrS1BtLtyg1dxcv3Dt/RpSwGZJ1BSfFXglK7RS0ZfNJMF29UMjDFGcB7C8Q==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/image-minimizer-webpack-plugin/-/image-minimizer-webpack-plugin-4.1.3.tgz", + "integrity": "sha512-yJvYlLAZosu2iqlGF81BEUHfUiWRPD05krtoax9Ffst3Yzbn3X7p04VXambwlx3uhbSwH/BeyM5+bJHQksnuyw==", "dev": true, "dependencies": { "schema-utils": "^4.2.0", @@ -14695,9 +15488,10 @@ } }, "node_modules/import-in-the-middle": { - "version": "1.11.3", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.11.3.tgz", - "integrity": "sha512-tNpKEb4AjZrCyrxi+Eyu43h5ig0O8ZRFSXPHh/00/o+4P4pKzVEW/m5lsVtsAT7fCIgmQOAPjdqecGDsBXRxsw==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.12.0.tgz", + "integrity": "sha512-yAgSE7GmtRcu4ZUSFX/4v69UGXwugFFSdIQJ14LHPOPPQrWv8Y7O9PHsw8Ovk7bKCLe4sjXMbZFqGFcLHpZ89w==", + "license": "Apache-2.0", "dependencies": { "acorn": "^8.8.2", "acorn-import-attributes": "^1.9.5", @@ -14752,6 +15546,15 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -14791,14 +15594,15 @@ } }, "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -14868,13 +15672,15 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -14889,12 +15695,17 @@ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -14904,12 +15715,16 @@ } }, "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-bigints": "^1.0.1" + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -14927,13 +15742,14 @@ } }, "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", + "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -14975,11 +15791,14 @@ } }, "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, + "license": "MIT", "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" }, "engines": { @@ -14990,12 +15809,14 @@ } }, "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -15037,12 +15858,13 @@ } }, "node_modules/is-finalizationregistry": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.0.tgz", - "integrity": "sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -15161,18 +15983,7 @@ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -15201,12 +16012,14 @@ } }, "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -15274,13 +16087,16 @@ "dev": true }, "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -15294,6 +16110,7 @@ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -15302,12 +16119,13 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -15328,12 +16146,14 @@ } }, "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -15343,12 +16163,15 @@ } }, "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -15358,12 +16181,13 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, + "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -15394,6 +16218,7 @@ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -15402,25 +16227,30 @@ } }, "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", + "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -15457,7 +16287,8 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", @@ -15555,15 +16386,6 @@ "node": ">=6" } }, - "node_modules/istanbul-lib-processinfo/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/istanbul-lib-processinfo/node_modules/p-map": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", @@ -15672,16 +16494,18 @@ } }, "node_modules/iterator.prototype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", - "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", "dev": true, + "license": "MIT", "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -16193,21 +17017,22 @@ } }, "node_modules/lint-staged": { - "version": "15.2.11", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.11.tgz", - "integrity": "sha512-Ev6ivCTYRTGs9ychvpVw35m/bcNDuBN+mnTeObCL5h+boS5WzBEC6LHI4I9F/++sZm1m+J2LEiy0gxL/R9TBqQ==", - "dev": true, - "dependencies": { - "chalk": "~5.3.0", - "commander": "~12.1.0", - "debug": "~4.4.0", - "execa": "~8.0.1", - "lilconfig": "~3.1.3", - "listr2": "~8.2.5", - "micromatch": "~4.0.8", - "pidtree": "~0.6.0", - "string-argv": "~0.3.2", - "yaml": "~2.6.1" + "version": "15.4.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.4.3.tgz", + "integrity": "sha512-FoH1vOeouNh1pw+90S+cnuoFwRfUD9ijY2GKy5h7HS3OR7JVir2N2xrsa0+Twc1B7cW72L+88geG5cW4wIhn7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.4.1", + "commander": "^13.1.0", + "debug": "^4.4.0", + "execa": "^8.0.1", + "lilconfig": "^3.1.3", + "listr2": "^8.2.5", + "micromatch": "^4.0.8", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.7.0" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -16247,9 +17072,9 @@ } }, "node_modules/lint-staged/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "dev": true, "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" @@ -16290,10 +17115,11 @@ } }, "node_modules/lint-staged/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=18" } @@ -16694,15 +17520,6 @@ "node": ">=6" } }, - "node_modules/listr2/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/listr2/node_modules/p-map": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", @@ -16843,6 +17660,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "dev": true + }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -17123,12 +17946,20 @@ "yallist": "^3.0.2" } }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, "node_modules/magic-string": { - "version": "0.30.15", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.15.tgz", - "integrity": "sha512-zXeaYRgZ6ldS1RJJUrMrYgNJ4fdwnyI6tVqoiIhyCyv5IVTK9BU8Ic2l253GGETQHxI4HNUwhJ3fjDhKqEoaAw==", + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } @@ -17152,8 +17983,7 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/mapcap": { "version": "1.0.0", @@ -17185,6 +18015,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/md5": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", @@ -17523,7 +18362,6 @@ "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", "dev": true, - "license": "Unlicense", "dependencies": { "fs-monkey": "^1.0.4" }, @@ -17536,7 +18374,6 @@ "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", "dev": true, - "license": "MIT", "dependencies": { "map-or-similar": "^1.5.0" } @@ -18241,7 +19078,6 @@ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -18317,10 +19153,11 @@ } }, "node_modules/mocha": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.0.1.tgz", - "integrity": "sha512-+3GkODfsDG71KSCQhc4IekSW+ItCK/kiez1Z28ksWvYhKXV/syxMlerR/sC7whDp7IyreZ4YxceMLdTs5hQE8A==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz", + "integrity": "sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-colors": "^4.1.3", "browser-stdout": "^1.3.1", @@ -18339,8 +19176,8 @@ "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" }, "bin": { @@ -18937,8 +19774,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/node-addon-api": { "version": "7.1.1", @@ -19150,7 +19986,6 @@ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0" }, @@ -19359,15 +20194,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/nyc/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/nyc/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -19536,14 +20362,17 @@ } }, "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" }, "engines": { @@ -19599,12 +20428,14 @@ } }, "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, @@ -19619,8 +20450,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.5.tgz", "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==", - "dev": true, - "license": "ISC" + "dev": true }, "node_modules/obuf": { "version": "1.1.2", @@ -19802,6 +20632,24 @@ "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", "dev": true }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -19984,8 +20832,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/path-exists": { "version": "4.0.0", @@ -20055,6 +20902,13 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.2.tgz", + "integrity": "sha512-15Ztpk+nov8DR524R4BF7uEuzESgzUEAV4Ah7CUMNGXdE5ELuvxElxGXndBl32vMSsWa1jpNf22Z+Er3sKwq+w==", + "dev": true, + "peer": true + }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -20107,9 +20961,9 @@ } }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -20361,9 +21215,9 @@ } }, "node_modules/postcss": { - "version": "8.4.45", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.45.tgz", - "integrity": "sha512-7KTLTdzdZZYscUc65XmjFiB73vBhBfbPztCYdUNvlaso9PrzjzcmjqBPR0lNGkcVlcO4BjiO5rK/qNz+XAen1Q==", + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", + "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", "funding": [ { "type": "opencollective", @@ -20379,9 +21233,9 @@ } ], "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -20415,41 +21269,6 @@ "postcss": "^8.0.0" } }, - "node_modules/postcss-cli/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/postcss-cli/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/postcss-cli/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/postcss-cli/node_modules/globby": { "version": "14.0.2", "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", @@ -20480,58 +21299,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/postcss-cli/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/postcss-cli/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/postcss-cli/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/postcss-cli/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "engines": { - "node": ">=12" - } - }, "node_modules/postcss-load-config": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-5.1.0.tgz", @@ -20886,15 +21653,55 @@ "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", "dev": true, - "license": "MIT", "dependencies": { "lodash": "^4.17.20", "renderkid": "^3.0.0" } }, - "node_modules/pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", "engines": { "node": ">= 0.8" @@ -21065,11 +21872,12 @@ } }, "node_modules/qs": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz", - "integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -21182,7 +21990,6 @@ "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-7.1.0.tgz", "integrity": "sha512-APPU8HB2uZnpl6Vt/+0AFoVYgSRtfiP6FLrZgPPTDmqSb2R4qZRbgd0A3VzIFxDt5e+Fozjx79WjLWnF69DK8g==", "dev": true, - "license": "MIT", "dependencies": { "@babel/core": "^7.18.9", "@babel/traverse": "^7.18.9", @@ -21204,7 +22011,6 @@ "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", "dev": true, - "license": "MIT", "peerDependencies": { "typescript": ">= 4.3.x" } @@ -21222,9 +22028,9 @@ } }, "node_modules/react-error-boundary": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-4.1.2.tgz", - "integrity": "sha512-GQDxZ5Jd+Aq/qUxbCm1UtzmL/s++V7zKgE8yMktJiCQXCCFZnMZh9ng+6/Ne6PjNSXH0L9CjeOEREfRnq6Duag==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-5.0.0.tgz", + "integrity": "sha512-tnjAxG+IkpLephNcePNA7v6F/QpWLH8He65+DmedchDwg162JZqx4NmbXj0mlAYVVEd81OW7aFhmbsScYfiAFQ==", "dependencies": { "@babel/runtime": "^7.12.5" }, @@ -21313,9 +22119,9 @@ } }, "node_modules/react-router": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.0.tgz", - "integrity": "sha512-VcFhWqkNIcojDRYaUO8qV0Jib52s9ULpCp3nkBbmrvtoCVFRp6tmk3tJ2w9BZauVctA1YRnJlFYDn9iJRuCpGA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.1.tgz", + "integrity": "sha512-39sXJkftkKWRZ2oJtHhCxmoCrBCULr/HAH4IT5DHlgu/Q0FCPV0S4Lx+abjDTx/74xoZzNYDYbOZWlJjruyuDQ==", "dependencies": { "@types/cookie": "^0.6.0", "cookie": "^1.0.1", @@ -21336,11 +22142,11 @@ } }, "node_modules/react-router-dom": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.1.0.tgz", - "integrity": "sha512-F4/nYBC9e4s0/ZjxM8GkZ9a68DpX76LN1a9W9mfPl2GfbDJ9/vzJro6MThNR5qGBH6KkgcK1BziyEzXhHV46Xw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.1.1.tgz", + "integrity": "sha512-vSrQHWlJ5DCfyrhgo0k6zViOe9ToK8uT5XGSmnuC2R3/g261IdIMpZVqfjD6vWSXdnf5Czs4VA/V60oVR6/jnA==", "dependencies": { - "react-router": "7.1.0" + "react-router": "7.1.1" }, "engines": { "node": ">=20.0.0" @@ -21367,9 +22173,9 @@ } }, "node_modules/react-to-print": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/react-to-print/-/react-to-print-3.0.2.tgz", - "integrity": "sha512-FS/Z4LLq0bgWaxd7obygFQ8yRFdKW74iE8fIVjFFsPJWIXmuL8CIO+4me1Hj44lrlxQ00gscSNb3BRM8olbwXg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-to-print/-/react-to-print-3.0.4.tgz", + "integrity": "sha512-33opQsuskUs0UyK1OLAAN2Ziy1GPneeTLvypRYjT6E9bl2NDxZtEr0KYMOxszcBY0bs+XlWOkGNlyla55GQjuA==", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ~19" } @@ -21558,6 +22364,31 @@ "node": ">= 10.13.0" } }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redent/node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/redis": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/redis/-/redis-4.7.0.tgz", @@ -21602,18 +22433,20 @@ } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.7.tgz", - "integrity": "sha512-bMvFGIUKlc/eSfXNX+aZ+EL95/EgZzuwA0OBPTbZZDEJw/0AkentjMuM1oiRfwHrshqk4RzdgiTg5CcDalXN5g==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "which-builtin-type": "^1.1.4" + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -21816,7 +22649,6 @@ "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", "dev": true, - "license": "MIT", "dependencies": { "css-select": "^4.1.3", "dom-converter": "^0.2.0", @@ -21830,7 +22662,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -21840,7 +22671,6 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -22604,6 +23434,45 @@ "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", "integrity": "sha512-fJhQQI5tLrQvYIYFpOnFinzv9dwmR7hRnUz1XqP3OJ1jIweTNOd6aTO4jwQSgcBSFUB+/KHJxuGneime+FdzOw==" }, + "node_modules/rollup": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.31.0.tgz", + "integrity": "sha512-9cCE8P4rZLx9+PjoyqHLs31V9a9Vpvfo4qNcs6JCiGWYhw2gijSetFbH6SSy1whnkgcefnUwr8sad7tgqsGvnw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.31.0", + "@rollup/rollup-android-arm64": "4.31.0", + "@rollup/rollup-darwin-arm64": "4.31.0", + "@rollup/rollup-darwin-x64": "4.31.0", + "@rollup/rollup-freebsd-arm64": "4.31.0", + "@rollup/rollup-freebsd-x64": "4.31.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.31.0", + "@rollup/rollup-linux-arm-musleabihf": "4.31.0", + "@rollup/rollup-linux-arm64-gnu": "4.31.0", + "@rollup/rollup-linux-arm64-musl": "4.31.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.31.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.31.0", + "@rollup/rollup-linux-riscv64-gnu": "4.31.0", + "@rollup/rollup-linux-s390x-gnu": "4.31.0", + "@rollup/rollup-linux-x64-gnu": "4.31.0", + "@rollup/rollup-linux-x64-musl": "4.31.0", + "@rollup/rollup-win32-arm64-msvc": "4.31.0", + "@rollup/rollup-win32-ia32-msvc": "4.31.0", + "@rollup/rollup-win32-x64-msvc": "4.31.0", + "fsevents": "~2.3.2" + } + }, "node_modules/rrweb-cssom": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", @@ -22663,14 +23532,16 @@ } }, "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" }, "engines": { @@ -22685,15 +23556,33 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "is-regex": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -22735,9 +23624,9 @@ } }, "node_modules/sass-loader": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.3.tgz", - "integrity": "sha512-gosNorT1RCkuCMyihv6FBRR7BMV06oKRAs+l4UMp1mlcVg9rWN6KMmUj3igjQwmYys4mDP3etEYJgiHRbgHCHA==", + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.4.tgz", + "integrity": "sha512-LavLbgbBGUt3wCiYzhuLLu65+fWXaXLmq7YxivLhEqmiupCFZ5sKUAipK3do6V80YSU0jvSxNhEdT13IXNr3rg==", "dependencies": { "neo-async": "^2.6.2" }, @@ -23164,6 +24053,21 @@ "node": ">=6.9" } }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -23266,14 +24170,69 @@ "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -23282,6 +24241,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "peer": true + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -23649,6 +24615,13 @@ "node": "*" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "peer": true + }, "node_modules/stackframe": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", @@ -23689,6 +24662,13 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", + "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", + "dev": true, + "peer": true + }, "node_modules/std-mocks": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/std-mocks/-/std-mocks-2.0.0.tgz", @@ -23711,13 +24691,12 @@ } }, "node_modules/storybook": { - "version": "8.4.7", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.4.7.tgz", - "integrity": "sha512-RP/nMJxiWyFc8EVMH5gp20ID032Wvk+Yr3lmKidoegto5Iy+2dVQnUoElZb2zpbVXNHWakGuAkfI0dY1Hfp/vw==", + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.5.0.tgz", + "integrity": "sha512-cEx42OlCetManF+cONVJVYP7SYsnI2K922DfWKmZhebP0it0n6TUof4y5/XzJ8YUruwPgyclGLdX8TvdRuNSfw==", "dev": true, - "license": "MIT", "dependencies": { - "@storybook/core": "8.4.7" + "@storybook/core": "8.5.0" }, "bin": { "getstorybook": "bin/index.cjs", @@ -23875,23 +24854,25 @@ } }, "node_modules/string.prototype.matchall": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", - "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "regexp.prototype.flags": "^1.5.2", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -23929,15 +24910,19 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -23947,15 +24932,20 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -24050,7 +25040,6 @@ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", "dev": true, - "license": "MIT", "dependencies": { "min-indent": "^1.0.1" }, @@ -24507,6 +25496,48 @@ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", "dev": true }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "peer": true + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "peer": true + }, + "node_modules/tinypool": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", + "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", + "dev": true, + "peer": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tmp": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", @@ -24660,7 +25691,6 @@ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, - "license": "MIT", "dependencies": { "json5": "^2.2.2", "minimist": "^1.2.6", @@ -24675,7 +25705,6 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -24766,30 +25795,32 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -24799,17 +25830,19 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { "node": ">= 0.4" @@ -24819,17 +25852,18 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-proto": "^1.0.3", "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -24905,15 +25939,19 @@ } }, "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -25116,11 +26154,10 @@ } }, "node_modules/unplugin": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.16.0.tgz", - "integrity": "sha512-5liCNPuJW8dqh3+DM6uNM2EI3MLLpCKp/KY+9pB5M2S2SR2qvvDHhKgBOaTWEbZTAws3CXfB0rKTIolWKL05VQ==", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.16.1.tgz", + "integrity": "sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==", "dev": true, - "license": "MIT", "dependencies": { "acorn": "^8.14.0", "webpack-virtual-modules": "^0.6.2" @@ -25134,7 +26171,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, - "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -25250,8 +26286,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/utils-merge": { "version": "1.0.1", @@ -25341,10 +26376,367 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/w3c-xmlserializer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", - "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "node_modules/vite": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.9.tgz", + "integrity": "sha512-MSgUxHcaXLtnBPktkbUSoQUANApKYuxZ6DrbVENlIorbhL2dZydTLaZ01tjUoE3szeFzlFk9ANOKk0xurh4MKA==", + "dev": true, + "peer": true, + "dependencies": { + "esbuild": "^0.24.2", + "postcss": "^8.4.49", + "rollup": "^4.23.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.2.tgz", + "integrity": "sha512-hsEQerBAHvVAbv40m3TFQe/lTEbOp7yDpyqMJqr2Tnd+W58+DEYOt+fluQgekOePcsNBmR77lpVAnIU2Xu4SvQ==", + "dev": true, + "peer": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.0", + "es-module-lexer": "^1.6.0", + "pathe": "^2.0.1", + "vite": "^5.0.0 || ^6.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite-node/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/vitest": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.2.tgz", + "integrity": "sha512-5bzaHakQ0hmVVKLhfh/jXf6oETDBtgPo8tQCHYB+wftNgFJ+Hah67IsWc8ivx4vFL025Ow8UiuTf4W57z4izvQ==", + "dev": true, + "peer": true, + "dependencies": { + "@vitest/expect": "3.0.2", + "@vitest/mocker": "3.0.2", + "@vitest/pretty-format": "^3.0.2", + "@vitest/runner": "3.0.2", + "@vitest/snapshot": "3.0.2", + "@vitest/spy": "3.0.2", + "@vitest/utils": "3.0.2", + "chai": "^5.1.2", + "debug": "^4.4.0", + "expect-type": "^1.1.0", + "magic-string": "^0.30.17", + "pathe": "^2.0.1", + "std-env": "^3.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinypool": "^1.0.2", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0", + "vite-node": "3.0.2", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.0.2", + "@vitest/ui": "3.0.2", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest-axe": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/vitest-axe/-/vitest-axe-0.1.0.tgz", + "integrity": "sha512-jvtXxeQPg8R/2ANTY8QicA5pvvdRP4F0FsVUAHANJ46YCDASie/cuhlSzu0DGcLmZvGBSBNsNuK3HqfaeknyvA==", + "dev": true, + "dependencies": { + "aria-query": "^5.0.0", + "axe-core": "^4.4.2", + "chalk": "^5.0.1", + "dom-accessibility-api": "^0.5.14", + "lodash-es": "^4.17.21", + "redent": "^3.0.0" + }, + "peerDependencies": { + "vitest": ">=0.16.0" + } + }, + "node_modules/vitest-axe/node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/vitest/node_modules/@vitest/expect": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.2.tgz", + "integrity": "sha512-dKSHLBcoZI+3pmP5hiZ7I5grNru2HRtEW8Z5Zp4IXog8QYcxhlox7JUPyIIFWfN53+3HW3KPLIl6nSzUGgKSuQ==", + "dev": true, + "peer": true, + "dependencies": { + "@vitest/spy": "3.0.2", + "@vitest/utils": "3.0.2", + "chai": "^5.1.2", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest/node_modules/@vitest/pretty-format": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.2.tgz", + "integrity": "sha512-yBohcBw/T/p0/JRgYD+IYcjCmuHzjC3WLAKsVE4/LwiubzZkE8N49/xIQ/KGQwDRA8PaviF8IRO8JMWMngdVVQ==", + "dev": true, + "peer": true, + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest/node_modules/@vitest/spy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.2.tgz", + "integrity": "sha512-8mI2iUn+PJFMT44e3ISA1R+K6ALVs47W6eriDTfXe6lFqlflID05MB4+rIFhmDSLBj8iBsZkzBYlgSkinxLzSQ==", + "dev": true, + "peer": true, + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest/node_modules/@vitest/utils": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.2.tgz", + "integrity": "sha512-Qu01ZYZlgHvDP02JnMBRpX43nRaZtNpIzw3C1clDXmn8eakgX6iQVGzTQ/NjkIr64WD8ioqOjkaYRVvHQI5qiw==", + "dev": true, + "peer": true, + "dependencies": { + "@vitest/pretty-format": "3.0.2", + "loupe": "^3.1.2", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest/node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/chai": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", + "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", + "dev": true, + "peer": true, + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 16" + } + }, + "node_modules/vitest/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "peer": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/vitest/node_modules/loupe": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.2.tgz", + "integrity": "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==", + "dev": true, + "peer": true + }, + "node_modules/vitest/node_modules/pathval": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", + "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/vitest/node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", "dev": true, "license": "MIT", "dependencies": { @@ -25386,15 +26778,16 @@ } }, "node_modules/webpack": { - "version": "5.96.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", - "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", + "version": "5.97.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", + "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", + "license": "MIT", "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", - "@webassemblyjs/ast": "^1.12.1", - "@webassemblyjs/wasm-edit": "^1.12.1", - "@webassemblyjs/wasm-parser": "^1.12.1", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.14.0", "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", @@ -25586,7 +26979,6 @@ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.3.tgz", "integrity": "sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw==", "dev": true, - "license": "MIT", "dependencies": { "colorette": "^2.0.10", "memfs": "^3.4.12", @@ -25833,8 +27225,7 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/webpack/node_modules/acorn": { "version": "8.14.0", @@ -25951,40 +27342,45 @@ } }, "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, + "license": "MIT", "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-builtin-type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.0.tgz", - "integrity": "sha512-I+qLGQ/vucCby4tf5HsLmGueEla4ZhwTBSqaooS+Y0BuxN4Cp+okmGuV+8mXZ84KDI9BA+oklo+RzKg0ONdSUA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", + "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", + "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", + "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", - "which-typed-array": "^1.1.15" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -25998,6 +27394,7 @@ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, + "license": "MIT", "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", @@ -26018,15 +27415,17 @@ "dev": true }, "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", + "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", "dev": true, + "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "for-each": "^0.3.3", - "gopd": "^1.0.1", + "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" }, "engines": { @@ -26036,6 +27435,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "peer": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", @@ -26292,30 +27708,30 @@ } }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-unparser": { diff --git a/package.json b/package.json index 456c9f7c122..046ac683ec6 100644 --- a/package.json +++ b/package.json @@ -68,9 +68,9 @@ "@nivo/tooltip": "^0.88.0", "@redux-devtools/extension": "^3.3.0", "@reduxjs/toolkit": "^2.5.0", - "@sentry/browser": "^8.47.0", - "@sentry/node": "^8.45.1", - "@sentry/react": "^8.45.1", + "@sentry/browser": "^8.50.0", + "@sentry/node": "^8.50.0", + "@sentry/react": "^8.50.0", "autoprefixer": "^10.4.20", "axios": "^1.7.9", "basic-auth": "^2.0.1", @@ -88,7 +88,7 @@ "date-fns": "^4.1.0", "del-cli": "^6.0.0", "dotenv": "^16.4.7", - "elastic-apm-node": "^4.9.0", + "elastic-apm-node": "^4.11.0", "element-closest": "^3.0.2", "express": "^4.21.2", "express-minify-html-2": "^2.0.0", @@ -98,7 +98,7 @@ "get-form-data": "^3.0.0", "govuk_frontend_toolkit": "^9.0.1", "govuk-elements-sass": "^3.1.3", - "govuk-frontend": "^5.7.1", + "govuk-frontend": "^5.8.0", "govuk-react": "^0.10.7", "hawk": "^9.0.2", "history": "^5.3.0", @@ -116,17 +116,17 @@ "postcss-loader": "^8.1.0", "prop-types": "^15.8.1", "pure-uuid": "^1.8.1", - "qs": "^6.13.1", + "qs": "^6.14.0", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-error-boundary": "^4.1.2", + "react-error-boundary": "^5.0.0", "react-icons": "^5.4.0", "react-lines-ellipsis": "^0.15.4", "react-markdown": "^9.0.1", "react-redux": "^9.2.0", - "react-router-dom": "^7.1.0", + "react-router-dom": "^7.1.1", "react-string-replace": "^1.1.1", - "react-to-print": "^3.0.2", + "react-to-print": "^3.0.4", "react-use": "^17.6.0", "redis": "4.7.0", "redux": "^5.0.1", @@ -136,7 +136,7 @@ "request-promise": "^4.2.6", "resolve-url-loader": "^5.0.0", "sass": "^1.83.0", - "sass-loader": "^16.0.3", + "sass-loader": "^16.0.4", "serve-favicon": "^2.5.0", "sniffr": "^1.3.1", "style-loader": "^4.0.0", @@ -147,7 +147,7 @@ }, "devDependencies": { "@babel/core": "^7.26.0", - "@babel/eslint-parser": "^7.25.9", + "@babel/eslint-parser": "^7.26.5", "@babel/helper-call-delegate": "^7.12.13", "@babel/plugin-syntax-import-assertions": "^7.25.6", "@babel/plugin-transform-class-properties": "^7.25.4", @@ -159,16 +159,16 @@ "@babel/preset-typescript": "^7.26.0", "@babel/register": "^7.25.9", "@babel/runtime": "^7.26.0", - "@chromatic-com/storybook": "^3.2.2", - "@cypress/code-coverage": "^3.13.9", + "@chromatic-com/storybook": "^3.2.3", + "@cypress/code-coverage": "^3.13.10", "@faker-js/faker": "^9.3.0", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.15", - "@storybook/addon-a11y": "^8.4.7", - "@storybook/addon-essentials": "^8.4.7", - "@storybook/addon-webpack5-compiler-babel": "^3.0.3", - "@storybook/manager-api": "^8.4.7", - "@storybook/react": "^8.4.7", - "@storybook/react-webpack5": "^8.4.7", + "@storybook/addon-a11y": "^8.5.0", + "@storybook/addon-essentials": "^8.5.0", + "@storybook/addon-webpack5-compiler-babel": "^3.0.5", + "@storybook/manager-api": "^8.5.0", + "@storybook/react": "^8.5.0", + "@storybook/react-webpack5": "^8.5.0", "babel-loader": "^9.2.1", "babel-plugin-istanbul": "7.0.0", "chai": "^4.5.0", @@ -176,26 +176,26 @@ "cypress": "^13.17.0", "cypress-axe": "^1.5.0", "eslint": "^8.57.0", - "eslint-config-prettier": "^9.1.0", + "eslint-config-prettier": "^10.0.1", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-mocha": "^10.5.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-promise": "^7.2.1", - "eslint-plugin-react": "^7.37.2", + "eslint-plugin-react": "^7.37.4", "eslint-plugin-react-hooks": "^5.1.0", "git-directory-deploy": "^1.5.1", "html": "^1.0.0", "http-server": "^14.1.1", - "image-minimizer-webpack-plugin": "^4.1.1", + "image-minimizer-webpack-plugin": "^4.1.3", "js-beautify": "^1.14.11", "js-cookie": "^3.0.5", "jsdom": "^25.0.1", "jsdom-global": "^3.0.2", "json-schema-faker": "^0.5.8", - "lint-staged": "^15.2.11", - "mocha": "^11.0.1", + "lint-staged": "^15.4.3", + "mocha": "^11.1.0", "mocha-junit-reporter": "^2.2.1", "mochapack": "^2.1.4", "nock": "^13.5.6", @@ -212,9 +212,9 @@ "sinon": "^19.0.2", "sinon-chai": "^3.7.0", "std-mocks": "^2.0.0", - "storybook": "^8.4.7", + "storybook": "^8.5.0", "supertest": "^7.0.0", - "webpack": "^5.96.1", + "webpack": "^5.97.1", "webpack-assets-manifest": "^5.1.0", "webpack-cli": "^6.0.1", "webpack-dev-server": "^5.2.0", @@ -225,4 +225,4 @@ "semver": "7.5.2", "tough-cookie": "4.1.3" } -} \ No newline at end of file +} diff --git a/src/apps/__test__/transformers.test.js b/src/apps/__test__/transformers.test.js index 93d7aaaac57..f1aac974279 100644 --- a/src/apps/__test__/transformers.test.js +++ b/src/apps/__test__/transformers.test.js @@ -109,44 +109,6 @@ describe('Global transformers', () => { }) }) - describe('#transformDateStringToDateObject', () => { - context('when invalid date string', () => { - it('should return empty date object for no args', () => { - const actual = this.transformers.transformDateStringToDateObject() - - expect(actual).to.deep.equal({ - year: '', - month: '', - day: '', - }) - }) - - it('should return empty date object for invalid date', () => { - const actual = - this.transformers.transformDateStringToDateObject('12345-098-11') - - expect(actual).to.deep.equal({ - year: '', - month: '', - day: '', - }) - }) - }) - - context('when valid date string', () => { - it('should return correct date object from date string', () => { - const actual = - this.transformers.transformDateStringToDateObject('2017-09-25') - - expect(actual).to.deep.equal({ - year: '2017', - month: '09', - day: '25', - }) - }) - }) - }) - describe('#transformCountryToOptionWithIsoCode', () => { it('should return object with id, name as label and code as value', () => { const actual = this.transformers.transformCountryToOptionWithIsoCode({ diff --git a/src/apps/companies/__test__/repos.test.js b/src/apps/companies/__test__/repos.test.js index 6028711481f..40f3991b5e5 100644 --- a/src/apps/companies/__test__/repos.test.js +++ b/src/apps/companies/__test__/repos.test.js @@ -143,17 +143,4 @@ describe('Company repository', () => { expect(actual).to.deep.equal({ hello: true }) }) }) - - describe('getRelatedCompanies', () => { - it('should make the correct call to the API', async () => { - const authorisedRequestStub = sinon.stub().resolves({}) - const repo = makeRepositoryWithAuthRequest(authorisedRequestStub) - - await repo.getRelatedCompanies(stubRequest, '123', false, true) - - expect(authorisedRequestStub).to.be.calledOnceWithExactly(stubRequest, { - url: `${config.apiRoot}/v4/dnb/123/related-companies?include_subsidiary_companies=true&include_parent_companies=false`, - }) - }) - }) }) diff --git a/src/apps/companies/apps/dnb-hierarchy/__test__/middleware.test.js b/src/apps/companies/apps/dnb-hierarchy/__test__/middleware.test.js deleted file mode 100644 index e230adb9407..00000000000 --- a/src/apps/companies/apps/dnb-hierarchy/__test__/middleware.test.js +++ /dev/null @@ -1,217 +0,0 @@ -const buildMiddlewareParameters = require('../../../../../../test/unit/helpers/middleware-parameters-builder') -const { - setCompanyHierarchyLocalNav, - setDnbHierarchyDetails, -} = require('../middleware') -const urls = require('../../../../../lib/urls') -const { mockGetDnbHierarchy } = require('./utils') - -const DUNS_NUMBER = 999999 - -const buildSubsidiaryMiddlewareParameters = ({ - reqMock = { baseUrl: urls.companies.subsidiaries.index('123') }, - company = { - isUltimate: true, - isGlobalHQ: true, - id: '123', - }, - CURRENT_PATH = urls.companies.dnbHierarchy.index('123'), - permissions = ['company.view_company'], -}) => - buildMiddlewareParameters({ - reqMock, - company, - CURRENT_PATH, - user: { - permissions, - }, - }) - -describe('D&B Hierarchy middleware', () => { - describe('#setCompanyHierarchyLocalNav', () => { - context( - 'when a company is both Global HQ and Ultimate HQ and the flag is ON', - () => { - const middlewareParameters = buildSubsidiaryMiddlewareParameters({}) - - setCompanyHierarchyLocalNav( - middlewareParameters.reqMock, - middlewareParameters.resMock, - middlewareParameters.nextSpy - ) - - it('should render local nav with D&B hierarchy and manual subsidiaries tabs', () => { - expect( - middlewareParameters.resMock.locals.localNavItems - ).to.be.deep.equal([ - { - isActive: true, - label: 'Dun & Bradstreet hierarchy', - permissions: ['company.view_company'], - url: urls.companies.dnbHierarchy.index('123'), - }, - { - isActive: false, - label: 'Manually linked subsidiaries', - permissions: ['company.view_company'], - url: urls.companies.subsidiaries.index('123'), - }, - ]) - }) - } - ) - - context('when the company is Global HQ but not Ultimate HQ', () => { - const middlewareParameters = buildSubsidiaryMiddlewareParameters({ - company: { - isGlobalHQ: true, - isUltimate: false, - }, - }) - - setCompanyHierarchyLocalNav( - middlewareParameters.reqMock, - middlewareParameters.resMock, - middlewareParameters.nextSpy - ) - - it('should not render tabs', () => { - expect( - middlewareParameters.resMock.locals.localNavItems - ).to.be.deep.equal([]) - }) - }) - - context('when the company is Ultimate HQ but not Global HQ', () => { - const middlewareParameters = buildSubsidiaryMiddlewareParameters({ - company: { - isGlobalHQ: false, - isUltimate: true, - }, - }) - - setCompanyHierarchyLocalNav( - middlewareParameters.reqMock, - middlewareParameters.resMock, - middlewareParameters.nextSpy - ) - - it('should not render tabs', () => { - expect( - middlewareParameters.resMock.locals.localNavItems - ).to.be.deep.equal([]) - }) - }) - }) -}) - -describe('#setDnbHierarchyDetails', async () => { - context('when the company DOES have a duns number', async () => { - let middlewareParameters - - before(async () => { - middlewareParameters = buildSubsidiaryMiddlewareParameters({ - company: { - id: 1, - duns_number: DUNS_NUMBER, - global_ultimate_duns_number: DUNS_NUMBER, - }, - }) - - mockGetDnbHierarchy({ - responseBody: { results: [{ id: '2', is_global_ultimate: true }] }, - relatedCompaniesCount: 5, - companyId: 1, - limit: 1, - }) - - await setDnbHierarchyDetails( - middlewareParameters.reqMock, - middlewareParameters.resMock, - middlewareParameters.nextSpy - ) - }) - - it('should set "globalUltimate"', async () => { - expect(middlewareParameters.resMock.locals.globalUltimate).to.deep.equal({ - id: '2', - is_global_ultimate: true, - url: urls.companies.detail(2), - }) - }) - - it('should set "dnbHierarchyCount"', async () => { - expect(middlewareParameters.resMock.locals.dnbHierarchyCount).to.equal(6) - }) - - it('should set "dnbRelatedCompaniesCount"', async () => { - expect( - middlewareParameters.resMock.locals.dnbRelatedCompaniesCount - ).to.equal(5) - }) - }) - - context('when the company DOES NOT have a duns number', async () => { - const middlewareParameters = buildSubsidiaryMiddlewareParameters({ - company: { - duns_number: null, - }, - }) - - before(async () => - setDnbHierarchyDetails( - middlewareParameters.reqMock, - middlewareParameters.resMock, - middlewareParameters.nextSpy - ) - ) - - it('should not set "globalUltimate"', async () => { - expect(middlewareParameters.resMock.locals.globalUltimate).to.be.undefined - }) - - it('should not set "dnbHierarchyCount"', async () => { - expect(middlewareParameters.resMock.locals.dnbHierarchyCount).to.equal(0) - }) - - it('should set "dnbRelatedCompaniesCount" equal to 0', async () => { - expect( - middlewareParameters.resMock.locals.dnbRelatedCompaniesCount - ).to.equal(0) - }) - }) - - context('when the api call fails to get related companies', async () => { - let middlewareParameters - - before(async () => { - middlewareParameters = buildSubsidiaryMiddlewareParameters({ - company: { - id: 1, - duns_number: DUNS_NUMBER, - }, - }) - - mockGetDnbHierarchy({ - companyId: 1, - responseCode: 502, - }) - - await setDnbHierarchyDetails( - middlewareParameters.reqMock, - middlewareParameters.resMock, - middlewareParameters.nextSpy - ) - }) - - it('should swallow exception and return empty response', async () => { - expect(middlewareParameters.resMock.locals.globalUltimate).to.be.undefined - expect(middlewareParameters.resMock.locals.dnbHierarchyCount).to.be.equal( - 0 - ) - expect( - middlewareParameters.resMock.locals.dnbRelatedCompaniesCount - ).to.be.equal(0) - }) - }) -}) diff --git a/src/apps/companies/apps/dnb-hierarchy/__test__/repos.test.js b/src/apps/companies/apps/dnb-hierarchy/__test__/repos.test.js deleted file mode 100644 index 6d31ce859de..00000000000 --- a/src/apps/companies/apps/dnb-hierarchy/__test__/repos.test.js +++ /dev/null @@ -1,30 +0,0 @@ -const config = require('../../../../../config') -const { getDnbHierarchy } = require('../repos') -const { mockGetDnbHierarchy } = require('./utils') - -const dnbHierarchyFixture = { - count: 2, - results: [{ id: '1' }, { id: '2' }], -} -const stubRequest = { session: { token: 'abcd' } } -const DUNS_NUMBER = 999999 - -describe('D&B Subsidiaries repos', () => { - describe('#getDnbHierarchy', () => { - it('should return the one subsidiary', async () => { - mockGetDnbHierarchy({ - globalUltimateDunsNumber: DUNS_NUMBER, - responseBody: dnbHierarchyFixture, - }) - - const actual = await getDnbHierarchy( - stubRequest, - DUNS_NUMBER, - config.paginationDefaultSize, - 1 - ) - - expect(actual).to.deep.equal(dnbHierarchyFixture) - }) - }) -}) diff --git a/src/apps/companies/apps/dnb-hierarchy/__test__/router.test.js b/src/apps/companies/apps/dnb-hierarchy/__test__/router.test.js deleted file mode 100644 index 692f961273a..00000000000 --- a/src/apps/companies/apps/dnb-hierarchy/__test__/router.test.js +++ /dev/null @@ -1,8 +0,0 @@ -const router = require('../router') - -describe('D&B hierarchy routes', () => { - it('should define all routes', () => { - const paths = router.stack.filter((r) => r.route).map((r) => r.route.path) - expect(paths).to.deep.equal(['/:companyId/dnb-hierarchy/data']) - }) -}) diff --git a/src/apps/companies/apps/dnb-hierarchy/__test__/transformers.test.js b/src/apps/companies/apps/dnb-hierarchy/__test__/transformers.test.js deleted file mode 100644 index c3c5d13e93d..00000000000 --- a/src/apps/companies/apps/dnb-hierarchy/__test__/transformers.test.js +++ /dev/null @@ -1,85 +0,0 @@ -const { transformCompanyToDnbHierarchyList } = require('../transformers') -const urls = require('../../../../../lib/urls') - -describe('Edit company form transformers', () => { - describe('#transformCompanyToDnbHierarchyList', () => { - context('when called with a fully populated company', () => { - const actual = transformCompanyToDnbHierarchyList({ - id: '123', - name: 'Test company', - sector: { - name: 'Test sector', - }, - uk_based: true, - uk_region: { - name: 'Test UK region', - }, - trading_names: ['Test trading name'], - address: { - country: { - name: 'Test country', - }, - }, - modified_on: '2016-07-05T12:00:00Z', - headquarter_type: { - name: 'ghq', - }, - is_global_ultimate: true, - }) - - it('should return transformed values', () => { - const expected = { - badges: [ - { text: 'Test country' }, - { text: 'Test UK region' }, - { text: 'Ultimate HQ' }, - { text: 'Global HQ' }, - ], - headingText: 'Test company', - headingUrl: '/companies/123', - metadata: [ - { - label: 'Trading names', - value: ['Test trading name'], - }, - { - label: 'Sector', - value: 'Test sector', - }, - { - label: 'Address', - value: 'Test country', - }, - ], - subheading: 'Updated on 5 Jul 2016, 1:00pm', - } - - expect(actual).to.deep.equal(expected) - }) - }) - - context('when called without ID', () => { - const actual = transformCompanyToDnbHierarchyList({}) - - it('should return undefined', () => { - expect(actual).to.be.undefined - }) - }) - - context('when called only with ID', () => { - const actual = transformCompanyToDnbHierarchyList({ - id: '123', - }) - - it('should return minimal object', () => { - expect(actual).to.deep.equal({ - headingText: undefined, - headingUrl: urls.companies.detail('123'), - subheading: undefined, - metadata: [], - badges: [], - }) - }) - }) - }) -}) diff --git a/src/apps/companies/apps/dnb-hierarchy/__test__/utils.js b/src/apps/companies/apps/dnb-hierarchy/__test__/utils.js deleted file mode 100644 index 112b8ccc2d9..00000000000 --- a/src/apps/companies/apps/dnb-hierarchy/__test__/utils.js +++ /dev/null @@ -1,37 +0,0 @@ -const nock = require('nock') - -const config = require('../../../../../config') - -function mockGetDnbHierarchy({ - globalUltimateDunsNumber, - responseBody, - companyId, - relatedCompaniesCount, - responseCode = 200, - offset = 0, - limit = 10, -}) { - nock(config.apiRoot) - .get( - `/v4/company?limit=${limit}&offset=${offset}&sortby=name&global_ultimate_duns_number=${globalUltimateDunsNumber}` - ) - .reply(responseCode, responseBody) - - nock(config.apiRoot) - .get( - `/v4/dnb/${companyId}/related-companies/count?include_manually_linked_companies=true` - ) - .reply(responseCode, { - related_companies_count: relatedCompaniesCount, - total: relatedCompaniesCount, - }) - - nock(config.apiRoot) - .post(`/v4/search/company`) - .query(true) - .reply(responseCode, responseBody) -} - -module.exports = { - mockGetDnbHierarchy, -} diff --git a/src/apps/companies/apps/dnb-hierarchy/client/DnbHierarchy.jsx b/src/apps/companies/apps/dnb-hierarchy/client/DnbHierarchy.jsx deleted file mode 100644 index 0d4736bef18..00000000000 --- a/src/apps/companies/apps/dnb-hierarchy/client/DnbHierarchy.jsx +++ /dev/null @@ -1,75 +0,0 @@ -import React, { useEffect, useState } from 'react' -import PropTypes from 'prop-types' -import axios from 'axios' -import useSearchParam from 'react-use/lib/useSearchParam' -import { Details, LoadingBox } from 'govuk-react' - -import { CollectionList } from '../../../../../client/components/' - -const DnbHierarchy = ({ dataEndpoint, isGlobalHQ }) => { - const [companies, setCompanies] = useState([]) - const [totalItems, setTotalItems] = useState(0) - const [isLoading, setIsLoading] = useState(true) - - const activePage = parseInt(useSearchParam('page'), 10) || 1 - const getPageUrl = (page) => `${window.location.pathname}?page=${page}` - const setActivePage = (page) => - window.history.pushState({}, '', getPageUrl(page)) - - const onPageClick = (page) => { - setActivePage(page) - } - - useEffect(() => { - async function fetchData() { - const { data } = await axios.get(dataEndpoint, { - params: { - page: activePage, - }, - }) - setCompanies(data.results) - setTotalItems(data.count) - setIsLoading(false) - } - setIsLoading(true) - window.scrollTo(0, 0) - fetchData() - }, [activePage]) - - return ( - <> -

This hierarchy information from Dun & Bradstreet cannot be edited.

- - {isGlobalHQ && ( -
- This does not mean that Dun & Bradstreet does not know about those - subsidiaries. -
- The Dun & Bradstreet hierarchy information can only show the company - records in Data Hub that have been matched to a verified Dun & - Bradstreet record. This matching process is ongoing and more related - company records will appear in the future. -
- )} - - - - - - ) -} - -DnbHierarchy.propTypes = { - dataEndpoint: PropTypes.string.isRequired, - isGlobalHQ: PropTypes.bool.isRequired, -} - -export default DnbHierarchy diff --git a/src/apps/companies/apps/dnb-hierarchy/controllers.js b/src/apps/companies/apps/dnb-hierarchy/controllers.js deleted file mode 100644 index f58c7af8906..00000000000 --- a/src/apps/companies/apps/dnb-hierarchy/controllers.js +++ /dev/null @@ -1,45 +0,0 @@ -/* eslint-disable camelcase */ - -const config = require('../../../../config') -const { transformCompanyToDnbHierarchyList } = require('./transformers') -const { getDnbHierarchy } = require('./repos') - -function removeCurrentCompany(dunsNumber, { count, results }) { - if (results.find((c) => c.duns_number !== dunsNumber)) { - return { - count: count > 0 ? count - 1 : 0, - results: results.filter((c) => c.duns_number !== dunsNumber), - } - } - - // istanbul ignore next: Covered by functional tests - return { count, results } -} - -async function fetchDnbHierarchyHandler(req, res, next) { - try { - const { company } = res.locals - const { page } = req.query - - const { count, results } = removeCurrentCompany( - company.duns_number, - await getDnbHierarchy( - req, - company.global_ultimate_duns_number, - config.paginationDefaultSize, - page - ) - ) - - res.json({ - count, - results: results.map(transformCompanyToDnbHierarchyList), - }) - } catch (error) { - next(error) - } -} - -module.exports = { - fetchDnbHierarchyHandler, -} diff --git a/src/apps/companies/apps/dnb-hierarchy/middleware.js b/src/apps/companies/apps/dnb-hierarchy/middleware.js deleted file mode 100644 index 86bc6e9a5f2..00000000000 --- a/src/apps/companies/apps/dnb-hierarchy/middleware.js +++ /dev/null @@ -1,79 +0,0 @@ -const { get } = require('lodash') - -const { setLocalNav } = require('../../../middleware') -const { getGlobalUltimate, getRelatedCompaniesCount } = require('./repos') -const urls = require('../../../../lib/urls') - -function setCompanyHierarchyLocalNav(req, res, next) { - const { company } = res.locals - - if (company.isUltimate && company.isGlobalHQ) { - const navItems = [ - { - url: urls.companies.dnbHierarchy.index(company.id), - label: 'Dun & Bradstreet hierarchy', - permissions: ['company.view_company'], - }, - { - url: urls.companies.subsidiaries.index(company.id), - label: 'Manually linked subsidiaries', - permissions: ['company.view_company'], - }, - ] - setLocalNav(navItems, false)(req, res, next) - } else { - setLocalNav()(req, res, next) - } -} - -async function getDnbHierarchyDetails(req, company) { - if (company.duns_number) { - try { - const dnbRelatedCompaniesCount = await getRelatedCompaniesCount( - req, - company.id - ) - let globalUltimateResult - if (company.global_ultimate_duns_number) { - const globalUltimate = await getGlobalUltimate( - req, - company.global_ultimate_duns_number - ) - globalUltimateResult = get(globalUltimate, 'results[0]') - } - - return { - globalUltimate: globalUltimateResult && { - ...globalUltimateResult, - url: urls.companies.detail(globalUltimateResult.id), - }, - dnbRelatedCompaniesCount: dnbRelatedCompaniesCount.total, - dnbHierarchyCount: dnbRelatedCompaniesCount.related_companies_count + 1, - } - } catch (err) { - return { dnbHierarchyCount: 0, dnbRelatedCompaniesCount: 0 } - } - } - - return { - dnbHierarchyCount: 0, - dnbRelatedCompaniesCount: 0, - } -} - -async function setDnbHierarchyDetails(req, res, next) { - const { company } = res.locals - - const { globalUltimate, dnbHierarchyCount, dnbRelatedCompaniesCount } = - await getDnbHierarchyDetails(req, company) - - res.locals.globalUltimate = globalUltimate - res.locals.dnbHierarchyCount = dnbHierarchyCount - res.locals.dnbRelatedCompaniesCount = dnbRelatedCompaniesCount - next() -} - -module.exports = { - setDnbHierarchyDetails, - setCompanyHierarchyLocalNav, -} diff --git a/src/apps/companies/apps/dnb-hierarchy/repos.js b/src/apps/companies/apps/dnb-hierarchy/repos.js deleted file mode 100644 index 6991423ead1..00000000000 --- a/src/apps/companies/apps/dnb-hierarchy/repos.js +++ /dev/null @@ -1,39 +0,0 @@ -const { authorisedRequest } = require('../../../../lib/authorised-request') -const config = require('../../../../config') - -function getDnbHierarchy(req, globalUltimateDunsNumber, limit, page = 1) { - const offset = limit * (page - 1) - - return authorisedRequest(req, { - url: `${config.apiRoot}/v4/company`, - qs: { - limit, - offset, - sortby: 'name', - global_ultimate_duns_number: globalUltimateDunsNumber, - }, - }) -} - -async function getRelatedCompaniesCount(req, companyId) { - return await authorisedRequest(req, { - url: `${config.apiRoot}/v4/dnb/${companyId}/related-companies/count?include_manually_linked_companies=true`, - }) -} - -async function getGlobalUltimate(req, globalUltimateDunsNumber) { - return await authorisedRequest(req, { - method: 'POST', - url: `${config.apiRoot}/v4/search/company`, - qs: { - limit: 1, - }, - body: { duns_number: globalUltimateDunsNumber }, - }) -} - -module.exports = { - getDnbHierarchy, - getGlobalUltimate, - getRelatedCompaniesCount, -} diff --git a/src/apps/companies/apps/dnb-hierarchy/router.js b/src/apps/companies/apps/dnb-hierarchy/router.js deleted file mode 100644 index 444c9388e21..00000000000 --- a/src/apps/companies/apps/dnb-hierarchy/router.js +++ /dev/null @@ -1,8 +0,0 @@ -const router = require('express').Router() - -const urls = require('../../../../lib/urls') -const { fetchDnbHierarchyHandler } = require('./controllers') - -router.get(urls.companies.dnbHierarchy.data.route, fetchDnbHierarchyHandler) - -module.exports = router diff --git a/src/apps/companies/apps/dnb-hierarchy/transformers.js b/src/apps/companies/apps/dnb-hierarchy/transformers.js deleted file mode 100644 index 1461901a28b..00000000000 --- a/src/apps/companies/apps/dnb-hierarchy/transformers.js +++ /dev/null @@ -1,85 +0,0 @@ -/* eslint-disable camelcase */ - -const { - formatAddress, - formatDateTime, -} = require('../../../../config/nunjucks/filters') -const urls = require('../../../../lib/urls') -const labels = require('../../labels') - -function transformCompanyToDnbHierarchyList({ - id, - name, - sector, - uk_based, - uk_region, - trading_names, - address, - modified_on, - headquarter_type, - is_global_ultimate, -} = {}) { - if (!id) { - return - } - - const metadata = [] - const badges = [] - - if (trading_names && trading_names.length) { - metadata.push({ - label: labels.hqLabels.trading_names, - value: trading_names, - }) - } - - if (sector && sector.name) { - metadata.push({ - label: 'Sector', - value: sector.name, - }) - } - - if (address && address.country && address.country.name) { - badges.push({ - text: address.country.name, - }) - } - - if (uk_based && uk_region && uk_region.name) { - badges.push({ - text: uk_region.name, - }) - } - - if (is_global_ultimate) { - badges.push({ - text: labels.companyDetailsLabels.ultimate_hq, - }) - } - - if (headquarter_type) { - badges.push({ - text: labels.hqLabels[headquarter_type.name], - }) - } - - if (address) { - metadata.push({ - label: labels.address.companyAddress, - value: formatAddress(address), - }) - } - - return { - headingText: name, - headingUrl: urls.companies.detail(id), - subheading: modified_on && `Updated on ${formatDateTime(modified_on)}`, - metadata, - badges, - } -} - -module.exports = { - transformCompanyToDnbHierarchyList, -} diff --git a/src/apps/companies/apps/match-company/__test__/transformers.test.js b/src/apps/companies/apps/match-company/__test__/transformers.test.js deleted file mode 100644 index e5d827caa23..00000000000 --- a/src/apps/companies/apps/match-company/__test__/transformers.test.js +++ /dev/null @@ -1,40 +0,0 @@ -const { transformToDnbInvestigation } = require('../transformers') - -describe('#transformToDnbInvestigation', () => { - it('should transform the request body', () => { - expect( - transformToDnbInvestigation( - { - id: 'id', - name: 'name', - address: { - line_1: 'line_1', - line_2: 'line_2', - town: 'town', - county: 'county', - postcode: 'postcode', - country: { - name: 'United Kingdom', - id: 'countryId', - }, - }, - }, - 'website', - 'telephone' - ) - ).to.deep.equal({ - company: 'id', - name: 'name', - website: 'website', - telephone_number: 'telephone', - address: { - line_1: 'line_1', - line_2: 'line_2', - town: 'town', - county: 'county', - postcode: 'postcode', - country: 'countryId', - }, - }) - }) -}) diff --git a/src/apps/companies/apps/match-company/client/CannotFindMatch.jsx b/src/apps/companies/apps/match-company/client/CannotFindMatch.jsx deleted file mode 100755 index 6338a39df36..00000000000 --- a/src/apps/companies/apps/match-company/client/CannotFindMatch.jsx +++ /dev/null @@ -1,105 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { H4 } from '@govuk-react/heading' -import InsetText from '@govuk-react/inset-text' -import Paragraph from '@govuk-react/paragraph' - -import LocalHeader from '../../../../../client/components/LocalHeader/LocalHeader.jsx' -import { Main, SummaryList, FieldInput } from '../../../../../client/components' -import urls from '../../../../../lib/urls' -import { WEBSITE_REGEX } from '../../add-company/client/constants' -import Form from '../../../../../client/components/Form' -import { buildCompanyBreadcrumbs } from '../../../../../client/modules/Companies/utils.js' - -const requiredWebsiteOrPhoneValidator = ( - value, - name, - { values: { website, telephoneNumber } } -) => { - return !website && !telephoneNumber ? 'Enter a website or phone number' : null -} - -const websiteValidator = (value) => { - WEBSITE_REGEX.test(value) ? null : 'Enter a valid website URL' -} - -function CannotFindMatch({ company, csrfToken }) { - return ( - <> - - - Add the company contact details below. It will be sent to our third - party data supplier for verification. - - -
-
urls.companies.detail(company.id)} - transformPayload={(values) => ({ values, company, csrfToken })} - flashMessage={() => - 'Verification request sent for third party review' - } - submitButtonLabel="Send" - cancelRedirectTo={() => urls.companies.match.index(company.id)} - cancelButtonLabel="Back" - > - {() => ( - <> -

Data Hub business details (un-verified)

- - - -

Company contact information

- - -

What happens next

- You don’t need to do anything else. - - Our third-party supplier will verify the company’s business - details directly, so make sure the details are correct and you - have consent to share them. - - - It will NOT change any recorded activity (interactions, OMIS - orders or Investment projects). - - - )} - -
- - ) -} - -CannotFindMatch.props = { - companyId: PropTypes.string.isRequired, -} - -export default CannotFindMatch diff --git a/src/apps/companies/apps/match-company/client/tasks.js b/src/apps/companies/apps/match-company/client/tasks.js index 4b70804a495..64fe2edb420 100644 --- a/src/apps/companies/apps/match-company/client/tasks.js +++ b/src/apps/companies/apps/match-company/client/tasks.js @@ -14,20 +14,6 @@ export const onMatchSubmit = ({ csrfToken, company, dnbCompany }) => return response.data }) -export const cannotFindMatchSubmit = ({ csrfToken, values, company }) => - axios - .post(urls.companies.match.cannotFind(company.id), { - _csrf: csrfToken, - website: values.website, - telephone_number: values.telephoneNumber, - }) - .catch((e) => { - return Promise.reject(e.message) - }) - .then((response) => { - return response.data - }) - export async function submitMergeRequest({ company, dnbCompany, csrfToken }) { await axios.post( `${urls.companies.match.merge(company.id)}?_csrf=${csrfToken}`, diff --git a/src/apps/companies/apps/match-company/controllers.js b/src/apps/companies/apps/match-company/controllers.js index 8e5ee87c3fb..043f8985403 100644 --- a/src/apps/companies/apps/match-company/controllers.js +++ b/src/apps/companies/apps/match-company/controllers.js @@ -2,11 +2,7 @@ const { get, isEmpty, pick } = require('lodash') const url = require('url') const { searchDnbCompanies } = require('../../../../modules/search/services') -const { - linkDataHubCompanyToDnBCompany, - createDnbCompanyInvestigation, -} = require('../../repos') -const { transformToDnbInvestigation } = require('./transformers') +const { linkDataHubCompanyToDnBCompany } = require('../../repos') const { getOptions } = require('../../../../lib/options') const { postToZenDesk } = require('../../../support/services') const urls = require('../../../../lib/urls') @@ -187,49 +183,6 @@ async function findDnbCompany(req, res, next) { } } -async function renderCannotFindMatch(req, res, next) { - try { - const { company } = res.locals - const countries = await getCountries(req) - - res.locals.title = `Send business details - ${company.name}` - res.render('companies/apps/match-company/views/cannot-find-match', { - props: { - company: { - ...pick(company, ['id', 'name']), - address: parseAddress({ - dnbCompany: company.address, - countries, - prefix: '', - }), - }, - }, - }) - } catch (error) { - next(error) - } -} - -async function submitNewDnbRecordRequest(req, res, next) { - try { - const { company } = res.locals - const { website, telephone_number } = req.body - - const transformed = transformToDnbInvestigation( - company, - website, - telephone_number - ) - - const dnbResponse = await createDnbCompanyInvestigation(req, transformed) - - req.flash('success', 'Verification request sent for third party review') - res.json(dnbResponse) - } catch (error) { - next(error) - } -} - async function submitMergeRequest(req, res, next) { try { const ticket = createMergeRequestMessage(req, res) @@ -277,8 +230,6 @@ module.exports = { renderMatchConfirmation, renderFindCompanyForm, findDnbCompany, - renderCannotFindMatch, - submitNewDnbRecordRequest, submitMergeRequest, linkCompanies, } diff --git a/src/apps/companies/apps/match-company/router.js b/src/apps/companies/apps/match-company/router.js index 966b7865a37..e768ceda34b 100644 --- a/src/apps/companies/apps/match-company/router.js +++ b/src/apps/companies/apps/match-company/router.js @@ -6,15 +6,11 @@ const { findDnbCompany, renderMatchConfirmation, linkCompanies, - renderCannotFindMatch, - submitNewDnbRecordRequest, submitMergeRequest, } = require('./controllers') router.get(urls.companies.match.index.route, renderFindCompanyForm) router.post(urls.companies.match.index.route, findDnbCompany) -router.get(urls.companies.match.cannotFind.route, renderCannotFindMatch) -router.post(urls.companies.match.cannotFind.route, submitNewDnbRecordRequest) router.get(urls.companies.match.confirmation.route, renderMatchConfirmation) router.post(urls.companies.match.link.route, linkCompanies) router.post(urls.companies.match.merge.route, submitMergeRequest) diff --git a/src/apps/companies/apps/match-company/transformers.js b/src/apps/companies/apps/match-company/transformers.js deleted file mode 100644 index 92cfe8624d5..00000000000 --- a/src/apps/companies/apps/match-company/transformers.js +++ /dev/null @@ -1,26 +0,0 @@ -const { isEmpty, omit } = require('lodash') - -const transformToDnbInvestigation = ( - { id, name, address }, - website, - telephone_number -) => { - const dnbInvestigation = { - company: id, - name, - website, - telephone_number, - address: { - ...omit(address, ['country', 'area']), - country: address.country.id, - }, - } - if (!isEmpty(address.area)) { - dnbInvestigation.address.area = address.area - } - return dnbInvestigation -} - -module.exports = { - transformToDnbInvestigation, -} diff --git a/src/apps/companies/apps/match-company/views/cannot-find-match.njk b/src/apps/companies/apps/match-company/views/cannot-find-match.njk deleted file mode 100644 index 23d30fca855..00000000000 --- a/src/apps/companies/apps/match-company/views/cannot-find-match.njk +++ /dev/null @@ -1,9 +0,0 @@ -{% extends "_layouts/template-no-local-header.njk" %} - -{% block body %} - {% component 'react-slot', { - id: 'cannot-find-match', - props: props - } %} - -{% endblock %} diff --git a/src/apps/companies/apps/referrals/__tests__/transformer.test.js b/src/apps/companies/apps/referrals/__tests__/transformer.test.js deleted file mode 100644 index 8b6e9fa952f..00000000000 --- a/src/apps/companies/apps/referrals/__tests__/transformer.test.js +++ /dev/null @@ -1,35 +0,0 @@ -const transformReferralDetails = require('../transformer') -const referralDetails = require('../../../../../../test/unit/data/referrals/referralDetails') - -describe('#transformReferralDetails', () => { - it('should return details', () => { - expect(transformReferralDetails(referralDetails)).to.deep.equal({ - subject: 'I am a subject', - completed: false, - company: { - name: 'Lambda plc', - id: '0fb3379c-341c-4da4-b825-bf8d47b26baa', - }, - contact: { - name: 'Johnny Cakeman', - id: '9b1138ab-ec7b-497f-b8c3-27fed21694ef', - }, - sendingAdviser: { - name: 'Ian Leggett', - email: 'caravans@ian.com', - team: 'Advanced Manufacturing Sector', - }, - receivingAdviser: { - name: 'Barry Oling', - email: 'barry@barry.com', - team: 'Aberdeen City Council', - }, - // We need to have explicit undefined, because deep equal is sensitive - // about not existent and set to undefined properties. - interaction: undefined, - date: '2020-02-16T18:24:58.641396Z', - notes: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.', - }) - }) -}) diff --git a/src/apps/companies/apps/referrals/details/client/ReferralDetails.jsx b/src/apps/companies/apps/referrals/details/client/ReferralDetails.jsx deleted file mode 100644 index 59b115d2cfd..00000000000 --- a/src/apps/companies/apps/referrals/details/client/ReferralDetails.jsx +++ /dev/null @@ -1,152 +0,0 @@ -import React from 'react' -import { connect } from 'react-redux' -import Details from '@govuk-react/details' -import Button from '@govuk-react/button' -import Link from '@govuk-react/link' -import PropTypes from 'prop-types' -import url from 'url' - -import urls from '../../../../../../lib/urls' -import { ID as STATE_ID } from './state' - -import SecondaryButton from '../../../../../../client/components/SecondaryButton' -import { SummaryTable, FormActions } from '../../../../../../client/components/' -import Task from '../../../../../../client/components/Task' - -import { REFERRAL_DETAILS } from '../../../../../../client/actions' - -const { - formatDate, - DATE_FORMAT_COMPACT, -} = require('../../../../../../client/utils/date-utils') - -export const AdviserDetails = ({ name, email, team }) => ( - <> - {name} - {email && ( - <> - , {email} - - )} - {team && <>, {team}} - -) - -AdviserDetails.propTypes = { - name: PropTypes.string.isRequired, - email: PropTypes.string, - team: PropTypes.string, -} - -export default connect(({ referrerUrl, ...state }) => ({ - ...state[STATE_ID], - referrerUrl, -}))(({ - subject, - referralId, - company, - contact, - sendingAdviser, - receivingAdviser, - date, - notes, - completed, - interaction, - referrerUrl, -}) => { - const cameFromHomePage = - url.parse(referrerUrl).pathname === urls.companies.referrals.list() - - return ( - - {() => - company && ( - <> - - - - {company.name} - - - {contact && ( - - - {contact.name} - - - )} - - {sendingAdviser && } - - - {receivingAdviser && } - - - {formatDate(date, DATE_FORMAT_COMPACT)} - - {notes} - - {completed ? ( - - - {formatDate(completed.on, DATE_FORMAT_COMPACT)} - - - - - - - {interaction.subject} - - - - ) : ( - <> -
-

- For now, you can't edit the referral once it's been sent. -

-

Contact the recipient if something's changed.

-
- - - - I cannot accept the referral - - - Back - - - - )} - - ) - } -
- ) -}) diff --git a/src/apps/companies/apps/referrals/details/client/reducer.js b/src/apps/companies/apps/referrals/details/client/reducer.js deleted file mode 100644 index bd640233970..00000000000 --- a/src/apps/companies/apps/referrals/details/client/reducer.js +++ /dev/null @@ -1,4 +0,0 @@ -import { REFERRAL_DETAILS } from '../../../../../../client/actions' - -export default (state = {}, { type, result }) => - type === REFERRAL_DETAILS ? result : state diff --git a/src/apps/companies/apps/referrals/details/client/tasks.js b/src/apps/companies/apps/referrals/details/client/tasks.js deleted file mode 100644 index aca80ddf01e..00000000000 --- a/src/apps/companies/apps/referrals/details/client/tasks.js +++ /dev/null @@ -1,8 +0,0 @@ -import { apiProxyAxios } from '../../../../../../client/components/Task/utils' - -const transformReferralDetails = require('../../transformer') - -export const fetchReferralDetails = (id) => - apiProxyAxios - .get(`v4/company-referral/${id}`) - .then(({ data }) => transformReferralDetails(data)) diff --git a/src/apps/companies/apps/referrals/details/controller.js b/src/apps/companies/apps/referrals/details/controller.js deleted file mode 100644 index 1ceff27ffa7..00000000000 --- a/src/apps/companies/apps/referrals/details/controller.js +++ /dev/null @@ -1,19 +0,0 @@ -const urls = require('../../../../../lib/urls') - -const renderReferralDetails = ({ params: { referralId } }, res) => { - const { - company: { name: companyName, id }, - } = res.locals - - res - .breadcrumb(companyName, urls.companies.detail(id)) - .breadcrumb('Referral') - .render('companies/apps/referrals/details/views/details-container', { - heading: 'Referral', - props: { - referralId, - }, - }) -} - -module.exports = renderReferralDetails diff --git a/src/apps/companies/apps/referrals/details/views/details-container.njk b/src/apps/companies/apps/referrals/details/views/details-container.njk deleted file mode 100644 index f636f54d37b..00000000000 --- a/src/apps/companies/apps/referrals/details/views/details-container.njk +++ /dev/null @@ -1,9 +0,0 @@ -{% extends "_layouts/template.njk" %} - -{% block body_main_content %} - {% component 'react-slot', { - id: 'referral-details', - props: props - } %} - -{% endblock %} diff --git a/src/apps/companies/apps/referrals/router.js b/src/apps/companies/apps/referrals/router.js index 7c253f7f80b..8b4090ec572 100644 --- a/src/apps/companies/apps/referrals/router.js +++ b/src/apps/companies/apps/referrals/router.js @@ -2,24 +2,12 @@ const router = require('express').Router() const urls = require('../../../../lib/urls') -const renderReferralDetails = require('./details/controller') -const { - renderSendReferralForm, - submitSendReferralForm, -} = require('./send-referral/controllers') const interactionsRouter = require('../../../interactions/router.sub-app') const { setReferralDetails, setInteractionsDetails, } = require('./middleware/interactions') -router - .route(urls.companies.referrals.send.route) - .get(renderSendReferralForm) - .post(submitSendReferralForm) -// the details route needs to go below the send route so that it does not try to handle the send route -router.get(urls.companies.referrals.details.route, renderReferralDetails) - // Adding an interaction to complete a referral // This mounts the interactions sub app on the details route router.use( diff --git a/src/apps/companies/apps/referrals/send-referral/client/SendReferralForm.jsx b/src/apps/companies/apps/referrals/send-referral/client/SendReferralForm.jsx deleted file mode 100644 index 1cc3940d87f..00000000000 --- a/src/apps/companies/apps/referrals/send-referral/client/SendReferralForm.jsx +++ /dev/null @@ -1,107 +0,0 @@ -import React from 'react' -import { connect } from 'react-redux' -import PropTypes from 'prop-types' - -import StepReferralDetails from './StepReferralDetails' -import StepReferralConfirmation from './StepReferralConfirmation' -import Step from '../../../../../../client/components/Form/elements/Step.jsx' -import LocalHeader from '../../../../../../client/components/LocalHeader/LocalHeader' -import { Main } from '../../../../../../client/components/' -import urls from '../../../../../../lib/urls' -import Task from '../../../../../../client/components/Task' -import Form from '../../../../../../client/components/Form' - -import { ID as STATE_ID, TASK_SAVE_REFERRAL } from './state' -import { TASK_REDIRECT_TO_CONTACT_FORM } from '../../../../../../client/components/ContactForm/state' - -const SendReferralForm = ({ - cancelUrl, - companyContacts, - companyName, - companyId, - sendingAdviserTeamName, - flashMessages, -}) => ( - <> - - -
-
({ - values, - companyId, - })} - submissionTaskName={TASK_SAVE_REFERRAL} - analyticsFormName="sendReferralForm" - analyticsData={({ adviser, subject }) => ({ - event: 'send_referral', - sendingAdviserTeam: sendingAdviserTeamName, - receivingAdviserTeam: adviser.label?.split(', ')[1], - referralSubject: subject, - })} - initialValuesTaskName="Get send referral initial values" - redirectTo={() => urls.companies.detail(companyId)} - flashMessage={() => [ - 'Referral sent', - `You can see all of your referrals on your Homepage.`, - ]} - > - - - {(getTask) => { - const openContactFormTask = getTask( - TASK_REDIRECT_TO_CONTACT_FORM, - STATE_ID - ) - - return ( - - ) - }} - - - - - -
-
- -) - -SendReferralForm.propTypes = { - companyContacts: PropTypes.arrayOf( - PropTypes.shape({ - name: PropTypes.string, - id: PropTypes.string, - }) - ), - cancelUrl: PropTypes.string.isRequired, - sendingAdviserTeamName: PropTypes.string, -} - -export default connect(({ values, ...state }) => ({ - ...state[STATE_ID], - values, -}))(({ ...props }) => ) diff --git a/src/apps/companies/apps/referrals/send-referral/controllers.js b/src/apps/companies/apps/referrals/send-referral/controllers.js index 41048158ccb..094385424c5 100644 --- a/src/apps/companies/apps/referrals/send-referral/controllers.js +++ b/src/apps/companies/apps/referrals/send-referral/controllers.js @@ -26,7 +26,9 @@ function renderSendReferralForm(req, res) { companyId: id, cancelUrl: urls.companies.detail(id), sendingAdviserTeamName, - flashMessages: res.locals.getMessages(), + + // TODO: This should not be necessary as flashMessages are included in global props + // flashMessages: res.locals.flashMessages, }, } ) diff --git a/src/apps/companies/apps/referrals/send-referral/views/client-container.njk b/src/apps/companies/apps/referrals/send-referral/views/client-container.njk deleted file mode 100644 index 8d9f3eb7466..00000000000 --- a/src/apps/companies/apps/referrals/send-referral/views/client-container.njk +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "_layouts/template-no-local-header.njk" %} - -{% block body %} - - {% component 'react-slot', { - id: 'send-referral-form', - props: props - } %} - -{% endblock %} diff --git a/src/apps/companies/apps/referrals/transformer.js b/src/apps/companies/apps/referrals/transformer.js deleted file mode 100644 index 3d4d18b4dae..00000000000 --- a/src/apps/companies/apps/referrals/transformer.js +++ /dev/null @@ -1,36 +0,0 @@ -const transformAdviser = ({ name, contact_email, dit_team }) => ({ - name, - email: contact_email, - team: dit_team && dit_team.name, -}) - -const transformReferralDetails = ({ - subject, - company, - contact, - created_by, - recipient, - created_on, - notes, - status, - completed_on, - completed_by, - interaction, -}) => { - return { - subject, - company, - contact, - sendingAdviser: transformAdviser(created_by), - receivingAdviser: transformAdviser(recipient), - date: created_on, - interaction, - completed: status === 'complete' && { - on: completed_on, - by: transformAdviser(completed_by), - }, - notes, - } -} - -module.exports = transformReferralDetails diff --git a/src/apps/companies/repos.js b/src/apps/companies/repos.js index bd71c7e91cd..f75faf46e02 100644 --- a/src/apps/companies/repos.js +++ b/src/apps/companies/repos.js @@ -79,16 +79,6 @@ function getCompanySubsidiaries(req, companyId, page = 1) { }) } -function getGlobalUltimateHierarchy(req, globalUltimateDunnsNumber) { - return authorisedRequest(req, { - url: `${config.apiRoot}/v4/company`, - qs: { - limit: 200, - global_ultimate_duns_number: globalUltimateDunnsNumber, - }, - }) -} - function getOneListGroupCoreTeam(req, companyId) { return authorisedRequest(req, { url: `${config.apiRoot}/v4/company/${companyId}/one-list-group-core-team`, @@ -135,17 +125,6 @@ function createDnbChangeRequest(req, dunsNumber, changes) { }) } -function getRelatedCompanies( - req, - companyId, - include_parent_companies, - include_subsidiary_companies -) { - return authorisedRequest(req, { - url: `${config.apiRoot}/v4/dnb/${companyId}/related-companies?include_subsidiary_companies=${include_subsidiary_companies}&include_parent_companies=${include_parent_companies}`, - }) -} - module.exports = { saveCompany, getDitCompany, @@ -156,11 +135,9 @@ module.exports = { unarchiveCompany, updateCompany, getCompanySubsidiaries, - getGlobalUltimateHierarchy, getOneListGroupCoreTeam, saveDnbCompany, createDnbCompanyInvestigation, linkDataHubCompanyToDnBCompany, createDnbChangeRequest, - getRelatedCompanies, } diff --git a/src/apps/companies/router.js b/src/apps/companies/router.js index 7af7c2c044a..f202deb5186 100644 --- a/src/apps/companies/router.js +++ b/src/apps/companies/router.js @@ -32,23 +32,16 @@ const formatPostcodes = require('./middleware/format-postcodes') const addCompanyFormRouter = require('./apps/add-company/router') const editCompanyFormRouter = require('./apps/edit-company/router') -const dnbHierarchyRouter = require('./apps/dnb-hierarchy/router') const matchCompanyRouter = require('./apps/match-company/router') const interactionsRouter = require('../interactions/router.sub-app') const companyListsRouter = require('../company-lists/router') const referralsRouter = require('./apps/referrals/router') const accountManagementRouter = require('./apps/account-management/router') -const { - setCompanyHierarchyLocalNav, - setDnbHierarchyDetails, -} = require('./apps/dnb-hierarchy/middleware') - router.use(handleRoutePermissions(APP_PERMISSIONS)) router.param('companyId', getCompany) router.param('companyId', setIsCompanyAlreadyAdded) -router.param('companyId', setDnbHierarchyDetails) router.get( urls.companies.export.route, @@ -83,10 +76,8 @@ router.use( router.post(urls.companies.manageCompanyList.route, addCompanyOrRemoveFromList) -router.use(urls.companies.subsidiaries.index.route, setCompanyHierarchyLocalNav) router.get(urls.companies.subsidiaries.index.route, renderSubsidiaries) -router.use(dnbHierarchyRouter) router.use(matchCompanyRouter) router.use(referralsRouter) router.use(accountManagementRouter) diff --git a/src/apps/companies/views/subsidiaries.njk b/src/apps/companies/views/subsidiaries.njk index a15678c54f8..82d54884d83 100644 --- a/src/apps/companies/views/subsidiaries.njk +++ b/src/apps/companies/views/subsidiaries.njk @@ -8,16 +8,6 @@ }) }} {% endblock %} -{% block local_nav %} - {% if localNavItems.length > 0 %} -
-
- {{ TabbedLocalNav({ items: localNavItems }) }} -
-
- {% endif %} -{% endblock %} - {% block body_main_content %}

diff --git a/src/apps/contacts/__test__/router.test.js b/src/apps/contacts/__test__/router.test.js index 5137413ebd3..34f3fb847a5 100644 --- a/src/apps/contacts/__test__/router.test.js +++ b/src/apps/contacts/__test__/router.test.js @@ -7,9 +7,7 @@ describe('Contacts router', () => { ['/create', '/:contactId/edit'], '/export', '/:contactId', - '/:contactId/details', '/:id/unarchive', - '/:contactId/audit', ]) }) }) diff --git a/src/apps/contacts/constants.js b/src/apps/contacts/constants.js index 4d56fe8476e..3fd1602f4ef 100644 --- a/src/apps/contacts/constants.js +++ b/src/apps/contacts/constants.js @@ -1,5 +1,3 @@ -const { concat } = require('lodash') - const GLOBAL_NAV_ITEM = { path: '/contacts', headerKey: 'datahub-contacts', @@ -24,7 +22,7 @@ const LOCAL_NAV = [ }, ] -const APP_PERMISSIONS = concat(LOCAL_NAV, GLOBAL_NAV_ITEM) +const APP_PERMISSIONS = [LOCAL_NAV, GLOBAL_NAV_ITEM] const QUERY_FIELDS = [ 'archived', @@ -35,9 +33,6 @@ const QUERY_FIELDS = [ 'company_uk_region', ] -const EMAIL_CONSENT_YES = 'Can be marketed to' -const EMAIL_CONSENT_NO = 'Cannot be marketed to' - const LEFT_COMPANY_OPTION = 'Left the company' const NO_CONTACT_OPTION = 'Does not want to be contacted' const ROLE_CHANGE_OPTION = 'Changed role/responsibility' @@ -47,8 +42,6 @@ module.exports = { LOCAL_NAV, APP_PERMISSIONS, QUERY_FIELDS, - EMAIL_CONSENT_YES, - EMAIL_CONSENT_NO, LEFT_COMPANY_OPTION, NO_CONTACT_OPTION, ROLE_CHANGE_OPTION, diff --git a/src/apps/contacts/controllers/activity.js b/src/apps/contacts/controllers/activity.js deleted file mode 100644 index e8d4073dafe..00000000000 --- a/src/apps/contacts/controllers/activity.js +++ /dev/null @@ -1,20 +0,0 @@ -function renderContactActivityForEntity(req, res, next) { - try { - const { view, contactId } = res.locals?.interactions - const permissions = res.locals?.user.permissions - const breadcrumbTitle = 'Activity' - - res.breadcrumb(breadcrumbTitle).render(view, { - props: { - contactId, - permissions, - }, - }) - } catch (error) { - next(error) - } -} - -module.exports = { - renderContactActivityForEntity, -} diff --git a/src/apps/contacts/controllers/audit.js b/src/apps/contacts/controllers/audit.js deleted file mode 100644 index 1cc6689d868..00000000000 --- a/src/apps/contacts/controllers/audit.js +++ /dev/null @@ -1,19 +0,0 @@ -async function getAudit(req, res, next) { - try { - const contactId = req.params.contactId - const permissions = res.locals?.user.permissions - - return res.breadcrumb('Audit history').render('contacts/views/audit', { - props: { - contactId, - permissions, - }, - }) - } catch (error) { - next(error) - } -} - -module.exports = { - getAudit, -} diff --git a/src/apps/contacts/controllers/details.js b/src/apps/contacts/controllers/details.js index 4a14d41defd..9b4616e1b1f 100644 --- a/src/apps/contacts/controllers/details.js +++ b/src/apps/contacts/controllers/details.js @@ -27,25 +27,6 @@ async function getCommon(req, res, next) { } } -function getDetails(req, res, next) { - try { - const contactId = req.params.contactId - const companyAddress = res.locals?.company.address - const permissions = res.locals?.user.permissions - - res.render('contacts/views/details', { - props: { - contactId, - companyAddress, - permissions, - }, - }) - } catch (error) { - next(error) - } -} - module.exports = { - getDetails, getCommon, } diff --git a/src/apps/contacts/controllers/index.js b/src/apps/contacts/controllers/index.js index 55089ea3442..0a3b72f469b 100644 --- a/src/apps/contacts/controllers/index.js +++ b/src/apps/contacts/controllers/index.js @@ -1,11 +1,9 @@ const details = require('./details') const edit = require('./edit') const archive = require('./archive') -const audit = require('./audit') module.exports = { details, edit, archive, - audit, } diff --git a/src/apps/contacts/router.js b/src/apps/contacts/router.js index 4f90e3bd3ed..6d7a08b6257 100644 --- a/src/apps/contacts/router.js +++ b/src/apps/contacts/router.js @@ -12,13 +12,9 @@ const { redirectToFirstNavItem, handleRoutePermissions, } = require('../middleware') -const { getCommon, getDetails } = require('./controllers/details') +const { getCommon } = require('./controllers/details') const createAndEdit = require('./controllers/create-and-edit') const { unarchiveContact } = require('./controllers/archive') -const { getAudit } = require('./controllers/audit') -const { renderContactActivityForEntity } = require('./controllers/activity') - -const { setInteractionsDetails } = require('./middleware/interactions') router.get(['/create', '/:contactId/edit'], createAndEdit) @@ -32,16 +28,7 @@ router.use( ) router.get('/:contactId', redirectToFirstNavItem) -router.get('/:contactId/details', getDetails) router.get('/:id/unarchive', unarchiveContact) -router.get('/:contactId/audit', getAudit) - -router.use( - '/:contactId/interactions', - setInteractionsDetails, - renderContactActivityForEntity -) - module.exports = router diff --git a/src/apps/contacts/services/__test__/form.test.js b/src/apps/contacts/services/__test__/form.test.js index 4b6fca3b033..c7a0a455c64 100644 --- a/src/apps/contacts/services/__test__/form.test.js +++ b/src/apps/contacts/services/__test__/form.test.js @@ -32,7 +32,6 @@ describe('contact form service', () => { primary: true, full_telephone_number: '+1 652423467167', email: 'zboasdaan@opasdasdov.com', - accepts_dit_email_marketing: true, address_same_as_company: false, notes: 'Some notes', archived_by: null, @@ -60,7 +59,6 @@ describe('contact form service', () => { primary: 'yes', full_telephone_number: '+1 652423467167', email: 'zboasdaan@opasdasdov.com', - accepts_dit_email_marketing: true, address_same_as_company: 'no', address_1: '99 N Shore Road', address_2: 'Suite 20', @@ -107,7 +105,6 @@ describe('contact form service', () => { address_postcode: null, address_country: null, notes: 'Some notes', - accepts_dit_email_marketing: true, } const actual = contactFormService.getContactAsFormData(contact) @@ -118,15 +115,5 @@ describe('contact form service', () => { it('should handle a null contact', () => { expect(contactFormService.getContactAsFormData(null)).to.be.null }) - - context('when the contact accepts DBT email marketing', () => { - it('should set the marketing preferences to accepts_dit_email_marketing', () => { - const contact = assign({}, contactData, { - accepts_dit_email_marketing: true, - }) - const actual = contactFormService.getContactAsFormData(contact) - expect(actual.accepts_dit_email_marketing).to.be.true - }) - }) }) }) diff --git a/src/apps/contacts/services/form.js b/src/apps/contacts/services/form.js index dec6765f39f..e4dbe790ba1 100644 --- a/src/apps/contacts/services/form.js +++ b/src/apps/contacts/services/form.js @@ -14,11 +14,6 @@ function getContactAsFormData(contact) { return null } - // default is that people are always marketable, unless opted out - if (!contact.hasOwnProperty('accepts_dit_email_marketing')) { - contact.accepts_dit_email_marketing = true - } - let result = { id: contact.id, company: contact.company.id, @@ -29,7 +24,6 @@ function getContactAsFormData(contact) { primary: contact.primary ? 'yes' : 'no', full_telephone_number: contact.full_telephone_number, email: contact.email, - accepts_dit_email_marketing: contact.accepts_dit_email_marketing, address_same_as_company: contact.address_same_as_company ? 'yes' : 'no', address_1: contact.address_1, address_2: contact.address_2, diff --git a/src/apps/contacts/views/audit.njk b/src/apps/contacts/views/audit.njk deleted file mode 100644 index eaf62860e5c..00000000000 --- a/src/apps/contacts/views/audit.njk +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "_layouts/template-no-local-header.njk" %} - -{% block body %} -

- {% component 'react-slot', { - id: 'contact-audit-history', - props: props - } %} -
-{% endblock %} diff --git a/src/apps/contacts/views/details.njk b/src/apps/contacts/views/details.njk deleted file mode 100644 index 06fc8822e8b..00000000000 --- a/src/apps/contacts/views/details.njk +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "_layouts/template-no-local-header.njk" %} - -{% block body %} -
- {% component 'react-slot', { - id: 'contact-details', - props: props - } %} -
-{% endblock %} diff --git a/src/apps/contacts/views/interactions.njk b/src/apps/contacts/views/interactions.njk deleted file mode 100644 index e4ac914720b..00000000000 --- a/src/apps/contacts/views/interactions.njk +++ /dev/null @@ -1,10 +0,0 @@ -{% extends "_layouts/template-no-local-header.njk" %} - -{% block body %} -
- {% component 'react-slot', { - id: 'contact-activity', - props: props - } %} -
-{% endblock %} diff --git a/src/apps/events/__test__/repos.test.js b/src/apps/events/__test__/repos.test.js index 9b59f2fac7a..e2215bcbe40 100644 --- a/src/apps/events/__test__/repos.test.js +++ b/src/apps/events/__test__/repos.test.js @@ -5,15 +5,12 @@ const proxyquire = require('proxyquire') const authorisedRequestStub = sinon.stub() const searchStub = sinon.stub() -const { saveEvent, fetchEvent, getAllEvents, getActiveEvents } = proxyquire( - '../repos', - { - '../../lib/authorised-request': { - authorisedRequest: authorisedRequestStub, - }, - '../../modules/search/services': { search: searchStub }, - } -) +const { saveEvent, getActiveEvents } = proxyquire('../repos', { + '../../lib/authorised-request': { + authorisedRequest: authorisedRequestStub, + }, + '../../modules/search/services': { search: searchStub }, +}) const config = require('../../../config') @@ -50,27 +47,6 @@ describe('Event Service', () => { }) }) - context('fetchEvent', () => { - it('should fetch single event by id', async () => { - const id = '123' - await fetchEvent(mockReq, id) - expect(authorisedRequestStub).to.have.been.calledWith( - mockReq, - `${config.apiRoot}/v3/event/${id}` - ) - }) - }) - - context('getAllEvents', () => { - it('should fetch all events with limit and offset', async () => { - await getAllEvents(mockReq) - expect(authorisedRequestStub).to.have.been.calledWith( - mockReq, - `${config.apiRoot}/v3/event?limit=100000&offset=0` - ) - }) - }) - context('getActiveEvents', () => { let clock diff --git a/src/apps/events/attendees/controllers/list.js b/src/apps/events/attendees/controllers/list.js index 4b757abaea5..37a258ad987 100644 --- a/src/apps/events/attendees/controllers/list.js +++ b/src/apps/events/attendees/controllers/list.js @@ -48,6 +48,7 @@ async function renderAttendees(req, res, next) { children: [{ value: sortby }], }) + // TODO: Can we remove this? res.breadcrumb(name).render('events/attendees/views/list', { incompleteEvent, attendees: attendeesCollection, diff --git a/src/apps/events/attendees/router.js b/src/apps/events/attendees/router.js index f00d3dd3dc0..7a592168bce 100644 --- a/src/apps/events/attendees/router.js +++ b/src/apps/events/attendees/router.js @@ -1,8 +1,9 @@ +// TODO: Remove this whole module and the whole parent folder ../ const router = require('express').Router() const { createAttendee, renderAttendees } = require('./controllers') -router.get('/', renderAttendees) +router.get('/*', renderAttendees) router.get('/create/:contactId', createAttendee) diff --git a/src/apps/events/middleware/details.js b/src/apps/events/middleware/details.js index 81d2cae30aa..546022e8a4d 100644 --- a/src/apps/events/middleware/details.js +++ b/src/apps/events/middleware/details.js @@ -1,3 +1,4 @@ +// TODO: Get rid of this whole module const { assign } = require('lodash') const { transformEventFormBodyToApiRequest } = require('../transformers') @@ -27,6 +28,7 @@ async function postDetails(req, res, next) { } } +// TODO: Get rid of this async function getEventDetails(req, res, next, eventId) { try { res.locals.event = await fetchEvent(req, eventId) diff --git a/src/apps/events/router.js b/src/apps/events/router.js index 3d996ed1731..bccdb73225a 100644 --- a/src/apps/events/router.js +++ b/src/apps/events/router.js @@ -5,7 +5,7 @@ const { APP_PERMISSIONS, LOCAL_NAV } = require('./constants') const { handleRoutePermissions, setLocalNav } = require('../middleware') const { getEventDetails } = require('./middleware/details') const { renderEventsView } = require('./controllers/events') -const attendeesRouter = require('./attendees/router') +const { createAttendee } = require('./attendees/controllers/create') router.get('/create', renderEventsView) router.use(handleRoutePermissions(APP_PERMISSIONS)) @@ -19,12 +19,9 @@ router.use( setLocalNav(LOCAL_NAV) ) -router.use('/:eventId/attendees', attendeesRouter) +// TODO: Get rid of this and fetch the event on the client router.param('eventId', getEventDetails) -// TODO: When everything in the events space is converted to react -// router.get('/*', renderEventsView) -router.get('/:eventId/edit', renderEventsView) -router.get('/:eventId', renderEventsView) -router.get('/:eventId/details', renderEventsView) +router.get('/:eventId/attendees/create/:contactId', createAttendee) +router.get('/:eventId*', renderEventsView) module.exports = router diff --git a/src/apps/interactions/apps/details-form/client/tasks.js b/src/apps/interactions/apps/details-form/client/tasks.js index 1890931dbef..e37ef809f65 100644 --- a/src/apps/interactions/apps/details-form/client/tasks.js +++ b/src/apps/interactions/apps/details-form/client/tasks.js @@ -36,7 +36,7 @@ import { DATE_FORMAT_YEAR, } from '../../../../../client/utils/date-utils' -const { transformValueForAPI } = require('../../../../../client/utils/date') +const { formatDateWithYearMonth } = require('../../../../../client/utils/date') const FIELDS_TO_OMIT = [ 'currently_exporting', @@ -276,7 +276,7 @@ export function saveInteraction({ values, companyIds, referralId }) { dit_participants: values.dit_participants.map((a) => ({ adviser: a.value, })), - date: transformValueForAPI(values.date), + date: formatDateWithYearMonth(values.date), policy_areas: transformArrayOfOptionsToValues(values.policy_areas), communication_channel: transformOptionToValue(values.communication_channel), event: transformOptionToValue(values.event), diff --git a/src/apps/investments/client/projects/create/transformers.js b/src/apps/investments/client/projects/create/transformers.js index 22ae6bec309..b510cd01146 100644 --- a/src/apps/investments/client/projects/create/transformers.js +++ b/src/apps/investments/client/projects/create/transformers.js @@ -1,4 +1,4 @@ -import { OPTION_NO } from '../../../../../common/constants' +import { OPTION_NO, OPTION_YES } from '../../../../../common/constants' import { FDI_TYPES, INVESTOR_TYPES, @@ -23,12 +23,14 @@ export const transformFormValuesToPayload = (values, csrfToken) => { client_contacts, other_business_activity, client_relationship_manager, + is_referral_source, referral_source_adviser, referral_source_activity, referral_source_activity_event, referral_source_activity_marketing, referral_source_activity_website, estimated_land_date, + likelihood_to_land, actual_land_date, investor_type, level_of_involvement, @@ -54,14 +56,15 @@ export const transformFormValuesToPayload = (values, csrfToken) => { ? client_relationship_manager.value : adviser.id, referral_source_adviser: - values.referralSourceAdviser === OPTION_NO - ? referral_source_adviser.value - : adviser.id, + is_referral_source === OPTION_YES + ? adviser.id + : referral_source_adviser.value, referral_source_activity: referral_source_activity, referral_source_activity_event: referral_source_activity_event, referral_source_activity_marketing: referral_source_activity_marketing, referral_source_activity_website: referral_source_activity_website, estimated_land_date: formatEstimatedLandDate(estimated_land_date), + likelihood_to_land: likelihood_to_land?.value, actual_land_date: formatActualLandDate(actual_land_date), investor_type: fdi_type?.value === FDI_TYPES.expansionOfExistingSiteOrActivity.value diff --git a/src/apps/routers.js b/src/apps/routers.js index 914aebadfe0..deb6b1e4bb5 100644 --- a/src/apps/routers.js +++ b/src/apps/routers.js @@ -24,6 +24,7 @@ const reactRoutes = [ '/export/create', '/export/:exportId/edit', '/export/:exportId/details', + '/export/:exportId/interactions', '/export/:exportId/delete', '/exportwins', '/companies/:companyId/exportwins/create', @@ -35,7 +36,6 @@ const reactRoutes = [ '/companies/:companyId/exportwins/:winId/edit', '/companies/:companyId/exportwins/:winId/edit-success', '/companies/:companyId/exportwins/:winId/customer-feedback', - '/companies/:companyId/dnb-hierarchy', '/companies/:companyId/company-tree', '/companies/:companyId/account-management/strategy/create', '/companies/:companyId/account-management/strategy/edit', @@ -137,6 +137,12 @@ const reactRoutes = [ '/investments/projects/:projectId/propositions/:propositionId/document', '/investments/eyb-leads', '/investments/eyb-leads/:eybLeadId/details', + '/companies/:companyId/referrals/send', + '/companies/:companyId/referrals/:referralId', + '/contacts/:contactId/details', + '/contacts/:contactId/interactions', + '/contacts/:contactId/audit', + '/companies/:companyId/match/cannot-find', ] reactRoutes.forEach((path) => { diff --git a/src/apps/support/macros.js b/src/apps/support/macros.js index 89047224017..3fa109779ac 100644 --- a/src/apps/support/macros.js +++ b/src/apps/support/macros.js @@ -17,6 +17,10 @@ const feedbackFormConfig = (browserInfo) => ({ value: 'user_admin', label: "I don't have access", }, + { + value: 'data_amendment', + label: 'I require a data amendment', + }, { value: 'bug', label: 'I have another problem', diff --git a/src/apps/transformers.js b/src/apps/transformers.js index c6631e0bb34..c67a7ab95a9 100644 --- a/src/apps/transformers.js +++ b/src/apps/transformers.js @@ -1,6 +1,5 @@ const { filter, upperFirst } = require('lodash') -const { format, isDateValid } = require('../client/utils/date') const { OPTION_NO, OPTION_YES } = require('../common/constants') const groupExportCountries = require('../lib/group-export-countries') @@ -41,16 +40,6 @@ function transformDateObjectToDateString(key) { } } -function transformDateStringToDateObject(dateString) { - const isValidDate = dateString && isDateValid(dateString) - - return { - year: isValidDate ? format(dateString, 'yyyy') : '', - month: isValidDate ? format(dateString, 'MM') : '', - day: isValidDate ? format(dateString, 'dd') : '', - } -} - const transformOptionToValue = (option) => { if (!option || !option.value) { return null @@ -94,7 +83,6 @@ module.exports = { transformContactToOption, transformCountryToOptionWithIsoCode, transformDateObjectToDateString, - transformDateStringToDateObject, transformOptionToValue, transformArrayOfOptionsToValues, transformToYesNo, diff --git a/src/client/DataHub/App.jsx b/src/client/DataHub/App.jsx index cec7a6708da..cfa3da1578e 100644 --- a/src/client/DataHub/App.jsx +++ b/src/client/DataHub/App.jsx @@ -13,23 +13,14 @@ import EditCompanyForm from '../../apps/companies/apps/edit-company/client/EditC import FindCompany from '../../apps/companies/apps/match-company/client/FindCompany.jsx' import DeleteCompanyList from '../../apps/company-lists/client/DeleteCompanyList.jsx' import MatchConfirmation from '../../apps/companies/apps/match-company/client/MatchConfirmation.jsx' -import CannotFindMatch from '../../apps/companies/apps/match-company/client/CannotFindMatch.jsx' import EditCompanyList from '../../apps/company-lists/client/EditCompanyList.jsx' import CreateListForm from '../../apps/company-lists/client/CreateListForm.jsx' import ManageAdviser from '../../apps/companies/apps/advisers/client/ManageAdviser.jsx' -import ReferralDetails from '../../apps/companies/apps/referrals/details/client/ReferralDetails.jsx' -import SendReferralForm from '../../apps/companies/apps/referrals/send-referral/client/SendReferralForm.jsx' -import InteractionReferralDetails from '../modules/Interactions/InteractionDetails/InteractionReferralDetails.jsx' import FlashMessages from '../components/LocalHeader/FlashMessages.jsx' import PersonalisedDashboard from '../components/PersonalisedDashboard/index.jsx' import InvestmentProjectForm from '../../apps/investments/client/projects/create/InvestmentProjectForm.jsx' -import ContactActivity from '../modules/Contacts/ContactActivity/ContactActivity.jsx' -import ContactLocalHeader from '../components/ContactLocalHeader/index.jsx' -import ContactDetails from '../modules/Contacts/ContactDetails/ContactDetails.jsx' -import ContactAuditHistory from '../modules/Contacts/ContactAuditHistory/ContactAuditHistory.jsx' import InteractionDetails from '../modules/Interactions/InteractionDetails/index.jsx' import PropositionDetails from '../modules/Investments/Projects/Propositions/PropositionDetails.jsx' -import CompanyHierarchy from '../modules/Companies/CompanyHierarchy/index.jsx' import Footer from '../components/Footer/index.jsx' @@ -119,11 +110,6 @@ export const App = () => { )} - - {(props) => ( - - )} - {(props) => ( @@ -156,25 +142,11 @@ export const App = () => { {(props) => } - - {(props) => } - {(props) => ( )} - - {(props) => ( - - )} - - - {(props) => } - - - {(props) => } - {(props) => } @@ -187,22 +159,9 @@ export const App = () => { /> )} - {() => } {(props) => } - - {(props) => } - - - {(props) => } - - - {(props) => } - - - {(props) => } - {(props) => } diff --git a/src/client/actions.js b/src/client/actions.js index 32cd82634ba..cb461323f21 100644 --- a/src/client/actions.js +++ b/src/client/actions.js @@ -109,8 +109,6 @@ export const REMINDERS__TASK_COMPLETED_REMINDERS_GOT_NEXT = export const REMINDERS__TASK_COMPLETED_REMINDERS_DELETED = 'REMINDERS__TASK_COMPLETED_REMINDERS_DELETED' -export const REFERRAL_DETAILS = 'REFERRAL_DETAILS' - export const TASK__START = 'TASK__START' export const TASK__PROGRESS = 'TASK__PROGRESS' export const TASK__CANCEL = 'TASK__CANCEL' diff --git a/src/client/components/ActivityFeed/activities/AventriAttendee.jsx b/src/client/components/ActivityFeed/activities/AventriAttendee.jsx index 30c3337f56d..f7deb70626a 100644 --- a/src/client/components/ActivityFeed/activities/AventriAttendee.jsx +++ b/src/client/components/ActivityFeed/activities/AventriAttendee.jsx @@ -11,7 +11,7 @@ import ActivityCardWrapper from './card/ActivityCardWrapper' import ActivityCardSubject from './card/ActivityCardSubject' import ActivityCardMetadata from './card/ActivityCardMetadata' import ActivityCardLabels from './card/ActivityCardLabels' -import { formatStartAndEndDate } from '../../../utils/date' +import { formatStartAndEndDate } from './date' export const AVENTRI_ATTENDEE_REG_STATUSES = { Attended: 'Attended', diff --git a/src/client/components/ActivityFeed/activities/AventriEvent.jsx b/src/client/components/ActivityFeed/activities/AventriEvent.jsx index 2580ee842fd..7e4bd3530ac 100644 --- a/src/client/components/ActivityFeed/activities/AventriEvent.jsx +++ b/src/client/components/ActivityFeed/activities/AventriEvent.jsx @@ -3,7 +3,7 @@ import Link from '@govuk-react/link' import PropTypes from 'prop-types' import styled from 'styled-components' -import { formatStartAndEndDate } from '../../../utils/date' +import { formatStartAndEndDate } from './date' import { ACTIVITY_TYPE } from '../constants' import CardUtils from './card/CardUtils' diff --git a/src/client/components/ActivityFeed/activities/DataHubEvent.jsx b/src/client/components/ActivityFeed/activities/DataHubEvent.jsx index 967f6b3454e..4bafdf58af2 100644 --- a/src/client/components/ActivityFeed/activities/DataHubEvent.jsx +++ b/src/client/components/ActivityFeed/activities/DataHubEvent.jsx @@ -5,7 +5,7 @@ import PropTypes from 'prop-types' import CardUtils from './card/CardUtils' -import { formatStartAndEndDate } from '../../../utils/date' +import { formatStartAndEndDate } from './date' import { ACTIVITY_TYPE } from '../constants' import ActivityCardWrapper from './card/ActivityCardWrapper' diff --git a/src/common/__test__/date.test.js b/src/client/components/ActivityFeed/activities/__test__/date.test.js similarity index 96% rename from src/common/__test__/date.test.js rename to src/client/components/ActivityFeed/activities/__test__/date.test.js index eec6dc9c16e..1ab3e13f02c 100644 --- a/src/common/__test__/date.test.js +++ b/src/client/components/ActivityFeed/activities/__test__/date.test.js @@ -1,4 +1,4 @@ -const { formatStartAndEndDate } = require('../../client/utils/date') +const { formatStartAndEndDate } = require('../date') describe('Date tests', () => { describe('#formatStartAndEndDate', () => { diff --git a/src/client/components/ActivityFeed/activities/date.js b/src/client/components/ActivityFeed/activities/date.js new file mode 100644 index 00000000000..98c42513506 --- /dev/null +++ b/src/client/components/ActivityFeed/activities/date.js @@ -0,0 +1,38 @@ +import { isAfter, parseISO, differenceInCalendarMonths } from 'date-fns' + +import { + formatDate, + DATE_FORMAT_COMPACT, + DATE_FORMAT_DAY_MONTH, +} from '../../../../client/utils/date-utils' + +export const formatStartAndEndDate = (startDate, endDate) => { + if (startDate) { + const startDateParsed = startDate ? parseISO(startDate) : startDate + const endDateParsed = endDate ? parseISO(endDate) : endDate + const startDateFormatted = startDate + ? formatDate(startDate, DATE_FORMAT_COMPACT) + : startDate + const endDateFormatted = endDate ? formatDate(endDate) : endDate + + //When end date is missing or before start date + if (!endDate || !isAfter(endDateParsed, startDateParsed)) { + return startDateFormatted + } + //When start and end date are on same day + if (startDateParsed.toDateString() === endDateParsed.toDateString()) { + return startDateFormatted + } + // When start and end date are in the same month + if (differenceInCalendarMonths(endDateParsed, startDateParsed) == 0) { + return `${startDateParsed.getDate()} to ${endDateFormatted}` + } + // When start and end date are in the same year + if (startDateParsed.getFullYear() === endDateParsed.getFullYear()) { + return `${formatDate(startDate, DATE_FORMAT_DAY_MONTH)} to ${endDateFormatted}` + } + // When start and end date are in different years + return `${startDateFormatted} to ${endDateFormatted}` + } + return null +} diff --git a/src/client/components/ContactForm/index.jsx b/src/client/components/ContactForm/index.jsx index 63c2f8d3bc0..b300f5728b4 100644 --- a/src/client/components/ContactForm/index.jsx +++ b/src/client/components/ContactForm/index.jsx @@ -5,7 +5,7 @@ import React, { useEffect } from 'react' import PropTypes from 'prop-types' import _ from 'lodash' import Link from '@govuk-react/link' -import { FONT_WEIGHTS, SPACING } from '@govuk-react/constants' +import { FONT_SIZE, FONT_WEIGHTS, SPACING } from '@govuk-react/constants' import styled from 'styled-components' import Label from '@govuk-react/label' @@ -17,7 +17,6 @@ import { FieldInput, FieldRadios, FieldTextarea, - FieldCheckboxes, FieldAddress, Main, FormLayout, @@ -72,6 +71,11 @@ const StyledLabel = styled(Label)` font-weight: ${FONT_WEIGHTS.bold}; ` +const StyledLink = styled(Link)({ + fontSize: FONT_SIZE.SIZE_20, + lineHeight: '32px', +}) + const _ContactForm = ({ update, contactId, @@ -80,7 +84,6 @@ const _ContactForm = ({ // We need to convert these to YES / NO strings primary, addressSameAsCompany, - acceptsDitEmailMarketing, // These need to be renamed, so that they are compatible with the fields of // the address sub-form addressPostcode: postcode, @@ -133,7 +136,9 @@ const _ContactForm = ({ {company.name} + + {company.name} + ) } heading={`${update ? 'Edit' : 'Add'} contact`} @@ -175,7 +180,6 @@ const _ContactForm = ({ city, county, postcode, - acceptsDitEmailMarketing, addressSameAsCompany, primary, email, @@ -189,8 +193,6 @@ const _ContactForm = ({ email, valid_email: true, notes: moreDetails, - accepts_dit_email_marketing: - acceptsDitEmailMarketing.includes(YES), primary, company, address_same_as_company: @@ -251,12 +253,9 @@ const _ContactForm = ({ country: addressCountry?.id, primary: boolToYesNo(primary), addressSameAsCompany: boolToYesNo(addressSameAsCompany), - acceptsDitEmailMarketing: [ - boolToYesNo(acceptsDitEmailMarketing), - ].filter(Boolean), }} > - {({ values }) => ( + {() => ( <> - ({ writeFlashMessage: (message) => @@ -58,60 +59,69 @@ const buildBreadcrumbs = (currentTab, id, name) => { return initialBreadcrumbs.concat(dynamicBreadcrumbs) } -const ContactLocalHeader = ({ contact, writeFlashMessage }) => { - return ( - <> - - - - ( + + + + + {contact.company.name} + + + {contact.name} + {contact.primary && ( + - {contact.company.name} - - - {contact.name} - {contact.primary && ( - - Primary - - )} - - - {!contact.archived && ( - - - + Primary + )} - - {contact.archived && ( - { - writeFlashMessage('Contact record updated') - }} - type="contact" - /> - )} - - + + + {!contact.archived && ( + + + + )} + + {contact.archived && ( + { + writeFlashMessage('Contact record updated') + }} + type="contact" + /> + )} + +) + +const ContactLocalHeader = ({ contactId, writeFlashMessage }) => { + return ( + + {(contact) => ( + + )} + ) } diff --git a/src/client/components/Form/elements/FieldDate/index.jsx b/src/client/components/Form/elements/FieldDate/index.jsx index 6d450c32175..7d8e1f3af78 100644 --- a/src/client/components/Form/elements/FieldDate/index.jsx +++ b/src/client/components/Form/elements/FieldDate/index.jsx @@ -1,5 +1,6 @@ import React from 'react' import PropTypes from 'prop-types' +import { isValid } from 'date-fns' import { castArray, snakeCase } from 'lodash' import styled from 'styled-components' import ErrorText from '@govuk-react/error-text' @@ -16,10 +17,7 @@ import FieldWrapper from '../FieldWrapper' import useField from '../../hooks/useField' import { useFormContext } from '../../hooks' -const { - isNormalisedDateValid, - isShortDateValid, -} = require('../../../../utils/date') +const { parseDateWithYearMonth } = require('../../../../utils/date') const DAY = 'day' const MONTH = 'month' @@ -56,10 +54,8 @@ const StyledList = styled.div` const getValidator = (required, invalid, format) => ({ day, month, year }) => { + const isDateValid = isValid(parseDateWithYearMonth(year, month, day)) const isLong = format === FORMAT_LONG - const isValid = isLong - ? isNormalisedDateValid(year, month, day) - : isShortDateValid(year, month) const isDateEmpty = isLong ? !day && !month && !year : !month && !year @@ -71,7 +67,7 @@ const getValidator = return required } - if (!isValid && !isDateEmpty) { + if (!isDateValid && !isDateEmpty) { return invalid || 'Enter a valid date' } diff --git a/src/client/components/Layout/ContactLayout.jsx b/src/client/components/Layout/ContactLayout.jsx index 56801eed8e1..6dbd412e808 100644 --- a/src/client/components/Layout/ContactLayout.jsx +++ b/src/client/components/Layout/ContactLayout.jsx @@ -1,4 +1,5 @@ import React from 'react' +import { connect } from 'react-redux' import PropTypes from 'prop-types' import styled from 'styled-components' import GridCol from '@govuk-react/grid-col' @@ -7,65 +8,87 @@ import { SPACING } from '@govuk-react/constants' import { ContactLocalHeader, + DefaultLayout, LocalNav, LocalNavLink, - Main, } from '../../components' import urls from '../../../lib/urls' +import { ContactResource } from '../Resource' +import { state2props } from './state' const StyledNavWrapper = styled('div')` margin-bottom: ${SPACING.SCALE_5}; ` -const ContactLayout = ({ contact, flashMessages, permissions, children }) => { - const canViewActivityLink = permissions.includes( +const ContactName = ({ id }) => ( + + {(contact) => contact.name} + +) + +const ContactLayout = ({ + contactId, + flashMessages, + userPermissions, + children, +}) => { + const canViewActivityLink = userPermissions.includes( 'interaction.view_all_interaction' ) return ( - <> - -
- - - - - - Details - - {canViewActivityLink && ( - - Activity - - )} + + - Contacts + + } + localHeader={ + + } + useReactRouter={false} + > + + + + + + Details + + {canViewActivityLink && ( - Audit history + Activity - - - - {children} - -
- + )} + + Audit history + + + + + {children} + + ) } ContactLayout.propTypes = { contact: PropTypes.object.isRequired, - permissions: PropTypes.array.isRequired, children: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.element), PropTypes.element, ]).isRequired, } -export default ContactLayout +export default connect(state2props)(ContactLayout) diff --git a/src/client/components/Layout/DefaultLayout.jsx b/src/client/components/Layout/DefaultLayout.jsx index fb053d24acb..23d9869d549 100644 --- a/src/client/components/Layout/DefaultLayout.jsx +++ b/src/client/components/Layout/DefaultLayout.jsx @@ -17,6 +17,7 @@ const GlobalStyles = createGlobalStyle` ` const DefaultLayout = ({ + superheading, heading, headingLink, subheading, @@ -26,6 +27,7 @@ const DefaultLayout = ({ children, useReactRouter = false, localHeaderChildren, + localHeader, }) => { const [showVerticalNav, setShowVerticalNav] = useState(false) @@ -43,18 +45,23 @@ const DefaultLayout = ({ showVerticalNav={showVerticalNav} onShowVerticalNav={setShowVerticalNav} /> - - {localHeaderChildren} - + {localHeader ? ( + localHeader + ) : ( + + {localHeaderChildren} + + )}
{children} @@ -66,6 +73,7 @@ const DefaultLayout = ({ } DefaultLayout.propTypes = { + superheading: PropTypes.node, heading: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), headingLink: PropTypes.shape({ url: PropTypes.string.isRequired, diff --git a/src/client/components/LocalHeader/LocalHeader.jsx b/src/client/components/LocalHeader/LocalHeader.jsx index eaa0fc671f3..d7b2c08b6e2 100644 --- a/src/client/components/LocalHeader/LocalHeader.jsx +++ b/src/client/components/LocalHeader/LocalHeader.jsx @@ -28,11 +28,6 @@ const BreadcrumbsWrapper = styled(Breadcrumbs)` margin-top: 0; ` -const StyledSuperheading = styled.div({ - fontSize: 20, - lineHeight: '32px', -}) - const StyledLink = styled('a')({ fontSize: 20, display: 'inline-block', @@ -47,10 +42,10 @@ const StyledLink = styled('a')({ const LocalHeader = ({ breadcrumbs, flashMessages, + superheading, heading, - subheading, headingLink, - superheading, + subheading, children, useReactRouter = false, }) => ( @@ -83,7 +78,7 @@ const LocalHeader = ({ )} - {superheading && {superheading}} + {superheading} {headingLink && ( {headingLink.text} diff --git a/src/client/components/LocalHeader/__stories__/LocalHeader.stories.jsx b/src/client/components/LocalHeader/__stories__/LocalHeader.stories.jsx index 0c0dfcb26e0..127a87aaeb6 100644 --- a/src/client/components/LocalHeader/__stories__/LocalHeader.stories.jsx +++ b/src/client/components/LocalHeader/__stories__/LocalHeader.stories.jsx @@ -1,4 +1,5 @@ import React from 'react' +import Link from '@govuk-react/link' import LocalHeader from '../LocalHeader' @@ -35,8 +36,8 @@ WithLink.story = { export const WithSuperheading = () => ( Company name} heading={exampleText} - superheading={exampleText} /> ) diff --git a/src/client/components/ReferralList/Referral.jsx b/src/client/components/ReferralList/Referral.jsx index ad89d861f89..7e76cd5f829 100644 --- a/src/client/components/ReferralList/Referral.jsx +++ b/src/client/components/ReferralList/Referral.jsx @@ -5,7 +5,7 @@ import PropTypes from 'prop-types' import styled from 'styled-components' import { BLUE, GREEN } from '../../../client/utils/colours' -import { AdviserDetails } from '../../../apps/companies/apps/referrals/details/client/ReferralDetails' +import { AdviserDetails } from '../../modules/Companies/Referrals/ReferralDetails' import { Card, CardHeader } from '../ActivityFeed/activities/card' import SummaryList from '../../components/SummaryList' import urls from '../../../lib/urls' diff --git a/src/client/components/Resource/InteractionsV3.js b/src/client/components/Resource/InteractionsV3.js new file mode 100644 index 00000000000..99bef7fb5f1 --- /dev/null +++ b/src/client/components/Resource/InteractionsV3.js @@ -0,0 +1,3 @@ +import { createCollectionResource } from './Resource' + +export default createCollectionResource('InteractionsV3', 'v3/interaction') diff --git a/src/client/components/Resource/Paginated.js b/src/client/components/Resource/Paginated.js index 97b01fb8bdd..bc567a19300 100644 --- a/src/client/components/Resource/Paginated.js +++ b/src/client/components/Resource/Paginated.js @@ -53,6 +53,9 @@ const StyledCollectionSort = styled(CollectionSort)` * Forwarded to {qsParamName} prop of {StyledCollectionSort}. * @param {number} [props.defaultSortOptionIndex = 0] - The index of the sort option * that should be selected when there's nothing set in the query string. + * @param {string} [props.addItemUrl =] - If set, an "Add " button + * will be displayed on the top-right corner of the header behaving as a link + * to the value of this prop. This is just forwarded to CollectionHeader. * @example * * {currentPage => @@ -100,6 +103,7 @@ const PaginatedResource = multiInstance({ result, shouldPluralize, noResults = "You don't have any results", + addItemUrl, }) => { // We know better than ESLint that we are in deed in a React component // eslint-disable-next-line react-hooks/rules-of-hooks @@ -150,6 +154,7 @@ const PaginatedResource = multiInstance({ totalItems={result.count} collectionName={heading || name} shouldPluralize={shouldPluralize} + addItemUrl={addItemUrl} /> {totalPages > 0 && ( )} - {result ? children(result.results) : null} + {result ? children(result.results || result) : null} `v4/company-referral/${id}` +) diff --git a/src/client/components/Resource/__stories__/tasks.js b/src/client/components/Resource/__stories__/tasks.js index ea94f22376f..59be840fe65 100644 --- a/src/client/components/Resource/__stories__/tasks.js +++ b/src/client/components/Resource/__stories__/tasks.js @@ -13,7 +13,6 @@ const CONTACT = { telephoneCountrycode: '123', telephoneNumber: '456789', email: 'andy.pipkin@littlebritain.co.uk', - acceptsDitEmailMarketing: true, addressSameAsCompany: true, address1: 'Foo', address2: 'Bar', @@ -112,7 +111,6 @@ export default { addressCountry: null, addressPostcode: null, notes: null, - acceptsDitEmailMarketing: false, archived: false, archivedDocumentsUrlPath: '', archivedOn: null, diff --git a/src/client/components/Resource/index.jsx b/src/client/components/Resource/index.jsx index dc01f9f2f1c..c822d5064c7 100644 --- a/src/client/components/Resource/index.jsx +++ b/src/client/components/Resource/index.jsx @@ -72,6 +72,7 @@ export { default as PropositionResource } from './Proposition' export { default as PropositionCollectionResource } from './Propositions' export { default as PropositionEvidenceResource } from './PropositionEvidence' export { default as RatingResource } from './Rating' +export { default as ReferralResource } from './Referral' export { default as ReferralSourceActivityResource } from './ReferralSourceActivity' export { default as ReferralSourceMarketingResource } from './ReferralSourceMarketing' export { default as ReferralSourceWebsiteResource } from './ReferralSourceWebsite' diff --git a/src/client/components/Resource/tasks.js b/src/client/components/Resource/tasks.js index bc28615076d..fcc7e4a6360 100644 --- a/src/client/components/Resource/tasks.js +++ b/src/client/components/Resource/tasks.js @@ -6,6 +6,7 @@ import Company from './Company' import CompanyContacts from './CompanyContacts' import Countries from './Countries' import Interactions from './Interactions' +import InteractionsV3 from './InteractionsV3' import Opportunity from './Opportunity' import OpportunityStatuses from './OpportunityStatuses' import UKRegions from './UKRegions' @@ -96,6 +97,7 @@ import CompanyAuditHistory from './CompanyAuditHistory' import EvidenceTag from './EvidenceTag' import ProjectAuditHistory from './ProjectAuditHistory' import WinUKRegions from './WinUKRegions' +import Referral from './Referral' export default { ...AssociatedProgramme.tasks, @@ -109,6 +111,7 @@ export default { ...ContactAuditHistory.tasks, ...Countries.tasks, ...Interactions.tasks, + ...InteractionsV3.tasks, ...Opportunity.tasks, ...OpportunityStatuses.tasks, ...CapitalInvestmentRequiredChecksConducted.tasks, @@ -196,4 +199,5 @@ export default { ...CompanyAuditHistory.tasks, ...EvidenceTag.tasks, ...ProjectAuditHistory.tasks, + ...Referral.tasks, } diff --git a/src/client/components/TabNav/index.jsx b/src/client/components/TabNav/index.jsx index decf033f32b..8b07f7b1834 100644 --- a/src/client/components/TabNav/index.jsx +++ b/src/client/components/TabNav/index.jsx @@ -274,6 +274,7 @@ export const VerticalTabNav = styled(SmallScreenTabNav)({ '&::before': { display: 'none', }, + textAlign: 'left', textDecoration: 'none', border: 'none', background: 'none', diff --git a/src/client/modules/Companies/AccountManagement/transformers.js b/src/client/modules/Companies/AccountManagement/transformers.js index c8d1129d4c8..a7b575bcd7c 100644 --- a/src/client/modules/Companies/AccountManagement/transformers.js +++ b/src/client/modules/Companies/AccountManagement/transformers.js @@ -1,5 +1,5 @@ import { transformDateStringToDateObject } from '../../../transformers' -import { transformValueForAPI } from '../../../utils/date' +import { formatDateWithYearMonth } from '../../../utils/date' import { transformBoolToRadioOption, transformRadioOptionToBool, @@ -16,7 +16,7 @@ export const transformFormValuesForAPI = ({ }) => ({ subject, detail, - target_date: transformValueForAPI(target_date), + target_date: formatDateWithYearMonth(target_date), company, has_blocker: transformRadioOptionToBool(has_blocker), blocker_description, diff --git a/src/client/modules/Companies/CompanyActivity/constants.js b/src/client/modules/Companies/CompanyActivity/constants.js index 8b0dbe85c25..9bae5056bbb 100644 --- a/src/client/modules/Companies/CompanyActivity/constants.js +++ b/src/client/modules/Companies/CompanyActivity/constants.js @@ -77,3 +77,15 @@ export const GREAT_EXPORT_TAG = { colour: TAGS.ACTIVITY_LABELS.KIND, dataTest: 'great-kind-label', } + +export const INVESTMENT_TAG = { + text: 'Investment', + colour: TAGS.ACTIVITY_LABELS.THEME, + dataTest: 'investment-theme-label', +} + +export const EYB_TAG = { + text: 'EYB', + colour: TAGS.ACTIVITY_LABELS.KIND, + dataTest: 'eyb-kind-label', +} diff --git a/src/client/modules/Companies/CompanyActivity/transformers.js b/src/client/modules/Companies/CompanyActivity/transformers.js index 469051fc412..c1852a12b7d 100644 --- a/src/client/modules/Companies/CompanyActivity/transformers.js +++ b/src/client/modules/Companies/CompanyActivity/transformers.js @@ -6,6 +6,8 @@ import { NEW_PROJECT_TAG, NEW_ORDER_TAG, GREAT_EXPORT_TAG, + INVESTMENT_TAG, + EYB_TAG, } from './constants' import urls from '../../../../lib/urls' import { formatDate, DATE_FORMAT_MEDIUM } from '../../../utils/date-utils' @@ -84,6 +86,8 @@ export const transformActivities = (activities) => { return transformOrderToListItem(activity) case 'great_export_enquiry': return transformGreatExportEnquiryToListItem(activity) + case 'eyb_lead': + return transformEYBLeadToListItem(activity) default: return {} } @@ -232,11 +236,8 @@ export const transformInvestmentToListItem = (activity) => { { label: 'Number of jobs', value: project.number_new_jobs }, ].filter(({ value }) => Boolean(value)), tags: [ - { - text: 'Investment', - colour: 'govBlue', - dataTest: 'investment-theme-label', - }, + activity.investment.eyb_leads.length && EYB_TAG, + INVESTMENT_TAG, { text: `Project - ${project.investment_type.name}`, colour: 'blue', @@ -330,6 +331,38 @@ export const transformGreatExportEnquiryToListItem = (activity) => { } } +const getEYBValue = (activity) => { + const eybValue = activity?.eyb_lead?.is_high_value + + switch (eybValue) { + case true: + return 'High' + case false: + return 'Low' + default: + return 'Unknown' + } +} + +export const transformEYBLeadToListItem = (activity) => ({ + id: activity.eyb_lead.id, + metadata: [ + { + label: 'Submitted to EYB date', + value: formatDate(activity.eyb_lead.triage_created), + }, + { + label: 'Value', + value: getEYBValue(activity), + }, + ].filter(({ value }) => Boolean(value)), + tags: [EYB_TAG, INVESTMENT_TAG].filter(({ text }) => Boolean(text)), + headingUrl: urls.investments.eybLeads.details(activity.eyb_lead.id), + headingText: activity.company.name + ? activity.company.name + : activity.eyb_lead.company_name, +}) + export const transformResponseToCollection = (activities) => ({ // activities.count comes from the backend because the frontend // only collects the paginated amount on each request. If a new data diff --git a/src/client/modules/Companies/CompanyBusinessDetails/SectionAbout.jsx b/src/client/modules/Companies/CompanyBusinessDetails/SectionAbout.jsx index e221a6f1349..4664a761419 100644 --- a/src/client/modules/Companies/CompanyBusinessDetails/SectionAbout.jsx +++ b/src/client/modules/Companies/CompanyBusinessDetails/SectionAbout.jsx @@ -10,6 +10,7 @@ import { currencyGBP } from '../../../utils/number-utils' import { NewWindowLink, SummaryTable } from '../../../components' import { exportSegmentsLabels, exportSubSegmentsLabels } from './labels' import urls from '../../../../lib/urls' +import { NOT_SET_TEXT } from '../../../../apps/companies/constants' const TableDetails = styled('div')` display: flex; @@ -54,7 +55,7 @@ const SectionAbout = ({ company, isDnbCompany, isArchived }) => ( )} - {isEmpty(company.tradingNames) ? 'Not set' : company.tradingNames} + {isEmpty(company.tradingNames) ? NOT_SET_TEXT : company.tradingNames} @@ -73,6 +74,10 @@ const SectionAbout = ({ company, isDnbCompany, isArchived }) => ( )} + + {company.dunsNumber ? company.dunsNumber : NOT_SET_TEXT} + + {company.turnoverGbp && ( <> @@ -93,7 +98,7 @@ const SectionAbout = ({ company, isDnbCompany, isArchived }) => ( )} {!company.turnoverGbp && - (company.turnoverRange ? company.turnoverRange.name : 'Not set')} + (company.turnoverRange ? company.turnoverRange.name : NOT_SET_TEXT)} @@ -114,14 +119,14 @@ const SectionAbout = ({ company, isDnbCompany, isArchived }) => ( )} {!company.numberOfEmployees && - (company.employeeRange ? company.employeeRange.name : 'Not set')} + (company.employeeRange ? company.employeeRange.name : NOT_SET_TEXT)} {company.website ? ( {company.website} ) : ( - 'Not set' + NOT_SET_TEXT )} diff --git a/src/client/modules/Companies/CompanyHierarchy/index.jsx b/src/client/modules/Companies/CompanyHierarchy/index.jsx deleted file mode 100644 index 7269ffe7ea3..00000000000 --- a/src/client/modules/Companies/CompanyHierarchy/index.jsx +++ /dev/null @@ -1,202 +0,0 @@ -import React from 'react' -import { useParams } from 'react-router-dom' -import { connect } from 'react-redux' -import styled from 'styled-components' - -import Task from '../../../components/Task' -import { - TASK_GET_COMPANY_DETAIL, - ID as COMPANY_DETAILS_ID, -} from '../CompanyDetails/state' -import { COMPANY_LOADED } from '../../../actions' -import { state2props } from './state' -import urls from '../../../../lib/urls' -import DnbHierarchy from '../../../../apps/companies/apps/dnb-hierarchy/client/DnbHierarchy' -import { DefaultLayout } from '../../../components' -import AccessDenied from '../../../components/AccessDenied' -import { - StyledAnchorTag, - StyledListItem, -} from '../../../components/CompanyTabbedLocalNavigation/CompanyLocalTab' -import { buildCompanyBreadcrumbs } from '../utils' - -//These styled components are copied from the CompanyLocalTab file. They will all be deleted in -//the next ticket, adding here temporarily to avoid needing to refactor code thatis about to -//be deleted -const StyledGridRow = styled.div` - margin-right: -15px; - margin-left: -15px; -` - -const StyledGridColumn = styled.div` - box-sizing: border-box; - width: 100%; - padding: 0 15px; - @media (min-width: 840px) { - width: 100%; - float: left; - } -` -const StyledNav = styled.nav` - margin-bottom: 15px; - color: #0b0c0c; - margin-top: 5px; - @media (min-width: 840px) { - margin-bottom: 30px; - margin-top: 5px; - } -` - -const StyledUnorderedList = styled.ul` - margin: 0; - padding: 0; - list-style: none; - display: flex; - border-bottom: none; - @media (max-width: 839px) { - display: block; - padding-bottom: 20px; - border-bottom: 0; - } -` - -const StyledTabAnchorTag = styled(StyledAnchorTag)` - width: 100%; -` - -const StyledTabListItem = styled(StyledListItem)` - flex-grow: 1; - max-width: 50%; -` - -const CompanyLocalTab = ({ navItem, index }) => { - return ( - navItem && ( - - - {navItem.label} - - - ) - ) -} - -const localTabItems = (company) => { - if (!company) { - return [] - } - - const tabItems = [] - if (company.is_global_ultimate) { - tabItems.push({ - url: urls.companies.dnbHierarchy.index(company.id), - path: '', - label: 'Dun & Bradstreet hierarchy', - isActive: true, - }) - } - if (company.is_global_headquarters) { - tabItems.push({ - url: urls.companies.subsidiaries.index(company.id), - path: '', - label: 'Manually linked subsidiaries', - isActive: false, - }) - } - return tabItems -} - -const breadcrumbs = (company) => - !company - ? [] - : buildCompanyBreadcrumbs( - [ - { - link: urls.companies.businessDetails(company.id), - text: 'Business details', - }, - { - text: 'Related companies', - }, - ], - company.id, - company.name - ) - -const CompanyHierarchy = ({ company }) => { - const { companyId } = useParams() - if (company && !company.global_ultimate_duns_number) { - return ( - - ) - } - - return ( - - - {() => - company && ( - <> - - - - - {localTabItems(company).map((t, index) => ( - - ))} - - - - - -
- -
- - ) - } -
-
- ) -} - -export default connect(state2props)(CompanyHierarchy) diff --git a/src/client/modules/Companies/CompanyInvestments/LargeCapitalProfile/validators.js b/src/client/modules/Companies/CompanyInvestments/LargeCapitalProfile/validators.js index 30ef0787873..b3b41e9cc1b 100644 --- a/src/client/modules/Companies/CompanyInvestments/LargeCapitalProfile/validators.js +++ b/src/client/modules/Companies/CompanyInvestments/LargeCapitalProfile/validators.js @@ -1,9 +1,15 @@ -import { createDateFromObject } from '../../../../utils/date' +import { isValid } from 'date-fns' + +import { parseDateWithYearMonth } from '../../../../utils/date' export const validateDateWithinTheLastYear = (value, field, { values }) => { if (values && values.date) { - const date = createDateFromObject(values.date) - if (date) { + const date = parseDateWithYearMonth( + values.date.year, + values.date.month, + values.date.day + ) + if (isValid(date)) { const now = new Date() const oneYearPrior = new Date() oneYearPrior.setFullYear(oneYearPrior.getFullYear() - 1) diff --git a/src/client/modules/Companies/CompanyOverview/TableCards/ActivityCards/transformers.js b/src/client/modules/Companies/CompanyOverview/TableCards/ActivityCards/transformers.js index 47bc712fe20..86f795f8ff1 100644 --- a/src/client/modules/Companies/CompanyOverview/TableCards/ActivityCards/transformers.js +++ b/src/client/modules/Companies/CompanyOverview/TableCards/ActivityCards/transformers.js @@ -5,6 +5,7 @@ import { NEW_PROJECT_TAG, NEW_ORDER_TAG, GREAT_EXPORT_TAG, + EYB_TAG, } from '../../../CompanyActivity/constants' import { formatDate, DATE_FORMAT_MEDIUM } from '../../../../../utils/date-utils' import { truncateData } from '../../../../../utils/truncate' @@ -222,13 +223,7 @@ export const transformEYBLeadToListItem = (activity) => { return { id: activity.eyb_lead.id, date: formatDate(activity.eyb_lead.created_on), - tags: [ - { - text: 'EYB', - colour: 'grey', - dataTest: 'eyb-label', - }, - ].filter(({ text }) => Boolean(text)), + tags: [EYB_TAG].filter(({ text }) => Boolean(text)), headingUrl: urls.investments.eybLeads.details(activity.eyb_lead.id), headingText: activity.company.name ? activity.company.name diff --git a/src/client/modules/Companies/MatchCompany/CannotFindMatch.jsx b/src/client/modules/Companies/MatchCompany/CannotFindMatch.jsx new file mode 100755 index 00000000000..8d116719ff7 --- /dev/null +++ b/src/client/modules/Companies/MatchCompany/CannotFindMatch.jsx @@ -0,0 +1,120 @@ +import React from 'react' +import { useParams } from 'react-router-dom' +import { H4 } from '@govuk-react/heading' +import InsetText from '@govuk-react/inset-text' +import Paragraph from '@govuk-react/paragraph' + +import { SummaryList, FieldInput, DefaultLayout } from '../../../components' +import urls from '../../../../lib/urls' +import { WEBSITE_REGEX } from '../../../../apps/companies/apps/add-company/client/constants' +import Form from '../../../components/Form' +import { buildCompanyBreadcrumbs } from '../utils' +import { CompanyResource } from '../../../components/Resource/index' +import { CompanyName } from '../Referrals/SendReferralForm/SendReferralForm' + +const requiredWebsiteOrPhoneValidator = ( + value, + name, + { values: { website, telephoneNumber } } +) => { + return !website && !telephoneNumber ? 'Enter a website or phone number' : null +} + +const websiteValidator = (value) => { + WEBSITE_REGEX.test(value) ? null : 'Enter a valid website URL' +} + +function CannotFindMatch() { + const { companyId } = useParams() + return ( + )} - Companies`} + breadcrumbs={buildCompanyBreadcrumbs( + { + text: 'Send business details', + }, + companyId, + + )} + localHeaderChildren={ + + Add the company contact details below. It will be sent to our third + party data supplier for verification. + + } + > + + {(company) => ( +
urls.companies.detail(companyId)} + transformPayload={(values) => ({ values, company })} + flashMessage={() => + 'Verification request sent for third party review' + } + submitButtonLabel="Send" + cancelRedirectTo={() => urls.companies.match.index(companyId)} + cancelButtonLabel="Back" + > + {() => ( + <> +

Data Hub business details (un-verified)

+ + + +

Company contact information

+ + +

What happens next

+ You don’t need to do anything else. + + Our third-party supplier will verify the company’s business + details directly, so make sure the details are correct and you + have consent to share them. + + + It will NOT change any recorded activity (interactions, OMIS + orders or Investment projects). + + + )} + + )} +
+
+ ) +} + +export default CannotFindMatch diff --git a/src/client/modules/Companies/MatchCompany/tasks.js b/src/client/modules/Companies/MatchCompany/tasks.js new file mode 100644 index 00000000000..5f581f8ba4d --- /dev/null +++ b/src/client/modules/Companies/MatchCompany/tasks.js @@ -0,0 +1,31 @@ +import { isEmpty, omit } from 'lodash' + +import { apiProxyAxios } from '../../../components/Task/utils' + +export const cannotFindMatchSubmit = ({ values, company }) => { + const { address } = company + const dnbInvestigation = { + company: company.id, + name: company.name, + website: values.website, + telephone_number: values.telephoneNumber, + address: { + ...omit(address, ['country', 'area']), + line_1: address.line1, + line_2: address.line2, + country: address.country.id, + }, + } + if (!isEmpty(address.area)) { + dnbInvestigation.address.area = address.area + } + + return apiProxyAxios + .post('v4/dnb/company-investigation', dnbInvestigation) + .catch((e) => { + return Promise.reject(e.message) + }) + .then((response) => { + return response.data + }) +} diff --git a/src/client/modules/Companies/Referrals/Help/reducer.js b/src/client/modules/Companies/Referrals/Help/reducer.js deleted file mode 100644 index 9af3198be06..00000000000 --- a/src/client/modules/Companies/Referrals/Help/reducer.js +++ /dev/null @@ -1,4 +0,0 @@ -import { REFERRAL_DETAILS } from '../../../../../client/actions' - -export default (state = {}, { type, result }) => - type === REFERRAL_DETAILS ? result : state diff --git a/src/client/modules/Companies/Referrals/Help/state.js b/src/client/modules/Companies/Referrals/Help/state.js deleted file mode 100644 index 0f781278138..00000000000 --- a/src/client/modules/Companies/Referrals/Help/state.js +++ /dev/null @@ -1,3 +0,0 @@ -export const ID = 'referralDetails' - -export const state2props = (state) => state[ID] diff --git a/src/client/modules/Companies/Referrals/Help/tasks.js b/src/client/modules/Companies/Referrals/Help/tasks.js deleted file mode 100644 index 4a5b1f59d5e..00000000000 --- a/src/client/modules/Companies/Referrals/Help/tasks.js +++ /dev/null @@ -1,11 +0,0 @@ -const axios = require('axios') - -const transformReferralDetails = require('../../../../../apps/companies/apps/referrals/transformer') - -const handleError = (e) => Promise.reject(Error(e.response.data.detail)) - -export const fetchReferralDetails = (id) => - axios - .get(`/api-proxy/v4/company-referral/${id}`) - .catch(handleError) - .then(({ data }) => transformReferralDetails(data)) diff --git a/src/client/modules/Companies/Referrals/ReferralDetails.jsx b/src/client/modules/Companies/Referrals/ReferralDetails.jsx new file mode 100644 index 00000000000..9fdbbdc0817 --- /dev/null +++ b/src/client/modules/Companies/Referrals/ReferralDetails.jsx @@ -0,0 +1,198 @@ +import React from 'react' +import { connect } from 'react-redux' +import Details from '@govuk-react/details' +import Button from '@govuk-react/button' +import Link from '@govuk-react/link' +import PropTypes from 'prop-types' +import { useParams } from 'react-router-dom' + +import urls from '../../../../lib/urls' +import { ID as STATE_ID } from './state' + +import SecondaryButton from '../../../components/SecondaryButton' +import { DefaultLayout, SummaryTable, FormActions } from '../../../components' +import { CompanyResource, ReferralResource } from '../../../components/Resource' +import { CompanyName } from './SendReferralForm/SendReferralForm' + +const { formatDate, DATE_FORMAT_COMPACT } = require('../../../utils/date-utils') + +export const AdviserDetails = ({ name, email, team }) => ( + <> + {name} + {email && ( + <> + , {email} + + )} + {team && <>, {team}} + +) + +AdviserDetails.propTypes = { + name: PropTypes.string.isRequired, + email: PropTypes.string, + team: PropTypes.string, +} + +const transformAdviser = ({ name, contactEmail, ditTeam }) => { + const transformedAdviser = { + name, + email: contactEmail, + team: ditTeam && ditTeam.name, + } + return +} + +const BackButton = ({ referrerUrl, companyId }) => { + const cameFromHomePage = referrerUrl + ? new URL(referrerUrl).pathname === urls.companies.referrals.list() + : false + return ( + + Back + + ) +} + +export default connect(({ referrerUrl, ...state }) => ({ + ...state[STATE_ID], + referrerUrl, +}))(({ referrerUrl }) => { + const { companyId, referralId } = useParams() + return ( + )} - Companies`} + breadcrumbs={[ + { link: urls.dashboard.index(), text: 'Home' }, + { + link: urls.companies.index(), + text: 'Companies', + }, + { + link: urls.companies.detail(companyId), + text: , + }, + { text: 'Referral' }, + ]} + useReactRouter={false} + > + + {(referral) => ( + + {(company) => ( + <> + + + + {company.name} + + + {referral.contact && ( + + + {referral.contact.name} + + + )} + + {referral.createdBy && transformAdviser(referral.createdBy)} + + + {referral.recipient && transformAdviser(referral.recipient)} + + + {formatDate(referral.createdOn, DATE_FORMAT_COMPACT)} + + + {referral.notes} + + + {referral.completedOn ? ( + <> + + + {formatDate(referral.completedOn, DATE_FORMAT_COMPACT)} + + + + + + + {referral.interaction?.subject} + + + + + + +
+ + ) : ( + <> +
+

+ For now, you can't edit the referral once it's been + sent. +

+

Contact the recipient if something's changed.

+
+ + + + I cannot accept the referral + + + + + )} + + )} +
+ )} +
+
+ ) +}) diff --git a/src/client/modules/Companies/Referrals/Help/ReferralHelp.jsx b/src/client/modules/Companies/Referrals/ReferralHelp.jsx similarity index 53% rename from src/client/modules/Companies/Referrals/Help/ReferralHelp.jsx rename to src/client/modules/Companies/Referrals/ReferralHelp.jsx index 2fd1249a4b1..4322cb0ac4e 100644 --- a/src/client/modules/Companies/Referrals/Help/ReferralHelp.jsx +++ b/src/client/modules/Companies/Referrals/ReferralHelp.jsx @@ -1,19 +1,14 @@ import React from 'react' -import { connect } from 'react-redux' import Link from '@govuk-react/link' import { H2 } from '@govuk-react/heading' import { LEVEL_SIZE } from '@govuk-react/constants' import { useParams } from 'react-router-dom' -import { DefaultLayout, NewWindowLink } from '../../../../components' -import urls from '../../../../../lib/urls' - -import Task from '../../../../components/Task' -import { state2props } from './state' - -import { REFERRAL_DETAILS } from '../../../../actions' - -import { buildCompanyBreadcrumbs } from '../../utils' +import { DefaultLayout, NewWindowLink } from '../../../components' +import urls from '../../../../lib/urls' +import { buildCompanyBreadcrumbs } from '../utils' +import { ReferralResource } from '../../../components/Resource' +import { CompanyName } from './SendReferralForm/SendReferralForm' const AdviserDetails = ({ name, email }) => ( <> @@ -26,7 +21,15 @@ const AdviserDetails = ({ name, email }) => ( ) -export default connect(state2props)(({ company, sendingAdviser }) => { +const transformAdviser = ({ name, contactEmail }) => { + const transformedAdviser = { + name, + email: contactEmail, + } + return +} + +const ReferralHelp = () => { const { companyId, referralId } = useParams() // Although this input creates impurity I think for simplicity its ok in this context @@ -40,37 +43,29 @@ export default connect(state2props)(({ company, sendingAdviser }) => { referralId )}` return ( - )} - Companies`} + heading="I cannot accept this referral" + breadcrumbs={buildCompanyBreadcrumbs( + [ + { + link: urls.companies.referrals.details(companyId, referralId), + text: 'Referral', + }, + { text: 'I cannot accept this referral' }, + ], + companyId, + + )} > - {() => - company && ( - + + {(referral) => ( + <>

I need more information

Contact the sender for more info:{' '} - + {transformAdviser(referral.createdBy, false)}

Or{' '} @@ -87,9 +82,11 @@ export default connect(state2props)(({ company, sendingAdviser }) => { Back to the referral

- - ) - } - + + )} + + ) -}) +} + +export default ReferralHelp diff --git a/src/client/modules/Companies/Referrals/SendReferralForm/SendReferralForm.jsx b/src/client/modules/Companies/Referrals/SendReferralForm/SendReferralForm.jsx new file mode 100644 index 00000000000..761eb6c964e --- /dev/null +++ b/src/client/modules/Companies/Referrals/SendReferralForm/SendReferralForm.jsx @@ -0,0 +1,118 @@ +import React from 'react' +import { connect } from 'react-redux' +import { useParams } from 'react-router-dom' + +import StepReferralDetails from './StepReferralDetails' +import StepReferralConfirmation from './StepReferralConfirmation' +import Step from '../../../../components/Form/elements/Step' +import urls from '../../../../../lib/urls' +import Task from '../../../../components/Task' +import Form from '../../../../components/Form' +import { DefaultLayout } from '../../../../components' +import { + AdviserResource, + CompanyResource, +} from '../../../../components/Resource' +import State from '../../../../components/State' + +import { ID as STATE_ID, TASK_SAVE_REFERRAL } from './state' +import { TASK_REDIRECT_TO_CONTACT_FORM } from '../../../../components/ContactForm/state' + +export const CompanyName = ({ id }) => ( + + {(company) => company.name} + +) + +const AdviserTeamName = ({ id }) => ( + + {(adviser) => (adviser && adviser.dit_team ? adviser.dit_team.name : '')} + +) + +const SendReferralForm = ({ flashMessages }) => { + const { companyId } = useParams() + return ( + )} - Companies`} + breadcrumbs={[ + { link: urls.dashboard.index(), text: 'Home' }, + { + link: urls.companies.index(), + text: 'Companies', + }, + { + link: urls.companies.detail(companyId), + text: , + }, + { text: 'Send a referral' }, + ]} + useReactRouter={false} + flashMessages={flashMessages} + > + + {(company) => ( + + {({ currentAdviserId }) => ( +

({ + values, + companyId, + })} + submissionTaskName={TASK_SAVE_REFERRAL} + analyticsFormName="sendReferralForm" + analyticsData={({ adviser, subject }) => ({ + event: 'send_referral', + sendingAdviserTeam: , + receivingAdviserTeam: adviser.label?.split(', ')[1], + referralSubject: subject, + })} + initialValuesTaskName="Get send referral initial values" + redirectTo={() => urls.companies.detail(companyId)} + flashMessage={() => [ + 'Referral sent', + `You can see all of your referrals on your Homepage.`, + ]} + > + + + {(getTask) => { + const openContactFormTask = getTask( + TASK_REDIRECT_TO_CONTACT_FORM, + STATE_ID + ) + + return ( + + ) + }} + + + + + + + )} + + )} + +
+ ) +} + +export default connect(({ values, ...state }) => ({ + ...state[STATE_ID], + values, +}))(({ ...props }) => ) diff --git a/src/apps/companies/apps/referrals/send-referral/client/StepReferralConfirmation.jsx b/src/client/modules/Companies/Referrals/SendReferralForm/StepReferralConfirmation.jsx similarity index 92% rename from src/apps/companies/apps/referrals/send-referral/client/StepReferralConfirmation.jsx rename to src/client/modules/Companies/Referrals/SendReferralForm/StepReferralConfirmation.jsx index 1f0cd809959..6aadd67b286 100644 --- a/src/apps/companies/apps/referrals/send-referral/client/StepReferralConfirmation.jsx +++ b/src/client/modules/Companies/Referrals/SendReferralForm/StepReferralConfirmation.jsx @@ -4,14 +4,14 @@ import { LEVEL_SIZE } from '@govuk-react/constants' import UnorderedList from '@govuk-react/unordered-list' import ListItem from '@govuk-react/list-item' -import { useFormContext } from '../../../../../../client/components/Form/hooks' +import { useFormContext } from '../../../../components/Form/hooks' import { SummaryTable, FormActions, SecondaryButton, FieldInput, -} from '../../../../../../client/components' +} from '../../../../components' const StepReferralConfirmation = ({ cancelUrl }) => { const { values = {}, goBack } = useFormContext() @@ -21,7 +21,7 @@ const StepReferralConfirmation = ({ cancelUrl }) => { {/* TODO: remove when bug with Steps not pulling data from form context is fixed */}

Check referral details

- + {values.adviser.label} diff --git a/src/apps/companies/apps/referrals/send-referral/client/StepReferralDetails.jsx b/src/client/modules/Companies/Referrals/SendReferralForm/StepReferralDetails.jsx similarity index 88% rename from src/apps/companies/apps/referrals/send-referral/client/StepReferralDetails.jsx rename to src/client/modules/Companies/Referrals/SendReferralForm/StepReferralDetails.jsx index 86fc6c4c55f..b7144532002 100644 --- a/src/apps/companies/apps/referrals/send-referral/client/StepReferralDetails.jsx +++ b/src/client/modules/Companies/Referrals/SendReferralForm/StepReferralDetails.jsx @@ -5,7 +5,7 @@ import { H2, Button, Link } from 'govuk-react' import { SPACING, LEVEL_SIZE } from '@govuk-react/constants' import { ID as STORE_ID } from './state' -import urls, { contacts } from '../../../../../../lib/urls' +import urls, { contacts } from '../../../../../lib/urls' import { Panel, NewWindowLink, @@ -13,17 +13,16 @@ import { FieldInput, FieldTypeahead, FieldTextarea, -} from '../../../../../../client/components' +} from '../../../../components' -import { useFormContext } from '../../../../../../client/components/Form/hooks' -import { apiProxyAxios } from '../../../../../../client/components/Task/utils' +import { useFormContext } from '../../../../components/Form/hooks' +import { apiProxyAxios } from '../../../../components/Task/utils' const StyledPanel = styled(Panel)({ marginBottom: SPACING.SCALE_4, }) const StepReferralDetails = ({ - cancelUrl, companyContacts, companyId, openContactFormTask, @@ -31,6 +30,13 @@ const StepReferralDetails = ({ const MAX_LENGTH = 255 const { values = {} } = useFormContext() + const transformedContacts = companyContacts.map( + ({ firstName, lastName, id }) => ({ + name: `${firstName} ${lastName}`, + id: id, + }) + ) + return ( <> @@ -139,7 +145,7 @@ const StepReferralDetails = ({ } - options={companyContacts.map(({ name, id }) => ({ + options={transformedContacts.map(({ name, id }) => ({ label: name, value: id, }))} @@ -149,7 +155,10 @@ const StepReferralDetails = ({ /> - + Cancel diff --git a/src/apps/companies/apps/referrals/send-referral/client/reducer.js b/src/client/modules/Companies/Referrals/SendReferralForm/reducer.js similarity index 79% rename from src/apps/companies/apps/referrals/send-referral/client/reducer.js rename to src/client/modules/Companies/Referrals/SendReferralForm/reducer.js index 17bde54dc06..8f29a8c282a 100644 --- a/src/apps/companies/apps/referrals/send-referral/client/reducer.js +++ b/src/client/modules/Companies/Referrals/SendReferralForm/reducer.js @@ -1,7 +1,4 @@ -import { - SEND_REFERRAL_FORM__SUBMIT, - TASK__ERROR, -} from '../../../../../../client/actions' +import { SEND_REFERRAL_FORM__SUBMIT, TASK__ERROR } from '../../../../actions' // eslint-disable-next-line no-unused-vars export default (state = {}, { type }) => { diff --git a/src/apps/companies/apps/referrals/send-referral/client/state.js b/src/client/modules/Companies/Referrals/SendReferralForm/state.js similarity index 100% rename from src/apps/companies/apps/referrals/send-referral/client/state.js rename to src/client/modules/Companies/Referrals/SendReferralForm/state.js diff --git a/src/apps/companies/apps/referrals/send-referral/client/tasks.js b/src/client/modules/Companies/Referrals/SendReferralForm/tasks.js similarity index 81% rename from src/apps/companies/apps/referrals/send-referral/client/tasks.js rename to src/client/modules/Companies/Referrals/SendReferralForm/tasks.js index b9d936ef8f0..c32693aaf84 100644 --- a/src/apps/companies/apps/referrals/send-referral/client/tasks.js +++ b/src/client/modules/Companies/Referrals/SendReferralForm/tasks.js @@ -1,6 +1,6 @@ import { ID as STORE_ID } from './state' -import getContactFromQuery from '../../../../../../client/utils/getContactFromQuery' -import { apiProxyAxios } from '../../../../../../client/components/Task/utils' +import getContactFromQuery from '../../../../utils/getContactFromQuery' +import { apiProxyAxios } from '../../../../components/Task/utils' export async function getInitialFormValues() { const valuesFromStorage = JSON.parse(window.sessionStorage.getItem(STORE_ID)) diff --git a/src/apps/companies/apps/referrals/details/client/state.js b/src/client/modules/Companies/Referrals/state.js similarity index 100% rename from src/apps/companies/apps/referrals/details/client/state.js rename to src/client/modules/Companies/Referrals/state.js diff --git a/src/client/modules/Contacts/ContactActivity/ContactActivity.jsx b/src/client/modules/Contacts/ContactActivity/ContactActivity.jsx index 8e00db1f29f..38dc06eb97d 100644 --- a/src/client/modules/Contacts/ContactActivity/ContactActivity.jsx +++ b/src/client/modules/Contacts/ContactActivity/ContactActivity.jsx @@ -1,7 +1,7 @@ import React from 'react' import { connect } from 'react-redux' import { GridRow, GridCol } from 'govuk-react' -import { useNavigate } from 'react-router-dom' +import { useNavigate, useParams } from 'react-router-dom' import qs from 'qs' import { TASK_GET_CONTACT_ACTIVITIES, ID, state2props } from './state' @@ -18,16 +18,18 @@ import ContactLayout from '../../../components/Layout/ContactLayout' import { ContactResource } from '../../../components/Resource' import { ItemTemplate } from '../../Companies/CompanyActivity' -const ContactActivity = ({ contactId, results, count, permissions }) => { +const ContactActivity = ({ results, count }) => { + const { contactId } = useParams() + const totalPages = Math.ceil(count / 10) const qsParams = qs.parse(location.search.slice(1)) const page = parseInt(qsParams.page, 10) || 1 const navigate = useNavigate() return ( - - {(contact) => ( - + + + {(contact) => ( @@ -80,9 +82,9 @@ const ContactActivity = ({ contactId, results, count, permissions }) => {
- - )} - + )} + + ) } diff --git a/src/client/modules/Contacts/ContactAuditHistory/ContactAuditHistory.jsx b/src/client/modules/Contacts/ContactAuditHistory/ContactAuditHistory.jsx index 8d5f54a2c06..e1663dd246a 100644 --- a/src/client/modules/Contacts/ContactAuditHistory/ContactAuditHistory.jsx +++ b/src/client/modules/Contacts/ContactAuditHistory/ContactAuditHistory.jsx @@ -1,39 +1,27 @@ import React from 'react' -import PropTypes from 'prop-types' +import { useParams } from 'react-router-dom' -import { - ContactResource, - ContactAuditHistoryResource, -} from '../../../components/Resource' +import { ContactAuditHistoryResource } from '../../../components/Resource' import { getValue, mapFieldNameToLabel } from './transformers' import { AuditHistory, SectionHeader } from '../../../components' import ContactLayout from '../../../components/Layout/ContactLayout' import { EXCLUDED_FIELDS } from './constants' -const ContactAuditHistory = ({ contactId, permissions }) => ( - - {(contact) => ( - <> - - <> - Audit history - - - - - )} - -) - -ContactAuditHistory.propTypes = { - contactId: PropTypes.string.isRequired, +const ContactAuditHistory = () => { + const { contactId } = useParams() + return ( + + Audit history + + + ) } export default ContactAuditHistory diff --git a/src/client/modules/Contacts/ContactAuditHistory/transformers.js b/src/client/modules/Contacts/ContactAuditHistory/transformers.js index df00cb80feb..2880d476309 100644 --- a/src/client/modules/Contacts/ContactAuditHistory/transformers.js +++ b/src/client/modules/Contacts/ContactAuditHistory/transformers.js @@ -1,8 +1,8 @@ import { isBoolean, isNumber } from 'lodash' +import { isValid } from 'date-fns' import { transformFieldName } from '../../../components/AuditHistory/transformers' import { CONTACT_FIELD_NAME_TO_LABEL_MAP } from './constants' -import { isUnparsedDateValid } from '../../../utils/date' import { formatDate, DATE_FORMAT_MEDIUM_WITH_TIME, @@ -29,6 +29,6 @@ export const getValue = (value, field) => : NO : isNumber(value) ? value.toString() - : isUnparsedDateValid(value) + : isValid(value) ? formatDate(value, DATE_FORMAT_MEDIUM_WITH_TIME) : value || NOT_SET diff --git a/src/client/modules/Contacts/ContactDetails/ConsentDetails.jsx b/src/client/modules/Contacts/ContactDetails/ConsentDetails.jsx new file mode 100644 index 00000000000..ab904a3e502 --- /dev/null +++ b/src/client/modules/Contacts/ContactDetails/ConsentDetails.jsx @@ -0,0 +1,56 @@ +import React from 'react' +import { isNil } from 'lodash' + +import { ButtonLink, SecondaryButton, SectionHeader } from '../../../components' +import { transformContactConsents } from './transformers' + +const ConsentDetails = ({ contact }) => { + const consentGiven = transformContactConsents(contact) + return ( + <> +
+ + Marketing communications preference + + {isNil(contact.consentData) ? ( +

+ There is no marketing communication preference available for this + contact +

+ ) : ( +

+ {`This contact has opted ${consentGiven ? 'into' : 'out of'} receiving marketing communications.`} +

+ )} +
+ {contact.consentDataManagementUrl && ( +
+

+ Send a secure link to let them update their own preferences. The + contact can update their preferences directly through the email + link. +

+
+ + Send a link + + + navigator.clipboard.writeText(contact.consentDataManagementUrl) + } + data-test="copy-consent-link-button" + > + Copy the link + +
+
+ )} + + ) +} + +export default ConsentDetails diff --git a/src/client/modules/Contacts/ContactDetails/ContactDetails.jsx b/src/client/modules/Contacts/ContactDetails/ContactDetails.jsx index 89ece6364d3..21d51dae3ca 100644 --- a/src/client/modules/Contacts/ContactDetails/ContactDetails.jsx +++ b/src/client/modules/Contacts/ContactDetails/ContactDetails.jsx @@ -1,14 +1,12 @@ import React from 'react' -import PropTypes from 'prop-types' import Button from '@govuk-react/button' +import { useParams } from 'react-router-dom' import { BLACK, GREY_3 } from '../../../../client/utils/colours' -import { ContactResource } from '../../../components/Resource' +import { CompanyResource, ContactResource } from '../../../components/Resource' import { SummaryTable, ErrorSummary } from '../../../components' import urls from '../../../../lib/urls' import { - EMAIL_CONSENT_NO, - EMAIL_CONSENT_YES, LEFT_COMPANY_OPTION, NO_CONTACT_OPTION, ROLE_CHANGE_OPTION, @@ -16,12 +14,13 @@ import { import { ID, TASK_ARCHIVE_CONTACT } from './state' import ArchiveForm from '../../../components/ArchiveForm' import ContactLayout from '../../../components/Layout/ContactLayout' +import ConsentDetails from './ConsentDetails' const getAddress = (contact, companyAddress) => { const address = contact.addressSameAsCompany ? { - line1: companyAddress.line_1, - line2: companyAddress.line_2, + line1: companyAddress.line1, + line2: companyAddress.line2, town: companyAddress.town, region: companyAddress.county || null, postcode: companyAddress.postcode, @@ -45,101 +44,102 @@ const getAddress = (contact, companyAddress) => { const errorMsg = 'The email address has been flagged as invalid' -const ContactDetails = ({ contactId, companyAddress, permissions }) => ( - - {(contact) => ( - <> - - {contact.validEmail === false ? ( - - ) : null} - - - - - - {contact.notes ? ( - - ) : null} - - - {!contact.archived ? ( - - ) : null} +const ContactDetails = () => { + const { contactId } = useParams() + return ( + + + {(contact) => ( + + {(company) => ( + <> + {contact.validEmail === false ? ( + + ) : null} + + + - ({ - values, - contactId, - })} - flashMessage={() => `Contact record updated`} - redirectUrl={urls.contacts.details(contactId)} - analyticsFormName="archiveContact" - archiveReasons={[ - { - label: LEFT_COMPANY_OPTION, - value: LEFT_COMPANY_OPTION, - }, - { - label: NO_CONTACT_OPTION, - value: NO_CONTACT_OPTION, - }, - { - label: ROLE_CHANGE_OPTION, - value: ROLE_CHANGE_OPTION, - }, - ]} - radioHint="This contact has:" - /> - - - )} - -) + -ContactDetails.propTypes = { - contactId: PropTypes.string.isRequired, - companyAddress: PropTypes.object.isRequired, + + {contact.notes ? ( + + ) : null} + + {!contact.archived ? ( + + ) : null} + + + + ({ + values, + contactId, + })} + flashMessage={() => `Contact record updated`} + redirectUrl={urls.contacts.details(contactId)} + analyticsFormName="archiveContact" + archiveReasons={[ + { + label: LEFT_COMPANY_OPTION, + value: LEFT_COMPANY_OPTION, + }, + { + label: NO_CONTACT_OPTION, + value: NO_CONTACT_OPTION, + }, + { + label: ROLE_CHANGE_OPTION, + value: ROLE_CHANGE_OPTION, + }, + ]} + radioHint="This contact has:" + /> + + )} + + )} + + + ) } export default ContactDetails diff --git a/src/client/modules/Contacts/ContactDetails/__test__/transformers.test.js b/src/client/modules/Contacts/ContactDetails/__test__/transformers.test.js new file mode 100644 index 00000000000..117ae41919d --- /dev/null +++ b/src/client/modules/Contacts/ContactDetails/__test__/transformers.test.js @@ -0,0 +1,93 @@ +import 'core-js/proposals/array-grouping-v2' +import { transformContactConsents } from '../transformers' + +describe('transformContactConsents', () => { + context('When a falsey contact is passed', () => { + it('Should return false', () => { + expect(transformContactConsents(undefined)).to.equal(false) + }) + }) + + context('When a contact has no consent data', () => { + it('Should return false', () => { + expect(transformContactConsents({})).to.equal(false) + }) + }) + + context( + 'When a contact has a single domain and has not given consent', + () => { + it('Should return false', () => { + expect( + transformContactConsents({ + consentData: [ + { + consentDomain: 'International', + emailContactConsent: false, + }, + ], + }) + ).to.equal(false) + }) + } + ) + + context('When a contact has a single domain and has given consent', () => { + it('Should return true', () => { + expect( + transformContactConsents({ + consentData: [ + { + consentDomain: 'International', + emailContactConsent: true, + }, + ], + }) + ).to.equal(true) + }) + }) + + context( + 'When a contact has a multiple domains and has given consent to one', + () => { + it('Should return true', () => { + expect( + transformContactConsents({ + consentData: [ + { + consentDomain: 'International', + emailContactConsent: true, + }, + { + consentDomain: 'International', + emailContactConsent: false, + }, + ], + }) + ).to.equal(true) + }) + } + ) + + context( + 'When a contact has a multiple domains and has given consent to all', + () => { + it('Should return true', () => { + expect( + transformContactConsents({ + consentData: [ + { + consentDomain: 'International', + emailContactConsent: true, + }, + { + consentDomain: 'International', + emailContactConsent: true, + }, + ], + }) + ).to.equal(true) + }) + } + ) +}) diff --git a/src/client/modules/Contacts/ContactDetails/transformers.js b/src/client/modules/Contacts/ContactDetails/transformers.js new file mode 100644 index 00000000000..28d69ec9a73 --- /dev/null +++ b/src/client/modules/Contacts/ContactDetails/transformers.js @@ -0,0 +1,7 @@ +export const transformContactConsents = (contact) => { + if (!contact || !contact.consentData) { + return false + } + + return contact.consentData.some((consent) => consent.emailContactConsent) +} diff --git a/src/client/modules/Events/CollectionList/index.jsx b/src/client/modules/Events/CollectionList/index.jsx index 4bcf5814275..5fc23cc65b1 100644 --- a/src/client/modules/Events/CollectionList/index.jsx +++ b/src/client/modules/Events/CollectionList/index.jsx @@ -69,7 +69,7 @@ const EventTemplate = (item) => { ( +
+

Event Attendees

+ {isDisabled && ( + + You cannot add an event attendee because the event has been disabled. + + )} + + {(page) => ( +
    + {page.map( + ({ contacts: [contact], companies: [company], date, service }) => ( + + {company?.name} + + ), + }, + { + label: 'Job title', + value: contact?.job_title || 'Not available', + }, + { + label: 'Date attended', + value: formatDate(date, DATE_FORMAT_FULL), + }, + { + label: 'Service delivery', + value: ( + + {service.name} + + ), + }, + ]} + /> + ) + )} +
+ )} +
+
+) + +const Details = ({ eventType, + eventDays, startDate, endDate, - eventDays, locationType, fullAddress, ukRegion, @@ -39,131 +109,139 @@ const EventDetails = ({ otherTeams, relatedProgrammes, relatedTradeAgreements, - service, disabledOn, -}) => { - const { id } = useParams() - const breadcrumbs = [ - { - link: urls.dashboard.index(), - text: 'Home', - }, - { - link: urls.events.index(), - text: 'Events', - }, - { - text: name || '', - }, - ] + service, + id, +}) => ( + <> + + + + {eventDays > 1 ? ( + + ) : null} + + {isEmpty(locationType) ? 'Not set' : locationType} + + {fullAddress} + + {isEmpty(ukRegion) ? 'Not set' : ukRegion} + + + {isEmpty(notes) ? 'Not set' : notes} + + + {isEmpty(leadTeam) ? 'Not set' : leadTeam} + + + {isEmpty(organiser) ? 'Not set' : organiser} + + + + + + + {!disabledOn && ( + + + + )} + +) + +const EventDetails = ({ name, ...props }) => { + const { id, ['*']: path } = useParams() return ( - - - {() => { - return ( - name && ( - - - - - Details - - - Attendees - - - - - - - - {eventDays > 1 ? ( - - ) : null} - - {isEmpty(locationType) ? 'Not set' : locationType} - - - {fullAddress} - - - {isEmpty(ukRegion) ? 'Not set' : ukRegion} - - - {isEmpty(notes) ? 'Not set' : notes} - - - {isEmpty(leadTeam) ? 'Not set' : leadTeam} - - - {isEmpty(organiser) ? 'Not set' : organiser} - - - - - - - {!disabledOn && ( - - - - )} - - - ) - ) - }} - - + + {({ flashMessages }) => ( + + + {() => ( + , + }, + [`/events/${id}/attendees`]: { + label: 'Attendees', + content: ( + + ), + }, + }} + /> + )} + + + )} + ) } +// TODO: Get rid of this export default connect(state2props)(EventDetails) diff --git a/src/client/modules/Events/EventForm/validators.jsx b/src/client/modules/Events/EventForm/validators.jsx index 213f0f4390e..0a956db23d5 100644 --- a/src/client/modules/Events/EventForm/validators.jsx +++ b/src/client/modules/Events/EventForm/validators.jsx @@ -1,4 +1,6 @@ -import { createDateFromObject } from '../../../utils/date' +import { isValid } from 'date-fns' + +import { parseDateWithYearMonth } from '../../../utils/date' export const validateStartDateBeforeOrEqualToEndDate = ( value, @@ -6,9 +8,17 @@ export const validateStartDateBeforeOrEqualToEndDate = ( { values } ) => { if (values && values.start_date && values.end_date) { - const startDate = createDateFromObject(values.start_date) - const endDate = createDateFromObject(values.end_date) - if (startDate && endDate) { + const startDate = parseDateWithYearMonth( + values.start_date.year, + values.start_date.month, + values.start_date.day + ) + const endDate = parseDateWithYearMonth( + values.end_date.year, + values.end_date.month, + values.end_date.day + ) + if (isValid(startDate) && isValid(endDate)) { const result = startDate > endDate ? 'Enter a valid end date. This must be after the start date.' diff --git a/src/client/modules/Events/transformers.js b/src/client/modules/Events/transformers.js index 2f878b350c2..6c548730d2f 100644 --- a/src/client/modules/Events/transformers.js +++ b/src/client/modules/Events/transformers.js @@ -2,7 +2,8 @@ import { compact } from 'lodash' import urls from '../../../lib/urls' -import { getDifferenceInDays, formatStartAndEndDate } from '../../utils/date' +import { getDifferenceInDays } from '../../utils/date' +import { formatStartAndEndDate } from '../../components/ActivityFeed/activities/date' import { TAG_COLOURS } from '../../components/Tag' import { diff --git a/src/client/modules/ExportPipeline/Export.jsx b/src/client/modules/ExportPipeline/Export.jsx new file mode 100644 index 00000000000..4c5d1a0953c --- /dev/null +++ b/src/client/modules/ExportPipeline/Export.jsx @@ -0,0 +1,79 @@ +import React from 'react' +import styled from 'styled-components' +import { useLocation } from 'react-router-dom' + +import ExportInteractionsList from './ExportInteractionsList' +import ExportResource from '../../components/Resource/Export' +import { DefaultLayout } from '../../components' +import TabNav from '../../components/TabNav' +import ExportDetails from './ExportDetails' +import urls from '../../../lib/urls' + +const EXPORT_ID_REGEX = /\/export\/([^/]+)\// +const EXPORT_ASPECT_REGEX = /\/([^/]+)$/ + +const StyledLink = styled('a')({ + fontSize: 20, + display: 'inline-block', + fontFamily: 'Arial, sans-serif', + marginTop: 8, + marginBottom: 8, +}) + +export const CompanyLink = (props) => ( + + {({ company }) => ( + + {company.name.toUpperCase()} + + )} + +) + +export const ExportProjectTitle = (props) => ( + + {(exportProject) => exportProject.title} + +) + +const Export = () => { + const location = useLocation() + const matchId = location.pathname.match(EXPORT_ID_REGEX) + const exportId = matchId ? matchId[1] : null + const matchAspect = location.pathname.match(EXPORT_ASPECT_REGEX) + const aspect = matchAspect ? matchAspect[1] : null // aspect will be either 'details' or 'interactions' + + return ( + } + heading={} + pageTitle={`Export ${aspect}`} + breadcrumbs={[ + { link: urls.exportPipeline.index(), text: 'Home' }, + { text: }, + ]} + > + , + }, + [urls.exportPipeline.interactions.index(exportId)]: { + label: 'Interactions', + content: , + }, + }} + /> + + ) +} + +export default Export diff --git a/src/client/modules/ExportPipeline/ExportDetails/index.jsx b/src/client/modules/ExportPipeline/ExportDetails/index.jsx index ed45c51af10..4bf6fc41b64 100644 --- a/src/client/modules/ExportPipeline/ExportDetails/index.jsx +++ b/src/client/modules/ExportPipeline/ExportDetails/index.jsx @@ -5,11 +5,11 @@ import styled from 'styled-components' import { isEmpty, capitalize } from 'lodash' import Button from '@govuk-react/button' import Link from '@govuk-react/link' -import { BREAKPOINTS } from '@govuk-react/constants' +import { BREAKPOINTS, SPACING } from '@govuk-react/constants' import urls from '../../../../lib/urls' import { EXPORT_LOADED } from '../../../actions' -import { DefaultLayout, SummaryTable } from '../../../components' +import { SummaryTable } from '../../../components' import Task from '../../../components/Task' import { ID, state2props, TASK_GET_EXPORT_DETAIL } from './state' import { @@ -26,10 +26,11 @@ const StyledSummaryTable = styled(SummaryTable)({ const Container = styled('div')` display: flex; + gap: ${SPACING.SCALE_4}; align-items: baseline; - margin-bottom: 30px; + margin-bottom: ${SPACING.SCALE_5}; ${Link} { - margin-right: 20px; + margin-right: ${SPACING.SCALE_4}; } @media (max-width: ${BREAKPOINTS.TABLET}) { flex-direction: column; @@ -58,166 +59,138 @@ const EstimatedExport = ({ return Not set } -const getBreadcrumbs = (exportItem) => { - const defaultBreadcrumbs = [ - { - link: urls.exportPipeline.index(), - text: 'Home', - }, - ] - - if (exportItem) { - return [...defaultBreadcrumbs, { text: exportItem.title }] - } - - return defaultBreadcrumbs -} - const ExportDetailsForm = ({ exportItem }) => { const { exportId } = useParams() return ( - - - {() => { - return ( - exportItem && ( - <> - - - - {isEmpty(exportItem.owner) - ? 'Not set' - : exportItem?.owner.name} - - - - - - - {isEmpty(exportItem.estimated_win_date) - ? 'Not set' - : formatDate( - exportItem.estimated_win_date, - DATE_FORMAT_MONTH_YEAR - )} - - - {isEmpty(exportItem.status) - ? 'Not set' - : capitalize(exportItem.status)} - - - {isEmpty(exportItem.export_potential) - ? 'Not set' - : capitalize(exportItem.export_potential)} - - - {isEmpty(exportItem.destination_country) - ? 'Not set' - : exportItem.destination_country.name} - - - {isEmpty(exportItem.sector) - ? 'Not set' - : exportItem.sector.name} - - { + return ( + exportItem && ( + <> + + + + {isEmpty(exportItem.owner) + ? 'Not set' + : exportItem?.owner.name} + + + + - - {isEmpty(exportItem.exporter_experience) - ? 'Not set' - : exportItem.exporter_experience.name} - - - {isEmpty(exportItem.notes) ? 'Not set' : exportItem.notes} - {' '} - - - - - - Delete - - - - ) + + + {isEmpty(exportItem.estimated_win_date) + ? 'Not set' + : formatDate( + exportItem.estimated_win_date, + DATE_FORMAT_MONTH_YEAR + )} + + + {isEmpty(exportItem.status) + ? 'Not set' + : capitalize(exportItem.status)} + + + {isEmpty(exportItem.export_potential) + ? 'Not set' + : capitalize(exportItem.export_potential)} + + + {isEmpty(exportItem.destination_country) + ? 'Not set' + : exportItem.destination_country.name} + + + {isEmpty(exportItem.sector) + ? 'Not set' + : exportItem.sector.name} + + + + {isEmpty(exportItem.exporter_experience) + ? 'Not set' + : exportItem.exporter_experience.name} + + + {isEmpty(exportItem.notes) ? 'Not set' : exportItem.notes} + {' '} + + + + + + Delete + + + ) - }} - - + ) + }} + ) } diff --git a/src/client/modules/ExportPipeline/ExportInteractionDetails/exportInteraction.json b/src/client/modules/ExportPipeline/ExportInteractionDetails/exportInteraction.json new file mode 100644 index 00000000000..6a007e23d7d --- /dev/null +++ b/src/client/modules/ExportPipeline/ExportInteractionDetails/exportInteraction.json @@ -0,0 +1,114 @@ +{ + "id": "d831fb8e-9b5a-417d-b53e-ebf9089934b8", + "company": { + "name": "DIAGEO PLC", + "id": "8d0016ed-f616-4813-9511-f795cb481d08" + }, + "companies": [], + "contacts": [ + { + "name": "James Brown", + "first_name": "James", + "last_name": "Brown", + "job_title": "Senior Associate", + "id": "2b4b2944-d18e-4b41-a662-08c079547216" + }, + { + "name": "Fred Peterson", + "first_name": "Fred", + "last_name": "Peterson", + "job_title": "Manager", + "id": "1430e18a-52ac-4185-b71d-b2be5a771fd0" + } + ], + "created_on": "2024-12-23T07:44:42.226309Z", + "created_by": { + "name": "Paul Gain", + "first_name": "Paul", + "last_name": "Gain", + "id": "8b76daf2-0f8a-4887-9b4b-43bbda21c934" + }, + "event": null, + "is_event": null, + "status": "complete", + "kind": "interaction", + "modified_by": { + "name": "Paul Gain", + "first_name": "Paul", + "last_name": "Gain", + "id": "8b76daf2-0f8a-4887-9b4b-43bbda21c934" + }, + "modified_on": "2024-12-23T07:44:42.226325Z", + "date": "2024-12-23", + "dit_participants": [ + { + "adviser": { + "name": "David Webber", + "first_name": "David", + "last_name": "Webber", + "id": "3994da68-cebc-42e2-bdd2-2f7c23c52114" + }, + "team": { + "name": "Doncaster Council", + "id": "3a48318c-9698-e211-a939-e4115bead28a" + } + }, + { + "adviser": { + "name": "Jason Jason", + "first_name": "Jason", + "last_name": "Jason", + "id": "3994da68-cebc-42e2-bdd2-2f7c23c52114" + }, + "team": { + "id": "23f12898-9698-e211-a939-e4115bead28a", + "name": "UK Fashion and Textile Association Ltd (UKFT)" + } + } + ], + "communication_channel": { + "name": "Fax", + "id": "71c226d7-5d95-e211-a939-e4115bead28a" + }, + "grant_amount_offered": null, + "company_export": { + "title": "Baileys export to Brazil", + "id": "e3f3f1e6-9f0e-4832-84d8-59ba108d1d95" + }, + "investment_project": null, + "large_capital_opportunity": null, + "net_company_receipt": null, + "service": { + "name": "Account management : General", + "id": "9484b82b-3499-e211-a939-e4115bead28a" + }, + "service_answers": null, + "service_delivery_status": null, + "subject": "Magnum bottles of Bailey", + "theme": "export", + "notes": "", + "archived_documents_url_path": "", + "policy_feedback_notes": "", + "helped_remove_export_barrier": true, + "export_barrier_types": [], + "export_barrier_notes": "", + "was_policy_feedback_provided": false, + "were_countries_discussed": null, + "export_countries": [], + "archived": false, + "archived_by": null, + "archived_on": null, + "archived_reason": "", + "company_referral": null, + "has_related_trade_agreements": null, + "related_trade_agreements": [ + { + "name": "Atlantic Declaration", + "id": "2aaa2df3-7a02-4ebc-912e-426edb76fff8" + }, + { + "name": "Comprehensive and Progressive Agreement for Trans-Pacific Partnership", + "id": "af704a93-5404-4bc6-adda-381756993902" + } + ] +} \ No newline at end of file diff --git a/src/client/modules/ExportPipeline/ExportInteractionDetails/index.jsx b/src/client/modules/ExportPipeline/ExportInteractionDetails/index.jsx new file mode 100644 index 00000000000..f4b738c1a8c --- /dev/null +++ b/src/client/modules/ExportPipeline/ExportInteractionDetails/index.jsx @@ -0,0 +1,148 @@ +import React from 'react' +import Link from '@govuk-react/link' +import styled from 'styled-components' +import { useLocation } from 'react-router-dom' + +// import InteractionResource from '../../../components/Resource/Interaction' +// Remove this import and delete the file once the endpoint is in place +import exportInteraction from './exportInteraction.json' +import { + formatDate, + DATE_FORMAT_DAY_MONTH_YEAR, +} from '../../../utils/date-utils' +import { + SummaryTable, + DefaultLayout, + SecondaryButton, +} from '../../../components' +import { ExportProjectTitle } from '../Export' +import urls from '../../../../lib/urls' + +const StyledSummaryTable = styled(SummaryTable)({ + marginTop: 0, +}) + +const ActionsContainer = styled.div` + display: flex; + gap: 20px; + align-items: center; +` + +const StyledLink = styled.a` + margin-bottom: 50px; +` + +const EXPORT_ID_REGEX = /\/export\/([a-f0-9-]+)\/interactions\/details/ +const HELPED_REMOVE_EXPORT_BARRIER = { + null: 'Unknown', + true: 'Yes', + false: 'No', +} + +const ExportInteractionsDetails = () => { + const location = useLocation() + const matchId = location.pathname.match(EXPORT_ID_REGEX) + const exportId = matchId && matchId[1] + + return ( + } + pageTitle="Export interaction details" + breadcrumbs={[ + { link: urls.exportPipeline.index(), text: 'Home' }, + { + link: urls.exportPipeline.interactions.index(exportId), + text: 'Interactions', + }, + { text: }, + ]} + > + {/* + Uncomment InteractionResource and move the StyledSummaryTable up into + the InteractionResource render function once the export projects + interaction endpoint is in place. Warning, we may have to create a + new Resource. + + + {(exportInteraction) => ()} + */} + + + + + {exportInteraction.company.name.toUpperCase()} + + + +
    + {exportInteraction.contacts.map((contact, index) => ( +
  • + + {contact.name} + +
  • + ))} +
+
+ + {exportInteraction.service.name} + + + {exportInteraction.notes} + + + {formatDate(exportInteraction.date, DATE_FORMAT_DAY_MONTH_YEAR)} + + +
    + {exportInteraction.dit_participants.map((participant, index) => ( +
  • + {participant.adviser.name}, {participant.team.name} +
  • + ))} +
+
+ + {exportInteraction.communication_channel.name} + + +
    + {exportInteraction.related_trade_agreements.map( + (tradeAgreement, index) => ( +
  • {tradeAgreement.name}
  • + ) + )} +
+
+ + { + HELPED_REMOVE_EXPORT_BARRIER[ + exportInteraction.helped_remove_export_barrier + ] + } + +
+ + + Add interaction + + + Back + + +
+ ) +} + +export default ExportInteractionsDetails diff --git a/src/client/modules/ExportPipeline/ExportInteractionsList/index.jsx b/src/client/modules/ExportPipeline/ExportInteractionsList/index.jsx new file mode 100644 index 00000000000..8bce93b86cc --- /dev/null +++ b/src/client/modules/ExportPipeline/ExportInteractionsList/index.jsx @@ -0,0 +1,66 @@ +import React from 'react' + +import { LEVEL_SIZE } from '@govuk-react/constants' +import { H2 } from 'govuk-react' + +import Interactions from '../../../components/Resource/Interactions' +import { formatDate, DATE_FORMAT_FULL } from '../../../utils/date-utils' +import { CollectionItem } from '../../../components' +import { ExportProjectTitle } from '../Export' +import urls from '../../../../lib/urls' +import { SORT_OPTIONS_EXPORT_INTERACTION } from '../constants' + +const ExportInteractionsList = ({ interactions = [], exportId }) => + interactions.length === 0 ? null : ( +
    + {interactions.map((item) => ( + } + headingUrl={urls.exportPipeline.interactions.details(exportId)} + metadata={[ + { + label: 'Date:', + value: formatDate(item.date, DATE_FORMAT_FULL), + }, + { + label: 'Contact(s):', + value: item.contacts.map(({ name }) => name).join(', '), + }, + { + label: 'Adviser(s):', + value: item.dit_participants + .map(({ adviser, team }) => `${adviser.name} - ${team.name}`) + .join(', '), + }, + { + label: 'Service:', + value: item.service.name, + }, + ]} + /> + ))} +
+ ) + +export default ({ exportId }) => ( + <> +

Interactions

+

+ An interaction could be a meeting, call, email or another activity + associated with this export. +

+ + {(page) => ( + + )} + + +) diff --git a/src/client/modules/ExportPipeline/constants.js b/src/client/modules/ExportPipeline/constants.js index ad332f0ddb2..61cf41cf51a 100644 --- a/src/client/modules/ExportPipeline/constants.js +++ b/src/client/modules/ExportPipeline/constants.js @@ -38,6 +38,12 @@ export const SORT_OPTIONS = [ }, ] +export const SORT_OPTIONS_EXPORT_INTERACTION = [ + { name: 'Recently created', value: '-created_on' }, + { name: 'Company name A-Z', value: 'company__name' }, + { name: 'Subject A-Z', value: 'subject' }, +] + export const EXPORT_POTENTIAL_OPTIONS = [ { label: 'High', value: 'high' }, { label: 'Medium', value: 'medium' }, diff --git a/src/client/modules/ExportWins/Form/WinDetailsStep.jsx b/src/client/modules/ExportWins/Form/WinDetailsStep.jsx index 81a6f61b120..9c3e8c40b5c 100644 --- a/src/client/modules/ExportWins/Form/WinDetailsStep.jsx +++ b/src/client/modules/ExportWins/Form/WinDetailsStep.jsx @@ -8,7 +8,7 @@ import Countries from '../../../components/Resource/Countries' import Sector from '../../../components/Resource/Sector' import { useFormContext } from '../../../../client/components/Form/hooks' -import { getStartDateOfTwelveMonthsAgo } from '../../../utils/date' +import { getStartDateOfTwelveMonthsAgo } from './date' import { formatValue, sumAllWinTypeYearlyValues } from './utils' import { BLACK, WHITE } from '../../../../client/utils/colours' import { validateWinDate, validateTextField } from './validators' diff --git a/src/client/modules/ExportWins/Form/__test__/date.test.js b/src/client/modules/ExportWins/Form/__test__/date.test.js new file mode 100644 index 00000000000..af002ef7239 --- /dev/null +++ b/src/client/modules/ExportWins/Form/__test__/date.test.js @@ -0,0 +1,81 @@ +import { addDays, subMonths, subDays, startOfMonth, isEqual } from 'date-fns' + +import { + getRandomDateInRange, + isWithinLastTwelveMonths, + getStartDateOfTwelveMonthsAgo, +} from '../date' + +describe('getStartDateOfTwelveMonthsAgo', () => { + it( + 'should return a date that is 12 months ago from the current ' + + 'date and includes the 1st of the month', + () => { + const today = new Date() + const expectedDate = subMonths(startOfMonth(today), 12) + const actualDate = getStartDateOfTwelveMonthsAgo() + expect(actualDate).to.be.instanceOf(Date) + expect(isEqual(actualDate, expectedDate)).to.equal(true) + } + ) +}) + +describe('isWithinLastTwelveMonths', () => { + const twelveMonthsAgo = getStartDateOfTwelveMonthsAgo() + const twelveMonthsAgoAddOneDay = addDays(twelveMonthsAgo, 1) + const twelveMonthsAgoSubOneDay = subDays(twelveMonthsAgo, 1) + const today = new Date() + const tomorrow = addDays(today, 1) + const yesterday = subDays(today, 1) + + it('should be valid for the 1st of the month twelve months ago', () => { + expect(isWithinLastTwelveMonths(twelveMonthsAgo)).to.equal(true) + }) + + it('should be valid for the 2nd of the month twelve months ago', () => { + expect(isWithinLastTwelveMonths(twelveMonthsAgoAddOneDay)).to.equal(true) + }) + + it('should be invalid one day before the 1st of the month, thirteen months ago', () => { + expect(isWithinLastTwelveMonths(twelveMonthsAgoSubOneDay)).to.equal(false) + }) + + it('should be valid for today', () => { + expect(isWithinLastTwelveMonths(today)).to.equal(true) + }) + + it('should be invalid for tomorrow', () => { + expect(isWithinLastTwelveMonths(tomorrow)).to.equal(false) + }) + + it('should be valid for yesterday', () => { + expect(isWithinLastTwelveMonths(yesterday)).to.equal(true) + }) +}) + +describe('getRandomDateInRange', () => { + it('should return a random date within the specified range', () => { + const startDate = new Date(2024, 0, 1) // January 1, 2024 + const endDate = new Date(2024, 0, 10) // January 10, 2024 + const randomDate = getRandomDateInRange(startDate, endDate) + expect(randomDate).to.be.instanceOf(Date) + expect(randomDate.getTime()).to.be.at.least(startDate.getTime()) + expect(randomDate.getTime()).to.be.at.most(endDate.getTime()) + }) + + it('should throw an error if the start date and the end date are the same', () => { + const startDate = new Date(2024, 0, 1) + const endDate = new Date(2024, 0, 1) + expect(() => getRandomDateInRange(startDate, endDate)).to.throw( + 'Start date and end date cannot be the same.' + ) + }) + + it('should throw error if the start date is greater than the end date', () => { + const startDate = new Date(2024, 0, 10) + const endDate = new Date(2024, 0, 1) + expect(() => getRandomDateInRange(startDate, endDate)).to.throw( + 'Start date cannot be greater than end date.' + ) + }) +}) diff --git a/src/client/modules/ExportWins/Form/date.js b/src/client/modules/ExportWins/Form/date.js new file mode 100644 index 00000000000..4bf447ec083 --- /dev/null +++ b/src/client/modules/ExportWins/Form/date.js @@ -0,0 +1,49 @@ +import { + addDays, + subMonths, + isSameDay, + startOfMonth, + differenceInDays, + isWithinInterval, +} from 'date-fns' + +/** + * Generates a random date within the range specified by startDate and endDate (inclusive). + * @param {Date} startDate - The start date of the range. + * @param {Date} endDate - The end date of the range. + * @returns {Date} A random date within the specified range. + * @throws {Error} If startDate is greater than endDate or if startDate and endDate are the same date. + */ +export const getRandomDateInRange = (startDate, endDate) => { + if (isSameDay(startDate, endDate)) { + throw new Error('Start date and end date cannot be the same.') + } + if (startDate > endDate) { + throw new Error('Start date cannot be greater than end date.') + } + const daysDifference = differenceInDays(endDate, startDate) + const randomNumberOfDays = Math.floor(Math.random() * (daysDifference + 1)) + return addDays(startDate, randomNumberOfDays) +} + +/** + * Returns the start date (1st day) of the month twelve months ago from the current date. + * @returns {Date} The start date (1st day) of the month twelve months ago from the current date. + */ +export const getStartDateOfTwelveMonthsAgo = () => { + return subMonths(startOfMonth(new Date()), 12) +} + +/** + * Checks if a given date falls within the last twelve months from the current date. + * The last twelve months include the 1st of the month. + * @param {Date} date - The date to be checked. + * @returns {boolean} Returns true if the date falls within the last twelve months + * from the current date, otherwise false. + */ +export const isWithinLastTwelveMonths = (date) => { + return isWithinInterval(date, { + start: getStartDateOfTwelveMonthsAgo(), + end: new Date(), + }) +} diff --git a/src/client/modules/ExportWins/Form/transformers.js b/src/client/modules/ExportWins/Form/transformers.js index 1c133ac741a..be90b2cbbaf 100644 --- a/src/client/modules/ExportWins/Form/transformers.js +++ b/src/client/modules/ExportWins/Form/transformers.js @@ -3,10 +3,8 @@ import { isEmpty } from 'lodash' import { OPTION_YES, OPTION_NO } from '../../../../common/constants' import { idNameToValueLabel } from '../../../../client/utils' import { sumWinTypeYearlyValues } from './utils' -import { - convertDateToFieldDateObject, - isWithinLastTwelveMonths, -} from '../../../utils/date' +import { isWithinLastTwelveMonths } from './date' +import { convertDateToFieldDateObject } from '../../../utils/date' import { winTypeId, GOODS_ID, diff --git a/src/client/modules/ExportWins/Form/validators.js b/src/client/modules/ExportWins/Form/validators.js index 5734fb73ff2..1d426866fe6 100644 --- a/src/client/modules/ExportWins/Form/validators.js +++ b/src/client/modules/ExportWins/Form/validators.js @@ -1,4 +1,4 @@ -import { isWithinLastTwelveMonths } from '../../../utils/date' +import { isWithinLastTwelveMonths } from './date' const TEXT_FIELD_MAX_LENGTH = 128 diff --git a/src/client/modules/Investments/EYBLeads/EYBLeadDetails.jsx b/src/client/modules/Investments/EYBLeads/EYBLeadDetails.jsx index 28d2f2a5815..e0c57991a8a 100644 --- a/src/client/modules/Investments/EYBLeads/EYBLeadDetails.jsx +++ b/src/client/modules/Investments/EYBLeads/EYBLeadDetails.jsx @@ -4,6 +4,10 @@ import { Link } from 'govuk-react' import { formatDate, DATE_FORMAT_COMPACT } from '../../../utils/date-utils' import urls from '../../../../lib/urls' +import { + convertEYBChoicesToLabels, + formatProposedInvestmentCity, +} from '../utils' import { EYBLeadResource } from '../../../components/Resource' import { EYBLeadLayout, NewWindowLink, SummaryTable } from '../../../components' import { NOT_SET_TEXT } from '../../../../apps/companies/constants' @@ -68,7 +72,7 @@ const EYBLeadDetails = () => {
{ /> { heading="Phone number" children={eybLead.telephoneNumber} /> + ) }} diff --git a/src/client/modules/Investments/EYBLeads/EYBLeadsCollection.jsx b/src/client/modules/Investments/EYBLeads/EYBLeadsCollection.jsx index a2b3b844b0e..c2ad4745413 100644 --- a/src/client/modules/Investments/EYBLeads/EYBLeadsCollection.jsx +++ b/src/client/modules/Investments/EYBLeads/EYBLeadsCollection.jsx @@ -29,6 +29,7 @@ const EYBLeadCollection = ({ filterOptions, payload, optionMetadata, + sortOptions, ...props }) => { const location = useLocation() @@ -45,6 +46,13 @@ const EYBLeadCollection = ({ options.filter(({ value }) => values.includes(value)) const setupSelectedFilters = (qsParams, filterOptions) => ({ + overseasRegionId: { + queryParam: QS_PARAMS.overseasRegionId, + options: resolveSelectedOptions( + qsParams[QS_PARAMS.overseasRegionId], + filterOptions.overseasRegions + ), + }, countryId: { queryParam: QS_PARAMS.countryId, options: resolveSelectedOptions( @@ -104,10 +112,12 @@ const EYBLeadCollection = ({ @@ -121,6 +131,16 @@ const EYBLeadCollection = ({ selectedOptions={selectedFilters.valueOfLead.options} data-test="lead-value-filter" /> + { results: results.map(transformLeadToListItem), payload: queryParams, filterOptions, + sortOptions: SORT_OPTIONS, } } diff --git a/src/client/modules/Investments/EYBLeads/tasks.js b/src/client/modules/Investments/EYBLeads/tasks.js index 9adcd2bacaf..a9f57afc8e2 100644 --- a/src/client/modules/Investments/EYBLeads/tasks.js +++ b/src/client/modules/Investments/EYBLeads/tasks.js @@ -9,19 +9,24 @@ export const getEYBLeads = ({ limit = 10, page = 1, company, - country, - sector, - value, + overseas_region = [], + country = [], + sector = [], + value = [], + sortby, }) => { let params = new URLSearchParams({ limit, offset: limit * (parseInt(page, 10) - 1) || 0, ...(company ? { company } : null), + sortby: sortby ? sortby : '-triage_created', }) - if (country) - country.forEach((countryId) => params.append('country', countryId)) - if (sector) sector.forEach((sectorId) => params.append('sector', sectorId)) - if (value) value.forEach((valueOfLead) => params.append('value', valueOfLead)) + overseas_region.forEach((overseasRegionId) => + params.append('overseas_region', overseasRegionId) + ) + country.forEach((countryId) => params.append('country', countryId)) + sector.forEach((sectorId) => params.append('sector', sectorId)) + value.forEach((valueOfLead) => params.append('value', valueOfLead)) return apiProxyAxios .get(`v4/investment-lead/eyb?${params.toString()}`) .then(({ data }) => ({ @@ -32,10 +37,15 @@ export const getEYBLeads = ({ export const loadEYBLeadFilterOptions = () => Promise.all([ + getMetadataOptions(urls.metadata.overseasRegion()), getMetadataOptions(urls.metadata.country()), getMetadataOptions(urls.metadata.sector(), { params: { level__lte: '0', }, }), - ]).then(([countries, sectors]) => ({ countries, sectors })) + ]).then(([overseasRegions, countries, sectors]) => ({ + overseasRegions, + countries, + sectors, + })) diff --git a/src/client/modules/Investments/EYBLeads/transformers.js b/src/client/modules/Investments/EYBLeads/transformers.js index 77f6270b7f4..e7e967d8070 100644 --- a/src/client/modules/Investments/EYBLeads/transformers.js +++ b/src/client/modules/Investments/EYBLeads/transformers.js @@ -2,6 +2,7 @@ import urls from '../../../../lib/urls' import { TAG_COLOURS } from '../../../components/Tag' import { VALUES_VALUE_TO_LABEL_MAP } from './constants' import { formatDate, DATE_FORMAT_COMPACT } from '../../../utils/date-utils' +import { convertEYBChoicesToLabels } from '../utils' export const transformLeadToListItem = ({ id, @@ -33,7 +34,10 @@ export const transformLeadToListItem = ({ }, { label: 'Estimated spend', value: spend }, { label: 'Sector', value: sector ? sector.name : '' }, - { label: 'Estimated land date', value: landing_timeframe }, + { + label: 'Estimated land date', + value: convertEYBChoicesToLabels(landing_timeframe), + }, { label: 'Location', value: proposed_investment_region ? proposed_investment_region.name : '', diff --git a/src/client/modules/Investments/Opportunities/tasks.js b/src/client/modules/Investments/Opportunities/tasks.js index 8c71e2111ab..f7f83a2edb9 100644 --- a/src/client/modules/Investments/Opportunities/tasks.js +++ b/src/client/modules/Investments/Opportunities/tasks.js @@ -1,7 +1,7 @@ import urls from '../../../../lib/urls' import { idNamesToValueLabels } from '../../../utils' import { apiProxyAxios } from '../../../components/Task/utils' -import { transformValueForAPI } from '../../../utils/date' +import { formatDateWithYearMonth } from '../../../utils/date' import { getMetadataOptions } from '../../../metadata' import { transformInvestmentOpportunityDetails } from './transformers' @@ -47,7 +47,7 @@ export function saveOpportunityDetails({ values, opportunityId }) { : undefined, required_checks_conducted_by: values.requiredChecksConductedBy?.value, required_checks_conducted_on: values.requiredChecksConductedOn - ? transformValueForAPI(values.requiredChecksConductedOn) + ? formatDateWithYearMonth(values.requiredChecksConductedOn) : undefined, lead_dit_relationship_manager: values.leadRelationshipManager?.value, other_dit_contacts: values.otherDitContacts?.map(({ value }) => value), diff --git a/src/client/modules/Investments/Projects/Details/transformers.js b/src/client/modules/Investments/Projects/Details/transformers.js index 9ac693a1ad0..780aa2c9fe6 100644 --- a/src/client/modules/Investments/Projects/Details/transformers.js +++ b/src/client/modules/Investments/Projects/Details/transformers.js @@ -58,13 +58,6 @@ const setReferralSourceEvent = (values) => { : '' } -const setReferralSourceAdviser = (currentAdviser, values) => { - const { is_referral_source, referral_source_adviser } = values - return is_referral_source === 'yes' - ? currentAdviser - : checkIfItemHasValue(referral_source_adviser?.value) -} - const transformRadioOptionToInvertedBool = (radioOption) => radioOption === null ? null : radioOption === OPTION_NO @@ -135,7 +128,7 @@ export const transformProjectRequirementsForApi = ({ projectId, values }) => { export const transformProjectSummaryForApi = ({ projectId, - currentAdviser, + currentAdviserId, values, }) => { const { @@ -151,6 +144,7 @@ export const transformProjectSummaryForApi = ({ investor_type, level_of_involvement, specific_programmes, + is_referral_source, business_activities, other_business_activity, client_contacts, @@ -186,7 +180,10 @@ export const transformProjectSummaryForApi = ({ referral_source_activity_website ), referral_source_activity_event: setReferralSourceEvent(values), - referral_source_adviser: setReferralSourceAdviser(currentAdviser, values), + referral_source_adviser: + is_referral_source === OPTION_YES + ? currentAdviserId + : values.referral_source_adviser.value, } if (Array.isArray(specific_programmes)) { diff --git a/src/client/modules/Investments/Projects/EditHistory/constants.js b/src/client/modules/Investments/Projects/EditHistory/constants.js index c678a612328..d2e005cbf58 100644 --- a/src/client/modules/Investments/Projects/EditHistory/constants.js +++ b/src/client/modules/Investments/Projects/EditHistory/constants.js @@ -29,4 +29,6 @@ export const PROJECT_FIELD_NAME_TO_LABEL_MAP = { associated_non_fdi_r_and_d_project: 'Non-FDI R&D project', client_considering_other_countries: 'Is the client considering other countries?', + site_address_is_company_address: + "Is the site address the same as the UK recipient company's address?", } diff --git a/src/client/modules/Investments/Projects/EditHistory/transformers.js b/src/client/modules/Investments/Projects/EditHistory/transformers.js index 75fc159fb21..b11ccc082c3 100644 --- a/src/client/modules/Investments/Projects/EditHistory/transformers.js +++ b/src/client/modules/Investments/Projects/EditHistory/transformers.js @@ -1,7 +1,7 @@ import { isBoolean, isNumber } from 'lodash' +import { isValid } from 'date-fns' import { PROJECT_FIELD_NAME_TO_LABEL_MAP } from './constants' -import { isUnparsedDateValid } from '../../../../utils/date' import { formatDate, DATE_FORMAT_MEDIUM } from '../../../../utils/date-utils' import { currencyGBP } from '../../../../utils/number-utils' import { NOT_SET, NO, YES } from '../../../../components/AuditHistory/constants' @@ -36,6 +36,6 @@ export const getValue = (value, field) => ? value.toString() : Array.isArray(value) ? value.join(', ') - : isUnparsedDateValid(value) + : isValid(value) ? formatDate(value, DATE_FORMAT_MEDIUM) : value || NOT_SET diff --git a/src/client/modules/Investments/Projects/ProjectTasks.jsx b/src/client/modules/Investments/Projects/ProjectTasks.jsx index 51160fb2b18..f034419efbb 100644 --- a/src/client/modules/Investments/Projects/ProjectTasks.jsx +++ b/src/client/modules/Investments/Projects/ProjectTasks.jsx @@ -1,7 +1,7 @@ import React from 'react' import { H2 } from 'govuk-react' import { LEVEL_SIZE } from '@govuk-react/constants' -import { useParams } from 'react-router-dom' +import { useParams, useNavigate } from 'react-router-dom' import useSearchParam from 'react-use/lib/useSearchParam' import { connect } from 'react-redux' import qs from 'qs' @@ -18,15 +18,14 @@ import InvestmentName from './InvestmentName' import ProjectLayoutNew from '../../../components/Layout/ProjectLayoutNew' const ProjectTasks = () => { + const navigate = useNavigate() const { projectId } = useParams() const parsedQueryString = qs.parse(location.search.slice(1)) const activePage = parseInt(useSearchParam('page'), 10) || 1 const getPageUrl = (page) => `${window.location.pathname}?page=${page}` - const setActivePage = (page) => - window.history.pushState({}, '', getPageUrl(page)) const onPageClick = (page) => { - setActivePage(page) + navigate(getPageUrl(page)) } const returnUrl = encodeURIComponent(location.pathname + location.search) diff --git a/src/client/modules/Investments/Projects/Propositions/transformers.js b/src/client/modules/Investments/Projects/Propositions/transformers.js index e4eedffba1b..1ac1d5448ac 100644 --- a/src/client/modules/Investments/Projects/Propositions/transformers.js +++ b/src/client/modules/Investments/Projects/Propositions/transformers.js @@ -2,7 +2,7 @@ import React from 'react' import { Link } from 'govuk-react' import styled from 'styled-components' -import { transformValueForAPI } from '../../../../utils/date' +import { formatDateWithYearMonth } from '../../../../utils/date' import { VIRUS_SCAN_STATUSES } from '../constants' import urls from '../../../../../lib/urls' @@ -32,7 +32,7 @@ export const transformPropositionForAPI = ({ projectId, values }) => { deadline_day: proposition_deadline.day, deadline_month: proposition_deadline.month, deadline_year: proposition_deadline.year, - deadline: transformValueForAPI(proposition_deadline), + deadline: formatDateWithYearMonth(proposition_deadline), } } diff --git a/src/client/modules/Investments/__test__/utils.test.js b/src/client/modules/Investments/__test__/utils.test.js new file mode 100644 index 00000000000..778ff908749 --- /dev/null +++ b/src/client/modules/Investments/__test__/utils.test.js @@ -0,0 +1,76 @@ +import { + convertEYBChoicesToLabels, + formatProposedInvestmentCity, +} from '../utils' + +describe('convertEYBChoicesToLabels', () => { + const validCases = [ + { input: null, output: null }, + { input: 'UNDER_SIX_MONTHS', output: 'Under six months' }, + { input: 'SIX_TO_TWELVE_MONTHS', output: 'Six to twelve months' }, + { input: 'ONE_TO_TWO_YEARS', output: 'One to two years' }, + { input: 'MORE_THAN_TWO_YEARS', output: 'More than two years' }, + { + input: [ + 'SET_UP_NEW_PREMISES', + 'SET_UP_A_NEW_DISTRIBUTION_CENTRE', + 'ONWARD_SALES_AND_EXPORTS_FROM_THE_UK', + 'RESEARCH_DEVELOP_AND_COLLABORATE', + 'FIND_PEOPLE_WITH_SPECIALIST_SKILLS', + 'OTHER', + ], + output: [ + 'Set up new premises', + 'Set up a new distribution centre', + 'Onward sales and exports from the UK', + 'Research develop and collaborate', + 'Find people with specialist skills', + 'Other', + ], + }, + ] + validCases.forEach((validCase) => { + it(`should output ${validCase.output} for the input ${validCase.input}`, () => { + expect(convertEYBChoicesToLabels(validCase.input)).to.deep.equal( + validCase.output + ) + }) + }) + const errorCases = [{ input: undefined }, { input: 123 }] + errorCases.forEach((errorCase) => { + it(`should throw an error for the input ${errorCase.input}`, () => { + expect(() => { + convertEYBChoicesToLabels(errorCase.input) + }).to.throw() + }) + }) +}) + +describe('formatProposedInvestmentCity', () => { + const validCases = [ + { input: null, output: null }, + { input: 'MILTON_KEYNES', output: 'Milton Keynes' }, + { input: 'CITY_OF_EDINBURGH', output: 'City of Edinburgh' }, + { input: 'MANCHESTER', output: 'Manchester' }, + { input: 'ANTRIM_AND_NEWTONABBEY', output: 'Antrim and Newtonabbey' }, + { input: 'ALEXANDER_THE_GREAT', output: 'Alexander the Great' }, + { input: 'HENLEY-ON-THEMES', output: 'Henley-on-Themes' }, + { input: 'NEWCASTLE_UPON_TYNE', output: 'Newcastle upon Tyne' }, + { input: 'BARROW-IN-FURNESS', output: 'Barrow-in-Furness' }, + ] + validCases.forEach((validCase) => { + it(`should output ${validCase.output} for the input ${validCase.input}`, () => { + expect(formatProposedInvestmentCity(validCase.input)).to.deep.equal( + validCase.output + ) + }) + }) + const errorCases = [{ input: undefined }, { input: 123 }] + errorCases.forEach((errorCase) => { + it(`should throw an error for the input ${errorCase.input}`, () => { + expect(() => { + formatProposedInvestmentCity(errorCase.input) + }).to.throw() + }) + }) +}) diff --git a/src/client/modules/Investments/utils.js b/src/client/modules/Investments/utils.js index 6298b507324..1760b728efa 100644 --- a/src/client/modules/Investments/utils.js +++ b/src/client/modules/Investments/utils.js @@ -1,3 +1,5 @@ +import { sentence } from 'case' + import urls from '../../../lib/urls' export const buildProjectBreadcrumbs = (pageBreadcrumbs) => { @@ -29,3 +31,69 @@ export const buildEYBLeadBreadcrumbs = (pageBreadcrumbs) => { ] return initialBreadcrumbs.concat(pageBreadcrumbs) } + +/** + * Converts EYB choices to sentence case labels + * @param {string|string[]|null} choices - Single string, or array of strings, or null to convert + * @returns {string|string[]|null} - Converted string(s) in the same format as the input + */ +export const convertEYBChoicesToLabels = (choices) => { + if (choices === null) { + return null + } + + // Helper function to handle capitalisation of UK + const capitaliseUK = (str) => { + return str.replace(/\b[Uu][Kk]\b/g, 'UK') + } + // Helper function to process a single string + const processString = (str) => { + return capitaliseUK(sentence(str)) + } + + if (typeof choices == 'string') { + return processString(choices) + } + if (Array.isArray(choices)) { + return choices.map((choice) => processString(choice)) + } + + throw new Error('Input must be null, a string, or array of strings') +} + +/** + * Formats EYB lead proposed investment city to Title Case labels + * @param {string|null} city - Single string or null to format + * @returns {string|null} - Formatted string + */ +export const formatProposedInvestmentCity = (choices) => { + if (choices === null) { + return null + } + if (typeof choices !== 'string') { + throw new Error('Input must be null or a string') + } + + const lowercaseWords = choices.toLowerCase().split('_') + + const formattedWords = lowercaseWords.map((word) => { + // Handle special case for "-on-" or "-in-" + if (word.includes('-on-') || word.includes('-in-')) { + return word + .split('-') + .map((subWord, index) => + index === 1 + ? subWord + : subWord.charAt(0).toUpperCase() + subWord.slice(1) + ) + .join('-') + } + + if (word === 'of' || word === 'the' || word === 'and' || word === 'upon') { + return word // Keep lowercase for "of," "the,", "and" or "upon" + } + return word.charAt(0).toUpperCase() + word.slice(1) // Capitalize the first letter + }) + + return formattedWords.join(' ') +} diff --git a/src/client/modules/Omis/EditQuoteInformation.jsx b/src/client/modules/Omis/EditQuoteInformation.jsx index 358fcbe1495..05c13633883 100644 --- a/src/client/modules/Omis/EditQuoteInformation.jsx +++ b/src/client/modules/Omis/EditQuoteInformation.jsx @@ -8,7 +8,7 @@ import urls from '../../../lib/urls' import { state2props, TASK_EDIT_OMIS_QUOTE_INFORMATION } from './state' import { FORM_LAYOUT } from '../../../common/constants' import { transformQuoteInformationForApi } from './transformers' -import { transformDateStringToDateObject } from '../../../apps/transformers' +import { transformDateStringToDateObject } from '../../../client/transformers' import { validateIfDateInFuture } from './validators' import OMISLayout from './OMISLayout' @@ -46,9 +46,10 @@ const EditQuoteInformation = ({ csrfToken }) => { name="delivery_date" label="Delivery date of work" hint="For example 28 10 2018" - initialValue={transformDateStringToDateObject( - order.deliveryDate - )} + initialValue={ + order.deliveryDate && + transformDateStringToDateObject(order.deliveryDate) + } validate={validateIfDateInFuture} /> diff --git a/src/client/modules/Tasks/TaskForm/__test__/validators.test.js b/src/client/modules/Tasks/TaskForm/__test__/validators.test.js new file mode 100644 index 00000000000..a78dc4f19e0 --- /dev/null +++ b/src/client/modules/Tasks/TaskForm/__test__/validators.test.js @@ -0,0 +1,63 @@ +import { addDays, subDays, format } from 'date-fns' + +import { validateIfDateInFuture } from '../validators' + +describe('validateIfDateInFuture', () => { + it('should return null for a date in the future (with day provided)', () => { + const futureDate = addDays(new Date(), 10) + const year = format(futureDate, 'yyyy') + const month = format(futureDate, 'MM') + const day = format(futureDate, 'dd') + + const result = validateIfDateInFuture({ year, month, day }) + expect(result).to.be.null + }) + + it('should return null for a date in the future (year and month only)', () => { + const futureDate = addDays(new Date(), 40) // Ensures crossing month boundary + const year = format(futureDate, 'yyyy') + const month = format(futureDate, 'MM') + + const result = validateIfDateInFuture({ year, month }) + expect(result).to.be.null + }) + + it('should return error message for a past date (with day provided)', () => { + const pastDate = subDays(new Date(), 10) + const year = format(pastDate, 'yyyy') + const month = format(pastDate, 'MM') + const day = format(pastDate, 'dd') + + const result = validateIfDateInFuture({ year, month, day }) + expect(result).to.equal('Enter a date in the future') + }) + + it('should return error message for a past date (year and month only)', () => { + const pastDate = subDays(new Date(), 40) + const year = format(pastDate, 'yyyy') + const month = format(pastDate, 'MM') + + const result = validateIfDateInFuture({ year, month }) + expect(result).to.equal('Enter a date in the future') + }) + + it('should handle edge cases correctly (today is not in the future)', () => { + const today = new Date() + const year = format(today, 'yyyy') + const month = format(today, 'MM') + const day = format(today, 'dd') + + const result = validateIfDateInFuture({ year, month, day }) + expect(result).to.equal('Enter a date in the future') + }) + + it('should handle invalid inputs gracefully', () => { + const invalidMessage = 'Enter a date in the future' + + expect(validateIfDateInFuture({})).to.equal(invalidMessage) + expect(validateIfDateInFuture({ year: '2025' })).to.equal(invalidMessage) + expect(validateIfDateInFuture({ year: '2025', month: '13' })).to.equal( + invalidMessage + ) + }) +}) diff --git a/src/client/modules/Tasks/TaskForm/transformers.js b/src/client/modules/Tasks/TaskForm/transformers.js index 36468822ba1..bcb2328c32a 100644 --- a/src/client/modules/Tasks/TaskForm/transformers.js +++ b/src/client/modules/Tasks/TaskForm/transformers.js @@ -7,7 +7,7 @@ import { transformIdNameToValueLabel, } from '../../../transformers' import { - transformValueForAPI, + formatDateWithYearMonth, convertDateToFieldDateObject, } from '../../../utils/date' import { formatDate, DATE_FORMAT_ISO } from '../../../utils/date-utils' @@ -61,7 +61,7 @@ export const getDueDate = (dueDate, customDate) => { const today = new Date() const handlers = { - custom: () => transformValueForAPI(customDate), + custom: () => formatDateWithYearMonth(customDate), month: () => formatDate(addMonths(today, 1), DATE_FORMAT_ISO), week: () => formatDate(addDays(today, 7), DATE_FORMAT_ISO), } diff --git a/src/client/modules/Tasks/TaskForm/validators.js b/src/client/modules/Tasks/TaskForm/validators.js index a148e097117..824e3f3fed0 100644 --- a/src/client/modules/Tasks/TaskForm/validators.js +++ b/src/client/modules/Tasks/TaskForm/validators.js @@ -1,9 +1,11 @@ import { isFuture } from 'date-fns' -import { transformValueForAPI } from '../../../utils/date' +import { parseDateWithYearMonth } from '../../../utils/date' -export const validateIfDateInFuture = (values) => - isFuture(transformValueForAPI(values)) ? null : 'Enter a date in the future' +export const validateIfDateInFuture = ({ year, month, day }) => + isFuture(parseDateWithYearMonth(year, month, day)) + ? null + : 'Enter a date in the future' export const validateDaysRange = (value) => !value || value < 1 || value > 365 ? 'Enter a number between 1 and 365' : null diff --git a/src/client/reducers.js b/src/client/reducers.js index 982e37b2d74..cd887ee8c73 100644 --- a/src/client/reducers.js +++ b/src/client/reducers.js @@ -3,11 +3,8 @@ import tasks from './components/Task/reducer' import { ID as COMPANY_LISTS_STATE_ID } from './components/CompanyLists/state' import companyListsReducer from './components/CompanyLists/reducer' -import { ID as REFERRALS_DETAILS_STATE_ID } from '../apps/companies/apps/referrals/details/client/state' -import referralsReducer from '../apps/companies/apps/referrals/details/client/reducer' - -import { ID as REFERRALS_SEND_ID } from '../apps/companies/apps/referrals/send-referral/client/state' -import referralsSendReducer from '../apps/companies/apps/referrals/send-referral/client/reducer' +import { ID as REFERRALS_SEND_ID } from './modules/Companies/Referrals/SendReferralForm/state' +import referralsSendReducer from './modules/Companies/Referrals/SendReferralForm/reducer' import { ID as EXPORTS_HISTORY_ID } from './modules/Companies/CompanyExports/ExportHistory/state.js' import exportsHistoryReducer from './modules/Companies/CompanyExports/ExportHistory/reducer.js' @@ -200,7 +197,6 @@ export const reducers = { [COMPANY_LISTS_STATE_ID]: companyListsReducer, [COMPANIES_ID]: companiesReducer, [EXPORTS_HISTORY_ID]: exportsHistoryReducer, - [REFERRALS_DETAILS_STATE_ID]: referralsReducer, [REFERRALS_SEND_ID]: referralsSendReducer, [addCompanyState.ID]: addCompanyReducer, ...HeadlessTabNav.reducerSpread, diff --git a/src/client/routes.js b/src/client/routes.js index 56408ae63e7..d77382cbecd 100644 --- a/src/client/routes.js +++ b/src/client/routes.js @@ -18,13 +18,13 @@ import { ExportFormEdit, } from './modules/ExportPipeline/ExportForm' import ExportFormDelete from './modules/ExportPipeline/ExportDelete' -import ExportDetails from './modules/ExportPipeline/ExportDetails' +import Export from './modules/ExportPipeline/Export' +import ExportInteractionDetails from './modules/ExportPipeline/ExportInteractionDetails' import ExportWinsTabNav from './modules/ExportWins/Status/ExportWinsTabNav' import { CreateExportWin, EditExportWin } from './modules/ExportWins/Form' import ExportWinsRedirect from './modules/ExportWins/Status/Redirect' import Success from './modules/ExportWins/Form/Success' import EditSuccess from './modules/ExportWins/Form/EditSuccess' -import CompanyHierarchy from './modules/Companies/CompanyHierarchy' import CompanyTree from './modules/Companies/CompanyHierarchy/CompanyTree' import Community from './modules/Community' import Strategy from './modules/Companies/AccountManagement/Strategy' @@ -74,7 +74,7 @@ import LinkGlobalHQ from './modules/Companies/CompanyBusinessDetails/LinkGlobalH import LinkSubsidiary from './modules/Companies/CompanyBusinessDetails/LinkSubsidiary' import ExportCountriesEdit from './modules/Companies/CompanyExports/ExportCountriesEdit' import ExportsEdit from './modules/Companies/CompanyExports/ExportsEdit' -import ReferralHelp from './modules/Companies/Referrals/Help/ReferralHelp' +import ReferralHelp from './modules/Companies/Referrals/ReferralHelp' import AbandonProposition from './modules/Investments/Projects/Propositions/AbandonProposition' import CreateProposition from './modules/Investments/Projects/Propositions/CreateProposition' import DeletePropositionDocument from './modules/Investments/Projects/Propositions/DeletePropositionDocument' @@ -107,6 +107,12 @@ import AddPropositionDocument from './modules/Investments/Projects/Propositions/ import ProtectedRoute from './components/ProtectedRoute/index' import CustomerFeedback from './modules/ExportWins/CustomerFeedback' import EYBLeadDetails from './modules/Investments/EYBLeads/EYBLeadDetails' +import SendReferralForm from './modules/Companies/Referrals/SendReferralForm/SendReferralForm' +import ReferralDetails from './modules/Companies/Referrals/ReferralDetails' +import ContactDetails from './modules/Contacts/ContactDetails/ContactDetails' +import ContactActivity from './modules/Contacts/ContactActivity/ContactActivity' +import ContactAuditHistory from './modules/Contacts/ContactAuditHistory/ContactAuditHistory' +import CannotFindMatch from './modules/Companies/MatchCompany/CannotFindMatch' function Routes() { const routes = useRoutes([ @@ -126,14 +132,6 @@ function Routes() { ), }, - { - path: '/companies/:companyId/dnb-hierarchy', - element: ( - - - - ), - }, { path: '/companies/:companyId/company-tree', element: ( @@ -359,6 +357,30 @@ function Routes() { ), }, + { + path: '/companies/:companyId/referrals/send', + element: ( + + + + ), + }, + { + path: '/companies/:companyId/referrals/:referralId', + element: ( + + + + ), + }, + { + path: '/companies/:companyId/match/cannot-find', + element: ( + + + + ), + }, { path: '/contacts', element: ( @@ -367,6 +389,30 @@ function Routes() { ), }, + { + path: '/contacts/:contactId/details', + element: ( + + + + ), + }, + { + path: '/contacts/:contactId/interactions', + element: ( + + + + ), + }, + { + path: '/contacts/:contactId/audit', + element: ( + + + + ), + }, { path: '/community', element: ( @@ -400,7 +446,7 @@ function Routes() { ), }, { - path: '/events/:id/details', + path: '/events/:id/*', element: ( @@ -667,7 +713,23 @@ function Routes() { path: '/export/:exportId/details', element: ( - + + + ), + }, + { + path: '/export/:exportId/interactions', + element: ( + + + + ), + }, + { + path: '/export/:exportId/interactions/details', + element: ( + + ), }, diff --git a/src/client/tasks.js b/src/client/tasks.js index d13a5e255ad..e53d10bf71e 100644 --- a/src/client/tasks.js +++ b/src/client/tasks.js @@ -1,9 +1,8 @@ import * as companyListsTasks from './components/CompanyLists/tasks' -import * as referralTasks from '../apps/companies/apps/referrals/details/client/tasks' import * as exportsHistoryTasks from './modules/Companies/CompanyExports/ExportHistory/tasks.js' import referralListTask from './components/ReferralList/tasks' -import { TASK_SAVE_REFERRAL } from '../apps/companies/apps/referrals/send-referral/client/state' -import * as referralsSendTasks from '../apps/companies/apps/referrals/send-referral/client/tasks' +import { TASK_SAVE_REFERRAL } from './modules/Companies/Referrals/SendReferralForm/state.js' +import * as referralsSendTasks from './modules/Companies/Referrals/SendReferralForm/tasks.js' import { TASK_NAME as EXPORT_COUNTRIES_EDIT_NAME } from './modules/Companies/CompanyExports/ExportCountriesEdit/state' import * as exportCountriesEditTasks from './modules/Companies/CompanyExports/ExportCountriesEdit/tasks' import { createCompany } from '../apps/companies/apps/add-company/client/tasks' @@ -245,6 +244,8 @@ import resourceTasks from '../client/components/Resource/tasks' import { getTypeaheadOptions } from '../client/components/Typeahead/tasks' import * as matchCompanyTasks from '../apps/companies/apps/match-company/client/tasks' +import { cannotFindMatchSubmit } from './modules/Companies/MatchCompany/tasks.js' + import * as companyListTasks from '../apps/company-lists/client/tasks' import { editCompany } from '../apps/companies/apps/edit-company/client/tasks' import { createList } from '../apps/company-lists/client/tasks.js' @@ -463,13 +464,12 @@ export const tasks = { 'Create company': createCompany, 'Edit company list': companyListTasks.editCompanyList, 'Match confirmation': matchCompanyTasks.onMatchSubmit, - 'Cannot find match': matchCompanyTasks.cannotFindMatchSubmit, + 'Cannot find match': cannotFindMatchSubmit, 'Submit merge request': matchCompanyTasks.submitMergeRequest, 'Company lists': companyListsTasks.fetchCompanyLists, 'Company list': companyListsTasks.fetchCompanyList, 'Add or remove from list': companyListsTasks.addOrRemoveFromList, 'Exports history': exportsHistoryTasks.fetchExportsHistory, - 'Referral details': referralTasks.fetchReferralDetails, Referrals: referralListTask, 'Update Lead ITA': manageAdviser.updateAdviser, 'Get send referral initial values': referralsSendTasks.getInitialFormValues, diff --git a/src/client/transformers/index.js b/src/client/transformers/index.js index 9f909a81422..d2874cc83a5 100644 --- a/src/client/transformers/index.js +++ b/src/client/transformers/index.js @@ -1,7 +1,12 @@ import { uniq } from 'lodash' import { OPTION_NO, OPTION_YES } from '../../common/constants' -import { format, isDateValid } from '../../client/utils/date' +import { + formatDate, + DATE_FORMAT_DAY, + DATE_FORMAT_YEAR, + DATE_FORMAT_MONTH, +} from '../../client/utils/date-utils' export const transformDateObjectToDateString = (value) => { if (value) { @@ -54,13 +59,11 @@ export const transformIdNameToValueLabel = (value) => { return null } -export const transformDateStringToDateObject = (dateString) => { - const isValidDate = dateString && isDateValid(dateString) - +export const transformDateStringToDateObject = (dateISO) => { return { - year: isValidDate ? format(dateString, 'yyyy') : '', - month: isValidDate ? format(dateString, 'MM') : '', - day: isValidDate ? format(dateString, 'dd') : '', + year: formatDate(dateISO, DATE_FORMAT_YEAR), + month: formatDate(dateISO, DATE_FORMAT_MONTH), + day: formatDate(dateISO, DATE_FORMAT_DAY), } } diff --git a/src/client/utils/__test__/date.test.js b/src/client/utils/__test__/date.test.js index 4132ccb6cb1..21e8d7e97d5 100644 --- a/src/client/utils/__test__/date.test.js +++ b/src/client/utils/__test__/date.test.js @@ -1,13 +1,10 @@ -import { subMonths, subYears, addDays } from 'date-fns' +import { isValid, format } from 'date-fns' import { - areDatesEqual, - getStartOfMonth, - getRandomDateInRange, - isWithinLastTwelveMonths, + parseDateWithYearMonth, + formatDateWithYearMonth, convertDateToFieldDateObject, convertDateToFieldShortDateObject, - getStartDateOfTwelveMonthsAgo, } from '../date' describe('convertDateToFieldShortDateObject', () => { @@ -56,76 +53,110 @@ describe('convertDateToFieldDateObject', () => { }) }) -describe('getStartDateOfTwelveMonthsAgo', () => { - it( - 'should return a date that is 12 months ago from the current ' + - 'date and includes the 1st of the month', - () => { - const today = new Date() - const expectedDate = subMonths(getStartOfMonth(today), 12) - const actualDate = getStartDateOfTwelveMonthsAgo() - expect(actualDate).to.be.instanceOf(Date) - expect(areDatesEqual(actualDate, expectedDate)).to.equal(true) - } - ) -}) +describe('parseDateWithYearMonth', () => { + it('should parse a valid full date (yyyy-MM-dd)', () => { + const date = parseDateWithYearMonth('2024', '12', '31') + expect(isValid(date)).to.be.true + expect(format(date, 'yyyy-MM-dd')).to.equal('2024-12-31') + }) + + it('should parse a valid year and month (yyyy-MM)', () => { + const date = parseDateWithYearMonth('2024', '12') + expect(isValid(date)).to.be.true + expect(format(date, 'yyyy-MM')).to.equal('2024-12') + }) + + it('should handle invalid year (non-numeric)', () => { + const date = parseDateWithYearMonth('abcd', '12', '31') + expect(isValid(date)).to.be.false + }) -describe('isWithinLastTwelveMonths', () => { - const twelveMonthsAgo = getStartDateOfTwelveMonthsAgo() - const twelveMonthsAgoAddOneDay = addDays(twelveMonthsAgo, 1) - const twelveMonthsAgoSubOneDay = subYears(twelveMonthsAgo, 1) - const today = new Date() - const tomorrow = addDays(today, 1) - const yesterday = subYears(today, 1) + it('should handle invalid month (out of range)', () => { + const date = parseDateWithYearMonth('2024', '13', '31') + expect(isValid(date)).to.be.false + }) + + it('should handle invalid day (out of range)', () => { + const date = parseDateWithYearMonth('2024', '12', '32') + expect(isValid(date)).to.be.false + }) - it('should be valid for the 1st of the month twelve months ago', () => { - expect(isWithinLastTwelveMonths(twelveMonthsAgo)).to.equal(true) + it('should handle missing day gracefully (assume first of month)', () => { + const date = parseDateWithYearMonth('2024', '12') + expect(isValid(date)).to.be.true + expect(format(date, 'yyyy-MM-dd')).to.equal('2024-12-01') }) - it('should be valid for the 2nd of the month twelve months ago', () => { - expect(isWithinLastTwelveMonths(twelveMonthsAgoAddOneDay)).to.equal(true) + it('should handle single-digit month and day', () => { + const date = parseDateWithYearMonth('2024', '2', '9') + expect(isValid(date)).to.be.true + expect(format(date, 'yyyy-MM-dd')).to.equal('2024-02-09') }) - it('should be invalid one day before the 1st of the month, thirteen months ago', () => { - expect(isWithinLastTwelveMonths(twelveMonthsAgoSubOneDay)).to.equal(false) + it('should handle valid leap year date', () => { + const date = parseDateWithYearMonth('2024', '2', '29') + expect(isValid(date)).to.be.true + expect(format(date, 'yyyy-MM-dd')).to.equal('2024-02-29') }) - it('should be valid for today', () => { - expect(isWithinLastTwelveMonths(today)).to.equal(true) + it('should handle invalid non-leap year date', () => { + const date = parseDateWithYearMonth('2023', '2', '29') + expect(isValid(date)).to.be.false }) - it('should be invalid for tomorrow', () => { - expect(isWithinLastTwelveMonths(tomorrow)).to.equal(false) + it('should handle missing month (invalid case)', () => { + const date = parseDateWithYearMonth('2024', null, '31') + expect(isValid(date)).to.be.false }) - it('should be valid for yesterday', () => { - expect(isWithinLastTwelveMonths(yesterday)).to.equal(true) + it('should handle missing year (invalid case)', () => { + const date = parseDateWithYearMonth(null, '12', '31') + expect(isValid(date)).to.be.false }) }) -describe('getRandomDateInRange', () => { - it('should return a random date within the specified range', () => { - const startDate = new Date(2024, 0, 1) // January 1, 2024 - const endDate = new Date(2024, 0, 10) // January 10, 2024 - const randomDate = getRandomDateInRange(startDate, endDate) - expect(randomDate).to.be.instanceOf(Date) - expect(randomDate.getTime()).to.be.at.least(startDate.getTime()) - expect(randomDate.getTime()).to.be.at.most(endDate.getTime()) - }) - - it('should throw an error if the start date and the end date are the same', () => { - const startDate = new Date(2024, 0, 1) - const endDate = new Date(2024, 0, 1) - expect(() => getRandomDateInRange(startDate, endDate)).to.throw( - 'Start date and end date cannot be the same.' - ) - }) - - it('should throw error if the start date is greater than the end date', () => { - const startDate = new Date(2024, 0, 10) - const endDate = new Date(2024, 0, 1) - expect(() => getRandomDateInRange(startDate, endDate)).to.throw( - 'Start date cannot be greater than end date.' - ) +describe('formatDateWithYearMonth', () => { + it('should format a full date (year, month, day)', () => { + const result = formatDateWithYearMonth({ year: 2025, month: 1, day: 6 }) + expect(result).to.equal('2025-01-06') + }) + + it('should format a date when only year and month are provided', () => { + const result = formatDateWithYearMonth({ year: 2025, month: 11 }) + expect(result).to.equal('2025-11') + }) + + it('should handle single-digit months and days', () => { + const result = formatDateWithYearMonth({ year: 2025, month: 4, day: 9 }) + expect(result).to.equal('2025-04-09') + }) + + it('should throw an error for invalid year', () => { + expect(() => + formatDateWithYearMonth({ year: 'invalid', month: 1, day: 1 }) + ).to.throw() + }) + + it('should throw an error for invalid month', () => { + expect(() => + formatDateWithYearMonth({ year: 2025, month: 13, day: 1 }) + ).to.throw() + }) + + it('should throw an error for invalid day', () => { + expect(() => + formatDateWithYearMonth({ year: 2025, month: 2, day: 30 }) + ).to.throw() + }) + + it('should handle edge case: February 29 on a leap year', () => { + const result = formatDateWithYearMonth({ year: 2024, month: 2, day: 29 }) + expect(result).to.equal('2024-02-29') + }) + + it('should throw an error for February 29 on a non-leap year', () => { + expect(() => + formatDateWithYearMonth({ year: 2023, month: 2, day: 29 }) + ).to.throw() }) }) diff --git a/src/client/utils/date.js b/src/client/utils/date.js index aaac5d1adf6..31f73b7298f 100644 --- a/src/client/utils/date.js +++ b/src/client/utils/date.js @@ -7,86 +7,76 @@ */ const { - addDays, - differenceInDays, differenceInCalendarDays, - isSameDay, endOfToday, - startOfMonth: getStartOfMonth, - isWithinInterval, - format: formatFns, formatDistanceToNowStrict, - isAfter, isValid, parse, parseISO, - subMonths, - differenceInCalendarMonths, - isEqual: areDatesEqual, } = require('date-fns') const { - DATE_LONG_FORMAT_2, - DATE_LONG_FORMAT_3, - DATE_SHORT_FORMAT, - DATE_DAY_MONTH, -} = require('../../common/constants') + formatDate, + DATE_FORMAT_ISO, + DATE_FORMAT_YEAR_MONTH, +} = require('./date-utils') /** - * Date validation functions - */ - -function isDateValid(date) { - return isValid(parseISO(date)) -} - -function isUnparsedDateValid(date) { - return isValid(date) -} - -function isNormalisedDateValid(year, month, day, format = DATE_LONG_FORMAT_3) { - const date = normaliseAndFormatDate(year, month, day) - return isValid(parse(date, format, new Date())) -} - -function isShortDateValid(year, month) { - return isNormalisedDateValid(year, month, null, DATE_SHORT_FORMAT) -} - -/** - * @deprecated This function is deprecated. Use `formatDate` instead. + * Parses a date string given a year, month, and optional day. + * + * @param {string} year - The year as a string (e.g., '2024'). + * @param {string} month - The month as a string (1-based, e.g., '12' for December). + * @param {string} [day] - The optional day as a string (e.g., '31'). If omitted, defaults to the first day of the month. + * @returns {Date} A `Date` object representing the parsed date. If the input values are invalid, + * the returned `Date` object will be invalid (check with `isValid(date)`). + * + * @example + * // Full date parsing + * const date = parseDateWithYearMonth('2024', '12', '31') + * console.log(date) // Outputs: Tue Dec 31 2024 00:00:00 GMT+0000 (UTC) * - * This function will be removed in the near future. + * @example + * // Parsing only year and month + * const date = parseDateWithYearMonth('2024', '12') + * console.log(date) // Outputs: Sun Dec 01 2024 00:00:00 GMT+0000 (UTC) + * + * @example + * // Invalid date + * const date = parseDateWithYearMonth('2024', '13', '31') + * console.log(isValid(date)) // Outputs: false + * + * @note This function does not throw errors for invalid inputs but returns an invalid `Date` object instead. */ -function format(dateStr, dateFormat = DATE_LONG_FORMAT_2) { - return isDateValid(dateStr) ? formatFns(parseISO(dateStr), dateFormat) : null +function parseDateWithYearMonth(year, month, day) { + const dateString = day ? `${year}-${month}-${day}` : `${year}-${month}` + const format = day ? DATE_FORMAT_ISO : DATE_FORMAT_YEAR_MONTH + return parse(dateString, format, new Date()) } /** - * Parsing functions + * Formats a date string based on a given year, month, and optional day. + * + * @param {Object} params - The date components to format. + * @param {string} params.year - The year as a string (e.g., '2024'). + * @param {string} params.month - The month as a string (1-based, e.g., '12' for December). + * @param {string} [params.day] - The optional day as a string (e.g., '31'). If omitted, defaults to the first day of the month. + * @returns {string} The formatted date string in either 'yyyy-MM-dd' or 'yyyy-MM'. + * + * @example + * // Format full date + * const formattedDate = formatDateWithYearMonth({ year: '2024', month: '12', day: '31' }) + * console.log(formattedDate) // Outputs: '2024-12-31' + * + * @example + * // Format year and month only + * const formattedDate = formatDateWithYearMonth({ year: '2024', month: '12' }) + * console.log(formattedDate) // Outputs: '2024-12' */ - -const padZero = (value) => { - const parsedValue = parseInt(value, 10) - if (Number.isNaN(parsedValue)) { - return value - } - return parsedValue < 10 ? `0${parsedValue}` : parsedValue.toString() -} - -function normaliseAndFormatDate(year, month, day) { - const y = padZero(year) - const m = padZero(month) - const yearAndMonth = `${padZero(y)}-${padZero(m)}` - return day ? `${yearAndMonth}-${padZero(day)}` : yearAndMonth -} - -function transformValueForAPI({ year, month, day = 1 }) { - if (year && month && day) { - return normaliseAndFormatDate(year, month, day) - } - - return null +const formatDateWithYearMonth = ({ year, month, day }) => { + return formatDate( + parseDateWithYearMonth(year, month, day), + day ? DATE_FORMAT_ISO : DATE_FORMAT_YEAR_MONTH + ) } /** @@ -124,41 +114,6 @@ function getDifferenceInWords(date, suffix = true) { } } -function createDateFromObject({ day, month, year }) { - const monthIndex = parseInt(month, 10) - 1 - const result = new Date(year, monthIndex, day) - return result -} - -function formatStartAndEndDate(startDate, endDate) { - if (startDate) { - const startDateParsed = startDate ? parseISO(startDate) : startDate - const endDateParsed = endDate ? parseISO(endDate) : endDate - const startDateFormatted = startDate ? format(startDate) : startDate - const endDateFormatted = endDate ? format(endDate) : endDate - - //When end date is missing or before start date - if (!endDate || !isAfter(endDateParsed, startDateParsed)) { - return startDateFormatted - } - //When start and end date are on same day - if (startDateParsed.toDateString() === endDateParsed.toDateString()) { - return startDateFormatted - } - // When start and end date are in the same month - if (differenceInCalendarMonths(endDateParsed, startDateParsed) == 0) { - return `${startDateParsed.getDate()} to ${endDateFormatted}` - } - // When start and end date are in the same year - if (startDateParsed.getFullYear() === endDateParsed.getFullYear()) { - return `${format(startDate, DATE_DAY_MONTH)} to ${endDateFormatted}` - } - // When start and end date are in different years - return `${startDateFormatted} to ${endDateFormatted}` - } - return null -} - /** * Convert a date to a short object format required by the FieldDate component * @param {*} date a string representing a date or a Date type @@ -218,69 +173,16 @@ function convertUnparsedDateToFieldDateObject(date) { return { day: '', month: '', year: '' } } -/** - * Generates a random date within the range specified by startDate and endDate (inclusive). - * @param {Date} startDate - The start date of the range. - * @param {Date} endDate - The end date of the range. - * @returns {Date} A random date within the specified range. - * @throws {Error} If startDate is greater than endDate or if startDate and endDate are the same date. - */ -function getRandomDateInRange(startDate, endDate) { - if (isSameDay(startDate, endDate)) { - throw new Error('Start date and end date cannot be the same.') - } - if (startDate > endDate) { - throw new Error('Start date cannot be greater than end date.') - } - const daysDifference = differenceInDays(endDate, startDate) - const randomNumberOfDays = Math.floor(Math.random() * (daysDifference + 1)) - return addDays(startDate, randomNumberOfDays) -} - -/** - * Returns the start date (1st day) of the month twelve months ago from the current date. - * @returns {Date} The start date (1st day) of the month twelve months ago from the current date. - */ -function getStartDateOfTwelveMonthsAgo() { - return subMonths(getStartOfMonth(new Date()), 12) -} - -/** - * Checks if a given date falls within the last twelve months from the current date. - * The last twelve months include the 1st of the month. - * @param {Date} date - The date to be checked. - * @returns {boolean} Returns true if the date falls within the last twelve months - * from the current date, otherwise false. - */ -function isWithinLastTwelveMonths(date) { - return isWithinInterval(date, { - start: getStartDateOfTwelveMonthsAgo(), - end: new Date(), - }) -} - module.exports = { - format, generateFinancialYearLabel, getDifferenceInDays, getDifferenceInDaysLabel, getDifferenceInWords, getFinancialYearStart, - isDateValid, - isValid, - isNormalisedDateValid, - isShortDateValid, - isUnparsedDateValid, - transformValueForAPI, - createDateFromObject, - formatStartAndEndDate, + parseDateWithYearMonth, + formatDateWithYearMonth, convertDateToFieldShortDateObject, convertDateToFieldDateObject, - getRandomDateInRange, - isWithinLastTwelveMonths, - getStartDateOfTwelveMonthsAgo, - getStartOfMonth, - areDatesEqual, convertUnparsedDateToFieldDateObject, convertUnparsedDateToFieldShortDateObject, } diff --git a/src/common/constants.js b/src/common/constants.js index 18150a951e1..2a0a30d789f 100644 --- a/src/common/constants.js +++ b/src/common/constants.js @@ -1,9 +1,3 @@ -// These are date-fns format codes - see https://date-fns.org/v2.23.0/docs/format -const DATE_LONG_FORMAT_2 = 'dd MMM yyyy' -const DATE_LONG_FORMAT_3 = 'yyyy-MM-dd' -const DATE_SHORT_FORMAT = 'yyyy-MM' -const DATE_DAY_MONTH = 'dd MMM' - const UNITED_KINGDOM_ID = '80756b9a-5d95-e211-a939-e4115bead28a' const UNITED_STATES_ID = '81756b9a-5d95-e211-a939-e4115bead28a' const CANADA_ID = '5daf72a6-5d95-e211-a939-e4115bead28a' @@ -60,10 +54,6 @@ const EXPORT_INTEREST_STATUS = { } module.exports = { - DATE_DAY_MONTH, - DATE_LONG_FORMAT_2, - DATE_LONG_FORMAT_3, - DATE_SHORT_FORMAT, UNITED_KINGDOM_ID, UNITED_STATES_ID, CANADA_ID, diff --git a/src/lib/__test__/urls.test.js b/src/lib/__test__/urls.test.js index ec85f01c05a..4f263b09ee1 100644 --- a/src/lib/__test__/urls.test.js +++ b/src/lib/__test__/urls.test.js @@ -99,20 +99,6 @@ describe('urls', () => { '/:companyId/account-management/advisers/remove' ) - expect(urls.companies.dnbHierarchy.index.route).to.equal( - '/:companyId/dnb-hierarchy' - ) - expect(urls.companies.dnbHierarchy.index(companyId)).to.equal( - `/companies/${companyId}/dnb-hierarchy` - ) - - expect(urls.companies.dnbHierarchy.data.route).to.equal( - '/:companyId/dnb-hierarchy/data' - ) - expect(urls.companies.dnbHierarchy.data(companyId)).to.equal( - `/companies/${companyId}/dnb-hierarchy/data` - ) - expect(urls.companies.exports.index.route).to.equal('/:companyId/exports') expect(urls.companies.exports.index(companyId)).to.equal( `/companies/${companyId}/exports` diff --git a/src/lib/urls.js b/src/lib/urls.js index 4d70d848a7e..0f21229722c 100644 --- a/src/lib/urls.js +++ b/src/lib/urls.js @@ -202,8 +202,6 @@ module.exports = { data: url('/companies', '/:companyId/edit-history/data'), }, dnbHierarchy: { - index: url('/companies', '/:companyId/dnb-hierarchy'), - data: url('/companies', '/:companyId/dnb-hierarchy/data'), tree: url('/companies', '/:companyId/company-tree'), relatedCompaniesCount: url( '/v4/dnb', @@ -669,6 +667,7 @@ module.exports = { ), oneListTier: url('/api-proxy/v4/metadata', '/one-list-tier'), tradeAgreement: url('/api-proxy/v4/metadata', '/trade-agreement'), + overseasRegion: url('/api-proxy/v4/metadata', '/overseas-region'), }, omis: { index: url('/omis', PRIMARY_LINK_PARAMS.omis), @@ -767,6 +766,10 @@ module.exports = { index: url('/export'), create: url('/export/create?companyId=', ':companyId'), details: url('/export', '/:exportId/details'), + interactions: { + index: url('/export', '/:exportId/interactions'), + details: url('/export', '/:exportId/interactions/details'), + }, edit: url('/export', '/:exportId/edit'), delete: url('/export', '/:exportId/delete'), }, diff --git a/src/middleware/__test__/user-locals.test.js b/src/middleware/__test__/user-locals.test.js index 278858b1cc3..ace496818ec 100644 --- a/src/middleware/__test__/user-locals.test.js +++ b/src/middleware/__test__/user-locals.test.js @@ -1,93 +1,29 @@ -const proxyquire = require('proxyquire') -const { faker } = require('@faker-js/faker') - -const words = faker.lorem.words -const modulePath = '../user-locals' - -describe('user-locals middleware', () => { - let req, res, next - beforeEach(() => { - res = { - locals: {}, +const { parseFlashMessages } = require('../user-locals') + +describe('parseFlashMessages', () => { + it('valid JSON in success:with-body', () => { + const BODY = { heading: 'foo bar', body: 'baz bing' } + const RAW_FLASH_MESSAGES = { + success: ['foo', '{"test":1}'], + error: ['bar', 'baz'], + 'success:with-body': [JSON.stringify(BODY)], } - next = sinon.spy() - }) - describe('#getMessages', () => { - afterEach(() => { - expect(next).to.have.been.called + expect(parseFlashMessages(RAW_FLASH_MESSAGES)).to.deep.equal({ + ...RAW_FLASH_MESSAGES, + 'success:with-body': [BODY], }) + }) - context('With no messages in the flash', () => { - it('returns the values', () => { - const userLocals = require(modulePath) - const flash = sinon.stub().returns({}) - req = { - path: '', - flash, - } - userLocals(req, res, next) - - const messages = res.locals.getMessages() - - expect(flash).to.have.been.calledWith() - expect(messages).to.deep.equal({}) - }) - }) - - context('With valid messages in the flash', () => { - it('returns the values', () => { - const userLocals = require(modulePath) - const flashData = { - success: [words(5), '{"test":1}'], - error: [words(5), words(5)], - 'success:with-body': [ - JSON.stringify({ heading: words(2), body: words(10) }), - ], - } - const flash = sinon.stub().returns(flashData) - req = { - path: '', - flash, - } - - userLocals(req, res, next) - - const messages = res.locals.getMessages() - - expect(messages).to.equal(flashData) - expect(typeof messages['success:with-body'][0]).to.equal('object') - expect(typeof messages.success[1]).to.equal('string') - expect(flash).to.have.been.calledWith() - }) - }) - - context('With invalid JSON messages in the flash', () => { - it('returns the string and reports the error', () => { - const captureException = sinon.spy() - const userLocals = proxyquire(modulePath, { - '../lib/reporter': { - captureException, - }, - }) - const flashData = { - 'success:with-body': [`heading: ${words(2)}`], - } - const flash = sinon.stub().returns(flashData) - req = { - path: '', - flash, - } - - userLocals(req, res, next) - - const messages = res.locals.getMessages() + it('invalid JSON in success:with-body', () => { + const RAW_FLASH_MESSAGES = { + success: ['foo', '{"test":1}'], + error: ['bar', 'baz'], + 'success:with-body': ["I'm no valid JSON"], + } - expect(messages).to.equal(flashData) - expect(typeof messages['success:with-body'][0]).to.equal('string') - expect(flash).to.have.been.calledWith() - expect(captureException).to.have.been.called - }) - }) + expect(parseFlashMessages(RAW_FLASH_MESSAGES)).to.deep.equal( + RAW_FLASH_MESSAGES + ) }) }) diff --git a/src/middleware/api-proxy.js b/src/middleware/api-proxy.js index 3366ce828b3..78c382fcaf6 100644 --- a/src/middleware/api-proxy.js +++ b/src/middleware/api-proxy.js @@ -90,6 +90,7 @@ const ALLOWLIST = [ '/v3/investment/:projectId/proposition/:propositionId/document/upload-callback', '/v4/investment-lead/eyb/:eybLeadId', '/v4/investment-lead/eyb', + '/v4/dnb/company-investigation', ] module.exports = (app) => { diff --git a/src/middleware/metadata-api-proxy.js b/src/middleware/metadata-api-proxy.js index c0bec015684..22e227dd05f 100644 --- a/src/middleware/metadata-api-proxy.js +++ b/src/middleware/metadata-api-proxy.js @@ -77,6 +77,7 @@ const ALLOWLIST = [ '/v4/metadata/hvo-programmes', '/v4/metadata/associated-programme', '/v4/metadata/hvc', + '/v4/metadata/overseas-region', ] module.exports = (app) => { diff --git a/src/middleware/react-global-props.js b/src/middleware/react-global-props.js index b87abe16727..c6737c35bdb 100644 --- a/src/middleware/react-global-props.js +++ b/src/middleware/react-global-props.js @@ -9,6 +9,7 @@ const transformModulePermissions = (modules) => module.exports = () => { return function reactGlobalProps(req, res, next) { res.locals.globalProps = { + flashMessages: res.locals.flashMessages, sentryDsn: config.sentryDsn, sentryEnvironment: config.sentryEnvironment, csrfToken: req.csrfToken(), diff --git a/src/middleware/user-locals.js b/src/middleware/user-locals.js index ec46d8ce1ed..f9ba51c4388 100644 --- a/src/middleware/user-locals.js +++ b/src/middleware/user-locals.js @@ -27,7 +27,15 @@ function convertValueToJson(value) { } } -module.exports = (req, res, next) => { +const parseFlashMessages = (rawFlashMessages) => + Object.fromEntries( + Object.entries(rawFlashMessages).map(([k, v]) => [ + k, + k.endsWith(':with-body') ? v.map(convertValueToJson) : v, + ]) + ) + +const userLocals = (req, res, next) => { const userPermissions = get(res, 'locals.user.permissions') const userProfile = config.oauth.bypassSSO ? null @@ -37,28 +45,22 @@ module.exports = (req, res, next) => { filterNonPermittedItem(userPermissions) ) - Object.assign(res.locals, { - PERMITTED_APPLICATIONS: config.oauth.bypassSSO - ? [{ key: 'datahub-crm' }] - : permittedApplications, - ALLOWED_APPS: permittedNavItems.reduce((apps, { headerKey }) => { - headerKey && apps.push(headerKey) - return apps - }, []), - ACTIVE_KEY: getActiveHeaderKey(req.path, permittedNavItems), - - getMessages() { - const items = req.flash() + res.locals.PERMITTED_APPLICATIONS = config.oauth.bypassSSO + ? [{ key: 'datahub-crm' }] + : permittedApplications - for (const [key, values] of Object.entries(items)) { - if (key.endsWith(':with-body')) { - items[key] = values.map(convertValueToJson) - } - } + res.locals.ALLOWED_APPS = permittedNavItems.reduce((apps, { headerKey }) => { + headerKey && apps.push(headerKey) + return apps + }, []) - return items - }, - }) + res.locals.ACTIVE_KEY = getActiveHeaderKey(req.path, permittedNavItems) + res.locals.flashMessages = parseFlashMessages(req.flash()) next() } + +module.exports = { + parseFlashMessages, + userLocals, +} diff --git a/src/server.js b/src/server.js index 4c161763695..0962944400c 100644 --- a/src/server.js +++ b/src/server.js @@ -20,7 +20,7 @@ const currentJourney = require('./modules/form/current-journey') const nunjucks = require('./config/nunjucks') const headers = require('./middleware/headers') const locals = require('./middleware/locals') -const userLocals = require('./middleware/user-locals') +const { userLocals } = require('./middleware/user-locals') const user = require('./middleware/user') const auth = require('./middleware/auth') const store = require('./middleware/store') diff --git a/src/templates/_macros/common/local-header.njk b/src/templates/_macros/common/local-header.njk index 15517e18401..437d64c621f 100644 --- a/src/templates/_macros/common/local-header.njk +++ b/src/templates/_macros/common/local-header.njk @@ -14,7 +14,7 @@ #} {% macro LocalHeader(props) %} {% set breadcrumbs = props.breadcrumbs | default(getBreadcrumbs()) %} - {% set messages = props.messages | default(getMessages() if getMessages) %} + {% set messages = props.messages | default(flashMessages) %} {% set modifier = props.modifier | concat('') | reverse | join(' c-local-header--') if props.modifier %} {% if props %} diff --git a/test/a11y/cypress/config/urlTestExclusions.js b/test/a11y/cypress/config/urlTestExclusions.js index 0e6c8b928fd..ac6970dff5b 100644 --- a/test/a11y/cypress/config/urlTestExclusions.js +++ b/test/a11y/cypress/config/urlTestExclusions.js @@ -54,6 +54,8 @@ export const urlTestExclusions = [ url: '/investments/projects/:projectId/edit-associated/:associatedProjectId', }, { url: '/export/:exportId/details' }, + { url: '/export/:exportId/interactions' }, + { url: '/export/:exportId/interactions/details' }, { url: '/omis/:orderId/edit/lead-adviser/:adviserId' }, { url: '/interactions/ess/:essInteractionId/details' }, { @@ -78,6 +80,10 @@ export const urlTestExclusions = [ { url: '/companies/:companyId/hierarchies/ghq/:globalHqId/add' }, { url: '/companies/:companyId/hierarchies/ghq/remove' }, { url: '/companies/:companyId' }, + { url: '/contacts/:contactId/interactions/:interactionId' }, + { url: '/contacts/:contactId/interactions/create' }, + { url: '/contacts/:contactId/interactions/create/:theme/:kind' }, + { url: '/contacts/:contactId/interactions/:interactionId/edit' }, // API calls with redirect { url: '/company-lists/' }, // Redirects to homepage (which is tested) { url: '/tasks/:taskId/status-complete' }, diff --git a/test/component/cypress/specs/Companies/BusinessDetails/SectionAbout.cy.jsx b/test/component/cypress/specs/Companies/BusinessDetails/SectionAbout.cy.jsx index 982e2fa2dff..d65e3d516ef 100644 --- a/test/component/cypress/specs/Companies/BusinessDetails/SectionAbout.cy.jsx +++ b/test/component/cypress/specs/Companies/BusinessDetails/SectionAbout.cy.jsx @@ -19,6 +19,7 @@ describe('Section about', () => { tradingNames: ['Venus company'], referenceCode: 'ORG-10096257', companyNumber: '12345678', + dunsNumber: '987654321', turnoverGbp: '1000000', numberOfEmployees: '5', website: 'www.example.com', @@ -52,6 +53,7 @@ describe('Section about', () => { 'Companies House number': companyWithDetails.companyNumber + 'View on Companies House website (opens in new tab)', + 'DUNS number': '987654321', 'Annual turnover': '£1,000,000', 'Number of employees': companyWithDetails.numberOfEmployees, Website: companyWithDetails.website + ' (opens in new tab)', @@ -78,6 +80,7 @@ describe('Section about', () => { showEditLink: true, content: { 'Trading name': 'Not set', + 'DUNS number': 'Not set', 'Annual turnover': 'Not set', 'Number of employees': 'Not set', Website: 'Not set', @@ -104,6 +107,7 @@ describe('Section about', () => { showEditLink: false, content: { 'Trading name': 'Not set', + 'DUNS number': 'Not set', 'Annual turnover': 'Not set', 'Number of employees': 'Not set', Website: 'Not set', diff --git a/test/component/cypress/specs/Companies/CompanyActivity/EYBActivity.cy.jsx b/test/component/cypress/specs/Companies/CompanyActivity/EYBActivity.cy.jsx new file mode 100644 index 00000000000..ced788591d5 --- /dev/null +++ b/test/component/cypress/specs/Companies/CompanyActivity/EYBActivity.cy.jsx @@ -0,0 +1,150 @@ +import React from 'react' + +import urls from '../../../../../../src/lib/urls' + +import { ItemTemplate } from '../../../../../../src/client/modules/Companies/CompanyActivity' +import { transformEYBLeadToListItem } from '../../../../../../src/client/modules/Companies/CompanyActivity/transformers' +import { CollectionList } from '../../../../../../src/client/components' +import { + assertActivitySubject, + assertEYBLabel, + assertMetadataItems, + assertInvestmentThemeLabel, +} from '../../../support/activity-assertions' + +const EYB_LEAD_ID = 'e686c9d9-d7ba-444d-a85b-a64c477fc1ba' +const PROJECT_URL = urls.investments.eybLeads.details(EYB_LEAD_ID) +const EYB_COMPANY_NAME = 'EYB Company Name' +const LINKED_COMPANY_NAME = 'Linked Company Name' + +const buildAndMountActivity = (value = null, linked_company_name = null) => { + const activity = { + company: { + name: linked_company_name, + }, + eyb_lead: { + is_high_value: value, + created_on: '2024-12-02T09:59:03.911296+00:00', + company_name: EYB_COMPANY_NAME, + triage_created: '2024-12-01T09:59:03+00:00', + id: EYB_LEAD_ID, + }, + } + + cy.mountWithProvider( + + ) +} + +describe('EYB lead activity card', () => { + context( + 'When the card is rendered with a lead of unknown value and linked company name', + () => { + beforeEach(() => { + buildAndMountActivity(null, LINKED_COMPANY_NAME) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should render the labels and metadata', () => { + assertEYBLabel() + assertInvestmentThemeLabel() + assertActivitySubject(LINKED_COMPANY_NAME, PROJECT_URL) + assertMetadataItems([ + `Submitted to EYB date 01 Dec 2024`, + 'Value Unknown', + ]) + }) + } + ) + + context( + 'When the card is rendered with a lead of high value and linked company name', + () => { + beforeEach(() => { + buildAndMountActivity(true, LINKED_COMPANY_NAME) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should render the labels and metadata', () => { + assertEYBLabel() + assertInvestmentThemeLabel() + assertActivitySubject(LINKED_COMPANY_NAME, PROJECT_URL) + assertMetadataItems([`Submitted to EYB date 01 Dec 2024`, 'Value High']) + }) + } + ) + + context( + 'When the card is rendered with a lead of low value and linked company name', + () => { + beforeEach(() => { + buildAndMountActivity(false, LINKED_COMPANY_NAME) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should render the labels and metadata', () => { + assertEYBLabel() + assertInvestmentThemeLabel() + assertActivitySubject(LINKED_COMPANY_NAME, PROJECT_URL) + assertMetadataItems([`Submitted to EYB date 01 Dec 2024`, 'Value Low']) + }) + } + ) + + context( + 'When the card is rendered with a lead of unknown value and no linked company name', + () => { + beforeEach(() => { + buildAndMountActivity() + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should render the labels and metadata', () => { + assertEYBLabel() + assertInvestmentThemeLabel() + assertActivitySubject(EYB_COMPANY_NAME, PROJECT_URL) + assertMetadataItems([ + `Submitted to EYB date 01 Dec 2024`, + 'Value Unknown', + ]) + }) + } + ) + + context( + 'When the card is rendered with a lead of high value and no linked company name', + () => { + beforeEach(() => { + buildAndMountActivity(true) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should render the labels and metadata', () => { + assertEYBLabel() + assertInvestmentThemeLabel() + assertActivitySubject(EYB_COMPANY_NAME, PROJECT_URL) + assertMetadataItems([`Submitted to EYB date 01 Dec 2024`, 'Value High']) + }) + } + ) + + context( + 'When the card is rendered with a lead of low value and no linked company name', + () => { + beforeEach(() => { + buildAndMountActivity(false) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should render the labels and metadata', () => { + assertEYBLabel() + assertInvestmentThemeLabel() + assertActivitySubject(EYB_COMPANY_NAME, PROJECT_URL) + assertMetadataItems([`Submitted to EYB date 01 Dec 2024`, 'Value Low']) + }) + } + ) +}) diff --git a/test/component/cypress/specs/Companies/CompanyActivity/InvestmentActivity.cy.jsx b/test/component/cypress/specs/Companies/CompanyActivity/InvestmentActivity.cy.jsx index 81d36a17400..f53ba61b726 100644 --- a/test/component/cypress/specs/Companies/CompanyActivity/InvestmentActivity.cy.jsx +++ b/test/component/cypress/specs/Companies/CompanyActivity/InvestmentActivity.cy.jsx @@ -7,7 +7,9 @@ import { transformInvestmentToListItem } from '../../../../../../src/client/modu import { CollectionList } from '../../../../../../src/client/components' import { assertActivitySubject, + assertEYBLabel, assertMetadataItems, + assertNotEYBLabel, assertProjectKindLabel, assertText, } from '../../../support/activity-assertions' @@ -21,11 +23,17 @@ import { const NAME = 'An investment project' const PROJECT_URL = urls.investments.projects.details('2') const EL_DATE = '2023-12-01' +const DEFAULT_CLIENT_CONTACTS = [] +const DEAFAULT_PROJECT_TYPE = 'FDI' + +const EYB_LEAD = [{ id: '1' }] +const EYB_LEADS = [{ id: '2' }, { id: '3' }, { id: '4' }] const buildAndMountActivity = ( showOptionalFields, - clientContacts = [], - type = 'FDI' + clientContacts = DEFAULT_CLIENT_CONTACTS, + type = DEAFAULT_PROJECT_TYPE, + eybLeads = [] ) => { const activity = { date: CREATED_ON, @@ -42,6 +50,7 @@ const buildAndMountActivity = ( }, number_new_jobs: showOptionalFields ? 1 : '', total_investment: showOptionalFields ? 1234567890 : '', + eyb_leads: eybLeads, }, } @@ -54,30 +63,99 @@ const buildAndMountActivity = ( } describe('Investment project activity card', () => { - context('When the card is rendered with a complete FDI project', () => { - beforeEach(() => { - buildAndMountActivity(true, [CONTACT_1]) - cy.get('[data-test=collection-item]').should('exist') - }) - - it('should render the labels and metadata', () => { - assertInvestmentLabels() - assertActivitySubject(NAME, PROJECT_URL) - assertMetadataItems([ - 'Created on 25 Nov 2058', - 'Investment type FDI', - 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', - 'Estimated land date 1 Dec 2023', - 'Company contact Alexander Hamilton', - 'Total investment £1,234,567,890', - 'Capital expenditure value £123,456,789', - 'Gross value added (GVA) £12,345', - 'Number of jobs 1', - ]) - }) - }) context( - 'When the card is rendered with a complete project with multiple client contacts', + 'When the card is rendered with a complete FDI project and no link to EYB leads', + () => { + beforeEach(() => { + buildAndMountActivity(true, [CONTACT_1]) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should render the labels and metadata', () => { + assertInvestmentLabels() + assertNotEYBLabel() + assertActivitySubject(NAME, PROJECT_URL) + assertMetadataItems([ + 'Created on 25 Nov 2058', + 'Investment type FDI', + 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', + 'Estimated land date 1 Dec 2023', + 'Company contact Alexander Hamilton', + 'Total investment £1,234,567,890', + 'Capital expenditure value £123,456,789', + 'Gross value added (GVA) £12,345', + 'Number of jobs 1', + ]) + }) + } + ) + + context( + 'When the card is rendered with a complete FDI project and one linked EYB lead', + () => { + beforeEach(() => { + buildAndMountActivity( + true, + [CONTACT_1], + DEAFAULT_PROJECT_TYPE, + EYB_LEAD + ) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should render the labels and metadata', () => { + assertInvestmentLabels() + assertEYBLabel() + assertActivitySubject(NAME, PROJECT_URL) + assertMetadataItems([ + 'Created on 25 Nov 2058', + 'Investment type FDI', + 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', + 'Estimated land date 1 Dec 2023', + 'Company contact Alexander Hamilton', + 'Total investment £1,234,567,890', + 'Capital expenditure value £123,456,789', + 'Gross value added (GVA) £12,345', + 'Number of jobs 1', + ]) + }) + } + ) + + context( + 'When the card is rendered with a complete FDI project and multiple linked EYB leads', + () => { + beforeEach(() => { + buildAndMountActivity( + true, + [CONTACT_1], + DEAFAULT_PROJECT_TYPE, + EYB_LEADS + ) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should render the labels and metadata', () => { + assertInvestmentLabels() + assertEYBLabel() + assertActivitySubject(NAME, PROJECT_URL) + assertMetadataItems([ + 'Created on 25 Nov 2058', + 'Investment type FDI', + 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', + 'Estimated land date 1 Dec 2023', + 'Company contact Alexander Hamilton', + 'Total investment £1,234,567,890', + 'Capital expenditure value £123,456,789', + 'Gross value added (GVA) £12,345', + 'Number of jobs 1', + ]) + }) + } + ) + + context( + 'When the card is rendered with a complete project with multiple client contacts and no link to EYB leads', () => { beforeEach(() => { buildAndMountActivity(true, [CONTACT_1, CONTACT_2]) @@ -86,6 +164,71 @@ describe('Investment project activity card', () => { it('should render the labels and metadata', () => { assertInvestmentLabels() + assertNotEYBLabel() + assertActivitySubject(NAME, PROJECT_URL) + assertMetadataItems([ + 'Created on 25 Nov 2058', + 'Investment type FDI', + 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', + 'Estimated land date 1 Dec 2023', + 'Company contacts Alexander Hamilton, Oliver Twist', + 'Total investment £1,234,567,890', + 'Capital expenditure value £123,456,789', + 'Gross value added (GVA) £12,345', + 'Number of jobs 1', + ]) + }) + } + ) + + context( + 'When the card is rendered with a complete project with multiple client contacts and one EYB lead', + () => { + beforeEach(() => { + buildAndMountActivity( + true, + [CONTACT_1, CONTACT_2], + DEAFAULT_PROJECT_TYPE, + EYB_LEAD + ) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should render the labels and metadata', () => { + assertInvestmentLabels() + assertEYBLabel() + assertActivitySubject(NAME, PROJECT_URL) + assertMetadataItems([ + 'Created on 25 Nov 2058', + 'Investment type FDI', + 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', + 'Estimated land date 1 Dec 2023', + 'Company contacts Alexander Hamilton, Oliver Twist', + 'Total investment £1,234,567,890', + 'Capital expenditure value £123,456,789', + 'Gross value added (GVA) £12,345', + 'Number of jobs 1', + ]) + }) + } + ) + + context( + 'When the card is rendered with a complete project with multiple client contacts and multiple EYB leads', + () => { + beforeEach(() => { + buildAndMountActivity( + true, + [CONTACT_1, CONTACT_2], + DEAFAULT_PROJECT_TYPE, + EYB_LEADS + ) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should render the labels and metadata', () => { + assertInvestmentLabels() + assertEYBLabel() assertActivitySubject(NAME, PROJECT_URL) assertMetadataItems([ 'Created on 25 Nov 2058', @@ -101,52 +244,228 @@ describe('Investment project activity card', () => { }) } ) - context('When the card is rendered with an incomplete project', () => { - beforeEach(() => { - buildAndMountActivity(false) - cy.get('[data-test=collection-item]').should('exist') - }) - - it('should only render the mandatory fields', () => { - assertInvestmentLabels() - assertActivitySubject(NAME, PROJECT_URL) - assertMetadataItems([ - 'Created on 25 Nov 2058', - 'Investment type FDI', - 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', - 'Estimated land date 1 Dec 2023', - ]) - }) - }) - - context('When the card is rendered with a Non-FDI project', () => { - beforeEach(() => { - buildAndMountActivity(false, [], 'Non-FDI') - cy.get('[data-test=collection-item]').should('exist') - }) - - it('should only render the mandatory fields', () => { - assertInvestmentLabels('Non-FDI') - assertActivitySubject(NAME, PROJECT_URL) - assertMetadataItems([ - 'Created on 25 Nov 2058', - 'Investment type Non-FDI', - 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', - 'Estimated land date 1 Dec 2023', - ]) - }) - }) context( - 'When the card is rendered with a Commitment to Invest project', + 'When the card is rendered with an incomplete project and no link to EYB leads', + () => { + beforeEach(() => { + buildAndMountActivity(false) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should only render the mandatory fields', () => { + assertInvestmentLabels() + assertNotEYBLabel() + assertActivitySubject(NAME, PROJECT_URL) + assertMetadataItems([ + 'Created on 25 Nov 2058', + 'Investment type FDI', + 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', + 'Estimated land date 1 Dec 2023', + ]) + }) + } + ) + + context( + 'When the card is rendered with an incomplete project and one EYB lead', + () => { + beforeEach(() => { + buildAndMountActivity( + false, + DEFAULT_CLIENT_CONTACTS, + DEAFAULT_PROJECT_TYPE, + EYB_LEAD + ) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should only render the mandatory fields', () => { + assertInvestmentLabels() + assertEYBLabel() + assertActivitySubject(NAME, PROJECT_URL) + assertMetadataItems([ + 'Created on 25 Nov 2058', + 'Investment type FDI', + 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', + 'Estimated land date 1 Dec 2023', + ]) + }) + } + ) + + context( + 'When the card is rendered with an incomplete project and multiple EYB leads', + () => { + beforeEach(() => { + buildAndMountActivity( + false, + DEFAULT_CLIENT_CONTACTS, + DEAFAULT_PROJECT_TYPE, + EYB_LEADS + ) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should only render the mandatory fields', () => { + assertInvestmentLabels() + assertEYBLabel() + assertActivitySubject(NAME, PROJECT_URL) + assertMetadataItems([ + 'Created on 25 Nov 2058', + 'Investment type FDI', + 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', + 'Estimated land date 1 Dec 2023', + ]) + }) + } + ) + + context( + 'When the card is rendered with a Non-FDI project and no link to EYB leads', + () => { + beforeEach(() => { + buildAndMountActivity(false, DEFAULT_CLIENT_CONTACTS, 'Non-FDI') + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should only render the mandatory fields', () => { + assertInvestmentLabels('Non-FDI') + assertNotEYBLabel() + assertActivitySubject(NAME, PROJECT_URL) + assertMetadataItems([ + 'Created on 25 Nov 2058', + 'Investment type Non-FDI', + 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', + 'Estimated land date 1 Dec 2023', + ]) + }) + } + ) + + context( + 'When the card is rendered with a Non-FDI project and one EYB lead', + () => { + beforeEach(() => { + buildAndMountActivity( + false, + DEFAULT_CLIENT_CONTACTS, + 'Non-FDI', + EYB_LEAD + ) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should only render the mandatory fields', () => { + assertInvestmentLabels('Non-FDI') + assertEYBLabel() + assertActivitySubject(NAME, PROJECT_URL) + assertMetadataItems([ + 'Created on 25 Nov 2058', + 'Investment type Non-FDI', + 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', + 'Estimated land date 1 Dec 2023', + ]) + }) + } + ) + + context( + 'When the card is rendered with a Non-FDI project and multiple EYB leads', + () => { + beforeEach(() => { + buildAndMountActivity( + false, + DEFAULT_CLIENT_CONTACTS, + 'Non-FDI', + EYB_LEADS + ) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should only render the mandatory fields', () => { + assertInvestmentLabels('Non-FDI') + assertEYBLabel() + assertActivitySubject(NAME, PROJECT_URL) + assertMetadataItems([ + 'Created on 25 Nov 2058', + 'Investment type Non-FDI', + 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', + 'Estimated land date 1 Dec 2023', + ]) + }) + } + ) + + context( + 'When the card is rendered with a Commitment to Invest project and no link to EYB leads', + () => { + beforeEach(() => { + buildAndMountActivity( + false, + DEFAULT_CLIENT_CONTACTS, + 'Commitment to invest' + ) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should only render the mandatory fields', () => { + assertInvestmentLabels('Commitment to invest') + assertNotEYBLabel() + assertActivitySubject(NAME, PROJECT_URL) + assertMetadataItems([ + 'Created on 25 Nov 2058', + 'Investment type Commitment to invest', + 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', + 'Estimated land date 1 Dec 2023', + ]) + }) + } + ) + + context( + 'When the card is rendered with a Commitment to Invest project and one EYB lead', + () => { + beforeEach(() => { + buildAndMountActivity( + false, + DEFAULT_CLIENT_CONTACTS, + 'Commitment to invest', + EYB_LEAD + ) + cy.get('[data-test=collection-item]').should('exist') + }) + + it('should only render the mandatory fields', () => { + assertInvestmentLabels('Commitment to invest') + assertEYBLabel() + assertActivitySubject(NAME, PROJECT_URL) + assertMetadataItems([ + 'Created on 25 Nov 2058', + 'Investment type Commitment to invest', + 'Added by Bernard Harris-Patel bernardharrispatel@test.com, Test Team 1 ', + 'Estimated land date 1 Dec 2023', + ]) + }) + } + ) + + context( + 'When the card is rendered with a Commitment to Invest project and multiple EYB leads', () => { beforeEach(() => { - buildAndMountActivity(false, [], 'Commitment to invest') + buildAndMountActivity( + false, + DEFAULT_CLIENT_CONTACTS, + 'Commitment to invest', + EYB_LEADS + ) cy.get('[data-test=collection-item]').should('exist') }) it('should only render the mandatory fields', () => { assertInvestmentLabels('Commitment to invest') + assertEYBLabel() assertActivitySubject(NAME, PROJECT_URL) assertMetadataItems([ 'Created on 25 Nov 2058', diff --git a/test/component/cypress/specs/Companies/CompanyOverview/ActivityCard/EYBActivityCard.cy.jsx b/test/component/cypress/specs/Companies/CompanyOverview/ActivityCard/EYBActivityCard.cy.jsx index d704537cd87..34f1cf19e5d 100644 --- a/test/component/cypress/specs/Companies/CompanyOverview/ActivityCard/EYBActivityCard.cy.jsx +++ b/test/component/cypress/specs/Companies/CompanyOverview/ActivityCard/EYBActivityCard.cy.jsx @@ -39,7 +39,7 @@ const buildAndMountActivity = (value = null, linked_company_name = null) => { describe('EYB lead activity card', () => { context( - 'When the card is rendered with a lead of unknown value and linked company', + 'When the card is rendered with a lead of unknown value and linked company name', () => { beforeEach(() => { buildAndMountActivity(null, LINKED_COMPANY_NAME) @@ -63,7 +63,7 @@ describe('EYB lead activity card', () => { ) context( - 'When the card is rendered with a lead of high value and linked company', + 'When the card is rendered with a lead of high value and linked company name', () => { beforeEach(() => { buildAndMountActivity(true, LINKED_COMPANY_NAME) @@ -87,7 +87,7 @@ describe('EYB lead activity card', () => { ) context( - 'When the card is rendered with a lead of low value and linked company', + 'When the card is rendered with a lead of low value and linked company name', () => { beforeEach(() => { buildAndMountActivity(false, LINKED_COMPANY_NAME) @@ -111,7 +111,7 @@ describe('EYB lead activity card', () => { ) context( - 'When the card is rendered with a lead of unknown value and no linked company', + 'When the card is rendered with a lead of unknown value and no linked company name', () => { beforeEach(() => { buildAndMountActivity() @@ -135,7 +135,7 @@ describe('EYB lead activity card', () => { ) context( - 'When the card is rendered with a lead of high value and no linked company', + 'When the card is rendered with a lead of high value and no linked company name', () => { beforeEach(() => { buildAndMountActivity(true) @@ -159,7 +159,7 @@ describe('EYB lead activity card', () => { ) context( - 'When the card is rendered with a lead of low value and no linked company', + 'When the card is rendered with a lead of low value and no linked company name', () => { beforeEach(() => { buildAndMountActivity(false) diff --git a/test/component/cypress/specs/Companies/CompanyOverview/ActivityCard/InvestmentActivityCard.cy.jsx b/test/component/cypress/specs/Companies/CompanyOverview/ActivityCard/InvestmentActivityCard.cy.jsx index 56da6669e91..9f5c2dc0fea 100644 --- a/test/component/cypress/specs/Companies/CompanyOverview/ActivityCard/InvestmentActivityCard.cy.jsx +++ b/test/component/cypress/specs/Companies/CompanyOverview/ActivityCard/InvestmentActivityCard.cy.jsx @@ -92,7 +92,7 @@ describe('Investment activity card', () => { }) context( - 'When the project has one new job and multiple linked EYB lead', + 'When the project has one new job and multiple linked EYB leads', () => { beforeEach(() => { buildAndMountActivity(1, EYB_LEADS) @@ -128,7 +128,7 @@ describe('Investment activity card', () => { }) }) - context('When the project has no new jobs and one linked EYB leads', () => { + context('When the project has no new jobs and one linked EYB lead', () => { beforeEach(() => { buildAndMountActivity(0, EYB_LEAD) cy.get('[data-test="activity-card-wrapper"]').should('exist') diff --git a/test/component/cypress/specs/Contacts/ConsentDetails.cy.jsx b/test/component/cypress/specs/Contacts/ConsentDetails.cy.jsx new file mode 100644 index 00000000000..e954d3175a8 --- /dev/null +++ b/test/component/cypress/specs/Contacts/ConsentDetails.cy.jsx @@ -0,0 +1,112 @@ +import React from 'react' + +import ConsentDetails from '../../../../../src/client/modules/Contacts/ContactDetails/ConsentDetails' + +describe('ConsentDetails', () => { + context('When contact has no consent data', () => { + beforeEach(() => { + cy.mount() + }) + + it('should render a message that this data is missing for this contact', () => { + cy.get('p').should( + 'have.text', + 'There is no marketing communication preference available for this contact' + ) + }) + }) + + context('When a contact has consented', () => { + beforeEach(() => { + cy.mount( + + ) + }) + + it('should render the expected message', () => { + cy.get('p').should( + 'have.text', + 'This contact has opted into receiving marketing communications.' + ) + }) + }) + + context('When a contact has not consented', () => { + beforeEach(() => { + cy.mount( + + ) + }) + + it('should render the expected message', () => { + cy.get('p').should( + 'have.text', + 'This contact has opted out of receiving marketing communications.' + ) + }) + }) + + context('When a contact has no consent management url', () => { + beforeEach(() => { + cy.mount( + + ) + }) + + it('should hide the consent-management section', () => { + cy.get('[data-test="consent-management"]').should('not.exist') + }) + }) + + context('When a contact has a consent management url', () => { + beforeEach(() => { + cy.mount( + + ) + }) + + it('should display a button that uses a mailto tag to open an email client', () => { + cy.get('[data-test="send-consent-email-button"]').should( + 'have.attr', + 'href', + 'mailto:test@dbt.com?subject=Marketing communications preference&body=http://domain.com?email=test@dbt.com' + ) + }) + + it('should display a link that copies the contact consent management url into clipboard', () => { + cy.get('[data-test="copy-consent-link-button"]').focus().click() + cy.window().then((win) => { + win.navigator.clipboard.readText().then((text) => { + expect(text).to.eq('http://domain.com?email=test@dbt.com') + }) + }) + }) + }) +}) diff --git a/test/component/cypress/specs/Contacts/ContactLocalHeader.cy.jsx b/test/component/cypress/specs/Contacts/ContactLocalHeader.cy.jsx index d623c8be9eb..acdc566653c 100644 --- a/test/component/cypress/specs/Contacts/ContactLocalHeader.cy.jsx +++ b/test/component/cypress/specs/Contacts/ContactLocalHeader.cy.jsx @@ -1,6 +1,6 @@ import React from 'react' -import ContactLocalHeader from '../../../../../src/client/components/ContactLocalHeader' +import { ContactLocalHeaderComponent } from '../../../../../src/client/components/ContactLocalHeader' import urls from '../../../../../src/lib/urls' const notPrimaryContact = require('../../../../sandbox/fixtures/v3/contact/contact-incomplete-details-uk.json') @@ -35,7 +35,9 @@ const addInteractionUrl = urls.companies.interactions.create( describe('ContactLocalHeader', () => { context('When a primary contact is passed in', () => { beforeEach(() => { - cy.mountWithProvider() + cy.mountWithProvider( + + ) }) it('should render the company link', () => { @@ -63,7 +65,9 @@ describe('ContactLocalHeader', () => { context('When a contact that is not primary is passed in', () => { beforeEach(() => { - cy.mountWithProvider() + cy.mountWithProvider( + + ) }) it('should render the company link', () => { @@ -91,7 +95,9 @@ describe('ContactLocalHeader', () => { context('When an archived contact is passed in', () => { beforeEach(() => { - cy.mountWithProvider() + cy.mountWithProvider( + + ) }) it('should render the company link', () => { diff --git a/test/component/cypress/specs/ExportPipeline/ExportInteractionsList.cy.jsx b/test/component/cypress/specs/ExportPipeline/ExportInteractionsList.cy.jsx new file mode 100644 index 00000000000..e190605abe4 --- /dev/null +++ b/test/component/cypress/specs/ExportPipeline/ExportInteractionsList.cy.jsx @@ -0,0 +1,165 @@ +import React from 'react' + +import ExportInteractionsList from '../../../../../src/client/modules/ExportPipeline/ExportInteractionsList' +import { interactionFaker } from '../../../../functional/cypress/fakers/interactions' + +describe('ExportInteractionsList', () => { + it('should render a list of export project interactions', () => { + const exportProject = { + id: '1', + title: 'Baileys export to Brazil', + } + + const interaction = { + date: '2024-12-23', + contacts: [ + { + name: 'James Brown', + }, + ], + dit_participants: [ + { + adviser: { + name: 'David Buffer', + }, + team: { + name: 'Digital Data Hub - Live Service', + }, + }, + ], + service: { + name: 'Account management : General', + }, + } + + const interactionList = [ + interaction, + interactionFaker(), + interactionFaker(), + ] + + cy.mountWithProvider( + , + { + tasks: { + Interactions: () => Promise.resolve(interactionList), + Export: () => Promise.resolve(exportProject), + }, + } + ) + + cy.get('[data-test="export-interactions-list"]').should('exist') + cy.get('[data-test="collection-item"]').as('collectionItems') + cy.get('@collectionItems').eq(0).as('firstItem') + + cy.get('@collectionItems').should('have.length', 3) + + cy.get('@firstItem').within(() => { + cy.get('h3 a') + .should('have.text', 'Baileys export to Brazil') + .and('have.attr', 'href', '/export/1/interactions/details') + + const items = '[data-test="metadata-item"]' + cy.get(items).should('have.length', 4) + cy.get(items).eq(0).should('have.text', 'Date: 23 December 2024') + cy.get(items).eq(1).should('have.text', 'Contact(s): James Brown') + cy.get(items) + .eq(2) + .should( + 'have.text', + 'Adviser(s): David Buffer - Digital Data Hub - Live Service' + ) + cy.get(items) + .eq(3) + .should('have.text', 'Service: Account management : General') + }) + }) + + it('should render a list of multiple contacts', () => { + const interaction = { + date: '2024-12-23', + contacts: [ + { + name: 'James Brown', + }, + { + name: 'Jim Brown', + }, + { + name: 'Jude Brown', + }, + ], + dit_participants: [], + service: { + name: 'Account management : General', + }, + } + cy.mountWithProvider(, { + tasks: { + Interactions: () => Promise.resolve([interaction]), + }, + }) + + cy.get('[data-test="metadata-item"]') + .eq(1) + .should('have.text', 'Contact(s): James Brown, Jim Brown, Jude Brown') + }) + + it('should render a list of multiple advisers', () => { + const interaction = { + date: '2024-12-23', + contacts: [], + dit_participants: [ + { + adviser: { + name: 'James Brown', + }, + team: { + name: 'British Water', + }, + }, + { + adviser: { + name: 'Jim Brown', + }, + team: { + name: 'Cumbria LEP', + }, + }, + { + adviser: { + name: 'Jude Brown', + }, + team: { + name: 'Doncaster Council', + }, + }, + ], + service: { + name: 'Account management : General', + }, + } + cy.mountWithProvider(, { + tasks: { + Interactions: () => Promise.resolve([interaction]), + }, + }) + + cy.get('[data-test="metadata-item"]') + .eq(2) + .should( + 'have.text', + 'Adviser(s): James Brown - British Water, Jim Brown - Cumbria LEP, Jude Brown - Doncaster Council' + ) + }) + + it('should not render a list of export project interactions', () => { + cy.mountWithProvider(, { + tasks: { + Interactions: () => Promise.resolve([]), + }, + }) + + cy.get('[data-test="export-interactions-list"]').should('not.exist') + }) +}) diff --git a/test/component/cypress/specs/ExportPipeline/TabNav.cy.jsx b/test/component/cypress/specs/ExportPipeline/TabNav.cy.jsx new file mode 100644 index 00000000000..3e005dcbafe --- /dev/null +++ b/test/component/cypress/specs/ExportPipeline/TabNav.cy.jsx @@ -0,0 +1,73 @@ +import React from 'react' + +import Export from '../../../../../src/client/modules/ExportPipeline/Export' +import { assertBreadcrumbs } from '../../../../functional/cypress/support/assertions' +import { assertTabNav } from '../../../../end-to-end/cypress/support/assertions' +import urls from '../../../../../src/lib/urls' +import fixtures from '../../../../functional/cypress/fixtures' + +const exportProjectDetails = fixtures.export.exportProjectDetails + +describe('Export project tab navigation', () => { + it('should render the breadcrumbs for details', () => { + cy.mountWithProvider(, { + initialPath: `/export/${exportProjectDetails.id}/details`, + tasks: { + Export: () => exportProjectDetails, + }, + }) + assertBreadcrumbs({ + Home: urls.exportPipeline.index(), + [exportProjectDetails.title]: null, + }) + }) + + it('should render the same breadcrumbs for interactions', () => { + cy.mountWithProvider(, { + initialPath: `/export/${exportProjectDetails.id}/interactions/`, + tasks: { + Export: () => exportProjectDetails, + }, + }) + assertBreadcrumbs({ + Home: urls.exportPipeline.index(), + [exportProjectDetails.title]: null, + }) + }) + + it('should render a company link and page heading', () => { + cy.mountWithProvider(, { + initialPath: `/export/${exportProjectDetails.id}/details`, + tasks: { + Export: () => exportProjectDetails, + }, + }) + + cy.get('[data-test=export-company-link]') + .should('have.text', exportProjectDetails.company.name.toUpperCase()) + .should( + 'have.attr', + 'href', + `/companies/${exportProjectDetails.company.id}` + ) + + cy.get('[data-test="heading"]').should( + 'have.text', + exportProjectDetails.title + ) + }) + + it('should render two tabs: Project details and Interactions', () => { + cy.mountWithProvider(, { + initialPath: `/export/${exportProjectDetails.id}/details`, + tasks: { + Export: () => Promise.resolve(exportProjectDetails), + TASK_GET_EXPORT_DETAIL: () => Promise.resolve(exportProjectDetails), + }, + }) + assertTabNav({ + tabs: ['Project details', 'Interactions'], + selectedIndex: 0, + }) + }) +}) diff --git a/test/component/cypress/specs/Referrals/SendReferralForm.cy.jsx b/test/component/cypress/specs/Referrals/SendReferralForm.cy.jsx deleted file mode 100644 index d09e1d880de..00000000000 --- a/test/component/cypress/specs/Referrals/SendReferralForm.cy.jsx +++ /dev/null @@ -1,46 +0,0 @@ -import React from 'react' - -import SendReferralForm from '../../../../../src/apps/companies/apps/referrals/send-referral/client/SendReferralForm' -import { companyFaker } from '../../../../functional/cypress/fakers/companies' -import { contactFaker } from '../../../../functional/cypress/fakers/contacts' - -const { - assertBreadcrumbs, - assertLocalHeader, -} = require('../../../../functional/cypress/support/assertions') -const urls = require('../../../../../src/lib/urls') - -describe('SendReferralForm component', () => { - const company = companyFaker() - const companyContacts = [contactFaker()] - - describe('All but successful completion', () => { - beforeEach(() => { - cy.mountWithProvider( -
- -
- ) - }) - - context('when viewing the "send referral" form', () => { - it('should display breadcrumbs', () => { - assertBreadcrumbs({ - Home: urls.dashboard.index(), - Companies: urls.companies.index(), - [company.name]: urls.companies.detail(company.id), - 'Send a referral': null, - }) - }) - - it('should display the header', () => { - assertLocalHeader('Send a referral') - }) - }) - }) -}) diff --git a/test/component/cypress/specs/Referrals/StepReferralDetails.cy.jsx b/test/component/cypress/specs/Referrals/StepReferralDetails.cy.jsx index 74980aba0e1..dc521284cbe 100644 --- a/test/component/cypress/specs/Referrals/StepReferralDetails.cy.jsx +++ b/test/component/cypress/specs/Referrals/StepReferralDetails.cy.jsx @@ -1,6 +1,6 @@ import React from 'react' -import StepReferralDetails from '../../../../../src/apps/companies/apps/referrals/send-referral/client/StepReferralDetails' +import StepReferralDetails from '../../../../../src/client/modules/Companies/Referrals/SendReferralForm/StepReferralDetails' import { companyFaker } from '../../../../functional/cypress/fakers/companies' import { contactFaker } from '../../../../functional/cypress/fakers/contacts' @@ -26,7 +26,7 @@ describe('StepReferralDetails component', () => { const company = companyFaker() const companyContacts = [contactFaker()] const task = taskFaker() - const cancelUrl = 'cancelUrl' + const cancelUrl = urls.companies.detail(company.id) describe('All but successful completion', () => { beforeEach(() => { @@ -36,7 +36,6 @@ describe('StepReferralDetails component', () => { @@ -103,7 +102,7 @@ describe('StepReferralDetails component', () => { }) context('the "Cancel" button link', () => { - it('should contain the "cancelUrl"', () => { + it('should contain the correct link', () => { assertLink('referral-details-cancel', cancelUrl) }) }) diff --git a/test/component/cypress/specs/components/ArchivePanel.cy.jsx b/test/component/cypress/specs/components/ArchivePanel.cy.jsx index 8d11b7a7128..875a27dcf06 100644 --- a/test/component/cypress/specs/components/ArchivePanel.cy.jsx +++ b/test/component/cypress/specs/components/ArchivePanel.cy.jsx @@ -20,6 +20,24 @@ const unarchiveUrl = 'https://www.example.com' const archiveReason = 'No longer needed' const prefixedArchiveReason = 'Reason: ' + archiveReason +const assertArchiveMessage = (message) => { + cy.get('[data-test="archive-message"]') + .should('exist') + .should('have.text', message) +} + +const assertArchiveReason = () => { + cy.get('[data-test=archive-reason]') + .should('exist') + .should('have.text', prefixedArchiveReason) +} + +const assertUnarchiveLink = () => { + cy.get('[data-test=unarchive-link]') + .should('exist') + .should('have.attr', 'href', unarchiveUrl) +} + describe('ArchivePanel', () => { const Component = (props) => ( { }) }) }) - -const assertArchiveMessage = (message) => { - cy.get('[data-test="archive-message"]') - .should('exist') - .should('have.text', message) -} - -const assertArchiveReason = () => { - cy.get('[data-test=archive-reason]') - .should('exist') - .should('have.text', prefixedArchiveReason) -} - -const assertUnarchiveLink = () => { - cy.get('[data-test=unarchive-link]') - .should('exist') - .should('have.attr', 'href', unarchiveUrl) -} diff --git a/test/component/cypress/support/activity-assertions.js b/test/component/cypress/support/activity-assertions.js index 7ddc39d161c..ccd852d2c2b 100644 --- a/test/component/cypress/support/activity-assertions.js +++ b/test/component/cypress/support/activity-assertions.js @@ -45,9 +45,12 @@ export const assertProjectKindLabel = () => { } export const assertEYBLabel = () => { - assertText('[data-test="eyb-label"]', 'EYB') + assertText('[data-test="eyb-kind-label"]', 'EYB') } +export const assertNotEYBLabel = () => { + cy.get('[data-test="eyb-kind-label"]').should('not.exist') +} export const assertOrderKindLabel = () => { assertText('[data-test="order-kind-label"]', 'New Order') } @@ -55,3 +58,7 @@ export const assertOrderKindLabel = () => { export const assertGreatKindLabel = () => { assertText('[data-test="great-kind-label"]', 'great.gov.uk') } + +export const assertInvestmentThemeLabel = () => { + assertText('[data-test="investment-theme-label"]', 'Investment') +} diff --git a/test/end-to-end/cypress/specs/DIT/audit-spec.js b/test/end-to-end/cypress/specs/DIT/audit-spec.js index c0b6b02a102..7cff5ccc136 100644 --- a/test/end-to-end/cypress/specs/DIT/audit-spec.js +++ b/test/end-to-end/cypress/specs/DIT/audit-spec.js @@ -3,7 +3,7 @@ const selectors = require('../../../../selectors') const urls = require('../../../../../src/lib/urls') const { formatDate, - DATE_FORMAT_COMPACT, + DATE_FORMAT_MEDIUM, } = require('../../../../../src/client/utils/date-utils') const { assertFlashMessage, @@ -16,7 +16,7 @@ const { assertBadgeNotPresent, } = require('../../../../functional/cypress/support/collection-list-assertions') -const todaysDate = formatDate(new Date(), DATE_FORMAT_COMPACT) +const todaysDate = formatDate(new Date(), DATE_FORMAT_MEDIUM) let companyObj let contactObj let investmentProjectObj diff --git a/test/end-to-end/cypress/specs/DIT/companies-spec.js b/test/end-to-end/cypress/specs/DIT/companies-spec.js index bc140513164..36c498953ed 100644 --- a/test/end-to-end/cypress/specs/DIT/companies-spec.js +++ b/test/end-to-end/cypress/specs/DIT/companies-spec.js @@ -5,6 +5,9 @@ const userActions = require('../../support/user-actions') const { companies, contacts } = require('../../../../../src/lib/urls') const { assertKeyValueTable } = require('../../support/assertions') +const { + assertFlashMessage, +} = require('../../../../functional/cypress/support/assertions') describe('Advisors', () => { const company = fixtures.company.create.corp() @@ -47,14 +50,15 @@ describe('Contacts', () => { cy.visit(contacts.create(company.pk)) userActions.contacts.create(data) - cy.contains('You have successfully added a new contact Company Contact') + assertFlashMessage( + 'You have successfully added a new contact Company Contact' + ) - assertKeyValueTable('bodyMainContent', { + assertKeyValueTable('contact-details-table', { 'Job title': 'Coffee machine operator', 'Phone number': '44 0778877778800', Address: '100 Path, A town, 12345, United States', Email: 'company.contact@dit.com', - 'Email marketing': 'Cannot be marketed to', }) }) diff --git a/test/end-to-end/cypress/specs/DIT/event-spec.js b/test/end-to-end/cypress/specs/DIT/event-spec.js index f77b8fe598e..cf33dae56f0 100644 --- a/test/end-to-end/cypress/specs/DIT/event-spec.js +++ b/test/end-to-end/cypress/specs/DIT/event-spec.js @@ -128,22 +128,15 @@ describe('Event', () => { cy.visit(urls.events.index()) cy.contains(eventName).click() cy.contains('Attendees').click() - cy.get(selectors.entityCollection.addAttendee).click() + cy.contains('Add attendee').click() - cy.get('[data-test="contact-name-filter"]') - .type('dean cox') - .type('{enter}') + cy.get('input[name="name"]').type('dean cox').type('{enter}') cy.contains('Dean Cox').click() - cy.get(selectors.message.flashMessages) - .should( - 'contain', - 'Event attendee added - This has created a service delivery record.' - ) - .and( - 'contain', + cy.contains( + 'Event attendee added - This has created a service delivery record. ' + 'If required, you can view or edit the service delivery directly from the attendee record.' - ) + ) }) }) @@ -164,7 +157,7 @@ describe('Event', () => { .invoke('text') .should('contain', 'Account management') cy.contains(eventName).click() - cy.get(selectors.entityCollection.editEvent).click() + cy.contains('a', 'Edit event') fillEventType('Exhibition') clickSaveAndReturnButton() @@ -185,30 +178,23 @@ describe('Event', () => { it('Should add an interaction with the attendee', () => { cy.visit(urls.events.details(event.pk)) - cy.contains('a', 'Attendees').click() + cy.contains('button', 'Attendees').click() cy.contains('Add attendee').click() - cy.get('[data-test="contact-name-filter"]') - .type('Attendee') - .type('{enter}') + cy.get('input[name="name"]').type('Attendee').type('{enter}') cy.contains('Joe Attendee').click() cy.contains('Event attendee added') }) it('Should not be able to add a duplicate attendee', () => { cy.visit(urls.events.details(event.pk)) - cy.contains('a', 'Attendees').click() + cy.contains('button', 'Attendees').click() cy.contains('Add attendee').click() - cy.get('[data-test="contact-name-filter"]') - .type('Attendee') - .type('{enter}') + cy.get('input[name="name"]').type('Attendee').type('{enter}') cy.contains('Joe Attendee').click() cy.contains('Add attendee').click() - cy.get('[data-test="contact-name-filter"]') - .type('Attendee') - .type('{enter}') + cy.get('input[name="name"]').type('Attendee').type('{enter}') cy.contains('Joe Attendee').click() - cy.get(selectors.message.flashMessages).should( - 'contain', + cy.contains( 'Event attendee not added - This contact has already been added as an event attendee' ) }) diff --git a/test/end-to-end/cypress/specs/DIT/local-nav-spec.js b/test/end-to-end/cypress/specs/DIT/local-nav-spec.js index 0c14e265066..883ec59d719 100644 --- a/test/end-to-end/cypress/specs/DIT/local-nav-spec.js +++ b/test/end-to-end/cypress/specs/DIT/local-nav-spec.js @@ -108,17 +108,4 @@ describe('DBT Permission', () => { ]) }) }) - - describe('event', () => { - beforeEach(() => { - const event = fixtures.event.create.defaultEvent() - cy.loadFixture([event]) - cy.visit(urls.events.details(event.pk)) - }) - - it('should display DBT only side navs', () => { - const navSelector = '[data-test="event-details-nav-link"]' - assertLocalNav(navSelector, ['Details', 'Attendee']) - }) - }) }) diff --git a/test/end-to-end/cypress/support/assertions.js b/test/end-to-end/cypress/support/assertions.js index 3a375a796e1..167f96086a7 100644 --- a/test/end-to-end/cypress/support/assertions.js +++ b/test/end-to-end/cypress/support/assertions.js @@ -68,6 +68,30 @@ const assertLocalNav = (selector, navList) => { }) } +function assertTabNav({ tabs, selectedIndex }) { + cy.viewport(1024, 768) + cy.get('[data-test="tablist"]') + .should('exist') + .and('have.attr', 'role', 'tablist') + + cy.get('[data-test="tablist"] [role="tab"]').should( + 'have.length', + tabs.length + ) + + tabs.forEach((tabText, index) => { + cy.get('[data-test="tablist"] [role="tab"]') + .eq(index) + .should('have.text', tabText) + .and( + 'have.attr', + 'aria-selected', + index === selectedIndex ? 'true' : 'false' + ) + .and('have.attr', 'tabindex', index === selectedIndex ? '0' : '-1') + }) +} + const assertActivitytab = (selector) => { const navElement = cy.get(selector) navElement.should('be.checked') @@ -90,6 +114,7 @@ module.exports = { assertError, assertCollection, assertLocalNav, + assertTabNav, assertKeyValueTable, assertLocalReactNav, assertActivitytab, diff --git a/test/functional/cypress/fakers/eyb-leads.js b/test/functional/cypress/fakers/eyb-leads.js index 44a1e9cf518..9fef8ef6672 100644 --- a/test/functional/cypress/fakers/eyb-leads.js +++ b/test/functional/cypress/fakers/eyb-leads.js @@ -22,12 +22,12 @@ const ALBERTA = { } const INTENT_CHOICES = [ - 'Set up new premises', - 'Set up a new distribution centre', - 'Onward sales and exports from the UK', - 'Research, develop and collaborate', - 'Find people with specialist skills', - 'Other', + 'SET_UP_NEW_PREMISES', + 'SET_UP_A_NEW_DISTRIBUTION_CENTRE', + 'ONWARD_SALES_AND_EXPORTS_FROM_THE_UK', + 'RESEARCH_DEVELOP_AND_COLLABORATE', + 'FIND_PEOPLE_WITH_SPECIALIST_SKILLS', + 'OTHER', ] const HIRING_CHOICES = [ @@ -49,10 +49,10 @@ const SPEND_CHOICES = [ ] const LANDING_TIMEFRAME_CHOICES = [ - 'In the next 6 months', - '6 to 12 months', - '1 to 2 years', - "In more than 2 years' time", + 'UNDER_SIX_MONTHS', + 'SIX_TO_TWELVE_MONTHS', + 'ONE_TO_TWO_YEARS', + 'MORE_THAN_TWO_YEARS', ] /** diff --git a/test/functional/cypress/fakers/overseas-regions.js b/test/functional/cypress/fakers/overseas-regions.js new file mode 100644 index 00000000000..b5048b2a444 --- /dev/null +++ b/test/functional/cypress/fakers/overseas-regions.js @@ -0,0 +1,15 @@ +import { faker } from '../../../sandbox/utils/random' + +import { listFaker } from './utils' + +export const overseasRegionFaker = (overrides = {}) => ({ + id: faker.string.uuid(), + name: faker.lorem.words(), + disabled_on: null, + ...overrides, +}) + +export const overseasRegionListFaker = (length = 1, overrides) => + listFaker({ fakerFunction: overseasRegionFaker, length, overrides }) + +export default overseasRegionListFaker diff --git a/test/functional/cypress/fixtures/index.js b/test/functional/cypress/fixtures/index.js index 9f1b389fbcc..d8664acb90a 100644 --- a/test/functional/cypress/fixtures/index.js +++ b/test/functional/cypress/fixtures/index.js @@ -73,6 +73,7 @@ module.exports = { }, export: { historyWithInteractions: require('../../../sandbox/fixtures/v4/export/history-with-interactions.json'), + exportProjectDetails: require('../../../sandbox/fixtures/v4/company/company-with-export-project-details.json'), }, omis: { diff --git a/test/functional/cypress/specs/companies/activity-feed-spec.js b/test/functional/cypress/specs/companies/activity-feed-spec.js index 8ce61e57e23..b4b85fb8f88 100644 --- a/test/functional/cypress/specs/companies/activity-feed-spec.js +++ b/test/functional/cypress/specs/companies/activity-feed-spec.js @@ -1,7 +1,8 @@ import { collectionListRequest } from '../../support/actions' import { - companyActivityOrderListFaker, + companyActivityEYBListFaker, companyActivityGreatListFaker, + companyActivityOrderListFaker, } from '../../fakers/company-activity' import { truncateData } from '../../../../../src/client/utils/truncate' @@ -223,4 +224,214 @@ describe('Company activity feed', () => { ) }) }) + + context('EYB leads', () => { + beforeEach(() => { + cy.visit(urls.companies.activity.index(company.id)) + }) + + it('displays the correct kind label', () => { + cy.get('[data-test="eyb-kind-label"]').contains('EYB') + }) + + it('displays the EYB Lead linked company name', () => { + cy.get('[data-test="collection-item"]').each(() => + cy + .get('a') + .contains('Booth Sykes (Linked Company Name)') + .should( + 'have.attr', + 'href', + '/investments/eyb-leads/e686c9d9-d7ba-444d-a85b-a64c477fc1ba/details' + ) + ) + }) + }) + + context('EYB lead has value and linked company name', () => { + const EYBListHighValue = companyActivityEYBListFaker( + 1, + { + company: { + name: 'Linked Company Name', + id: '1c5f7b5f-acd0-4a17-ac9d-8600bb5ded86', + }, + }, + { + id: '54f0a0c3-1aba-4047-b4c2-9fe30fee6b12', + company_name: 'EYB Company Name', + is_high_value: true, + } + ) + const EYBListLowValue = companyActivityEYBListFaker( + 1, + { + company: { + name: 'Linked Company Name', + id: '1c5f7b5f-acd0-4a17-ac9d-8600bb5ded86', + }, + }, + { + id: '54f0a0c3-1aba-4047-b4c2-9fe30fee6b12', + company_name: 'EYB Company Name', + is_high_value: false, + } + ) + const EYBListUnknownValue = companyActivityEYBListFaker( + 1, + { + company: { + name: 'Linked Company Name', + id: '1c5f7b5f-acd0-4a17-ac9d-8600bb5ded86', + }, + }, + { + id: '54f0a0c3-1aba-4047-b4c2-9fe30fee6b12', + company_name: 'EYB Company Name', + is_high_value: null, + } + ) + it('displays a lead of high value and EYB company name', () => { + collectionListRequest( + 'v4/search/company-activity', + EYBListHighValue, + urls.companies.activity.index(fixtures.company.venusLtd.id) + ) + cy.get('[data-test="metadata-item"]').contains('Value High') + cy.get('[data-test="collection-item"]').each(() => + cy + .get('a') + .contains('Linked Company Name') + .should( + 'have.attr', + 'href', + '/investments/eyb-leads/54f0a0c3-1aba-4047-b4c2-9fe30fee6b12/details' + ) + ) + }) + + it('displays a lead of low value and EYB company name', () => { + collectionListRequest( + 'v4/search/company-activity', + EYBListLowValue, + urls.companies.activity.index(fixtures.company.venusLtd.id) + ) + cy.get('[data-test="metadata-item"]').contains('Value Low') + cy.get('[data-test="collection-item"]').each(() => + cy + .get('a') + .contains('Linked Company Name') + .should( + 'have.attr', + 'href', + '/investments/eyb-leads/54f0a0c3-1aba-4047-b4c2-9fe30fee6b12/details' + ) + ) + }) + + it('displays a lead of unknown value and EYB company name', () => { + collectionListRequest( + 'v4/search/company-activity', + EYBListUnknownValue, + urls.companies.activity.index(fixtures.company.venusLtd.id) + ) + cy.get('[data-test="metadata-item"]').contains('Value Unknown') + cy.get('[data-test="collection-item"]').each(() => + cy + .get('a') + .contains('Linked Company Name') + .should( + 'have.attr', + 'href', + '/investments/eyb-leads/54f0a0c3-1aba-4047-b4c2-9fe30fee6b12/details' + ) + ) + }) + }) + + context('EYB lead has value and no linked company name', () => { + const EYBListHighValue = companyActivityEYBListFaker( + 1, + { company: [] }, + { + id: '54f0a0c3-1aba-4047-b4c2-9fe30fee6b12', + company_name: 'EYB Company Name', + is_high_value: true, + } + ) + const EYBListLowValue = companyActivityEYBListFaker( + 1, + { company: [] }, + { + id: '54f0a0c3-1aba-4047-b4c2-9fe30fee6b12', + company_name: 'EYB Company Name', + is_high_value: false, + } + ) + const EYBListUnknownValue = companyActivityEYBListFaker( + 1, + { company: [] }, + { + id: '54f0a0c3-1aba-4047-b4c2-9fe30fee6b12', + company_name: 'EYB Company Name', + is_high_value: null, + } + ) + it('displays a lead of high value and EYB company name', () => { + collectionListRequest( + 'v4/search/company-activity', + EYBListHighValue, + urls.companies.activity.index(fixtures.company.venusLtd.id) + ) + cy.get('[data-test="metadata-item"]').contains('Value High') + cy.get('[data-test="collection-item"]').each(() => + cy + .get('a') + .contains('EYB Company Name') + .should( + 'have.attr', + 'href', + '/investments/eyb-leads/54f0a0c3-1aba-4047-b4c2-9fe30fee6b12/details' + ) + ) + }) + + it('displays a lead of low value and EYB company name', () => { + collectionListRequest( + 'v4/search/company-activity', + EYBListLowValue, + urls.companies.activity.index(fixtures.company.venusLtd.id) + ) + cy.get('[data-test="metadata-item"]').contains('Value Low') + cy.get('[data-test="collection-item"]').each(() => + cy + .get('a') + .contains('EYB Company Name') + .should( + 'have.attr', + 'href', + '/investments/eyb-leads/54f0a0c3-1aba-4047-b4c2-9fe30fee6b12/details' + ) + ) + }) + + it('displays a lead of unknown value and EYB company name', () => { + collectionListRequest( + 'v4/search/company-activity', + EYBListUnknownValue, + urls.companies.activity.index(fixtures.company.venusLtd.id) + ) + cy.get('[data-test="metadata-item"]').contains('Value Unknown') + cy.get('[data-test="collection-item"]').each(() => + cy + .get('a') + .contains('EYB Company Name') + .should( + 'have.attr', + 'href', + '/investments/eyb-leads/54f0a0c3-1aba-4047-b4c2-9fe30fee6b12/details' + ) + ) + }) + }) }) diff --git a/test/functional/cypress/specs/companies/dnb-hierarchy-spec.js b/test/functional/cypress/specs/companies/dnb-hierarchy-spec.js deleted file mode 100644 index 09a69a925e0..00000000000 --- a/test/functional/cypress/specs/companies/dnb-hierarchy-spec.js +++ /dev/null @@ -1,170 +0,0 @@ -const { - assertLocalHeader, - assertBreadcrumbs, -} = require('../../support/assertions') -const { - assertLocalNav, -} = require('../../../../end-to-end/cypress/support/assertions') - -const selectors = require('../../../../selectors') -const urls = require('../../../../../src/lib/urls') - -const { - company: { - dnbGlobalUltimate, - dnbLtd, - dnBGlobalUltimateAndGlobalHq, - dnbSubsidiary, - }, -} = require('../../fixtures') - -function assertRelatedCompaniesPage({ - company, - areTabsVisible, - companiesInHierarchy, -}) { - beforeEach(() => { - cy.visit(urls.companies.dnbHierarchy.index(company.id)) - }) - - it('should render the header', () => { - assertLocalHeader(`Company records related to ${company.name}`) - }) - - it('should render the helper text', () => { - cy.contains( - 'This hierarchy information from Dun & Bradstreet cannot be edited.' - ) - }) - - it('should render breadcrumbs', () => { - assertBreadcrumbs({ - Home: urls.dashboard.index(), - Companies: urls.companies.index(), - [company.name]: urls.companies.detail(company.id), - 'Business details': urls.companies.businessDetails(company.id), - 'Related companies': null, - }) - }) - - it('should render the list of companies', () => { - cy.get(selectors.companyDnbHierarchy.collection) - .should('contain', '2 related company records') - .and('not.contain', company.name) - .get('h3') - .parent() - .should('have.length', companiesInHierarchy.length) - .each((item, i) => { - const expectedCompany = companiesInHierarchy[i] - const expectedHref = urls.companies.detail(expectedCompany.id) - - cy.get(item) - .as('hierarchyItem') - .contains(expectedCompany.name) - .invoke('attr', 'href') - .should('eq', expectedHref || undefined) - - cy.get('@hierarchyItem') - .should('contain', 'Updated on') - .should('contain', 'Address') - - if ( - expectedCompany.trading_names && - expectedCompany.trading_names.length - ) { - cy.get('@hierarchyItem').should( - 'contain', - `Trading names ${expectedCompany.trading_names.join('')}` - ) - } - - if (expectedCompany.sector) { - cy.get('@hierarchyItem').should( - 'contain', - `Sector ${expectedCompany.sector.name}` - ) - } - }) - }) - - if (areTabsVisible) { - it('should display the local nav', () => { - assertLocalNav('[data-test="tabbedLocalNav"] a', [ - 'Dun & Bradstreet hierarchy', - 'Manually linked subsidiaries', - ]) - }) - } else { - it('should not display the local nav', () => { - cy.get(selectors.tabbedLocalNav().tabs).should('not.exist') - }) - } -} - -describe('D&B Company hierarchy', () => { - context('when viewing hierarchy for a D&B Global Ultimate', () => { - assertRelatedCompaniesPage({ - company: dnbGlobalUltimate, - companiesInHierarchy: [dnbSubsidiary, dnbLtd], - areTabsVisible: false, - }) - - it('should now show explanation why the D&B hierarchy might have fewer records than manual one', () => { - cy.contains( - "Why aren't all manually linked subsidiaries listed here?" - ).should('not.exist') - }) - }) - - context( - "when viewing a company which is a part of D&B hierarchy but isn't a Global Ultimate nor a Global HQ", - () => { - assertRelatedCompaniesPage({ - company: dnbSubsidiary, - companiesInHierarchy: [dnbGlobalUltimate, dnbLtd], - areTabsVisible: false, - }) - } - ) - - context( - 'when viewing hierarchy for a D&B Global Ultimate which is also Global HQ', - () => { - assertRelatedCompaniesPage({ - company: dnBGlobalUltimateAndGlobalHq, - companiesInHierarchy: [dnbSubsidiary, dnbLtd], - areTabsVisible: true, - }) - - it('should show explanation why the D&B hierarchy might have fewer records than manual one', () => { - cy.get( - 'details:contains("Why aren\'t all manually linked subsidiaries listed here?")' - ).should( - 'have.text', - '' + - "Why aren't all manually linked subsidiaries listed here?This does not" + - ' mean that Dun & Bradstreet does not know about those subsidiaries.The' + - ' Dun & Bradstreet hierarchy information can only show the company records' + - ' in Data Hub that have been matched to a verified Dun & Bradstreet record.' + - ' This matching process is ongoing and more related company records will' + - ' appear in the future.' - ) - }) - } - ) - - context('when attempting to view the hierarchy without a D&B id', () => { - const accessDeniedId = 1234 - before(() => { - cy.intercept(`api-proxy/v4/company/${accessDeniedId}`, { - id: accessDeniedId, - global_ultimate_duns_number: null, - }).as('companyApi') - cy.visit(urls.companies.dnbHierarchy.index(accessDeniedId)) - }) - it('should display the access denied page', () => { - cy.wait('@companyApi') - cy.get('[data-test="access-denied"]').should('be.visible') - }) - }) -}) diff --git a/test/functional/cypress/specs/companies/overview-spec.js b/test/functional/cypress/specs/companies/overview-spec.js index 5b6f856df2f..27f199809c0 100644 --- a/test/functional/cypress/specs/companies/overview-spec.js +++ b/test/functional/cypress/specs/companies/overview-spec.js @@ -667,7 +667,7 @@ describe('Company overview page', () => { EYBListHighValue, urls.companies.overview.index(fixtures.company.venusLtd.id) ) - cy.get('[data-test="eyb-label"]').contains('EYB') + cy.get('[data-test="eyb-kind-label"]').contains('EYB') cy.get('[data-test="activity-summary"]').contains( 'A high-value EYB lead associated with this company has been added to Data Hub' ) @@ -679,7 +679,7 @@ describe('Company overview page', () => { EYBListLowValue, urls.companies.overview.index(fixtures.company.venusLtd.id) ) - cy.get('[data-test="eyb-label"]').contains('EYB') + cy.get('[data-test="eyb-kind-label"]').contains('EYB') cy.get('[data-test="activity-summary"]').contains( 'A low-value EYB lead associated with this company has been added to Data Hub' ) @@ -691,7 +691,7 @@ describe('Company overview page', () => { EYBListUnknownValue, urls.companies.overview.index(fixtures.company.venusLtd.id) ) - cy.get('[data-test="eyb-label"]').contains('EYB') + cy.get('[data-test="eyb-kind-label"]').contains('EYB') cy.get('[data-test="activity-summary"]').contains( 'An unknown-value EYB lead associated with this company has been added to Data Hub' ) diff --git a/test/functional/cypress/specs/companies/referrals/referral-details-spec.js b/test/functional/cypress/specs/companies/referrals/referral-details-spec.js index 16b8c9f8ac3..9018c49eb03 100644 --- a/test/functional/cypress/specs/companies/referrals/referral-details-spec.js +++ b/test/functional/cypress/specs/companies/referrals/referral-details-spec.js @@ -1,265 +1,168 @@ -const urls = require('../../../../../../src/lib/urls') -const { - id: companyId, -} = require('../../../../../sandbox/fixtures/v4/company/company-lambda-plc') - -const selectors = require('../../../../../selectors') -const { assertBreadcrumbs } = require('../../../support/assertions') -const { +import { companies, dashboard } from '../../../../../../src/lib/urls' +import { id as companyId } from '../../../../../sandbox/fixtures/v4/company/company-lambda-plc.json' + +import { localHeader } from '../../../../../selectors' +import { + assertBreadcrumbs, + assertDetails, + assertSummaryTable, +} from '../../../support/assertions' +import { REFERRAL_ID, REFERRAL_ID_NO_CONTACT, -} = require('../../../../../sandbox/constants/referrals') +} from '../../../../../sandbox/constants/referrals' describe('Referral details', () => { context('when viewing referral details', () => { beforeEach(() => - cy.visit(urls.companies.referrals.details(companyId, REFERRAL_ID)) + cy.visit(companies.referrals.details(companyId, REFERRAL_ID)) ) - it('should render breadcrumbs', () => { + it('should render the details page', () => { assertBreadcrumbs({ - Home: urls.dashboard.index(), - Companies: urls.companies.index(), - 'Lambda plc': urls.companies.detail(companyId), + Home: dashboard.index(), + Companies: companies.index(), + 'Lambda plc': companies.detail(companyId), Referral: null, }) - }) - - it('should render the heading', () => { - cy.get(selectors.localHeader().heading).should('have.text', 'Referral') - }) - it('should render the content and elements in order', () => { - cy.get('#referral-details table') - .eq(0) - .find('caption') - .should('have.text', 'I am a subject') - .parents() - .find('tbody tr') - .as('row') - .eq(0) - .should('have.text', 'CompanyLambda plc') - .find('a') - .should( - 'have.attr', - 'href', - urls.companies.detail(companyId, REFERRAL_ID) - ) - - cy.get('@row') - .eq(1) - .should('have.text', 'ContactHelena Referral') - .find('a') - .and( - 'have.attr', - 'href', - urls.contacts.contact('6891d583-7f52-41af-a0d3-d8d527f20d43') - ) - - cy.get('@row') - .eq(2) - .should( - 'have.text', - 'Sending adviserIan Leggett, caravans@campervans.com, Advanced Manufacturing Sector' - ) - .find('a') - .should('have.attr', 'href', 'mailto:caravans@campervans.com') + cy.get(localHeader().heading).should('have.text', 'Referral') + + assertSummaryTable({ + dataTest: 'referral-details-table', + heading: 'I am a subject', + content: { + Company: 'Lambda plc', + Contact: 'Helena Referral', + 'Sending adviser': + 'Ian Leggett, caravans@campervans.com, Advanced Manufacturing Sector', + 'Receiving adviser': + 'Barry Oling, barry@barry.com, Aberdeen City Council', + 'Date of referral': '14 Feb 2020', + Notes: 'Just a note about a referral', + }, + }) - cy.get('@row') - .eq(3) - .should( - 'have.text', - 'Receiving adviserBarry Oling, barry@barry.com, Aberdeen City Council' - ) - .find('a') - .should('have.attr', 'href', 'mailto:barry@barry.com') + cy.get('[data-test="cannot-edit-details"]').then((element) => { + assertDetails({ + element, + summary: 'Why can I not edit the referral?', + content: + "For now, you can't edit the referral once it's been sent.Contact the recipient if something's changed.", + }) + }) - cy.get('@row').eq(4).should('have.text', 'Date of referral14 Feb 2020') + assertAcceptAndHelpButtons(REFERRAL_ID) + assertBackButton() - cy.get('@row') - .eq(5) - .should('have.text', 'NotesJust a note about a referral') - .parents() - .find('summary') - .should('have.text', 'Why can I not edit the referral?') - .next() - .should( - 'have.text', - "For now, you can't edit the referral once it's been sent.Contact the recipient if something's changed." - ) - .parents() - .find('details') - .next() - .find('a:first-child') - .should('have.text', 'Accept referral') - .parent() - .find('a:nth-child(2)') - .should('have.text', 'I cannot accept the referral') - .should( - 'have.attr', - 'href', - urls.companies.referrals.help(companyId, REFERRAL_ID) - ) - .parent() - .find('a:nth-child(3)') - .should('have.text', 'Back') + cy.contains('[data-test="complete-referral-table"]').should('not.exist') }) }) context('when viewing referral details with no contact', () => { beforeEach(() => - cy.visit( - urls.companies.referrals.details(companyId, REFERRAL_ID_NO_CONTACT) - ) + cy.visit(companies.referrals.details(companyId, REFERRAL_ID_NO_CONTACT)) ) - it('should render breadcrumbs', () => { + it('should render the details page', () => { assertBreadcrumbs({ - Home: urls.dashboard.index.route, - Companies: urls.companies.index(), - 'Lambda plc': urls.companies.detail(companyId), + Home: dashboard.index.route, + Companies: companies.index(), + 'Lambda plc': companies.detail(companyId), Referral: null, }) - }) - - it('should render the heading', () => { - cy.get(selectors.localHeader().heading).should('have.text', 'Referral') - }) - it('should render the content and elements in order', () => { - cy.get('#referral-details table') - .eq(0) - .find('caption') - .should('have.text', 'I am a subject') - .parents() - .find('tbody tr') - .as('row') - .eq(0) - .should('have.text', 'CompanyLambda plc') - - cy.get('@row') - .eq(1) - .should( - 'have.text', - 'Sending adviserIan Leggett, caravans@campervans.com, Advanced Manufacturing Sector' - ) - .find('a') - .should('have.attr', 'href', 'mailto:caravans@campervans.com') + cy.get(localHeader().heading).should('have.text', 'Referral') + + assertSummaryTable({ + dataTest: 'referral-details-table', + heading: 'I am a subject', + content: { + Company: 'Lambda plc', + 'Sending adviser': + 'Ian Leggett, caravans@campervans.com, Advanced Manufacturing Sector', + 'Receiving adviser': + 'Barry Oling, barry@barry.com, Aberdeen City Council', + 'Date of referral': '14 Feb 2020', + Notes: 'Just a note about a referral', + }, + }) - cy.get('@row') - .eq(2) - .should( - 'have.text', - 'Receiving adviserBarry Oling, barry@barry.com, Aberdeen City Council' - ) - .find('a') - .should('have.attr', 'href', 'mailto:barry@barry.com') + cy.get('[data-test="cannot-edit-details"]').then((element) => { + assertDetails({ + element, + summary: 'Why can I not edit the referral?', + content: + "For now, you can't edit the referral once it's been sent.Contact the recipient if something's changed.", + }) + }) - cy.get('@row').eq(3).should('have.text', 'Date of referral14 Feb 2020') + assertAcceptAndHelpButtons(REFERRAL_ID_NO_CONTACT) + assertBackButton() - cy.get('@row') - .eq(4) - .should('have.text', 'NotesJust a note about a referral') - .parents() - .find('summary') - .should('have.text', 'Why can I not edit the referral?') - .next() - .should( - 'have.text', - "For now, you can't edit the referral once it's been sent.Contact the recipient if something's changed." - ) - .parents() - .find('details') - .next() - .find('a:first-child') - .should('have.text', 'Accept referral') - .parent() - .find('a:nth-child(2)') - .should('have.text', 'I cannot accept the referral') - .should( - 'have.attr', - 'href', - urls.companies.referrals.help(companyId, REFERRAL_ID_NO_CONTACT) - ) - .parent() - .find('a:nth-child(3)') - .should('have.text', 'Back') + cy.contains('[data-test="complete-referral-table"]').should('not.exist') }) }) context('when viewing details of a complete referral', () => it('should display the Referral accepted summary instead of the buttons', () => { - cy.visit(urls.companies.referrals.details('any-id-will-do', 'completed')) - - cy.contains('Complete referral').should('not.exist') - cy.contains('I cannot complete the referral').should('not.exist') - - cy.contains('Referral accepted') - .next() - .within(() => { - cy.get('tr') - .as('row') - .eq(0) - .within(() => { - cy.get('th').should('have.text', 'Date') - cy.get('td').should('have.text', '19 Mar 2020') - }) - - cy.get('@row') - .eq(1) - .within(() => { - cy.get('th').should('have.text', 'By') - cy.get('td') - .should( - 'have.text', - 'Andy Pipkin, andy.pipkin@little.britain.co.uk, Andy & Lou' - ) - .find('a') - .should('have.text', 'andy.pipkin@little.britain.co.uk') - .and( - 'have.attr', - 'href', - 'mailto:andy.pipkin@little.britain.co.uk' - ) - }) - - cy.get('@row') - .eq(2) - .within(() => { - cy.get('th').should('have.text', 'With interaction') - cy.get('td') - .find('a') - .should('have.text', 'Covert action') - .and('have.attr', 'href', '/interactions/foo-bar-baz') - }) - }) + cy.visit(companies.referrals.details('any-id-will-do', 'completed')) + + cy.contains('[data-test="accept-button"]').should('not.exist') + cy.contains('[data-test="help-button"]').should('not.exist') + + assertSummaryTable({ + dataTest: 'complete-referral-table', + heading: 'Referral accepted', + content: { + Date: '19 Mar 2020', + By: 'Andy Pipkin', + 'With interaction': 'Covert action', + }, + }) }) ) + context('When you come to the details page from /my-referrals', () => { it('should take you back there when you click "back"', () => { - cy.visit(urls.dashboard.index()) + cy.visit(dashboard.index()) cy.contains('Referrals').click() cy.contains('Andy to Lou').click() - cy.contains('Back').should( - 'have.attr', - 'href', - urls.companies.referrals.list() - ) + assertBackButton(companies.referrals.list()) + }) + }) + + context('When you come to the details page from anywhere else', () => { + it('should take you to the company page when you click "back"', () => { + cy.visit(companies.referrals.details(companyId, REFERRAL_ID_NO_CONTACT)) + assertBackButton() }) }) - context( - 'When you come to the details page from anywhere but the homepage', - () => { - it('should take you to the company page when you click "back"', () => { - cy.visit( - urls.companies.referrals.details(companyId, REFERRAL_ID_NO_CONTACT) - ) - cy.contains('Back').should( - 'have.attr', - 'href', - urls.companies.detail(companyId) - ) - }) - } - ) }) + +const assertAcceptAndHelpButtons = (referralId) => { + cy.get('[data-test=accept-button') + .should('be.visible') + .should('have.text', 'Accept referral') + .should( + 'have.attr', + 'href', + companies.referrals.interactions.create(companyId, referralId) + ) + + cy.get('[data-test=help-button') + .should('be.visible') + .should('have.text', 'I cannot accept the referral') + .should( + 'have.attr', + 'href', + companies.referrals.help(companyId, referralId) + ) +} + +const assertBackButton = (url = companies.detail(companyId)) => { + cy.get('[data-test=back-button') + .should('be.visible') + .should('have.text', 'Back') + .should('have.attr', 'href', url) +} diff --git a/test/functional/cypress/specs/companies/referrals/send-referral-spec.js b/test/functional/cypress/specs/companies/referrals/send-referral-spec.js index 573267b1146..4b071aa7ef5 100644 --- a/test/functional/cypress/specs/companies/referrals/send-referral-spec.js +++ b/test/functional/cypress/specs/companies/referrals/send-referral-spec.js @@ -1,7 +1,13 @@ -const urls = require('../../../../../../src/lib/urls') -const fixtures = require('../../../fixtures') -const selectors = require('../../../../../selectors') -const { assertFlashMessage } = require('../../../support/assertions') +import { companies, dashboard } from '../../../../../../src/lib/urls' +import { company } from '../../../fixtures' +import { sendReferral } from '../../../../../selectors' +import { + assertBreadcrumbs, + assertErrorSummary, + assertFlashMessage, + assertLocalHeader, + assertSummaryTable, +} from '../../../support/assertions' const selectTypeahead = (field, input) => cy.get(field).within(() => { @@ -12,25 +18,29 @@ const selectTypeahead = (field, input) => }) const enterAdviserDefault = () => - selectTypeahead(selectors.sendReferral.adviserField, 'shawn') + selectTypeahead(sendReferral.adviserField, 'shawn') const enterSubjectDefault = () => - cy.get(selectors.sendReferral.subjectField).click().type('Example subject') + cy.get(sendReferral.subjectField).click().type('Example subject') const enterNotesDefault = () => - cy.get(selectors.sendReferral.notesField).click().type('Example notes') + cy.get(sendReferral.notesField).click().type('Example notes') const enterContactDefault = () => - selectTypeahead(selectors.sendReferral.contactField, 'johnny') + selectTypeahead(sendReferral.contactField, 'johnny') describe('Send a referral form', () => { - before(() => { - cy.visit(urls.companies.referrals.send(fixtures.company.withContacts.id)) - }) - describe('All but successful completion', () => { beforeEach(() => { - cy.visit(urls.companies.referrals.send(fixtures.company.withContacts.id)) + cy.visit(companies.referrals.send(company.withContacts.id)) + + assertBreadcrumbs({ + Home: dashboard.index(), + Companies: companies.index(), + [company.withContacts.name]: companies.detail(company.withContacts.id), + 'Send a referral': null, + }) + assertLocalHeader('Send a referral') }) context( @@ -40,10 +50,9 @@ describe('Send a referral form', () => { enterAdviserDefault() enterNotesDefault() cy.contains('button', 'Continue').click() - cy.get('form').should( - 'contain', - 'Enter a subject for the referral (Max 255 characters)' - ) + assertErrorSummary([ + 'Enter a subject for the referral (Max 255 characters)', + ]) }) } ) @@ -55,7 +64,7 @@ describe('Send a referral form', () => { enterAdviserDefault() enterSubjectDefault() cy.contains('button', 'Continue').click() - cy.get('form').should('contain', 'Enter notes for the referral') + assertErrorSummary(['Enter notes for the referral']) }) } ) @@ -63,12 +72,12 @@ describe('Send a referral form', () => { describe('Advisor input fields', () => { beforeEach(() => { - cy.visit(urls.companies.referrals.send(fixtures.company.withContacts.id)) + cy.visit(companies.referrals.send(company.withContacts.id)) }) context('When you search advisors', () => { it('should return inactive advisers with text indicating they are inactive next to their name', () => { - cy.get(selectors.sendReferral.adviserField).within(() => { + cy.get(sendReferral.adviserField).within(() => { cy.intercept('/api-proxy/adviser/?*').as('adviserResults') cy.get('input').clear().type('John Doe') cy.wait('@adviserResults') @@ -82,7 +91,7 @@ describe('Send a referral form', () => { }) it('should return active advisers without an inactive text next to their name', () => { - cy.get(selectors.sendReferral.adviserField).within(() => { + cy.get(sendReferral.adviserField).within(() => { cy.intercept('/api-proxy/adviser/?*').as('adviserResults') cy.get('input').clear().type('Shawn Cohen') cy.wait('@adviserResults') @@ -98,9 +107,7 @@ describe('Send a referral form', () => { 'when "Continue" button is clicked after all fields filled in', () => { it('should display the confirmation component with the values just input', () => { - cy.visit( - urls.companies.referrals.send(fixtures.company.withContacts.id) - ) + cy.visit(companies.referrals.send(company.withContacts.id)) enterAdviserDefault() enterSubjectDefault() enterNotesDefault() @@ -108,37 +115,27 @@ describe('Send a referral form', () => { cy.contains('button', 'Continue').click() + assertSummaryTable({ + dataTest: 'referral-confirmation-table', + content: { + 'Refer this company to': 'Shawn Cohen, Charles Gilbert', + Subject: 'Example subject', + Notes: 'Example notes', + 'Company contact': 'Johnny Cakeman', + }, + }) + cy.contains('Check referral details').should('be.visible') - cy.get('table') - .should('contain', 'Shawn Cohen') - .and('contain', 'Example subject') - .and('contain', 'Example notes') - .and('contain', 'Johnny Cakeman') - .parents() - .find('button') - .should('contain', 'Edit Referral') - .next() - .should('contain', 'What happens next') - .next() - .find('li') - .eq(0) - .should( - 'contain', - "You won't be able to edit the referral after this point" - ) - .next() - .should( - 'contain', - "A link to the referral will appear on the company record, your homepage and the recipient's homepage" - ) - .next() - .should('contain', 'The referral might take 24 hours to appear') - .parents() - .next() - .find('button') - .should('contain', 'Send referral') - .next() - .should('contain', 'Cancel') + cy.contains('What happens next').should('be.visible') + cy.contains( + "You won't be able to edit the referral after this point" + ).should('be.visible') + cy.contains( + "A link to the referral will appear on the company record, your homepage and the recipient's homepage" + ).should('be.visible') + cy.contains('The referral might take 24 hours to appear').should( + 'be.visible' + ) }) } ) @@ -147,9 +144,7 @@ describe('Send a referral form', () => { 'when "Continue" then "Edit" button is clicked after all fields filled in', () => { it('the input data should appear in the form when "Edit Referral" is clicked', () => { - cy.visit( - urls.companies.referrals.send(fixtures.company.withContacts.id) - ) + cy.visit(companies.referrals.send(company.withContacts.id)) enterAdviserDefault() enterSubjectDefault() enterNotesDefault() @@ -158,19 +153,16 @@ describe('Send a referral form', () => { cy.contains('button', 'Continue').click() cy.contains('Edit Referral').click() - cy.get(selectors.sendReferral.adviserField) + cy.get(sendReferral.adviserField) .find('input') .should('have.attr', 'value', 'Shawn Cohen, Charles Gilbert') - cy.get(selectors.sendReferral.subjectFieldInput).should( + cy.get(sendReferral.subjectFieldInput).should( 'have.attr', 'value', 'Example subject' ) - cy.get(selectors.sendReferral.notesField).should( - 'contain', - 'Example notes' - ) - cy.get(selectors.sendReferral.contactField) + cy.get(sendReferral.notesField).should('contain', 'Example notes') + cy.get(sendReferral.contactField) .find('input') .should('have.attr', 'value', 'Johnny Cakeman') }) @@ -181,9 +173,7 @@ describe('Send a referral form', () => { 'When the "Cancel" link is clicked from the confirmation component', () => { it('should return to the company page', () => { - cy.visit( - urls.companies.referrals.send(fixtures.company.withContacts.id) - ) + cy.visit(companies.referrals.send(company.withContacts.id)) enterAdviserDefault() enterSubjectDefault() enterNotesDefault() @@ -191,7 +181,7 @@ describe('Send a referral form', () => { cy.contains('Cancel').click() cy.url().should( 'contain', - urls.companies.overview.index(fixtures.company.withContacts.id) + companies.overview.index(company.withContacts.id) ) }) } @@ -201,9 +191,7 @@ describe('Send a referral form', () => { 'When the "Send referral" button is clicked from the confirmation component', () => { before(() => { - cy.visit( - urls.companies.referrals.send(fixtures.company.withContacts.id) - ) + cy.visit(companies.referrals.send(company.withContacts.id)) }) it('should take user to the company page, display flash message and link to the homepage', () => { enterAdviserDefault() @@ -214,12 +202,12 @@ describe('Send a referral form', () => { cy.contains('button', 'Send referral').click() cy.url().should( 'contain', - urls.companies.overview.index(fixtures.company.withContacts.id) + companies.overview.index(company.withContacts.id) ) assertFlashMessage('Referral sent') cy.contains('You can see all of your referrals on your Homepage.') .contains('see all of your referrals on your Homepage') - .should('have.attr', 'href', urls.companies.referrals.list()) + .should('have.attr', 'href', companies.referrals.list()) }) } ) @@ -228,7 +216,7 @@ describe('Send a referral form', () => { describe('Contact loop', () => { context('when a contact does not exist and user wants to add one', () => { beforeEach(() => { - cy.visit(urls.companies.referrals.send(fixtures.company.withContacts.id)) + cy.visit(companies.referrals.send(company.withContacts.id)) }) after(() => { @@ -236,7 +224,7 @@ describe('Contact loop', () => { }) it('should redirect the user back to the interaction form and add the contact after the contact is added', () => { - cy.get(selectors.sendReferral.subjectField) + cy.get(sendReferral.subjectField) .click() .type('Test if values are restored') @@ -245,7 +233,7 @@ describe('Contact loop', () => { cy.contains('a', 'Cancel').should( 'have.attr', 'href', - urls.companies.referrals.send(fixtures.company.withContacts.id) + companies.referrals.send(company.withContacts.id) ) cy.contains('div', 'First name').find('input').type('John') @@ -262,20 +250,20 @@ describe('Contact loop', () => { cy.url().should( 'include', - urls.companies.referrals.send(fixtures.company.withContacts.id) + companies.referrals.send(company.withContacts.id) ) // We are not expecting John Doe here, because the mocked sandbox response // returns Json Russel cy.contains(`You have successfully added a new contact Json Russel`) - cy.get(selectors.sendReferral.subjectFieldInput).should( + cy.get(sendReferral.subjectFieldInput).should( 'have.attr', 'value', 'Test if values are restored' ) - cy.get(selectors.sendReferral.contactField) + cy.get(sendReferral.contactField) .find('input') .should('have.attr', 'value', 'Json Russel') }) diff --git a/test/functional/cypress/specs/companies/subsidiaries-spec.js b/test/functional/cypress/specs/companies/subsidiaries-spec.js index 9a06b882ac9..3be909e6fbc 100644 --- a/test/functional/cypress/specs/companies/subsidiaries-spec.js +++ b/test/functional/cypress/specs/companies/subsidiaries-spec.js @@ -2,9 +2,6 @@ const { assertBreadcrumbs } = require('../../support/assertions') const urls = require('../../../../../src/lib/urls') const fixtures = require('../../fixtures') const selectors = require('../../../../selectors') -const { - assertLocalNav, -} = require('../../../../end-to-end/cypress/support/assertions') describe('Companies subsidiaries', () => { context('when viewing subsidiaries for a Dun & Bradstreet company', () => { @@ -109,13 +106,6 @@ describe('Companies subsidiaries', () => { }) }) - it('should display tabs for two types of hierarchies', () => { - assertLocalNav(selectors.tabbedLocalNav().tabs, [ - 'Dun & Bradstreet hierarchy', - 'Manually linked subsidiaries', - ]) - }) - it('should render the helper text', () => { cy.get('p').should( 'contain', diff --git a/test/functional/cypress/specs/contacts/activity-spec.js b/test/functional/cypress/specs/contacts/activity-spec.js index 5a34a777863..c8a55cc86ca 100644 --- a/test/functional/cypress/specs/contacts/activity-spec.js +++ b/test/functional/cypress/specs/contacts/activity-spec.js @@ -55,7 +55,7 @@ describe('Contact activity', () => { }) it('should display 0 activities', () => { - cy.get('#contact-activity').contains('0 activities') + cy.get('[data-test="collection-header"]').contains('0 activities') }) }) @@ -71,7 +71,7 @@ describe('Contact activity', () => { }) it('should display the total number of activites', () => { - cy.get('#contact-activity').contains('25 activities') + cy.get('[data-test="collection-header"]').contains('25 activities') cy.get('[data-test=pagination-summary]').contains('Page 1 of 3') cy.get('[data-test=pagination]').should( 'have.attr', diff --git a/test/functional/cypress/specs/contacts/create-and-edit-spec.js b/test/functional/cypress/specs/contacts/create-and-edit-spec.js index 198e17e5da8..882d84a813f 100644 --- a/test/functional/cypress/specs/contacts/create-and-edit-spec.js +++ b/test/functional/cypress/specs/contacts/create-and-edit-spec.js @@ -45,13 +45,6 @@ const assertRadioGroup = (label, option) => const assertRadioGroupNoOptionChecked = (label) => cy.contains(label).parent().find('input').should('not.be.checked') -const assertNoMarketingConsent = () => - cy - .contains('The company contact does accept email marketing') - .parent() - .find('input') - .should('not.be.checked') - const NEW_CONTACT_ID = '14890695-ce54-4419-88d3-9224754ecbc0' describe('Create contact form', () => { beforeEach(() => { @@ -63,8 +56,6 @@ describe('Create contact form', () => { 'Add contact at Zboncak Group|271eb29e-425b-4cd8-b386-3208c3a5f978': null, }) - assertNoMarketingConsent() - assertRadioGroupNoOptionChecked('Is this person a primary contact?') assertRadioGroupNoOptionChecked( 'Is this contact’s work address the same as the company address?' @@ -316,8 +307,6 @@ describe('Edit contact', () => { `/companies/${ZBONCAK_COMPANY_ID}` ) - assertNoMarketingConsent() - assertRadioGroup('Is this person a primary contact?', 'Yes') assertRadioGroup( 'Is this contact’s work address the same as the company address?', diff --git a/test/functional/cypress/specs/contacts/details-spec.js b/test/functional/cypress/specs/contacts/details-spec.js index a0a95bc13da..c3dd2b6ae16 100644 --- a/test/functional/cypress/specs/contacts/details-spec.js +++ b/test/functional/cypress/specs/contacts/details-spec.js @@ -1,8 +1,4 @@ import { contacts } from '../../../../../src/lib/urls' -import { - EMAIL_CONSENT_NO, - EMAIL_CONSENT_YES, -} from '../../../../../src/apps/contacts/constants' const completeUKContact = require('../../../../sandbox/fixtures/v3/contact/contact-complete-details-uk.json') const incompleteUKContact = require('../../../../sandbox/fixtures/v3/contact/contact-incomplete-details-uk.json') @@ -49,7 +45,6 @@ describe('View contact details', () => { '123 Test Street, Address Line 2, Sandbox Town, Test County, AB1 2CD, United Kingdom', Email: completeUKContact.email, 'More details': completeUKContact.notes, - 'Email marketing': EMAIL_CONSENT_YES, }) }) @@ -60,6 +55,14 @@ describe('View contact details', () => { .should('have.attr', 'href', contacts.edit(completeUKContact.id)) }) + it('should render the contacts consent choice', () => { + cy.get('[data-test=no-contact-consents]').should('not.exist') + }) + + it('should render the consent management section', () => { + cy.get('[data-test=consent-management]').should('exist') + }) + it('should render the archive container', () => { cy.get('[data-test=archive-contact-container]').should('exist') cy.get('[data-test=archive-header]') @@ -122,7 +125,6 @@ describe('View contact details', () => { 'Job title': incompleteUKContact.job_title, Address: '123 Test Street, Sandbox Town, AB1 2CD, United Kingdom', Email: incompleteUKContact.email, - 'Email marketing': EMAIL_CONSENT_YES, }) }) }) @@ -138,7 +140,6 @@ describe('View contact details', () => { Address: '3 Priory Court, Kingshill Road, Dursley, Gloucestershire, GL11 4DH, United Kingdom', Email: companyAddresscontact.email, - 'Email marketing': EMAIL_CONSENT_NO, }) }) }) @@ -155,7 +156,6 @@ describe('View contact details', () => { '123 Test Boulevard, Basney, US State, 9416875, United States', Email: usContact.email, 'More details': usContact.notes, - 'Email marketing': EMAIL_CONSENT_NO, }) }) }) @@ -200,10 +200,17 @@ describe('View contact details', () => { '123 Test Street, Address Line 2, Sandbox Town, Test County, AB1 2CD, United Kingdom', Email: archiveContact.email, 'More details': archiveContact.notes, - 'Email marketing': EMAIL_CONSENT_YES, }) }) + it('should not render the contacts consent choice', () => { + cy.get('[data-test=no-contact-consents]').should('exist') + }) + + it('should not render the consent management section', () => { + cy.get('[data-test=consent-management]').should('not.exist') + }) + it('should not render the Edit Contact button', () => { cy.get('[data-test=edit-contact-button]').should('not.exist') }) @@ -249,7 +256,6 @@ describe('View contact details', () => { '123 Test Street, Address Line 2, Sandbox Town, Test County, AB1 2CD, United Kingdom', Email: invalidEmailContact.email, 'More details': invalidEmailContact.notes, - 'Email marketing': EMAIL_CONSENT_YES, }) }) }) diff --git a/test/functional/cypress/specs/events/attendees-search-spec.js b/test/functional/cypress/specs/events/attendees-search-spec.js index 012730c3854..03f9904e16e 100644 --- a/test/functional/cypress/specs/events/attendees-search-spec.js +++ b/test/functional/cypress/specs/events/attendees-search-spec.js @@ -174,12 +174,9 @@ describe('Event attendee search', () => { it('should add an attendee to the event', () => { cy.contains('Hanna Reinger').click() - cy.get('.c-message') - .should('exist') - .should( - 'have.text', - 'Event attendee added - This has created a service delivery record. If required, you can view or edit the service delivery directly from the attendee record.Dismiss' - ) + cy.contains( + 'Event attendee added - This has created a service delivery record. If required, you can view or edit the service delivery directly from the attendee record.' + ) }) }) }) diff --git a/test/functional/cypress/specs/events/attendees-spec.js b/test/functional/cypress/specs/events/attendees-spec.js index 240d26608ef..992b74e5d60 100644 --- a/test/functional/cypress/specs/events/attendees-spec.js +++ b/test/functional/cypress/specs/events/attendees-spec.js @@ -1,5 +1,4 @@ const fixtures = require('../../fixtures') -const selectors = require('../../../../selectors') const urls = require('../../../../../src/lib/urls') const { @@ -8,101 +7,35 @@ const { } = require('../../support/assertions') describe('Event Attendees', () => { - context('Enabled events', () => { - beforeEach(() => { - cy.visit(`/events/${fixtures.event.oneDayExhibition.id}/attendees`) - cy.get('.c-collection').as('collectionList') - }) - - it('should render breadcrumbs', () => { - assertBreadcrumbs({ - Home: urls.dashboard.index(), - Events: urls.events.index(), - 'One-day exhibition': null, - }) - }) - - it('should render the header', () => { - assertLocalHeader('One-day exhibition') - }) - - it('should display a collection header', () => { - cy.get('main article h2').should('contain', 'Event Attendees') - }) - - it('should display attendee collection list', () => { - cy.get(selectors.entityCollection.collection) - .find('header') - .should('contain', '1,233') - .parent() - .find('span') - .should('contain', 'Page 1 of 13') - .parents('header') - .next() - .find('li') - .should('have.length', 100) - }) - - it('should be able to use the pagination', () => { - cy.get(selectors.entityCollection.collection) - .find('nav ul li') - .as('pageLinks') - .eq(1) - .click() - - cy.get(selectors.entityCollection.collection) - .find('header') - .should('contain', 'Page 2 of 13') - - cy.get('@pageLinks').eq(0).click() - - cy.get(selectors.entityCollection.collection) - .find('header') - .should('contain', 'Page 1 of 13') - }) + it('Enabled events', () => { + cy.visit(`/events/${fixtures.event.oneDayExhibition.id}/attendees`) + assertBreadcrumbs({ + Home: urls.dashboard.index(), + Events: urls.events.index(), + 'One-day exhibition': null, + Attendees: null, + }) + assertLocalHeader('One-day exhibition') + cy.contains('h2', 'Event Attendees') + cy.contains('h2', '1,233 attendees') + cy.contains('Page 1 of 124') }) - context('Disabled events', () => { - beforeEach(() => { - cy.visit(`/events/${fixtures.event.teddyBearExpo.id}/attendees`) - }) - - it('should render breadcrumbs', () => { - assertBreadcrumbs({ - Home: urls.dashboard.index(), - Events: urls.events.index(), - 'Teddy bear expo': null, - }) - }) - - it('should render the header', () => { - assertLocalHeader('Teddy bear expo') - }) - - it('should display a message indicating when the event was disabled', () => { - assertLocalHeader( - 'This event was disabled on 5 September 2017 and can no longer be edited' - ) - }) - it('should not display add attendees button for disabled events', () => { - cy.get(selectors.entityCollection.addAttendee).should('not.exist') - }) - - it('should display a message indicating that you cannot add an event attendee', () => { - cy.get('main article h2') - .next() - .should( - 'contain', - 'You cannot add an event attendee because the event has been disabled.' - ) - }) - - it('should display a collection header', () => { - cy.get('main article h2').should('contain', 'Event Attendees') - }) - - it('should display attendee collection list', () => { - cy.get(selectors.collection.headerCount).should('contain', '1,233') - }) + it('Disabled events', () => { + cy.visit(`/events/${fixtures.event.teddyBearExpo.id}/attendees`) + assertBreadcrumbs({ + Home: urls.dashboard.index(), + Events: urls.events.index(), + 'Teddy bear expo': null, + Attendees: null, + }) + assertLocalHeader('Teddy bear expo') + assertLocalHeader( + 'This event was disabled on 5 September 2017 and can no longer be edited' + ) + cy.contains( + 'You cannot add an event attendee because the event has been disabled.' + ) + cy.contains('Add attendee').should('not.exist') }) }) diff --git a/test/functional/cypress/specs/events/details-spec.js b/test/functional/cypress/specs/events/details-spec.js index 673d253ccc6..afb5a5f5630 100644 --- a/test/functional/cypress/specs/events/details-spec.js +++ b/test/functional/cypress/specs/events/details-spec.js @@ -1,141 +1,124 @@ import urls from '../../../../../src/lib/urls' const { - assertKeyValueTable, assertBreadcrumbs, + assertSummaryTableStrict, } = require('../../support/assertions') const fixtures = require('../../fixtures') const event = require('../../../../sandbox/fixtures/v3/event/single-event-missing-teams.json') -const selectors = require('../../../../selectors') + +const EVENT_DETAILS_ROWS = { + 'Type of event': 'Exhibition', + 'Event date': '1 January 2021', + 'Event location type': 'HQ', + Address: 'Day Court Exhibition Centre, Day Court Lane, China, SW9 9AB, China', + Region: 'Not set', + Notes: 'This is a dummy event for testing.', + 'Lead team': 'CBBC Hangzhou', + Organiser: 'John Rogers', + 'Other teams': 'CBBC HangzhouCBBC North West', + 'Related programmes': 'Grown in Britain', + 'Related Trade Agreements': 'UK - Japan', + Service: 'Events : UK based', +} describe('Event Details', () => { - it('should display one day event details', () => { + it('should display one day event details with correct event', () => { cy.visit(urls.events.details(fixtures.event.oneDayExhibition.id)) - cy.get(selectors.entityCollection.editEvent).should('be.visible') - assertBreadcrumbs({ Home: urls.dashboard.index.route, Events: urls.events.index(), 'One-day exhibition': null, + Details: null, }) - assertKeyValueTable('eventDetails', { - 'Type of event': 'Exhibition', - 'Event date': '1 January 2021', - 'Event location type': 'HQ', - Address: - 'Day Court Exhibition Centre, Day Court Lane, China, SW9 9AB, China', - Region: 'Not set', - Notes: 'This is a dummy event for testing.', - 'Lead team': 'CBBC Hangzhou', - Organiser: 'John Rogers', - 'Other teams': 'CBBC HangzhouCBBC North West', - 'Related programmes': 'Grown in Britain', - 'Related Trade Agreements': 'UK - Japan', - Service: 'Events : UK based', + assertSummaryTableStrict({ + rows: EVENT_DETAILS_ROWS, }) + + cy.contains('a', 'Edit event').should( + 'have.attr', + 'href', + urls.events.edit(fixtures.event.oneDayExhibition.id) + ) }) it('should display one day event details with no teams', () => { cy.visit(urls.events.details(event.id)) - cy.get(selectors.entityCollection.editEvent).should('be.visible') - - assertKeyValueTable('eventDetails', { - 'Type of event': 'Exhibition', - 'Event date': '1 January 2021', - 'Event location type': 'HQ', - Address: - 'Day Court Exhibition Centre, Day Court Lane, China, SW9 9AB, China', - Region: 'Not set', - Notes: 'This is a dummy event for testing.', - 'Lead team': 'Not set', - Organiser: 'John Rogers', - 'Other teams': 'Not set', - 'Related programmes': 'Grown in Britain', - 'Related Trade Agreements': 'UK - Japan', - Service: 'Events : UK based', + assertSummaryTableStrict({ + rows: { + ...EVENT_DETAILS_ROWS, + 'Lead team': 'Not set', + 'Other teams': 'Not set', + }, }) + + cy.contains('a', 'Edit event') }) - describe('Disabled event with no document', () => { - beforeEach(() => { - cy.visit(urls.events.details(fixtures.event.teddyBearExpo.id)) + it('should display no document link details', () => { + cy.visit(urls.events.details(fixtures.event.teddyBearExpo.id)) + + assertBreadcrumbs({ + Home: urls.dashboard.index.route, + Events: urls.events.index(), + 'Teddy bear expo': null, + Details: null, }) - it('should display no document link details', () => { - assertBreadcrumbs({ - Home: urls.dashboard.index.route, - Events: urls.events.index(), - 'Teddy bear expo': null, - }) - - assertKeyValueTable('eventDetails', { - 'Type of event': 'Exhibition', - 'Event date': '1 January 2021', - 'Event location type': 'HQ', - Address: - 'Day Court Exhibition Centre, Day Court Lane, China, SW9 9AB, China', - Region: 'Not set', - Notes: 'This is a dummy event for testing.', - 'Lead team': 'CBBC Hangzhou', - Organiser: 'John Rogers', - 'Other teams': 'CBBC HangzhouCBBC North West', - 'Related programmes': 'Grown in Britain', + assertSummaryTableStrict({ + rows: { + ...EVENT_DETAILS_ROWS, 'Related Trade Agreements': 'Not set', - Service: 'Events : UK based', - }) + }, }) - it('should hide edit event button for disabled events', () => { - cy.get(selectors.entityCollection.editEvent).should('not.exist') - }) + cy.contains('a', 'Edit event').should('not.exist') }) - describe('Certain fields that are null', () => { - before(() => { - cy.intercept( - 'GET', - `/api-proxy/v4/event/${fixtures.event.teddyBearExpo.id}`, - { - address_1: '16 Grande Parade', - address_2: '', - address_country: { - name: 'China', - id: '63af72a6-5d95-e211-a939-e4115bead28a', - }, - address_county: '', - address_postcode: '', - address_town: 'Shanghai', - end_date: '2016-03-16', - event_type: { - name: 'Exhibition', - id: '2fade471-e868-4ea9-b125-945eb90ae5d4', - }, - lead_team: { - name: 'UK Fashion and Textile Association Ltd (UKFT)', - id: '23f12898-9698-e211-a939-e4115bead28a', - }, - name: 'Shanghai Fashion Week including The Hub, Chic-Pure-Intertextile March 2016', - notes: null, - organiser: null, - start_date: '2016-03-16', - service: { - name: 'DBT export service or funding : UK Tradeshow Programme (UKTP) – exhibitor', - id: '380bba2b-3499-e211-a939-e4115bead28a', - }, - uk_region: null, - } - ).as('apiRequest') - cy.visit(urls.events.details(fixtures.event.teddyBearExpo.id)) - cy.wait('@apiRequest') - }) + it('should set fields that are null to "Not set"', () => { + cy.intercept( + 'GET', + `/api-proxy/v4/event/${fixtures.event.teddyBearExpo.id}`, + { + address_1: '16 Grande Parade', + address_2: '', + address_country: { + name: 'China', + id: '63af72a6-5d95-e211-a939-e4115bead28a', + }, + address_county: '', + address_postcode: '', + address_town: 'Shanghai', + end_date: '2016-03-16', + event_type: { + name: 'Exhibition', + id: '2fade471-e868-4ea9-b125-945eb90ae5d4', + }, + lead_team: { + name: 'UK Fashion and Textile Association Ltd (UKFT)', + id: '23f12898-9698-e211-a939-e4115bead28a', + }, + name: 'Shanghai Fashion Week including The Hub, Chic-Pure-Intertextile March 2016', + notes: null, + organiser: null, + start_date: '2016-03-16', + service: { + name: 'DBT export service or funding : UK Tradeshow Programme (UKTP) – exhibitor', + id: '380bba2b-3499-e211-a939-e4115bead28a', + }, + uk_region: null, + } + ) + + cy.visit(urls.events.details(fixtures.event.teddyBearExpo.id)) - it('should set fields that are null to "Not set"', () => { - assertKeyValueTable('eventDetails', { - 'Type of event': 'Exhibition', + assertSummaryTableStrict({ + rows: { + ...EVENT_DETAILS_ROWS, 'Event date': '16 March 2016', 'Event location type': 'Not set', Address: '16 Grande Parade, Shanghai, China', @@ -148,7 +131,7 @@ describe('Event Details', () => { 'Related Trade Agreements': 'Not set', Service: 'DBT export service or funding : UK Tradeshow Programme (UKTP) – exhibitor', - }) + }, }) }) }) diff --git a/test/functional/cypress/specs/export-pipeline/export-details-spec.js b/test/functional/cypress/specs/export-pipeline/export-details-spec.js index bef20aeb9ae..68f991a0536 100644 --- a/test/functional/cypress/specs/export-pipeline/export-details-spec.js +++ b/test/functional/cypress/specs/export-pipeline/export-details-spec.js @@ -6,7 +6,7 @@ import { formatDate, DATE_FORMAT_MONTH_YEAR, } from '../../../../../src/client/utils/date-utils' -import { exportFaker } from '../../fakers/export' +import fixtures from '../../fixtures' const { assertBreadcrumbs, @@ -14,72 +14,92 @@ const { assertUrl, } = require('../../support/assertions') -describe('Export Details summary ', () => { - const exportItem = exportFaker() +describe('Export Project Details summary ', () => { + const exportProjectDetails = fixtures.export.exportProjectDetails + context('when summary table renders', () => { beforeEach(() => { - cy.intercept('GET', `/api-proxy/v4/export/${exportItem.id}`, { - body: exportItem, + cy.intercept('GET', `/api-proxy/v4/export/${exportProjectDetails.id}`, { + body: exportProjectDetails, }).as('getExportItemApiRequest') - cy.visit(`/export/${exportItem.id}/details`) + cy.visit(`/export/${exportProjectDetails.id}/details`) }) it('should render breadcrumbs', () => { assertBreadcrumbs({ Home: urls.exportPipeline.index(), - [exportItem.title]: null, + [exportProjectDetails.title]: null, }) }) + it('shoud render a company link and page heading', () => { + cy.get('[data-test=export-company-link]') + .should('have.text', exportProjectDetails.company.name.toUpperCase()) + .should( + 'have.attr', + 'href', + `/companies/${exportProjectDetails.company.id}` + ) + + cy.get('[data-test="heading"]').should( + 'have.text', + exportProjectDetails.title + ) + }) + it('should display the "Export" details summary table', () => { const estimatedExportValue = `${ - exportItem.estimated_export_value_years?.name - } / ${currencyGBP(exportItem.estimated_export_value_amount)}` + exportProjectDetails.estimated_export_value_years?.name + } / ${currencyGBP(exportProjectDetails.estimated_export_value_amount)}` const estimatedWinDate = formatDate( - exportItem.estimated_win_date, + exportProjectDetails.estimated_win_date, DATE_FORMAT_MONTH_YEAR ) assertKeyValueTable('bodyMainContent', { - 'Export title': exportItem.title, - Owner: exportItem.owner.name, - 'Team members': exportItem.team_members.map((obj) => obj.name).join(''), + 'Export title': exportProjectDetails.title, + Owner: exportProjectDetails.owner.name, + 'Team members': exportProjectDetails.team_members + .map((obj) => obj.name) + .join(''), 'Total estimated export value': estimatedExportValue, 'Estimated date for win': estimatedWinDate, - Status: capitalize(exportItem.status), - 'Export potential': capitalize(exportItem.export_potential), - Destination: exportItem.destination_country.name, - 'Main sector': exportItem.sector.name, - 'Company contacts': exportItem.contacts.map((obj) => obj.name).join(''), - 'Exporter experience': exportItem.exporter_experience.name, - Notes: exportItem.notes, + Status: capitalize(exportProjectDetails.status), + 'Export potential': capitalize(exportProjectDetails.export_potential), + Destination: exportProjectDetails.destination_country.name, + 'Main sector': exportProjectDetails.sector.name, + 'Company contacts': exportProjectDetails.contacts + .map((obj) => obj.name) + .join(''), + 'Exporter experience': exportProjectDetails.exporter_experience.name, + Notes: 'Not set', }) }) }) context('when the form edit button is clicked', () => { beforeEach(() => { - cy.intercept('GET', `/api-proxy/v4/export/${exportItem.id}`, { - body: exportItem, + cy.intercept('GET', `/api-proxy/v4/export/${exportProjectDetails.id}`, { + body: exportProjectDetails, }).as('getExportItemApiRequest') - cy.visit(`/export/${exportItem.id}/details`) + cy.visit(`/export/${exportProjectDetails.id}/details`) }) it('the form should redirect to the edit page', () => { cy.get('[data-test="edit-export-details-button"]').click() - assertUrl(urls.exportPipeline.edit(exportItem.id)) + assertUrl(urls.exportPipeline.edit(exportProjectDetails.id)) }) }) context('when the form delete button is clicked', () => { beforeEach(() => { - cy.intercept('GET', `/api-proxy/v4/export/${exportItem.id}`, { - body: exportItem, + cy.intercept('GET', `/api-proxy/v4/export/${exportProjectDetails.id}`, { + body: exportProjectDetails, }).as('getExportItemApiRequest') - cy.visit(`/export/${exportItem.id}/details`) + cy.visit(`/export/${exportProjectDetails.id}/details`) }) it('the form should redirect to the delete page', () => { cy.get('[data-test="delete-export-details-button"]').click() - assertUrl(urls.exportPipeline.delete(exportItem.id)) + assertUrl(urls.exportPipeline.delete(exportProjectDetails.id)) }) }) }) diff --git a/test/functional/cypress/specs/export-pipeline/export-project-interaction-spec.js b/test/functional/cypress/specs/export-pipeline/export-project-interaction-spec.js new file mode 100644 index 00000000000..5f0eef27ae0 --- /dev/null +++ b/test/functional/cypress/specs/export-pipeline/export-project-interaction-spec.js @@ -0,0 +1,91 @@ +import fixtures from '../../fixtures' +import { assertUrl } from '../../support/assertions' + +const companyExportProject = fixtures.export.exportProjectDetails +const queryParams = '&limit=10&offset=0' + +describe('Export project interaction collection list', () => { + context('When export project render with multiple interaction linked', () => { + beforeEach(() => { + cy.intercept( + 'GET', + `/api-proxy/v4/interaction?company_export_id=${companyExportProject.id}&sortby=-created_on${queryParams}` + ).as('apiRequest') + cy.visit(`/export/${companyExportProject.id}/interactions`) + }) + + it('should display the interactions list', () => { + cy.get('[data-test="collection-header-name').should( + 'contain', + '1,233 interactions' + ) + }) + + it('should show the current and number of pages', () => { + cy.contains('Page 1 of 124').should('be.visible') + }) + + it('should display 10 interactions per page', () => { + cy.get('[data-test="collection-item"]').should('have.length', 10) + }) + + it('should show the pagination', () => { + cy.get('[data-test="pagination"]').should('be.visible') + cy.get('[data-test="page-number-active"]').should('have.text', '1') + cy.get('[data-test="page-number"]').should('contain', '124') + cy.get('[data-test="next"]').should('have.text', 'Next page') + }) + }) +}) + +describe('Export interaction collections filters "Sort by"', () => { + context('Default sort by "Recently created"', () => { + beforeEach(() => { + cy.intercept( + 'GET', + `/api-proxy/v4/interaction?company_export_id=${companyExportProject.id}&sortby=-created_on${queryParams}` + ).as('apiRequest') + cy.visit(`/export/${companyExportProject.id}/interactions`) + }) + + it('should render "Sort by" label', () => { + cy.get('[data-test="sortby"]').should('contain', 'Sort by') + }) + + it('should have all sort by options', () => { + cy.get('[data-test="sortby"] option').then((options) => { + const sortOptions = [...options].map((o) => ({ + value: o.value, + name: o.label, + })) + expect(sortOptions).to.deep.eq([ + { value: '-created_on', name: 'Recently created' }, + { value: 'company__name', name: 'Company name A-Z' }, + { value: 'subject', name: 'Subject A-Z' }, + ]) + }) + }) + }) + + context('Other sort by filters', () => { + const element = '[data-test="sortby"] select' + + beforeEach(() => { + cy.intercept( + 'GET', + `/api-proxy/v4/interaction?company_export_id=${companyExportProject.id}&sortby=-created_on${queryParams}` + ).as('apiRequest') + cy.visit(`/export/${companyExportProject.id}/interactions`) + }) + + it('should sort by "Company name A-Z"', () => { + cy.get(element).select('Company name A-Z') + assertUrl('sortby=company__name') + }) + + it('should sort by "Subject A-Z"', () => { + cy.get(element).select('Subject A-Z') + assertUrl('sortby=subject') + }) + }) +}) diff --git a/test/functional/cypress/specs/export-win/utils.js b/test/functional/cypress/specs/export-win/utils.js index bad32da21de..5c81acf65ee 100644 --- a/test/functional/cypress/specs/export-win/utils.js +++ b/test/functional/cypress/specs/export-win/utils.js @@ -3,7 +3,7 @@ import { addMonths, subMonths } from 'date-fns' import { getRandomDateInRange, getStartDateOfTwelveMonthsAgo, -} from '../../../../../src/client/utils/date' +} from '../../../../../src/client/modules/ExportWins/Form/date' import { clickContinueButton } from '../../support/actions' import { assertUrl } from '../../support/assertions' import { formFields } from './constants' diff --git a/test/functional/cypress/specs/investments/eyb-lead-details-spec.js b/test/functional/cypress/specs/investments/eyb-lead-details-spec.js index 81fe7baaef7..ea3e1a8b45f 100644 --- a/test/functional/cypress/specs/investments/eyb-lead-details-spec.js +++ b/test/functional/cypress/specs/investments/eyb-lead-details-spec.js @@ -3,6 +3,7 @@ import { assertLeadBreadcrumbs, } from '../../support/assertions' import { investments } from '../../../../../src/lib/urls' +import { convertEYBChoicesToLabels } from '../../../../../src/client/modules/Investments/utils' import { eybLeadFaker } from '../../fakers/eyb-leads' import { NOT_SET_TEXT } from '../../../../../src/apps/companies/constants' import { VALUES_VALUE_TO_LABEL_MAP } from '../../../../../src/client/modules/Investments/EYBLeads/constants' @@ -31,19 +32,19 @@ describe('EYB lead details', () => { }, triage_created: '2023-06-07T10:00:00Z', intent: [ - 'Find people with specialist skills', - 'Set up a new distribution centre', - 'Other', - 'Onward sales and exports from the UK', + 'FIND_PEOPLE_WITH_SPECIALIST_SKILLS', + 'SET_UP_A_NEW_DISTRIBUTION_CENTRE', + 'OTHER', + 'ONWARD_SALES_AND_EXPORTS_FROM_THE_UK', ], - hiring: '6-50', - spend: '500000-1000000', + hiring: '6 to 50', + spend: '£500,000 to £1 million', is_high_value: true, full_name: 'Joe Bloggs', role: 'CEO', email: 'email@example.com', telephone_number: '01234567890', - landing_timeframe: 'In the next 6 months', + landing_timeframe: 'UNDER_SIX_MONTHS', company_website: 'fake.website.com', investment_projects: [], }) @@ -65,11 +66,11 @@ describe('EYB lead details', () => { 'Submitted to EYB': '07 Jun 2023', 'Company website address': eybLeadWithValues.company_website + ' (opens in new tab)', - 'When do you want to set up?': eybLeadWithValues.landing_timeframe, + 'When do you want to set up?': convertEYBChoicesToLabels(eybLeadWithValues.landing_timeframe), 'Do you know where you want to set up in the UK?': 'Yes', 'Where do you want to set up in the UK?': 'Cardiff', 'How do you plan to expand your business in the UK?': - eybLeadWithValues.intent.join(''), + convertEYBChoicesToLabels(eybLeadWithValues.intent).join(''), 'How many people do you want to hire in the UK in the first 3 years?': eybLeadWithValues.hiring, 'How much do you want to spend on setting up in the first 3 years?': @@ -77,6 +78,7 @@ describe('EYB lead details', () => { 'Full name': eybLeadWithValues.full_name, 'Job title': eybLeadWithValues.role, 'Phone number': eybLeadWithValues.telephone_number, + 'Email': eybLeadWithValues.email, }, }) }) @@ -137,6 +139,7 @@ describe('EYB lead details', () => { ) }) }) + context('When viewing an EYB lead without a company associated to it', () => { const eybLeadWithoutCompany = eybLeadFaker({ company: null, @@ -144,19 +147,19 @@ describe('EYB lead details', () => { sector: null, triage_created: '2023-06-07T10:00:00Z', intent: [ - 'Find people with specialist skills', - 'Set up a new distribution centre', - 'Other', - 'Onward sales and exports from the UK', + 'FIND_PEOPLE_WITH_SPECIALIST_SKILLS', + 'SET_UP_A_NEW_DISTRIBUTION_CENTRE', + 'OTHER', + 'ONWARD_SALES_AND_EXPORTS_FROM_THE_UK', ], - hiring: '6-50', - spend: '500000-1000000', + hiring: '6 to 50', + spend: '£500,000 to £1 million', is_high_value: true, full_name: 'Joe Bloggs', role: 'CEO', email: 'email@example.com', telephone_number: '01234567890', - landing_timeframe: 'In the next 6 months', + landing_timeframe: 'UNDER_SIX_MONTHS', company_website: null, company_name: 'Mars Temp', investment_projects: [], @@ -178,11 +181,11 @@ describe('EYB lead details', () => { 'Location of company headquarters': 'Canada', 'Submitted to EYB': '07 Jun 2023', 'Company website address': NOT_SET_TEXT, - 'When do you want to set up?': eybLeadWithoutCompany.landing_timeframe, + 'When do you want to set up?': convertEYBChoicesToLabels(eybLeadWithoutCompany.landing_timeframe), 'Do you know where you want to set up in the UK?': 'Yes', 'Where do you want to set up in the UK?': 'Cardiff', 'How do you plan to expand your business in the UK?': - eybLeadWithoutCompany.intent.join(''), + convertEYBChoicesToLabels(eybLeadWithoutCompany.intent).join(''), 'How many people do you want to hire in the UK in the first 3 years?': eybLeadWithoutCompany.hiring, 'How much do you want to spend on setting up in the first 3 years?': @@ -190,6 +193,7 @@ describe('EYB lead details', () => { 'Full name': eybLeadWithoutCompany.full_name, 'Job title': eybLeadWithoutCompany.role, 'Phone number': eybLeadWithoutCompany.telephone_number, + 'Email': eybLeadWithoutCompany.email, }, }) }) @@ -220,6 +224,7 @@ describe('EYB lead details', () => { cy.get('[data-test="button-add-investment-project"]').should('not.exist') }) }) + context( 'When viewing an EYB lead with company and investment projects associated', () => { @@ -266,6 +271,7 @@ describe('EYB lead details', () => { }) } ) + context('When viewing an EYB lead with high, low, and unknown values', () => { const testCases = [true, false, null] testCases.forEach((value) => { @@ -283,4 +289,69 @@ describe('EYB lead details', () => { }) }) }) + + context('When viewing an EYB lead without an email', () => { + const eybLeadWithNoEmail = eybLeadFaker({ + company: { + name: 'Mars', + id: 'fc752802-e454-4c7c-bbfd-4bdd84759b84', + }, + value: true, + sector: { + name: 'Mining', + id: 'a622c9d2-5f95-e211-a939-e4115bead28a', + }, + triage_created: '2023-06-07T10:00:00Z', + intent: [ + 'FIND_PEOPLE_WITH_SPECIALIST_SKILLS', + 'SET_UP_A_NEW_DISTRIBUTION_CENTRE', + 'OTHER', + 'ONWARD_SALES_AND_EXPORTS_FROM_THE_UK', + ], + hiring: '6 to 50', + spend: '£500,000 to £1 million', + is_high_value: true, + full_name: 'Joe Bloggs', + role: 'CEO', + email: null, + telephone_number: '01234567890', + landing_timeframe: 'UNDER_SIX_MONTHS', + company_website: 'fake.website.com', + investment_projects: [], + }) + beforeEach(() => { + setup(eybLeadWithNoEmail) + cy.visit(investments.eybLeads.details(eybLeadWithNoEmail.id)) + cy.wait('@getEYBLeadDetails') + }) + + it('should render all the fields of the details table with email test displayed as "Not set"', () => { + assertSummaryTable({ + dataTest: 'eyb-lead-details-table', + // prettier-ignore + content: { + 'Company name': eybLeadWithNoEmail.company.name, + 'Value': 'High value', + 'Sector or industry': eybLeadWithNoEmail.sector.name, + 'Location of company headquarters': 'Canada', + 'Submitted to EYB': '07 Jun 2023', + 'Company website address': + eybLeadWithNoEmail.company_website + ' (opens in new tab)', + 'When do you want to set up?': convertEYBChoicesToLabels(eybLeadWithNoEmail.landing_timeframe), + 'Do you know where you want to set up in the UK?': 'Yes', + 'Where do you want to set up in the UK?': 'Cardiff', + 'How do you plan to expand your business in the UK?': + convertEYBChoicesToLabels(eybLeadWithNoEmail.intent).join(''), + 'How many people do you want to hire in the UK in the first 3 years?': + eybLeadWithNoEmail.hiring, + 'How much do you want to spend on setting up in the first 3 years?': + eybLeadWithNoEmail.spend, + 'Full name': eybLeadWithNoEmail.full_name, + 'Job title': eybLeadWithNoEmail.role, + 'Phone number': eybLeadWithNoEmail.telephone_number, + 'Email': NOT_SET_TEXT, + }, + }) + }) + }) }) diff --git a/test/functional/cypress/specs/investments/eyb-leads-spec.js b/test/functional/cypress/specs/investments/eyb-leads-spec.js index 891578901cf..edf0241d699 100644 --- a/test/functional/cypress/specs/investments/eyb-leads-spec.js +++ b/test/functional/cypress/specs/investments/eyb-leads-spec.js @@ -19,6 +19,7 @@ import { } from '../../../../../src/client/utils/date-utils' import { eybLeadFaker } from '../../fakers/eyb-leads' import { VALUES_VALUE_TO_LABEL_MAP } from '../../../../../src/client/modules/Investments/EYBLeads/constants' +import { convertEYBChoicesToLabels } from '../../../../../src/client/modules/Investments/utils' const EYB_RETRIEVE_API_ROUTE = '/api-proxy/v4/investment-lead/eyb' @@ -27,6 +28,7 @@ const FILTER_ELEMENTS = { sector: '[data-test="sector-filter"]', value: '[data-test="lead-value-filter"]', country: '[data-test="lead-country-filter"]', + overseas_region: '[data-test="overseas-region-filter"]', } const DATE_TIME_STRING = '2024-09-25T08:30:00.000000Z' @@ -44,19 +46,37 @@ const COUNTRY_NAME_1 = 'Canada' const COUNTRY_ID_1 = '5daf72a6-5d95-e211-a939-e4115bead28a' const COUNTRY_NAME_2 = 'Brazil' const COUNTRY_ID_2 = 'b05f66a0-5d95-e211-a939-e4115bead28a' +const OVERSEAS_REGION_NAME_1 = 'North America' +const OVERSEAS_REGION_ID_1 = 'fdfbbc8d-0e8a-479a-b10f-4979d582ff87' +const OVERSEAS_REGION_NAME_2 = 'Latin America' +const OVERSEAS_REGION_ID_2 = '5616ccf5-ab4a-4c2c-9624-13c69be3c46b' const EYB_LEAD_LIST = Array( eybLeadFaker({ triage_created: DATE_TIME_STRING, company: { name: `${COMPANY_NAME} and Co` }, is_high_value: true, - country: { name: COUNTRY_NAME_1, id: COUNTRY_ID_1 }, + country: { + name: COUNTRY_NAME_1, + id: COUNTRY_ID_1, + overseas_region: { + name: OVERSEAS_REGION_NAME_1, + id: OVERSEAS_REGION_ID_1, + }, + }, }), eybLeadFaker({ triage_created: DATE_TIME_STRING, sector: { name: SECTOR_NAME, id: SECTOR_ID }, is_high_value: false, - country: { name: COUNTRY_NAME_1, id: COUNTRY_ID_1 }, + country: { + name: COUNTRY_NAME_1, + id: COUNTRY_ID_1, + overseas_region: { + name: OVERSEAS_REGION_NAME_1, + id: OVERSEAS_REGION_ID_1, + }, + }, }), eybLeadFaker({ triage_created: DATE_TIME_STRING, is_high_value: null }), eybLeadFaker({ triage_created: DATE_TIME_STRING, is_high_value: false }), @@ -65,18 +85,27 @@ const EYB_LEAD_LIST = Array( is_high_value: false, company: null, company_name: COMPANY_NAME_DEFAULT, - country: { name: COUNTRY_NAME_2, id: COUNTRY_ID_2 }, + country: { + name: COUNTRY_NAME_2, + id: COUNTRY_ID_2, + overseas_region: { + name: OVERSEAS_REGION_NAME_2, + id: OVERSEAS_REGION_ID_2, + }, + }, }) ) const PAYLOADS = { - minimum: { limit: '10', offset: '0' }, + minimum: { limit: '10', offset: '0', sortby: '-triage_created' }, companyFilter: { company: COMPANY_NAME }, sectorFilter: { sector: SECTOR_ID }, highValueFilter: { value: HIGH_VALUE }, lowValueFilter: { value: LOW_VALUE }, unknownValueFilter: { value: UNKNOWN_VALUE }, countryFilter: { country: COUNTRY_ID_1 }, + sortByCreated: { sortby: '-triage_created' }, + sortByCompanyAZ: { sortby: 'company__name' }, } const buildQueryString = (queryParams = {}) => @@ -117,6 +146,13 @@ const getEYBLeadsByCountryId = (countryId) => { ) } +const getEYBLeadsByOverseasRegionId = (overseasRegionID) => { + return EYB_LEAD_LIST.filter( + (lead) => + lead.country && lead.country?.overseas_region.id === overseasRegionID + ) +} + describe('EYB leads collection page', () => { context('When visiting the EYB leads tab', () => { const eybLead = EYB_LEAD_LIST[0] @@ -155,6 +191,7 @@ describe('EYB leads collection page', () => { }) it('should render the filters', () => { + cy.get('[data-test="overseas-region-filter"]').should('be.visible') cy.get('[data-test="lead-country-filter"]').should('be.visible') cy.get('[data-test="lead-value-filter"]').should('be.visible') cy.get('[data-test="sector-filter"]').should('be.visible') @@ -178,7 +215,10 @@ describe('EYB leads collection page', () => { ) .should('contain', `Estimated spend ${eybLead.spend}`) .should('contain', `Sector ${eybLead.sector.name}`) - .should('contain', `Estimated land date ${eybLead.landing_timeframe}`) + .should( + 'contain', + `Estimated land date ${convertEYBChoicesToLabels(eybLead.landing_timeframe)}` + ) .should( 'contain', `Location ${eybLead.proposed_investment_region.name}` @@ -211,10 +251,14 @@ describe('EYB leads collection page', () => { }) it('should filter from user input', () => { + cy.intercept('GET', `${EYB_RETRIEVE_API_ROUTE}?*`, (req) => { + if (req.query.company) { + req.alias = 'filteredRequest' + } + }) cy.visit(`${investments.eybLeads.index()}`) - cy.intercept('GET', `${EYB_RETRIEVE_API_ROUTE}?*`).as('apiRequest') cy.get(FILTER_ELEMENTS.company).type(`${COMPANY_NAME}{enter}`) - cy.wait('@apiRequest') + cy.wait('@filteredRequest') .its('request.query') .should('include', expectedPayload) assertQueryParams('company', COMPANY_NAME) @@ -258,8 +302,12 @@ describe('EYB leads collection page', () => { }) it('should filter from user input', () => { + cy.intercept('GET', `${EYB_RETRIEVE_API_ROUTE}?*`, (req) => { + if (req.query.sector) { + req.alias = 'filteredRequest' + } + }) cy.visit(`${investments.eybLeads.index()}`) - cy.intercept('GET', `${EYB_RETRIEVE_API_ROUTE}?*`).as('apiRequest') assertTypeaheadHints({ element: FILTER_ELEMENTS.sector, label: 'Sector of interest', @@ -273,7 +321,7 @@ describe('EYB leads collection page', () => { element: FILTER_ELEMENTS.sector, expectedOption: SECTOR_NAME, }) - cy.wait('@apiRequest') + cy.wait('@filteredRequest') .its('request.query') .should('include', expectedPayload) assertQueryParams('sector[0]', SECTOR_ID) @@ -353,14 +401,17 @@ describe('EYB leads collection page', () => { }) it('should filter from user input', () => { - cy.intercept('GET', `${EYB_RETRIEVE_API_ROUTE}?*`).as('apiRequest') + cy.intercept('GET', `${EYB_RETRIEVE_API_ROUTE}?*`, (req) => { + if (req.query.value) { + req.alias = 'filteredRequest' + } + }) cy.visit(`${investments.eybLeads.index()}`) - cy.wait('@apiRequest') clickCheckboxGroupOption({ element: FILTER_ELEMENTS.value, value: testCase.queryParamValue, }) - cy.wait('@apiRequest') + cy.wait('@filteredRequest') .its('request.query') .should('include', testCase.expectedPayload) assertQueryParams('value[0]', testCase.queryParamValue) @@ -407,8 +458,12 @@ describe('EYB leads collection page', () => { }) it('should filter from user input', () => { + cy.intercept('GET', `${EYB_RETRIEVE_API_ROUTE}?*`, (req) => { + if (req.query.country) { + req.alias = 'filteredRequest' + } + }) cy.visit(`${investments.eybLeads.index()}`) - cy.intercept('GET', `${EYB_RETRIEVE_API_ROUTE}?*`).as('apiRequest') assertTypeaheadHints({ element: FILTER_ELEMENTS.country, label: 'Country', @@ -422,7 +477,7 @@ describe('EYB leads collection page', () => { element: FILTER_ELEMENTS.country, expectedOption: COUNTRY_NAME_1, }) - cy.wait('@apiRequest') + cy.wait('@filteredRequest') .its('request.query') .should('include', expectedPayload) assertQueryParams('country[0]', COUNTRY_ID_1) @@ -430,8 +485,8 @@ describe('EYB leads collection page', () => { }) it('should return and display the filtered collection', () => { - let queryString = buildQueryString({ 'sector[0]': SECTOR_ID }) - let expectedNumberOfResults = 2 // Number of leads with COUNTRY_ID_1 in the fixture data + const queryString = buildQueryString({ 'country[0]': COUNTRY_ID_1 }) + const expectedNumberOfResults = 2 // Number of leads with COUNTRY_ID_1 in the fixture data cy.intercept('GET', `${EYB_RETRIEVE_API_ROUTE}?*`, { statusCode: 200, body: { @@ -449,4 +504,117 @@ describe('EYB leads collection page', () => { ) }) }) + + context( + 'When filtering the EYB leads collection by HMTC (overseas) region', + () => { + const expectedPayload = { + ...PAYLOADS.minimum, + ...PAYLOADS.country, + } + + it('should filter from the url', () => { + const queryString = buildQueryString({ + 'overseas_region[0]': OVERSEAS_REGION_ID_1, + }) + cy.intercept('GET', `${EYB_RETRIEVE_API_ROUTE}?*`).as('apiRequest') + cy.visit(`${investments.eybLeads.index()}?${queryString}`) + cy.wait('@apiRequest') + .its('request.query') + .should('include', expectedPayload) + }) + + it('should filter from user input', () => { + cy.intercept('GET', `${EYB_RETRIEVE_API_ROUTE}?*`, (req) => { + if (req.query.overseas_region) { + req.alias = 'filteredRequest' + } + }) + cy.visit(`${investments.eybLeads.index()}`) + assertTypeaheadHints({ + element: FILTER_ELEMENTS.overseas_region, + label: 'HMTC region', + placeholder: 'Search HMTC region', + }) + selectFirstTypeaheadOption({ + element: FILTER_ELEMENTS.overseas_region, + input: 'north', + }) + assertTypeaheadOptionSelected({ + element: FILTER_ELEMENTS.overseas_region, + expectedOption: OVERSEAS_REGION_NAME_1, + }) + cy.wait('@filteredRequest') + .its('request.query') + .should('include', expectedPayload) + assertQueryParams('overseas_region[0]', OVERSEAS_REGION_ID_1) + assertChipExists({ label: OVERSEAS_REGION_NAME_1, position: 1 }) + }) + + it('should return and display the filtered collection', () => { + const queryString = buildQueryString({ + 'overseas_region[0]': OVERSEAS_REGION_ID_1, + }) + const expectedNumberOfResults = 2 // Number of leads with OVERSEAS_REGION_ID_1 in the fixture data + cy.intercept('GET', `${EYB_RETRIEVE_API_ROUTE}?*`, { + statusCode: 200, + body: { + count: expectedNumberOfResults, + next: null, + previous: null, + results: getEYBLeadsByOverseasRegionId(OVERSEAS_REGION_ID_1), + }, + }).as('apiRequest') + cy.visit(`${investments.eybLeads.index()}?${queryString}`) + cy.wait('@apiRequest') + cy.get('[data-test="collection-item"]').should( + 'have.length', + expectedNumberOfResults + ) + }) + } + ) + context('When sorting the EYB leads collection', () => { + beforeEach(() => { + cy.intercept('GET', `${EYB_RETRIEVE_API_ROUTE}?*`).as('apiRequest') + cy.visit(investments.eybLeads.index()) + }) + + it('should load sort by dropdown', () => { + cy.get('[data-test="sortby"] select option').then((options) => { + const actual = [...options].map((o) => o.value) + expect(actual).to.deep.eq(['-triage_created', 'company__name']) + }) + }) + + it('should sort by most recently created by default', () => { + assertQueryParams('sortby', '-triage_created') + cy.wait('@apiRequest') + .its('request.query') + .should('include', PAYLOADS.sortByCreated) + }) + + it('should sort by company name A-Z', () => { + cy.intercept('GET', `${EYB_RETRIEVE_API_ROUTE}?*`, (req) => { + if (req.query.sortby === 'company__name') req.alias = 'sortedRequest' + }) + cy.get('[data-test="sortby"] select').select('company__name') + assertQueryParams('sortby', 'company__name') + cy.wait('@sortedRequest') + .its('request.query') + .should('include', PAYLOADS.sortByCompanyAZ) + }) + + it('should sort by most recently created when another sort option is selected', () => { + cy.get('[data-test="sortby"] select').select('company__name') + cy.intercept('GET', `${EYB_RETRIEVE_API_ROUTE}?*`, (req) => { + if (req.query.sortby === '-triage_created') req.alias = 'sortedRequest' + }) + cy.get('[data-test="sortby"] select').select('-triage_created') + assertQueryParams('sortby', '-triage_created') + cy.wait('@sortedRequest') + .its('request.query') + .should('include', PAYLOADS.sortByCreated) + }) + }) }) diff --git a/test/functional/cypress/specs/investments/project-add-investment-spec.js b/test/functional/cypress/specs/investments/project-add-investment-spec.js index beb7aebc7a2..3e2f48bfef0 100644 --- a/test/functional/cypress/specs/investments/project-add-investment-spec.js +++ b/test/functional/cypress/specs/investments/project-add-investment-spec.js @@ -1,7 +1,13 @@ +import { + clickButton, + selectFirstMockedTypeaheadOption, +} from '../../support/actions' + const { expect } = require('chai') const urls = require('../../../../../src/lib/urls') const { company } = require('../../fixtures') + const { assertSummaryTable, assertFieldTypeahead, @@ -496,3 +502,54 @@ describe('Validation error messages', () => { cy.contains('Actual land date cannot be in the future') }) }) + +describe('When creating investment project check payload is transformed for API', () => { + beforeEach(() => { + cy.visit(urls.investments.projects.index()) + cy.get('[data-test="add-collection-item-button"]').click() + cy.intercept('POST', '/api-proxy/v3/investment').as('createInvestment') + + cy.get('input[data-test="company-name"]').clear() + cy.get('input[data-test="company-name"]').type('alphabet') + cy.get('form button').click() + cy.get('form ol li:nth-child(1)').click() + cy.get('[data-test="investment-type-non-fdi"]').click() + cy.get('[data-test="continue"]').click() + + cy.get('input[data-test="name-input"]').type('project name') + cy.get('textarea[name="description"]').type('project description') + cy.get('#sector').parent().selectTypeaheadOption('Advanced Engineering') + cy.get('#business_activities').parent().selectTypeaheadOption('Assembly') + cy.get('#client_contacts').parent().selectTypeaheadOption('Joseph Woof') + cy.get('input[data-test="client-relationship-manager-yes"]').click() + cy.get('#referral_source_activity').select('LEP') + cy.get('input[data-test="estimated_land_date-month"').type(10) + cy.get('input[data-test="estimated_land_date-year"').type(2024) + + cy.intercept('POST', '/api-proxy/v3/investment').as('createInvestment') + }) + + it('should pass referral source as the user if they are the referral source', () => { + cy.get('[data-test="field-is_referral_source"]').contains('Yes').click() + clickButton('Submit') + + cy.wait('@createInvestment').its('request.body').should('include', { + referral_source_adviser: '7d19d407-9aec-4d06-b190-d3f404627f21', + }) + }) + + it('should pass referral source as given adviser if they are the referral source', () => { + cy.get('[data-test="field-is_referral_source"]').contains('No').click() + + selectFirstMockedTypeaheadOption({ + element: '[data-test="field-referral_source_adviser"]', + input: 'Puck Head', + mockAdviserResponse: false, + }) + + clickButton('Submit') + cy.wait('@createInvestment').its('request.body').should('include', { + referral_source_adviser: 'e83a608e-84a4-11e6-ae22-56b6b6499611', + }) + }) +}) diff --git a/test/functional/cypress/specs/investments/project-edit-details-spec.js b/test/functional/cypress/specs/investments/project-edit-details-spec.js index 18871541cf9..8ed817c74a9 100644 --- a/test/functional/cypress/specs/investments/project-edit-details-spec.js +++ b/test/functional/cypress/specs/investments/project-edit-details-spec.js @@ -495,6 +495,41 @@ describe('Editing the project summary', () => { } ) + context('When submitting data check payload is transformmed for API', () => { + const project = setupProjectFaker({}) + beforeEach(() => { + setup(project) + cy.intercept('PATCH', `/api-proxy/v3/investment/*`).as( + 'editDetailsRequest' + ) + cy.get('[data-test="submit"]').should('exist') + }) + it('should pass referral source as the user if they are the referral source', () => { + cy.get('[data-test="field-is_referral_source"]').contains('Yes').click() + clickButton('Submit') + cy.wait('@editDetailsRequest').its('request.body').should('include', { + referral_source_adviser: '7d19d407-9aec-4d06-b190-d3f404627f21', + }) + }) + + it('should pass referral source as given adviser if they are the referral source', () => { + cy.get('[data-test="field-is_referral_source"]').contains('No') + cy.get('[data-test="field-referral_source_adviser"]').then((element) => { + assertFieldTypeahead({ + element, + label: 'Referral source adviser', + placeholder: 'Choose a referral source adviser', + value: 'Puck Head', + isMulti: false, + }) + }) + clickButton('Submit') + cy.wait('@editDetailsRequest').its('request.body').should('include', { + referral_source_adviser: 'e83a608e-84a4-11e6-ae22-56b6b6499611', + }) + }) + }) + context('When changing the project FDI type from other to Expansion', () => { beforeEach(() => { const project = setupProjectFaker({ diff --git a/test/functional/cypress/support/assertions.js b/test/functional/cypress/support/assertions.js index 6ea7c95dfb5..97057aec34d 100644 --- a/test/functional/cypress/support/assertions.js +++ b/test/functional/cypress/support/assertions.js @@ -76,13 +76,15 @@ const assertSummaryTable = ({ } /** - * @param {{rows: [string, string | number][], caption?: string}} options + * @param {{rows: [string, string | number][] | Record, caption?: string}} options */ const assertSummaryTableStrict = ({ caption, rows }) => { + const _rows = Array.isArray(rows) ? rows : Object.entries(rows) + const assertRows = (el) => { - cy.wrap(el).find('tr').as('rows').should('have.length', rows.length) + cy.wrap(el).find('tr').as('rows').should('have.length', _rows.length) - rows.forEach(([key, val], i) => { + _rows.forEach(([key, val], i) => { cy.get('@rows') .eq(i) .within(() => { diff --git a/test/functional/cypress/support/utils.js b/test/functional/cypress/support/utils.js deleted file mode 100644 index be6451a1257..00000000000 --- a/test/functional/cypress/support/utils.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - randomString: () => { - return Math.random().toString(36).substring(7) - }, -} diff --git a/test/sandbox/fixtures/v3/contact/contact-by-id-uk.json b/test/sandbox/fixtures/v3/contact/contact-by-id-uk.json index 323ff2911d8..b3eef423adb 100644 --- a/test/sandbox/fixtures/v3/contact/contact-by-id-uk.json +++ b/test/sandbox/fixtures/v3/contact/contact-by-id-uk.json @@ -1,43 +1,50 @@ { - "id":"f3d19ea7-d4cf-43e0-8e97-755c57cae313", - "title":null, - "first_name":"Joseph", - "last_name":"Woof", - "name":"Joseph Woof", - "job_title":"Dog master", - "company":{ - "name":"Zboncak Group|271eb29e-425b-4cd8-b386-3208c3a5f978", - "id":"4cd4128b-1bad-4f1e-9146-5d4678c6a018" + "id": "f3d19ea7-d4cf-43e0-8e97-755c57cae313", + "title": null, + "first_name": "Joseph", + "last_name": "Woof", + "name": "Joseph Woof", + "job_title": "Dog master", + "company": { + "name": "Zboncak Group|271eb29e-425b-4cd8-b386-3208c3a5f978", + "id": "4cd4128b-1bad-4f1e-9146-5d4678c6a018" }, - "adviser":{ - "name":"DBT Staff", - "first_name":"DBT", - "last_name":"Staff", - "id":"7d19d407-9aec-4d06-b190-d3f404627f21" + "adviser": { + "name": "DBT Staff", + "first_name": "DBT", + "last_name": "Staff", + "id": "7d19d407-9aec-4d06-b190-d3f404627f21" }, - "primary":true, - "telephone_countrycode":"", - "telephone_number":"", - "full_telephone_number":"222 3453454", - "email":"contact@bob.com", - "address_same_as_company":false, + "primary": true, + "telephone_countrycode": "", + "telephone_number": "", + "full_telephone_number": "222 3453454", + "email": "contact@bob.com", + "address_same_as_company": false, "address_1": null, - "address_2":null, - "address_town":null, - "address_county":null, + "address_2": null, + "address_town": null, + "address_county": null, "address_country": { "id": "80756b9a-5d95-e211-a939-e4115bead28a" }, - "address_postcode":"E14 8RJ", - "telephone_alternative":null, - "email_alternative":null, - "notes":null, - "accepts_dit_email_marketing":false, - "archived":false, - "archived_documents_url_path":"/document/123", - "archived_on":null, - "archived_reason":null, - "archived_by":null, - "created_on":"2019-02-04T15:59:14.267412Z", - "modified_on":"2019-02-05T13:17:23.112153Z" + "address_postcode": "E14 8RJ", + "telephone_alternative": null, + "email_alternative": null, + "notes": null, + "accepts_dit_email_marketing": false, + "archived": false, + "archived_documents_url_path": "/document/123", + "archived_on": null, + "archived_reason": null, + "archived_by": null, + "created_on": "2019-02-04T15:59:14.267412Z", + "modified_on": "2019-02-05T13:17:23.112153Z", + "consent_data": [ + { + "source_system": "System A", + "consent_domain": "Domestic", + "consent": false + } + ] } diff --git a/test/sandbox/fixtures/v3/contact/contact-complete-details-uk.json b/test/sandbox/fixtures/v3/contact/contact-complete-details-uk.json index 5874086a9c2..b3059a1cc44 100644 --- a/test/sandbox/fixtures/v3/contact/contact-complete-details-uk.json +++ b/test/sandbox/fixtures/v3/contact/contact-complete-details-uk.json @@ -1,44 +1,52 @@ { - "id":"2676ea91-9dd7-4cf3-a4a3-67b06f841b54", - "title":null, - "first_name":"Joseph", - "last_name":"Woof", - "name":"Joseph Woof", - "job_title":"Dog master", - "company":{ - "name":"Zboncak Group|271eb29e-425b-4cd8-b386-3208c3a5f978", - "id":"4cd4128b-1bad-4f1e-9146-5d4678c6a018" - }, - "adviser":{ - "name":"DBT Staff", - "first_name":"DBT", - "last_name":"Staff", - "id":"7d19d407-9aec-4d06-b190-d3f404627f21" - }, - "primary":true, - "telephone_countrycode":"", - "telephone_number":"", - "full_telephone_number":"222 3453454", - "email":"contact@bob.com", - "address_same_as_company":false, - "address_1":"123 Test Street", - "address_2":"Address Line 2", - "address_town":"Sandbox Town", - "address_county":"Test County", - "address_country": { - "id": "80756b9a-5d95-e211-a939-e4115bead28a", - "name": "United Kingdom" - }, - "address_postcode":"AB1 2CD", - "telephone_alternative":null, - "email_alternative":null, - "notes":"An example of a contact for testing purposes", - "accepts_dit_email_marketing":true, - "archived":false, - "archived_documents_url_path":"/document/123", - "archived_on":null, - "archived_reason":null, - "archived_by":null, - "created_on":"2019-02-04T15:59:14.267412Z", - "modified_on":"2019-02-05T13:17:23.112153Z" - } + "id": "2676ea91-9dd7-4cf3-a4a3-67b06f841b54", + "title": null, + "first_name": "Joseph", + "last_name": "Woof", + "name": "Joseph Woof", + "job_title": "Dog master", + "company": { + "name": "Zboncak Group|271eb29e-425b-4cd8-b386-3208c3a5f978", + "id": "4cd4128b-1bad-4f1e-9146-5d4678c6a018" + }, + "adviser": { + "name": "DBT Staff", + "first_name": "DBT", + "last_name": "Staff", + "id": "7d19d407-9aec-4d06-b190-d3f404627f21" + }, + "primary": true, + "telephone_countrycode": "", + "telephone_number": "", + "full_telephone_number": "222 3453454", + "email": "contact@bob.com", + "address_same_as_company": false, + "address_1": "123 Test Street", + "address_2": "Address Line 2", + "address_town": "Sandbox Town", + "address_county": "Test County", + "address_country": { + "id": "80756b9a-5d95-e211-a939-e4115bead28a", + "name": "United Kingdom" + }, + "address_postcode": "AB1 2CD", + "telephone_alternative": null, + "email_alternative": null, + "notes": "An example of a contact for testing purposes", + "accepts_dit_email_marketing": true, + "archived": false, + "archived_documents_url_path": "/document/123", + "archived_on": null, + "archived_reason": null, + "archived_by": null, + "created_on": "2019-02-04T15:59:14.267412Z", + "modified_on": "2019-02-05T13:17:23.112153Z", + "consent_data": [ + { + "source_system": "System B", + "consent_domain": "International", + "consent": true + } + ], + "consent_data_management_url": "http://dbt.com?email=contact@bob.com" +} diff --git a/test/sandbox/fixtures/v3/omis/paid-order.json b/test/sandbox/fixtures/v3/omis/paid-order.json index 9913b8b3b96..99ecdfad15c 100644 --- a/test/sandbox/fixtures/v3/omis/paid-order.json +++ b/test/sandbox/fixtures/v3/omis/paid-order.json @@ -59,7 +59,7 @@ "further_info": "legacy further info", "existing_agents": "legacy existing agents", "permission_to_approach_contacts": "legacy permission to approach contacts", - "delivery_date": "", + "delivery_date": null, "po_number": "123PO", "vat_status": "eu", "vat_number": "0123456789", diff --git a/test/sandbox/fixtures/v4/company/company-with-export-project-details.json b/test/sandbox/fixtures/v4/company/company-with-export-project-details.json new file mode 100644 index 00000000000..b6f4b1a7383 --- /dev/null +++ b/test/sandbox/fixtures/v4/company/company-with-export-project-details.json @@ -0,0 +1,64 @@ +{ + "id": "f5bc555e-0eba-4a7e-abe9-db89a78afc5c", + "company": { + "name": "Venus Ltd", + "id": "0f5216e0-849f-11e6-ae22-56b6b6499611" + }, + "owner": { + "name": "John Doe", + "first_name": "John", + "last_name": "Doe", + "dit_team": { + "name": "Agricultural Engineers Association Ltd", + "id": "d2f02898-9698-e211-a939-e4115bead28a" + }, + "id": "c0e09068-ce3e-4798-9437-2d258d83881e" + }, + "team_members": [ + { + "name": "Puck Head", + "id": "e83a608e-84a4-11e6-ae22-56b6b6499611" + }, + { + "name": "Jacob Webster", + "id": "b4848b30-f532-4cfc-a063-b064d8435b65" + } + ], + "contacts": [ + { + "name": "Johnny Cakeman", + "email": "johnny@cakeman.com", + "id": "9b1138ab-ec7b-497f-b8c3-27fed21694ef" + } + ], + "destination_country": { + "name": "Åland Islands", + "id": "ff996375-8adf-459a-b2a6-a477b66c7c6a" + }, + "sector": { + "name": "Advanced engineering : Metallurgical process plant", + "id": "a422c9d2-5f95-e211-a939-e4115bead28a" + }, + "exporter_experience": { + "name": "Exported in the last 12 months, but has not won an export order by having an export plan", + "id": "8937c359-157e-41dd-8520-679383847ea0" + }, + "estimated_win_date": "2025-03-01", + "estimated_export_value_amount": "500000", + "estimated_export_value_years": { + "name": "4 years", + "id": "3f289d56-aec1-4472-a046-10828cad4992" + }, + "export_potential": "high", + "created_on": "2025-01-15T10:38:12.694291Z", + "modified_on": "2025-01-15T10:40:30.928565Z", + "archived": false, + "archived_on": null, + "archived_reason": "", + "title": "Export Project for Venus ltd - TEST", + "status": "active", + "notes": "", + "created_by": "c0e09068-ce3e-4798-9437-2d258d83881e", + "modified_by": "c0e09068-ce3e-4798-9437-2d258d83881e", + "archived_by": null +} diff --git a/test/sandbox/fixtures/v4/interaction/interaction-by-export-project.js b/test/sandbox/fixtures/v4/interaction/interaction-by-export-project.js new file mode 100644 index 00000000000..f9daaabf9c8 --- /dev/null +++ b/test/sandbox/fixtures/v4/interaction/interaction-by-export-project.js @@ -0,0 +1,39 @@ +import { faker } from '../../../utils/random.js' +import interactionsFixture from './interactions.json' assert { type: 'json' } + +export const interactionByExportProject = (req) => { + const interactionsByExportProjectList = interactionsFixture.results.map( + (interaction) => ({ + ...interaction, + company_export: { + id: req.query.company_export_id, + title: faker.word.sample(), + }, + dit_participants: [ + { + adviser: { + name: faker.person.fullName(), + first_name: faker.person.firstName(), + last_name: faker.person.lastName(), + id: faker.string.uuid(), + }, + team: { + name: faker.company.name(), + id: faker.string.uuid(), + }, + }, + ], + }) + ) + + const limit = parseInt(req.query.limit, 10) + const offset = parseInt(req.query.offset, 10) + + return Object.assign( + {}, + { + ...interactionsFixture, + results: interactionsByExportProjectList.slice(offset, offset + limit), + } + ) +} diff --git a/test/sandbox/fixtures/v4/metadata/overseas-region.json b/test/sandbox/fixtures/v4/metadata/overseas-region.json new file mode 100644 index 00000000000..70c7c595c3e --- /dev/null +++ b/test/sandbox/fixtures/v4/metadata/overseas-region.json @@ -0,0 +1,47 @@ +[ + { + "id": "8d4c4f31-06ce-4320-8e2f-1c13559e125f", + "name": "Africa", + "disabled_on": null + }, + { + "id": "04a7cff0-03dd-4677-aa3c-12dd8426f0d7", + "name": "Asia Pacific", + "disabled_on": null + }, + { + "id": "b97749fb-2273-4447-a239-62dd8fb29e01", + "name": "China and Hong Kong", + "disabled_on": null + }, + { + "id": "cb2864aa-d19f-44b6-946c-d850a3fd7e3a", + "name": "Eastern Europe and Central Asia", + "disabled_on": null + }, + { + "id": "3e6809d6-89f6-4590-8458-1d0dab73ad1a", + "name": "Europe", + "disabled_on": null + }, + { + "id": "5616ccf5-ab4a-4c2c-9624-13c69be3c46b", + "name": "Latin America", + "disabled_on": null + }, + { + "id": "c4679b44-079e-4394-8bf7-bb0881a5031d", + "name": "Middle East, Afghanistan and Pakistan", + "disabled_on": null + }, + { + "id": "fdfbbc8d-0e8a-479a-b10f-4979d582ff87", + "name": "North America", + "disabled_on": null + }, + { + "id": "12ed13cf-4b2c-4a46-b2f9-068e397d8c84", + "name": "South Asia", + "disabled_on": null + } +] diff --git a/test/sandbox/fixtures/v4/search/company-activity/activity-by-company-id.json b/test/sandbox/fixtures/v4/search/company-activity/activity-by-company-id.json index 0db4a66cee0..8fce6184b09 100644 --- a/test/sandbox/fixtures/v4/search/company-activity/activity-by-company-id.json +++ b/test/sandbox/fixtures/v4/search/company-activity/activity-by-company-id.json @@ -1,5 +1,5 @@ { - "count": 5, + "count": 6, "results": [ { "id": "e25696d1-a54b-4e2e-b0bf-9657e9c4c55b", @@ -205,6 +205,29 @@ "id": "985f66a0-5d95-e211-a939-e4115bead28a" } } + }, + { + "great_export_enquiry": null, + "date": "2024-12-02T09:59:03.911296+00:00", + "referral": null, + "activity_source": "eyb_lead", + "interaction": null, + "investment": null, + "company": { + "trading_names": ["Harris, Hunt and Rogers", "Cunningham Group"], + "name": "Booth Sykes (Linked Company Name)", + "id": "1c5f7b5f-acd0-4a17-ac9d-8600bb5ded86" + }, + "id": "4d5efb64-806a-412d-8b4c-df11c3c3ff46", + "eyb_lead": { + "is_high_value": true, + "created_on": "2024-12-02T09:59:03.911296+00:00", + "company_name": "Booth Sykes (EYB lead)", + "triage_created": "2024-12-01T09:59:03+00:00", + "id": "e686c9d9-d7ba-444d-a85b-a64c477fc1ba", + "duns_number": "001968213" + }, + "order": null } ] } diff --git a/test/sandbox/package-lock.json b/test/sandbox/package-lock.json index ec832d177e0..ef502da0eab 100644 --- a/test/sandbox/package-lock.json +++ b/test/sandbox/package-lock.json @@ -16,16 +16,16 @@ "seedrandom": "^3.0.5" }, "devDependencies": { - "@babel/core": "^7.26.0", - "@babel/eslint-parser": "^7.25.9", + "@babel/core": "^7.26.7", + "@babel/eslint-parser": "^7.26.5", "@babel/plugin-syntax-import-assertions": "^7.26.0", - "@babel/runtime": "^7.26.0", - "@faker-js/faker": "^9.3.0", + "@babel/runtime": "^7.26.7", + "@faker-js/faker": "^9.4.0", "eslint": "^8.57.0", - "eslint-config-prettier": "^9.0.0", + "eslint-config-prettier": "^10.0.1", "eslint-plugin-import": "^2.31.0", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^5.2.1" + "eslint-plugin-prettier": "^5.2.3" }, "engines": { "node": "20.11.0" @@ -54,10 +54,11 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.0.tgz", - "integrity": "sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", @@ -68,30 +69,32 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.0.tgz", - "integrity": "sha512-qETICbZSLe7uXv9VE8T/RWOdIE5qqyTucOt4zLYMafj2MRO271VGgLd4RACJMeBO37UPWhXiKMBk7YlJ0fOzQA==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz", + "integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", - "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz", + "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.0", - "@babel/generator": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.5", + "@babel/helper-compilation-targets": "^7.26.5", "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.0", - "@babel/parser": "^7.26.0", + "@babel/helpers": "^7.26.7", + "@babel/parser": "^7.26.7", "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.26.0", + "@babel/traverse": "^7.26.7", + "@babel/types": "^7.26.7", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -107,9 +110,9 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.9.tgz", - "integrity": "sha512-5UXfgpK0j0Xr/xIdgdLEhOFxaDZ0bRPWJJchRpqOSur/3rZoPbqqki5mm0p4NE2cs28krBEiSM2MB7//afRSQQ==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.26.5.tgz", + "integrity": "sha512-Kkm8C8uxI842AwQADxl0GbcG1rupELYLShazYEZO/2DYjhyWXJIOUVOE3tBYm6JXzUCNJOZEzqc4rCW/jsEQYQ==", "dev": true, "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", @@ -125,13 +128,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.0.tgz", - "integrity": "sha512-/AIkAmInnWwgEAJGQr9vY0c66Mj6kjkE2ZPB1PurTRaRAh3U+J45sAQMjQDJdh4WbR3l0x5xkimXBKyBXXAu2w==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", + "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.0", - "@babel/types": "^7.26.0", + "@babel/parser": "^7.26.5", + "@babel/types": "^7.26.5", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -141,12 +145,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", - "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.9", + "@babel/compat-data": "^7.26.5", "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", @@ -218,30 +223,33 @@ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", - "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.7.tgz", + "integrity": "sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==", "dev": true, + "license": "MIT", "dependencies": { "@babel/template": "^7.25.9", - "@babel/types": "^7.26.0" + "@babel/types": "^7.26.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.1.tgz", - "integrity": "sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz", + "integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.26.0" + "@babel/types": "^7.26.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -266,10 +274,11 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", - "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", + "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", "dev": true, + "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -292,16 +301,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", - "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz", + "integrity": "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/parser": "^7.25.9", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.5", + "@babel/parser": "^7.26.7", "@babel/template": "^7.25.9", - "@babel/types": "^7.25.9", + "@babel/types": "^7.26.7", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -310,10 +320,11 @@ } }, "node_modules/@babel/types": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", - "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz", + "integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" @@ -406,9 +417,9 @@ } }, "node_modules/@faker-js/faker": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.3.0.tgz", - "integrity": "sha512-r0tJ3ZOkMd9xsu3VRfqlFR6cz0V/jFYRswAIpC+m/DIfAUXq7g8N7wTAlhSANySXYGKzGryfDXwtwsY8TxEIDw==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-9.4.0.tgz", + "integrity": "sha512-85+k0AxaZSTowL0gXp8zYWDIrWclTbRPg/pm/V0dSFZ6W6D4lhcG3uuZl4zLsEKfEvs69xDbLN2cHQudwp95JA==", "dev": true, "funding": [ { @@ -886,9 +897,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", - "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", "dev": true, "funding": [ { @@ -904,10 +915,11 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.1" }, "bin": { @@ -958,9 +970,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001673", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001673.tgz", - "integrity": "sha512-WTrjUCSMp3LYX0nE12ECkV0a+e6LC85E0Auz75555/qr78Oc8YWhEPNfDd6SHdtlCMSzqtuXY0uyEMNRcsKpKw==", + "version": "1.0.30001695", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001695.tgz", + "integrity": "sha512-vHyLade6wTgI2u1ec3WQBxv+2BrTERV28UXQu9LO6lZ9pYeMk34vjXFLOxo1A4UBA8XTL4njRQZdno/yYaSmWw==", "dev": true, "funding": [ { @@ -975,7 +987,8 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chokidar": { "version": "3.6.0", @@ -1218,10 +1231,11 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.5.47", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.47.tgz", - "integrity": "sha512-zS5Yer0MOYw4rtK2iq43cJagHZ8sXN0jDHDKzB+86gSBSAI4v07S97mcq+Gs2vclAxSh1j7vOAHxSVgduiiuVQ==", - "dev": true + "version": "1.5.88", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.88.tgz", + "integrity": "sha512-K3C2qf1o+bGzbilTDCTBhTQcMS9KW60yTAaTeeXsfvQuTDDwlokLam/AdqlqcSy9u4UainDgsHV23ksXAOgamw==", + "dev": true, + "license": "ISC" }, "node_modules/encodeurl": { "version": "2.0.0", @@ -1367,6 +1381,7 @@ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -1432,12 +1447,12 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.0.1.tgz", + "integrity": "sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw==", "dev": true, "bin": { - "eslint-config-prettier": "bin/cli.js" + "eslint-config-prettier": "build/bin/cli.js" }, "peerDependencies": { "eslint": ">=7.0.0" @@ -1583,9 +1598,9 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", + "integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0", @@ -2924,6 +2939,7 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } @@ -3022,10 +3038,11 @@ } }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "dev": true + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" }, "node_modules/nodemon": { "version": "3.1.9", @@ -4136,9 +4153,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", "dev": true, "funding": [ { @@ -4154,9 +4171,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -4250,7 +4268,8 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yocto-queue": { "version": "0.1.0", diff --git a/test/sandbox/package.json b/test/sandbox/package.json index 77e93e5a877..97948de9e95 100644 --- a/test/sandbox/package.json +++ b/test/sandbox/package.json @@ -13,16 +13,16 @@ "seedrandom": "^3.0.5" }, "devDependencies": { - "@babel/core": "^7.26.0", - "@babel/eslint-parser": "^7.25.9", + "@babel/core": "^7.26.7", + "@babel/eslint-parser": "^7.26.5", "@babel/plugin-syntax-import-assertions": "^7.26.0", - "@babel/runtime": "^7.26.0", - "@faker-js/faker": "^9.3.0", + "@babel/runtime": "^7.26.7", + "@faker-js/faker": "^9.4.0", "eslint": "^8.57.0", - "eslint-config-prettier": "^9.0.0", + "eslint-config-prettier": "^10.0.1", "eslint-plugin-import": "^2.31.0", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^5.2.1" + "eslint-plugin-prettier": "^5.2.3" }, "engines": { "node": "20.11.0" diff --git a/test/sandbox/routes/v3/interaction/interaction.js b/test/sandbox/routes/v3/interaction/interaction.js index 0eb01b33458..8020e1d9a5f 100644 --- a/test/sandbox/routes/v3/interaction/interaction.js +++ b/test/sandbox/routes/v3/interaction/interaction.js @@ -13,6 +13,7 @@ import interactionDraftPastMeeting from '../../../fixtures/v3/interaction/intera import interactionValidationError from '../../../fixtures/v3/interaction/interaction-validation-error.json' assert { type: 'json' } import interactionWithReferral from '../../../fixtures/v3/interaction/interaction-with-referral.json' assert { type: 'json' } import interactionWithoutTheme from '../../../fixtures/v3/interaction/interaction-without-theme.js' +import { interactionByExportProject } from '../../../fixtures/v4/interaction/interaction-by-export-project.js' export const getInteractions = function (req, res) { if (req.query.contact_id) { @@ -33,6 +34,10 @@ export const getInteractions = function (req, res) { return res.json(noInteractions) } + if (req.query.company_export_id === 'f5bc555e-0eba-4a7e-abe9-db89a78afc5c') { + return res.json(interactionByExportProject(req)) + } + res.json(interactions) } diff --git a/test/sandbox/routes/v4/company/company.js b/test/sandbox/routes/v4/company/company.js index 525e9ef5f23..84cb680e9e4 100644 --- a/test/sandbox/routes/v4/company/company.js +++ b/test/sandbox/routes/v4/company/company.js @@ -26,6 +26,7 @@ import companyWithValidationError from '../../../fixtures/v4/company/company-val import companyAudit from '../../../fixtures/v4/company-audit/company-audit.json' assert { type: 'json' } import companyUsState from '../../../fixtures/v4/company/company-us-state.json' assert { type: 'json' } import companyCanadianProvince from '../../../fixtures/v4/company/company-canada-province.json' assert { type: 'json' } +import companyWithExportProjectDetails from '../../../fixtures/v4/company/company-with-export-project-details.json' assert { type: 'json' } import exportWins from '../../../fixtures/v4/company-export-wins/export-wins.json' assert { type: 'json' } import exportWinsPage1 from '../../../fixtures/v4/company-export-wins/export-wins-page-1.json' assert { type: 'json' } import exportWinsPage2 from '../../../fixtures/v4/company-export-wins/export-wins-page-2.json' assert { type: 'json' } @@ -245,13 +246,19 @@ export const getReferralDetails = function (req, res) { export const exportDetail = function (req, res) { var companyId = req.params.companyId + var exportId = req.params.exportId + + var errorResponse = { non_field_errors: ['A 400 error message here'] } if (companyId === companyLambdaPlc.id) { res.status(500).send('') } else if (companyId === companyDnBCorp.id) { - res.status(400).json({ non_field_errors: ['A 400 error message here'] }) + res.status(400).json(errorResponse) + } else if (exportId === companyWithExportProjectDetails.id) { + res.json(companyWithExportProjectDetails) } else { - res.send('') + //Throw error message + res.status(400).json(errorResponse) } } diff --git a/test/sandbox/routes/v4/interaction/interaction.js b/test/sandbox/routes/v4/interaction/interaction.js index 15999c8bb07..4b840e868f7 100644 --- a/test/sandbox/routes/v4/interaction/interaction.js +++ b/test/sandbox/routes/v4/interaction/interaction.js @@ -17,6 +17,8 @@ import interactionWithExportCountries from '../../../fixtures/v4/interaction/int import interactionWithoutExportCountries from '../../../fixtures/v4/interaction/interaction-with-no-countries-discussed.json' assert { type: 'json' } import interactionWithBusIntel from '../../../fixtures/v4/interaction/interaction-with-business-intelligence.json' assert { type: 'json' } +import { interactionByExportProject } from '../../../fixtures/v4/interaction/interaction-by-export-project.js' + export const getInteractions = function (req, res) { if (req.query.contact_id) { return res.json(interactionByContactId) @@ -32,6 +34,10 @@ export const getInteractions = function (req, res) { return res.json(interactionByInvestmentProjectId) } + if (req.query.company_export_id === 'f5bc555e-0eba-4a7e-abe9-db89a78afc5c') { + return res.json(interactionByExportProject(req)) + } + res.json(interactions) } diff --git a/test/sandbox/routes/v4/metadata/index.js b/test/sandbox/routes/v4/metadata/index.js index 9a47fe755ca..64eab1e8229 100644 --- a/test/sandbox/routes/v4/metadata/index.js +++ b/test/sandbox/routes/v4/metadata/index.js @@ -65,6 +65,7 @@ import hvc from '../../../fixtures/v4/metadata/hvc.json' assert { type: 'json' } import associatedProgramme from '../../../fixtures/v4/metadata/associated-programme.json' assert { type: 'json' } import hqTeamRegionOrPostInvestment from '../../../fixtures/v4/metadata/hq-team-region-or-post-investment.json' assert { type: 'json' } import hqTeamRegionOrPostTrade from '../../../fixtures/v4/metadata/hq-team-region-or-post-trade.json' assert { type: 'json' } +import overseasRegion from '../../../fixtures/v4/metadata/overseas-region.json' assert { type: 'json' } export const getLikelihoodToLand = function (req, res) { res.json(likelihoodToLand) @@ -338,3 +339,7 @@ export const getHqTeamRegionOrPost = function (req, res) { } res.json(hqTeamRegionOrPost[req.query.team_type] || {}) } + +export const getOverseasRegion = function (req, res) { + res.json(overseasRegion) +} diff --git a/test/sandbox/server.js b/test/sandbox/server.js index 3b15ba4f015..4c197f71236 100644 --- a/test/sandbox/server.js +++ b/test/sandbox/server.js @@ -225,6 +225,7 @@ import { getEvidenceTag as _evidenceTag, getEmployeeRange as _employeeRange, getCountry as _country, + getOverseasRegion as _overseasRegion, getUkRegion as _ukRegion, getAdministrativeArea, getReferralSourceWebsite as _referralSourceWebsite, @@ -457,6 +458,7 @@ app.get('/v4/metadata/business-type', _businessType) app.get('/v4/metadata/evidence-tag', _evidenceTag) app.get('/v4/metadata/employee-range', _employeeRange) app.get('/v4/metadata/country', _country) +app.get('/v4/metadata/overseas-region', _overseasRegion) app.get('/v4/metadata/uk-region', _ukRegion) app.get('/v4/metadata/winukregion', _ukRegion) app.get('/v4/metadata/administrative-area', getAdministrativeArea) @@ -891,6 +893,8 @@ app.post('/v4/task', createTask) app.patch('/v4/task/:taskId', updateTask) app.get('/v4/export', (req, res) => res.json({ count: 0, results: [] })) +app.get('/v4/export/:exportId', (req, res) => exportDetail(req, res)) + app.get('/v4/export/owner', (req, res) => res.json([ { diff --git a/test/selectors/entity-collection.js b/test/selectors/entity-collection.js index b046069ac36..98f03103776 100644 --- a/test/selectors/entity-collection.js +++ b/test/selectors/entity-collection.js @@ -1,6 +1,4 @@ module.exports = { - addAttendee: '[data-test="Add attendee"]', - editEvent: 'a:contains("Edit event")', addProposition: '[data-test="add-collection-item-button"]', collection: '.c-collection', sortBy: '[name="sortBy"] > select', diff --git a/test/selectors/index.js b/test/selectors/index.js index d563f105fb0..6d146056ee5 100644 --- a/test/selectors/index.js +++ b/test/selectors/index.js @@ -18,10 +18,6 @@ exports.companyList = { edit: require('./company-lists/edit'), } -exports.companyDnbHierarchy = { - collection: '#dnb-hierarchy', -} - exports.eventCreate = require('./event/createOrEdit') exports.entityCollection = require('./entity-collection') diff --git a/test/unit/data/referrals/referralDetails.json b/test/unit/data/referrals/referralDetails.json deleted file mode 100644 index 559bf75eb6e..00000000000 --- a/test/unit/data/referrals/referralDetails.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "id": "9c906f09-913e-4e30-935b-952236f46b86", - "closed_by": null, - "closed_on": null, - "company": { - "name": "Lambda plc", - "id": "0fb3379c-341c-4da4-b825-bf8d47b26baa" - }, - "completed_by": null, - "completed_on": null, - "contact": { - "name": "Johnny Cakeman", - "id": "9b1138ab-ec7b-497f-b8c3-27fed21694ef" - }, - "created_by": { - "name": "Ian Leggett", - "contact_email": "caravans@ian.com", - "dit_team": { - "name": "Advanced Manufacturing Sector", - "id": "08c14624-2f50-e311-a56a-e4115bead28a" - }, - "id": "0c004222-5626-4ef6-b663-18f99fc67cd6" - }, - "created_on": "2020-02-16T18:24:58.641396Z", - "notes": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", - "recipient": { - "name": "Barry Oling", - "contact_email": "barry@barry.com", - "dit_team": { - "name": "Aberdeen City Council", - "id": "cff02898-9698-e211-a939-e4115bead28a" - }, - "id": "a80ff5fd-8904-4940-bf96-fe8047e34be5" - }, - "status": "outstanding", - "subject": "I am a subject" -}