From fdfef8efa3feaf1f9b52f1fea4433c590ab315b2 Mon Sep 17 00:00:00 2001 From: Nick Skriabin Date: Wed, 23 Aug 2023 14:49:45 +0100 Subject: [PATCH 01/14] Upgrade react to version 18 --- package.json | 7 ++--- src/LabelStudio.js | 56 +++++++++++++++++++++++++++------------ src/utils/reactCleaner.js | 3 ++- yarn.lock | 34 +++++++++++++++--------- 4 files changed, 67 insertions(+), 33 deletions(-) diff --git a/package.json b/package.json index 57b54633a2..a83d3bd095 100644 --- a/package.json +++ b/package.json @@ -125,7 +125,8 @@ "@types/mini-css-extract-plugin": "^2.5.1", "@types/nanoid": "^3.0.0", "@types/offscreencanvas": "^2019.6.4", - "@types/react-dom": "^17.0.11", + "@types/react": "^18.2.21", + "@types/react-dom": "^18.2.7", "@types/react-window": "^1.8.5", "@types/strman": "^2.0.0", "@types/wavesurfer.js": "^6.0.0", @@ -175,8 +176,8 @@ "postcss-preset-env": "^7.4.1", "prettier": "^1.19.1", "raw-loader": "^4.0.2", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", "react-hot-loader": "^4.13.0", "react-konva": "^17.0.2-0", "react-rating": "^1.6.2", diff --git a/src/LabelStudio.js b/src/LabelStudio.js index f0f6c6fd5e..5a815699dc 100644 --- a/src/LabelStudio.js +++ b/src/LabelStudio.js @@ -1,4 +1,4 @@ -import { render, unmountComponentAtNode } from 'react-dom'; +import { createRoot } from 'react-dom/client'; import App from './components/App/App'; import { configureStore } from './configureStore'; import { LabelStudio as LabelStudioReact } from './Component'; @@ -14,6 +14,7 @@ import { destroy } from 'mobx-state-tree'; import { destroy as destroySharedStore } from './mixins/SharedChoiceStore/mixin'; import { cleanDomAfterReact, findReactKey } from './utils/reactCleaner'; import { FF_LSDV_4620_3_ML, isFF } from './utils/feature-flags'; +import { StrictMode } from 'react'; configure({ isolateGlobalState: true, @@ -60,6 +61,7 @@ export class LabelStudio { async createApp() { const { store, getRoot } = await configureStore(this.options, this.events); const rootElement = getRoot(this.root); + const appRoot = createRoot(rootElement); this.store = store; window.Htx = this.store; @@ -68,30 +70,50 @@ export class LabelStudio { const renderApp = () => { if (isRendered) { - clearRenderedApp(); + unmountApp(); } - render(( - - ), rootElement); + appRoot.render( + + + + ) }; - const clearRenderedApp = () => { - const childNodes = [...rootElement.childNodes]; - // cleanDomAfterReact needs this key to be sure that cleaning affects only current react subtree - const reactKey = findReactKey(childNodes[0]); + const PERFORM_REACT_CLEANUP = true; + + const cleanupReactNodes = (callback) => { + let childNodes, reactKey; + + if (PERFORM_REACT_CLEANUP) { + childNodes = Array.from(rootElement.childNodes); + console.log(childNodes); + + // cleanDomAfterReact needs this key to be sure that cleaning affects + // only current react subtree + reactKey = findReactKey(childNodes[0]); + } + + callback(); - unmountComponentAtNode(rootElement); /* Unmounting doesn't help with clearing React's fibers but removing the manually helps @see https://github.com/facebook/react/pull/20290 (similar problem) That's maybe not relevant in version 18 */ - cleanDomAfterReact(childNodes, reactKey); - cleanDomAfterReact([rootElement], reactKey); + if (childNodes && reactKey) { + cleanDomAfterReact(childNodes, reactKey); + cleanDomAfterReact([rootElement], reactKey); + } + } + + const unmountApp = () => { + cleanupReactNodes(() => { + appRoot.unmount(); + }); }; renderApp(); @@ -100,12 +122,12 @@ export class LabelStudio { return isRendered; }, render: renderApp, - clear: clearRenderedApp, + clear: unmountApp, }); this.destroy = () => { if (isFF(FF_LSDV_4620_3_ML)) { - clearRenderedApp(); + unmountApp(); } destroySharedStore(); if (isFF(FF_LSDV_4620_3_ML)) { diff --git a/src/utils/reactCleaner.js b/src/utils/reactCleaner.js index a6874e6b5a..26b6a03c6e 100644 --- a/src/utils/reactCleaner.js +++ b/src/utils/reactCleaner.js @@ -8,7 +8,8 @@ export function cutFibers(object) { const isSvg = obj.elementType === 'svg'; // preventing processing svgs due to the problem with props, - // props sometimes come from the global variables, so it's tricky to clean them without breaking icons itself + // props sometimes come from the global variables, so it's + // tricky to clean them without breaking icons itself if (isSvg) continue; for (const key of keys) { diff --git a/yarn.lock b/yarn.lock index 074a56bfce..017de7de74 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3459,9 +3459,10 @@ dependencies: "@types/react" "*" -"@types/react-dom@^17.0.11": - version "17.0.13" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.13.tgz#a3323b974ee4280070982b3112351bb1952a7809" +"@types/react-dom@^18.2.7": + version "18.2.7" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.7.tgz#67222a08c0a6ae0a0da33c3532348277c70abb63" + integrity sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA== dependencies: "@types/react" "*" @@ -3497,6 +3498,15 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/react@^18.2.21": + version "18.2.21" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.21.tgz#774c37fd01b522d0b91aed04811b58e4e0514ed9" + integrity sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + "@types/retry@^0.12.0": version "0.12.1" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" @@ -9963,13 +9973,13 @@ react-beautiful-dnd@^13.1.1: redux "^4.0.4" use-memo-one "^1.1.1" -react-dom@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" +react-dom@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" + integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== dependencies: loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler "^0.20.2" + scheduler "^0.23.0" react-hot-loader@^4.13.0: version "4.13.0" @@ -10087,12 +10097,12 @@ react-window@^1.8.6: "@babel/runtime" "^7.0.0" memoize-one ">=3.1.1 <6" -react@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" +react@^18.2.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" + integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== dependencies: loose-envify "^1.1.0" - object-assign "^4.1.1" read-pkg-up@^7.0.1: version "7.0.1" From 9002347b8fdafd9db528603b79bfc867b45e4e29 Mon Sep 17 00:00:00 2001 From: Nick Skriabin Date: Wed, 23 Aug 2023 15:08:15 +0100 Subject: [PATCH 02/14] Replace Enzyme adapter --- package.json | 2 +- .../__tests__/AnnotationButton.test.tsx | 2 +- .../__tests__/AnnotationsCarousel.test.tsx | 2 +- src/components/Hint/Hint.test.js | 2 +- .../SidePanels/__tests__/PanelBase.test.tsx | 2 +- src/setupTests.js | 2 +- src/tags/visual/__tests__/Header.test.jsx | 2 +- yarn.lock | 117 ++++-------------- 8 files changed, 32 insertions(+), 99 deletions(-) diff --git a/package.json b/package.json index a83d3bd095..61bcbee07c 100644 --- a/package.json +++ b/package.json @@ -114,6 +114,7 @@ "@babel/preset-react": "7.18.6", "@babel/preset-typescript": "7.18.6", "@babel/runtime": "7.18.6", + "@cfaester/enzyme-adapter-react-18": "^0.7.0", "@heartexlabs/eslint-plugin-frontend": "https://github.com/heartexlabs/eslint-plugin-frontend.git", "@svgr/webpack": "^8.0.1", "@testing-library/react": "12.1.2", @@ -130,7 +131,6 @@ "@types/react-window": "^1.8.5", "@types/strman": "^2.0.0", "@types/wavesurfer.js": "^6.0.0", - "@wojtekmaj/enzyme-adapter-react-17": "^0.4.1", "antd": "^4.3.3", "autoprefixer": "^10.4.2", "babel-jest": "^29.3.1", diff --git a/src/components/AnnotationsCarousel/__tests__/AnnotationButton.test.tsx b/src/components/AnnotationsCarousel/__tests__/AnnotationButton.test.tsx index 053e5a2e2f..8ebed1129d 100644 --- a/src/components/AnnotationsCarousel/__tests__/AnnotationButton.test.tsx +++ b/src/components/AnnotationsCarousel/__tests__/AnnotationButton.test.tsx @@ -1,6 +1,6 @@ /* global test, expect, jest, describe */ import Enzyme, { mount } from 'enzyme'; -import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; +import Adapter from '@cfaester/enzyme-adapter-react-18'; import { AnnotationButton } from '../AnnotationButton'; // eslint-disable-next-line // @ts-ignore diff --git a/src/components/AnnotationsCarousel/__tests__/AnnotationsCarousel.test.tsx b/src/components/AnnotationsCarousel/__tests__/AnnotationsCarousel.test.tsx index 08e347cb72..e0efba2d11 100644 --- a/src/components/AnnotationsCarousel/__tests__/AnnotationsCarousel.test.tsx +++ b/src/components/AnnotationsCarousel/__tests__/AnnotationsCarousel.test.tsx @@ -1,7 +1,7 @@ /* global test, expect, jest */ import React from 'react'; import Enzyme, { mount } from 'enzyme'; -import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; +import Adapter from '@cfaester/enzyme-adapter-react-18'; import { AnnotationsCarousel } from '../AnnotationsCarousel'; // eslint-disable-next-line // @ts-ignore diff --git a/src/components/Hint/Hint.test.js b/src/components/Hint/Hint.test.js index dc5cd4aae4..8a4402efe1 100644 --- a/src/components/Hint/Hint.test.js +++ b/src/components/Hint/Hint.test.js @@ -2,7 +2,7 @@ import React from 'react'; import Enzyme, { shallow } from 'enzyme'; import { shallowToJson } from 'enzyme-to-json'; -import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; +import Adapter from '@cfaester/enzyme-adapter-react-18'; Enzyme.configure({ adapter: new Adapter() }); diff --git a/src/components/SidePanels/__tests__/PanelBase.test.tsx b/src/components/SidePanels/__tests__/PanelBase.test.tsx index e66647a095..fba02f7bfa 100644 --- a/src/components/SidePanels/__tests__/PanelBase.test.tsx +++ b/src/components/SidePanels/__tests__/PanelBase.test.tsx @@ -1,6 +1,6 @@ /* global test, expect, describe */ import Enzyme, { mount } from 'enzyme'; -import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; +import Adapter from '@cfaester/enzyme-adapter-react-18'; import { PanelBase, PanelProps } from '../PanelBase'; import { createRef } from 'react'; diff --git a/src/setupTests.js b/src/setupTests.js index d709509b5b..67e322fcf0 100644 --- a/src/setupTests.js +++ b/src/setupTests.js @@ -4,7 +4,7 @@ /* global jest, global */ import { configure } from 'enzyme'; -import Adapter from '@wojtekmaj/enzyme-adapter-react-17'; +import Adapter from '@cfaester/enzyme-adapter-react-18'; const localStorageMock = { getItem: jest.fn(), diff --git a/src/tags/visual/__tests__/Header.test.jsx b/src/tags/visual/__tests__/Header.test.jsx index 0aec206ec9..687d52d679 100644 --- a/src/tags/visual/__tests__/Header.test.jsx +++ b/src/tags/visual/__tests__/Header.test.jsx @@ -1,6 +1,6 @@ /* global test, expect, jest */ import Enzyme, { render } from "enzyme"; -import Adapter from "@wojtekmaj/enzyme-adapter-react-17"; +import Adapter from "@cfaester/enzyme-adapter-react-18"; import { HtxHeader } from "../Header"; Enzyme.configure({ adapter: new Adapter() }); diff --git a/yarn.lock b/yarn.lock index 017de7de74..a35b1e0eeb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2560,6 +2560,15 @@ version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" +"@cfaester/enzyme-adapter-react-18@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@cfaester/enzyme-adapter-react-18/-/enzyme-adapter-react-18-0.7.0.tgz#92d81903855ed542ab54d2241a787c1b95883d0a" + integrity sha512-24rdgq6ncwmuyHizvKpdPUSczx5PjIhSr+LfXH/q5/Y28WbNZB6iGIqQ2iSiXp41qs+lutRIQQgwRJIf/a1N9w== + dependencies: + enzyme-shallow-equal "^1.0.0" + react-is "^18.0.0" + react-test-renderer "^18.0.0" + "@csstools/postcss-color-function@^1.0.2": version "1.0.3" resolved "https://registry.yarnpkg.com/@csstools/postcss-color-function/-/postcss-color-function-1.0.3.tgz#251c961a852c99e9aabdbbdbefd50e9a96e8a9ff" @@ -3788,20 +3797,6 @@ resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.1.tgz#34bdc31727a1889198855913db2f270ace6d7bf8" integrity sha512-0G7tNyS+yW8TdgHwZKlDWYXFA6OJQnoLCQvYKkQP0Q2X205PSQ6RNUj0M+1OB/9gRQaUZ/ccYfaxd0nhaWKfjw== -"@wojtekmaj/enzyme-adapter-react-17@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@wojtekmaj/enzyme-adapter-react-17/-/enzyme-adapter-react-17-0.4.1.tgz#a9d4a2873025c6de19e1142ca076661bac69f587" - dependencies: - enzyme-adapter-utils "^1.14.0" - enzyme-shallow-equal "^1.0.4" - has "^1.0.3" - object.assign "^4.1.0" - object.values "^1.1.1" - prop-types "^15.7.2" - react-is "^17.0.0" - react-test-renderer "^17.0.0" - semver "^5.7.0" - "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" @@ -3876,20 +3871,6 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -airbnb-prop-types@^2.16.0: - version "2.16.0" - resolved "https://registry.yarnpkg.com/airbnb-prop-types/-/airbnb-prop-types-2.16.0.tgz#b96274cefa1abb14f623f804173ee97c13971dc2" - dependencies: - array.prototype.find "^2.1.1" - function.prototype.name "^1.1.2" - is-regex "^1.1.0" - object-is "^1.1.2" - object.assign "^4.1.0" - object.entries "^1.1.2" - prop-types "^15.7.2" - prop-types-exact "^1.2.0" - react-is "^16.13.1" - ajv-formats@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" @@ -4131,14 +4112,6 @@ array.prototype.filter@^1.0.0: es-array-method-boxes-properly "^1.0.0" is-string "^1.0.7" -array.prototype.find@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/array.prototype.find/-/array.prototype.find-2.1.2.tgz#6abbd0c2573925d8094f7d23112306af8c16d534" - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - array.prototype.flat@^1.2.3: version "1.2.5" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13" @@ -5909,19 +5882,15 @@ envinfo@^7.7.3: version "7.8.1" resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" -enzyme-adapter-utils@^1.14.0: - version "1.14.0" - resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.14.0.tgz#afbb0485e8033aa50c744efb5f5711e64fbf1ad0" +enzyme-shallow-equal@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.5.tgz#5528a897a6ad2bdc417c7221a7db682cd01711ba" + integrity sha512-i6cwm7hN630JXenxxJFBKzgLC3hMTafFQXflvzHgPmDhOBhxUWDe8AeRv1qp2/uWJ2Y8z5yLWMzmAfkTOiOCZg== dependencies: - airbnb-prop-types "^2.16.0" - function.prototype.name "^1.1.3" has "^1.0.3" - object.assign "^4.1.2" - object.fromentries "^2.0.3" - prop-types "^15.7.2" - semver "^5.7.1" + object-is "^1.1.5" -enzyme-shallow-equal@^1.0.1, enzyme-shallow-equal@^1.0.4: +enzyme-shallow-equal@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.4.tgz#b9256cb25a5f430f9bfe073a84808c1d74fced2e" dependencies: @@ -6599,7 +6568,7 @@ function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" -function.prototype.name@^1.1.2, function.prototype.name@^1.1.3, function.prototype.name@^1.1.5: +function.prototype.name@^1.1.2, function.prototype.name@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" dependencies: @@ -7308,7 +7277,7 @@ is-promise@^2.1.0: version "2.2.2" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" -is-regex@^1.0.5, is-regex@^1.1.0, is-regex@^1.1.4: +is-regex@^1.0.5, is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" dependencies: @@ -8705,7 +8674,7 @@ object.assign@^4.1.3, object.assign@^4.1.4: has-symbols "^1.0.3" object-keys "^1.1.1" -object.entries@^1.1.1, object.entries@^1.1.2: +object.entries@^1.1.1: version "1.1.5" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861" dependencies: @@ -8722,14 +8691,6 @@ object.entries@^1.1.5, object.entries@^1.1.6: define-properties "^1.1.4" es-abstract "^1.20.4" -object.fromentries@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.5.tgz#7b37b205109c21e741e605727fe8b0ad5fa08251" - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - object.fromentries@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.6.tgz#cdb04da08c539cffa912dcd368b886e0904bfa73" @@ -9511,14 +9472,6 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types-exact@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/prop-types-exact/-/prop-types-exact-1.2.0.tgz#825d6be46094663848237e3925a98c6e944e9869" - dependencies: - has "^1.0.3" - object.assign "^4.1.0" - reflect.ownkeys "^0.2.0" - prop-types@^15.6.1, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -9998,16 +9951,16 @@ react-is@^16.12.0, react-is@^16.13.1, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" -"react-is@^16.12.0 || ^17.0.0", react-is@^17.0.0, react-is@^17.0.1, react-is@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" - integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== - "react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^18.0.0, react-is@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +react-is@^17.0.1, react-is@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + react-konva-utils@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/react-konva-utils/-/react-konva-utils-0.2.0.tgz#e79ed7776edd50f40c152d8d49d2693ff12e910b" @@ -10053,13 +10006,6 @@ react-redux@^7.2.0: prop-types "^15.7.2" react-is "^17.0.2" -react-shallow-renderer@^16.13.1: - version "16.14.1" - resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.14.1.tgz#bf0d02df8a519a558fd9b8215442efa5c840e124" - dependencies: - object-assign "^4.1.1" - react-is "^16.12.0 || ^17.0.0" - react-shallow-renderer@^16.15.0: version "16.15.0" resolved "https://registry.yarnpkg.com/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz#48fb2cf9b23d23cde96708fe5273a7d3446f4457" @@ -10068,16 +10014,7 @@ react-shallow-renderer@^16.15.0: object-assign "^4.1.1" react-is "^16.12.0 || ^17.0.0 || ^18.0.0" -react-test-renderer@^17.0.0: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-17.0.2.tgz#4cd4ae5ef1ad5670fc0ef776e8cc7e1231d9866c" - dependencies: - object-assign "^4.1.1" - react-is "^17.0.2" - react-shallow-renderer "^16.13.1" - scheduler "^0.20.2" - -react-test-renderer@^18.2.0: +react-test-renderer@^18.0.0, react-test-renderer@^18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-18.2.0.tgz#1dd912bd908ff26da5b9fca4fd1c489b9523d37e" integrity sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA== @@ -10190,10 +10127,6 @@ redux@^4.0.0, redux@^4.0.4: dependencies: "@babel/runtime" "^7.9.2" -reflect.ownkeys@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460" - regenerate-unicode-properties@^10.0.1: version "10.0.1" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56" @@ -10566,7 +10499,7 @@ semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" -"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.7.0, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" From 61843601d0957447b0089f9e84ab84ad497bdc4e Mon Sep 17 00:00:00 2001 From: Nick Skriabin Date: Wed, 23 Aug 2023 17:54:14 +0100 Subject: [PATCH 03/14] Migrate to @testing-library/react --- package.json | 4 +- .../__tests__/AnnotationButton.test.tsx | 17 ++- .../__tests__/AnnotationsCarousel.test.tsx | 17 +-- src/components/Hint/Hint.test.js | 11 +- src/components/SidePanels/PanelBase.tsx | 16 +-- .../SidePanels/__tests__/PanelBase.test.tsx | 38 ++++--- src/tags/visual/__tests__/Header.test.jsx | 9 +- yarn.lock | 100 +++++++++++++++--- 8 files changed, 139 insertions(+), 73 deletions(-) diff --git a/package.json b/package.json index 61bcbee07c..1568b7a511 100644 --- a/package.json +++ b/package.json @@ -117,7 +117,9 @@ "@cfaester/enzyme-adapter-react-18": "^0.7.0", "@heartexlabs/eslint-plugin-frontend": "https://github.com/heartexlabs/eslint-plugin-frontend.git", "@svgr/webpack": "^8.0.1", - "@testing-library/react": "12.1.2", + "@testing-library/jest-dom": "^6.1.1", + "@testing-library/react": "^14.0.0", + "@testing-library/user-event": "^14.4.3", "@types/chroma-js": "^2.1.3", "@types/enzyme": "^3.10.12", "@types/jest": "^29.2.3", diff --git a/src/components/AnnotationsCarousel/__tests__/AnnotationButton.test.tsx b/src/components/AnnotationsCarousel/__tests__/AnnotationButton.test.tsx index 8ebed1129d..7836f0d753 100644 --- a/src/components/AnnotationsCarousel/__tests__/AnnotationButton.test.tsx +++ b/src/components/AnnotationsCarousel/__tests__/AnnotationButton.test.tsx @@ -1,12 +1,10 @@ /* global test, expect, jest, describe */ -import Enzyme, { mount } from 'enzyme'; -import Adapter from '@cfaester/enzyme-adapter-react-18'; +import { render } from "@testing-library/react"; import { AnnotationButton } from '../AnnotationButton'; // eslint-disable-next-line // @ts-ignore import { annotationStore } from './sampleData.js'; - -Enzyme.configure({ adapter: new Adapter() }); +import "@testing-library/jest-dom"; jest.mock('react', () => ({ ...jest.requireActual('react'), @@ -16,14 +14,15 @@ jest.mock('react', () => ({ describe('AnnotationsButton', () => { test('Annotation', () => { const entity = annotationStore.annotations[0]; - const view = mount(); + const view = render(); - expect(view.find('.dm-annotation-button__entity-id').text()).toBe(`#${entity.pk}`); + expect(view.getByText(`#${entity.pk}`)).toBeInTheDocument(); }); + test('Prediction', () => { const entity = annotationStore.predictions[0]; - const view = mount(); - - expect(view.find('.dm-annotation-button__entity-id').text()).toBe(`#${entity.pk}`); + const view = render(); + + expect(view.getByText(`#${entity.pk}`)).toBeInTheDocument(); }); }); diff --git a/src/components/AnnotationsCarousel/__tests__/AnnotationsCarousel.test.tsx b/src/components/AnnotationsCarousel/__tests__/AnnotationsCarousel.test.tsx index e0efba2d11..80332d902a 100644 --- a/src/components/AnnotationsCarousel/__tests__/AnnotationsCarousel.test.tsx +++ b/src/components/AnnotationsCarousel/__tests__/AnnotationsCarousel.test.tsx @@ -1,21 +1,24 @@ /* global test, expect, jest */ import React from 'react'; -import Enzyme, { mount } from 'enzyme'; -import Adapter from '@cfaester/enzyme-adapter-react-18'; +import { render } from "@testing-library/react"; import { AnnotationsCarousel } from '../AnnotationsCarousel'; // eslint-disable-next-line // @ts-ignore import { annotationStore, store } from './sampleData.js'; -Enzyme.configure({ adapter: new Adapter() }); - jest.mock('react', () => ({ ...jest.requireActual('react'), useLayoutEffect: jest.requireActual('react').useEffect, })); test('AnnotationsCarousel', async () => { - const view = mount(); - - expect(view.find('.dm-annotations-carousel__carosel').children().length).toBe(9); + const view = render( + + ); + const carouselItems = view.container.querySelectorAll('.dm-annotations-carousel__carosel > *'); + + expect(carouselItems).toHaveLength(9); }); diff --git a/src/components/Hint/Hint.test.js b/src/components/Hint/Hint.test.js index 8a4402efe1..edb1ab1e55 100644 --- a/src/components/Hint/Hint.test.js +++ b/src/components/Hint/Hint.test.js @@ -1,12 +1,7 @@ /* global describe, it, expect */ import React from 'react'; -import Enzyme, { shallow } from 'enzyme'; -import { shallowToJson } from 'enzyme-to-json'; -import Adapter from '@cfaester/enzyme-adapter-react-18'; - -Enzyme.configure({ adapter: new Adapter() }); - import Hint from './Hint'; +import { render } from '@testing-library/react'; describe('Hint', () => { it('Should render correctly', () => { @@ -16,8 +11,8 @@ describe('Hint', () => { ); - const output = shallow(component); + const output = render(component); - expect(shallowToJson(output)).toMatchSnapshot(); + expect(output.asFragment()).toMatchSnapshot(); }); }); diff --git a/src/components/SidePanels/PanelBase.tsx b/src/components/SidePanels/PanelBase.tsx index 63a5d29855..fcaeffe8c0 100644 --- a/src/components/SidePanels/PanelBase.tsx +++ b/src/components/SidePanels/PanelBase.tsx @@ -1,4 +1,4 @@ -import { FC, MutableRefObject, MouseEvent as RMouseEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { FC, MutableRefObject, MouseEvent as RMouseEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { Block, Elem } from '../../utils/bem'; import { IconArrowLeft, IconArrowRight, IconOutlinerCollapse, IconOutlinerExpand } from '../../assets/icons'; @@ -32,7 +32,7 @@ const resizers = [ interface PanelBaseProps { root: MutableRefObject; name: PanelType; - mix?: string|string[]; + mix?: string | string[]; title: string; tooltip: string; top: number; @@ -57,6 +57,7 @@ interface PanelBaseProps { onPositionChange: PositonChangeHandler; onVisibilityChange: VisibilityChangeHandler; onPositionChangeBegin: PositonChangeHandler; + children: React.ReactNode; } export type PanelProps = Omit @@ -145,9 +146,9 @@ export const PanelBase: FC = ({ }, [alignment, visible, detached, resizing, locked]); const currentIcon = useMemo(() => { - if (detached) return visible ? : ; - if (alignment === 'left') return visible ? : ; - if (alignment === 'right') return visible ? : ; + if (detached) return visible ? : ; + if (alignment === 'left') return visible ? : ; + if (alignment === 'right') return visible ? : ; return null; }, [detached, visible, alignment]); @@ -232,7 +233,7 @@ export const PanelBase: FC = ({ const target = e.target as HTMLElement; const type = target.dataset.resize; const shift = (() => { - switch(type) { + switch (type) { case 'top-left': return 'top-left'; case 'top': @@ -332,6 +333,7 @@ export const PanelBase: FC = ({ mod={{ enabled: visible }} onClick={(detached && !visible) ? handleExpand : handleCollapse} data-tooltip={tooltipText} + data-testid="panel-toggle-collapsed" > {currentIcon} @@ -364,4 +366,4 @@ export const PanelBase: FC = ({ )} ); -}; \ No newline at end of file +}; diff --git a/src/components/SidePanels/__tests__/PanelBase.test.tsx b/src/components/SidePanels/__tests__/PanelBase.test.tsx index fba02f7bfa..9e026d3f18 100644 --- a/src/components/SidePanels/__tests__/PanelBase.test.tsx +++ b/src/components/SidePanels/__tests__/PanelBase.test.tsx @@ -1,17 +1,16 @@ /* global test, expect, describe */ -import Enzyme, { mount } from 'enzyme'; -import Adapter from '@cfaester/enzyme-adapter-react-18'; import { PanelBase, PanelProps } from '../PanelBase'; import { createRef } from 'react'; - -Enzyme.configure({ adapter: new Adapter() }); +import { render } from '@testing-library/react'; +import "@testing-library/jest-dom"; +import userEvent from "@testing-library/user-event"; describe('PanelBase', () => { test('Panel', async () => { const panelName = 'details'; const rootRef = createRef(); let isCurrentlyExpanded = true; - const sampleProps: Partial = { + const sampleProps: PanelProps = { 'top': 113, 'left': 0, 'relativeLeft': 0, @@ -22,13 +21,13 @@ describe('PanelBase', () => { 'visible': true, 'detached': false, 'alignment': 'left', - 'onResize': () => {}, - 'onResizeStart': () => {}, - 'onResizeEnd': () => {}, - 'onPositionChange': () => {}, - 'onVisibilityChange': (name: string, isExpanded) => {isCurrentlyExpanded = isExpanded;}, - 'onPositionChangeBegin': () => {}, - 'onSnap': () => {}, + 'onResize': () => { }, + 'onResizeStart': () => { }, + 'onResizeEnd': () => { }, + 'onPositionChange': () => { }, + 'onVisibilityChange': (name: string, isExpanded) => { isCurrentlyExpanded = isExpanded; }, + 'onPositionChangeBegin': () => { }, + 'onSnap': () => { }, // eslint-disable-next-line // @ts-ignore 'root': rootRef, @@ -77,22 +76,21 @@ describe('PanelBase', () => { 'isDraftSaving': false, 'versions': '{draft: undefined, result: Array(0)}', 'resultSnapshot': '', - 'autosave': () => {}, + 'autosave': () => { }, }, }; const sampleContent = 'Sample Panel'; - const view = mount(
- { /* eslint-disable-next-line */ - /* @ts-ignore */ } + const view = render(<> {sampleContent} -
); + ); - expect(view.find('.dm-panel__title').text()).toBe(panelName); - expect(view.find('.dm-panel__body .dm-details').text()).toBe(sampleContent); + expect(view.getByText(panelName)).toBeInTheDocument(); + expect(view.getByText(sampleContent)).toBeInTheDocument(); expect(isCurrentlyExpanded).toBe(true); - view.find('.dm-panel__toggle').simulate('click'); + + await userEvent.click(view.getByTestId("panel-toggle-collapsed")); expect(isCurrentlyExpanded).toBe(false); }); }); diff --git a/src/tags/visual/__tests__/Header.test.jsx b/src/tags/visual/__tests__/Header.test.jsx index 687d52d679..76f19a0818 100644 --- a/src/tags/visual/__tests__/Header.test.jsx +++ b/src/tags/visual/__tests__/Header.test.jsx @@ -1,9 +1,7 @@ /* global test, expect, jest */ -import Enzyme, { render } from "enzyme"; -import Adapter from "@cfaester/enzyme-adapter-react-18"; +import { render } from "@testing-library/react"; import { HtxHeader } from "../Header"; - -Enzyme.configure({ adapter: new Adapter() }); +import "@testing-library/jest-dom"; jest.mock('react', () => ({ ...jest.requireActual('react'), @@ -18,7 +16,6 @@ test("Header basic test", () => { }; const view = render(); - const text = view.text(); - expect(text).toBe("header text"); + expect(view.getByText('header text')).toBeInTheDocument(); }); diff --git a/yarn.lock b/yarn.lock index a35b1e0eeb..dd96843039 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@adobe/css-tools@^4.0.1": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.1.tgz#abfccb8ca78075a2b6187345c26243c1a0842f28" + integrity sha512-/62yikz7NLScCGAAST5SHdnjaDJQBDq0M2muyRTpf2VQhw6StBg2ALiu73zSJQ4fMVLA+0uBhBHAle7Wg+2kSg== + "@ampproject/remapping@^2.1.0": version "2.1.2" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34" @@ -3119,27 +3124,47 @@ "@svgr/plugin-jsx" "8.0.1" "@svgr/plugin-svgo" "8.0.1" -"@testing-library/dom@^8.0.0": - version "8.20.0" - resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.20.0.tgz#914aa862cef0f5e89b98cc48e3445c4c921010f6" - integrity sha512-d9ULIT+a4EXLX3UU8FBjauG9NnsZHkHztXoIcTsOKoOw030fyjheN9svkTULjJxtYag9DZz5Jz5qkWZDPxTFwA== +"@testing-library/dom@^9.0.0": + version "9.3.1" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-9.3.1.tgz#8094f560e9389fb973fe957af41bf766937a9ee9" + integrity sha512-0DGPd9AR3+iDTjGoMpxIkAsUihHZ3Ai6CneU6bRRrffXMgzCdlNk43jTrD2/5LT6CBb3MWTP8v510JzYtahD2w== dependencies: "@babel/code-frame" "^7.10.4" "@babel/runtime" "^7.12.5" "@types/aria-query" "^5.0.1" - aria-query "^5.0.0" + aria-query "5.1.3" chalk "^4.1.0" dom-accessibility-api "^0.5.9" - lz-string "^1.4.4" + lz-string "^1.5.0" pretty-format "^27.0.2" -"@testing-library/react@12.1.2": - version "12.1.2" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.2.tgz#f1bc9a45943461fa2a598bb4597df1ae044cfc76" - integrity sha512-ihQiEOklNyHIpo2Y8FREkyD1QAea054U0MVbwH1m8N9TxeFz+KoJ9LkqoKqJlzx2JDm56DVwaJ1r36JYxZM05g== +"@testing-library/jest-dom@^6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.1.1.tgz#1a159b93f03f55ffc00adae86c6d412af39588b1" + integrity sha512-PEDx4fwesRjrUqhnqMz2+DxJtA0Qfy8IChXfx2P+f1mOI4ssc2b+fnzcmaevWPtfqFDE1q3veB9iJRFDw+xUVg== + dependencies: + "@adobe/css-tools" "^4.0.1" + "@babel/runtime" "^7.9.2" + aria-query "^5.0.0" + chalk "^3.0.0" + css.escape "^1.5.1" + dom-accessibility-api "^0.5.6" + lodash "^4.17.15" + redent "^3.0.0" + +"@testing-library/react@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-14.0.0.tgz#59030392a6792450b9ab8e67aea5f3cc18d6347c" + integrity sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg== dependencies: "@babel/runtime" "^7.12.5" - "@testing-library/dom" "^8.0.0" + "@testing-library/dom" "^9.0.0" + "@types/react-dom" "^18.0.0" + +"@testing-library/user-event@^14.4.3": + version "14.4.3" + resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.4.3.tgz#af975e367743fa91989cd666666aec31a8f50591" + integrity sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q== "@thi.ng/bitstream@^1.1.43": version "1.1.43" @@ -3468,7 +3493,7 @@ dependencies: "@types/react" "*" -"@types/react-dom@^18.2.7": +"@types/react-dom@^18.0.0", "@types/react-dom@^18.2.7": version "18.2.7" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.7.tgz#67222a08c0a6ae0a0da33c3532348277c70abb63" integrity sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA== @@ -4033,13 +4058,20 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -aria-query@^5.0.0: +aria-query@5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.1.3.tgz#19db27cd101152773631396f7a95a3b58c22c35e" integrity sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ== dependencies: deep-equal "^2.0.5" +aria-query@^5.0.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" + integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== + dependencies: + dequal "^2.0.3" + array-back@^1.0.2, array-back@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" @@ -4582,6 +4614,14 @@ chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -5110,6 +5150,11 @@ css-what@^6.1.0: resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== +css.escape@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== + css@^2.0.0: version "2.2.4" resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" @@ -5619,6 +5664,11 @@ depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" +dequal@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" @@ -5690,7 +5740,7 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dom-accessibility-api@^0.5.9: +dom-accessibility-api@^0.5.6, dom-accessibility-api@^0.5.9: version "0.5.16" resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== @@ -8268,7 +8318,7 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -lz-string@^1.4.4: +lz-string@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== @@ -8406,6 +8456,11 @@ min-document@^2.19.0: dependencies: dom-walk "^0.1.0" +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + mini-css-extract-plugin@*, mini-css-extract-plugin@^2.7.5: version "2.7.5" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.5.tgz#afbb344977659ec0f1f6e050c7aea456b121cfc5" @@ -10091,6 +10146,14 @@ rechoir@^0.8.0: dependencies: resolve "^1.20.0" +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + reduce-extract@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/reduce-extract/-/reduce-extract-1.0.0.tgz#67f2385beda65061b5f5f4312662e8b080ca1525" @@ -11011,6 +11074,13 @@ strip-final-newline@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" From 7e564f56f0883dc7a494c6e548995277dc74bc7b Mon Sep 17 00:00:00 2001 From: Nick Skriabin Date: Wed, 23 Aug 2023 17:59:31 +0100 Subject: [PATCH 04/14] Remove enzyme completely --- src/setupTests.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/setupTests.js b/src/setupTests.js index 67e322fcf0..a19c27a6cc 100644 --- a/src/setupTests.js +++ b/src/setupTests.js @@ -2,10 +2,6 @@ * Initializing Test Environment */ /* global jest, global */ - -import { configure } from 'enzyme'; -import Adapter from '@cfaester/enzyme-adapter-react-18'; - const localStorageMock = { getItem: jest.fn(), setItem: jest.fn(), @@ -15,4 +11,3 @@ const localStorageMock = { global.localStorage = localStorageMock; -configure({ adapter: new Adapter() }); From 3a0f4547afabdb042e25a342fa098dce1f7d6927 Mon Sep 17 00:00:00 2001 From: Sergey Date: Tue, 26 Sep 2023 16:14:49 +0100 Subject: [PATCH 05/14] Update libs and approach. Add testing flag. --- package.json | 6 +-- src/lib/AudioUltra/Visual/Visualizer.ts | 1 + src/regions/AudioRegion/AudioRegionModel.js | 7 ++++ .../AudioRegion/AudioUltraRegionModel.js | 7 ++++ src/tags/object/AudioNext/model.js | 4 +- src/tags/object/AudioUltra/model.js | 4 +- src/utils/reactCleaner.js | 8 ++++ tests/functional/package.json | 2 + yarn.lock | 39 +++++++++++-------- 9 files changed, 54 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index cbb0872d77..bd7e447f6c 100644 --- a/package.json +++ b/package.json @@ -167,9 +167,9 @@ "lodash.ismatch": "^4.4.0", "lodash.throttle": "^4.1.1", "mini-css-extract-plugin": "^2.7.5", - "mobx": "^5.15.4", - "mobx-react": "^6", - "mobx-state-tree": "^3.16.0", + "mobx": "6.10.2", + "mobx-react": "7", + "mobx-state-tree": "5.2.0", "nanoid": "^3.3.0", "node-fetch": "^2.6.1", "pleasejs": "^0.4.2", diff --git a/src/lib/AudioUltra/Visual/Visualizer.ts b/src/lib/AudioUltra/Visual/Visualizer.ts index 6544fbdf92..9ea7e3a32c 100644 --- a/src/lib/AudioUltra/Visual/Visualizer.ts +++ b/src/lib/AudioUltra/Visual/Visualizer.ts @@ -254,6 +254,7 @@ export class Visualizer extends Events { } clear() { + this.setLoading(false); this.layers.get('main')?.clear(); this.transferImage(); } diff --git a/src/regions/AudioRegion/AudioRegionModel.js b/src/regions/AudioRegion/AudioRegionModel.js index fadbc9215f..3bbd83a671 100644 --- a/src/regions/AudioRegion/AudioRegionModel.js +++ b/src/regions/AudioRegion/AudioRegionModel.js @@ -216,4 +216,11 @@ export const AudioRegionModel = types self._ws_region.element.style.display = self.hidden ? 'none' : 'block'; e?.stopPropagation(); }, + + clearWSRegion() { + self._ws_region = null; + }, + setWSRegion(wsRegion) { + self._ws_region = wsRegion; + }, })); diff --git a/src/regions/AudioRegion/AudioUltraRegionModel.js b/src/regions/AudioRegion/AudioUltraRegionModel.js index bbcff8bc24..c6768aaae2 100644 --- a/src/regions/AudioRegion/AudioUltraRegionModel.js +++ b/src/regions/AudioRegion/AudioUltraRegionModel.js @@ -144,5 +144,12 @@ export const AudioUltraRegionModel = types self.updatePosition(); } }, + + clearWSRegion() { + self._ws_region = null; + }, + setWSRegion(wsRegion) { + self._ws_region = wsRegion; + }, }; }); diff --git a/src/tags/object/AudioNext/model.js b/src/tags/object/AudioNext/model.js index a89062637f..8d2f6fcf9c 100644 --- a/src/tags/object/AudioNext/model.js +++ b/src/tags/object/AudioNext/model.js @@ -212,7 +212,7 @@ export const AudioModel = types.compose( states, }); - r._ws_region = wsRegion; + r.setWSRegion(wsRegion); self.regions.push(r); self.annotation.addRegion(r); @@ -288,7 +288,7 @@ export const AudioModel = types.compose( const r = self._ws.addRegion(region.wsRegionOptions); - region._ws_region = r; + region.setWSRegion(r); region.updateAppearenceFromState(); }, diff --git a/src/tags/object/AudioUltra/model.js b/src/tags/object/AudioUltra/model.js index b7681de10f..c1028d7288 100644 --- a/src/tags/object/AudioUltra/model.js +++ b/src/tags/object/AudioUltra/model.js @@ -443,7 +443,7 @@ export const AudioModel = types.compose( const r = self._ws.addRegion(options, false); - region._ws_region = r; + region.setWSRegion(r); }, updateWsRegion(region) { @@ -458,7 +458,7 @@ export const AudioModel = types.compose( clearRegionMappings() { self.regs.forEach(r => { - r._ws_region = null; + r.clearWSRegion?.(); }); }, diff --git a/src/utils/reactCleaner.js b/src/utils/reactCleaner.js index 26b6a03c6e..78ed7cc257 100644 --- a/src/utils/reactCleaner.js +++ b/src/utils/reactCleaner.js @@ -1,4 +1,7 @@ +const NO_CLEANING = true; + export function cutFibers(object) { + if (NO_CLEANING) return; const objects = [object]; let obj; @@ -29,6 +32,7 @@ export function cutFibers(object) { } export function findReactKey(node) { + if (NO_CLEANING) return; const keys = Object.keys(node); for (const key of keys) { @@ -42,6 +46,7 @@ export function findReactKey(node) { } export function cleanDomAfterReact(nodes, reactKey) { + if (NO_CLEANING) return; for (const node of nodes) { if (node.isConnected) return; // preventing processing svgs due to the problem with props, @@ -64,6 +69,7 @@ export function cleanDomAfterReact(nodes, reactKey) { const globalCache = new WeakMap(); function createCleaner() { + if (NO_CLEANING) return; let ref = null; return (node) => { @@ -84,6 +90,8 @@ function createCleaner() { } export function reactCleaner(object, key = 'default') { + if (NO_CLEANING) return; + return void 0; if (!globalCache.has(object)) { globalCache.set(object, new Map()); } diff --git a/tests/functional/package.json b/tests/functional/package.json index f720ba6fdf..2a5ce01582 100644 --- a/tests/functional/package.json +++ b/tests/functional/package.json @@ -9,6 +9,8 @@ "scripts": { "test": "cypress run --quiet --browser chrome", "test:ui": "cypress open", + "test:ui:e2e:chrome": "cypress open --browser chrome --e2e", + "test:ui:e2e:firefox": "cypress open --browser firefox --e2e", "test:with-coverage": "COLLECT_COVERAGE=true yarn test:parallel", "test:parallel": "cypress-parallel -r spec -b -m -s test -t ${CPU_NUMBER:=2} -d ./specs/", "test:reset": "rm -rf output && yarn run cvg:reset", diff --git a/yarn.lock b/yarn.lock index f121feecdf..d988fe3127 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8167,7 +8167,7 @@ loader-runner@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" -loader-utils@2.0.4, loader-utils@^1.1.0, loader-utils@^1.4.0, loader-utils@^2.0.0: +loader-utils@2.0.4, loader-utils@^1.4.0, loader-utils@^2.0.0, loader-utils@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== @@ -8486,23 +8486,27 @@ mkdirp@^1.0.4, mkdirp@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" -mobx-react-lite@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-2.2.2.tgz#87c217dc72b4e47b22493daf155daf3759f868a6" +mobx-react-lite@^3.4.0: + version "3.4.3" + resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-3.4.3.tgz#3a4c22c30bfaa8b1b2aa48d12b2ba811c0947ab7" + integrity sha512-NkJREyFTSUXR772Qaai51BnE1voWx56LOL80xG7qkZr6vo8vEaLF3sz1JNUVh+rxmUzxYaqOhfuxTfqUh0FXUg== -mobx-react@^6: - version "6.3.1" - resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-6.3.1.tgz#204f9756e42e19d91cb6598837063b7e7de87c52" +mobx-react@7: + version "7.6.0" + resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-7.6.0.tgz#ebf0456728a9bd2e5c24fdcf9b36e285a222a7d6" + integrity sha512-+HQUNuh7AoQ9ZnU6c4rvbiVVl+wEkb9WqYsVDzGLng+Dqj1XntHu79PvEWKtSMoMj67vFp/ZPXcElosuJO8ckA== dependencies: - mobx-react-lite "^2.2.0" + mobx-react-lite "^3.4.0" -mobx-state-tree@^3.16.0: - version "3.17.3" - resolved "https://registry.yarnpkg.com/mobx-state-tree/-/mobx-state-tree-3.17.3.tgz#e9c40dca17e7b72ad01270852a516145bf6b6c72" +mobx-state-tree@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/mobx-state-tree/-/mobx-state-tree-5.2.0.tgz#784fb22b7d2b1598c6b4fb8987d68d86eaf66d8b" + integrity sha512-TAKfMHEF9F59iAcLbD1Y9D8Kand4NoYM1h8Yv3Ol5la9X0I7T4Y/mhVN/oK/bi3g0v7dYy9wsoni2T66zCohGQ== -mobx@^5.15.4: - version "5.15.7" - resolved "https://registry.yarnpkg.com/mobx/-/mobx-5.15.7.tgz#b9a5f2b6251f5d96980d13c78e9b5d8d4ce22665" +mobx@6.10.2: + version "6.10.2" + resolved "https://registry.yarnpkg.com/mobx/-/mobx-6.10.2.tgz#96e123deef140750360ca9a5b02a8b91fbffd4d9" + integrity sha512-B1UGC3ieK3boCjnMEcZSwxqRDMdzX65H/8zOHbuTY8ZhvrIjTUoLRR2TP2bPqIgYRfb3+dUigu8yMZufNjn0LQ== moment@^2.24.0, moment@^2.25.3: version "2.29.4" @@ -9978,13 +9982,14 @@ react-dom@18.2.0: scheduler "^0.23.0" react-hot-loader@^4.13.0: - version "4.13.0" - resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.13.0.tgz#c27e9408581c2a678f5316e69c061b226dc6a202" + version "4.13.1" + resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.13.1.tgz#979fd7598e27338b3faffae6ed01c65374dace5e" + integrity sha512-ZlqCfVRqDJmMXTulUGic4lN7Ic1SXgHAFw7y/Jb7t25GBgTR0fYAJ8uY4mrpxjRyWGWmqw77qJQGnYbzCvBU7g== dependencies: fast-levenshtein "^2.0.6" global "^4.3.0" hoist-non-react-statics "^3.3.0" - loader-utils "^1.1.0" + loader-utils "^2.0.3" prop-types "^15.6.1" react-lifecycles-compat "^3.0.4" shallowequal "^1.1.0" From dae022d27afcd00493e10191a6377ccbf29069ac Mon Sep 17 00:00:00 2001 From: Sergey Date: Wed, 11 Oct 2023 14:29:41 +0100 Subject: [PATCH 06/14] Fix DateTime --- src/tags/control/DateTime.js | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/tags/control/DateTime.js b/src/tags/control/DateTime.js index 679639b36d..98314775df 100644 --- a/src/tags/control/DateTime.js +++ b/src/tags/control/DateTime.js @@ -363,29 +363,14 @@ const HtxDateTime = inject('store')( className: 'ant-input', }; const [minTime, maxTime] = [item.min, item.max].map(s => s?.match(/\d?\d:\d\d/)?.[0]); - const [dateInputValue, setDateInputValue] = useState(''); const handleDateInputValueChange = event => { const value = event.target.value; const validDateArray = item.validDateFormat(value); - setDateInputValue(value); if (!value || validDateArray) item.setDate(validDateArray); }; - if (item.updateValue) { - if (item.showDate && (item.date === undefined || item.date !== dateInputValue)) { - setDateInputValue(item.date || ''); - } - item.setNeedsUpdate(false); - } - - const handleDateOnBlur = () => { - const dateWasNotSaved = dateInputValue !== item.date; - - if (dateWasNotSaved) setDateInputValue(item.date || ''); - }; - return (
{item.showMonth && ( @@ -426,11 +411,10 @@ const HtxDateTime = inject('store')( type="date" readOnly={disabled} name={item.name + '-date'} - value={dateInputValue} + value={item.date ?? ''} min={item.min} max={item.max} onChange={disabled ? undefined : handleDateInputValueChange} - onBlur={disabled ? undefined : handleDateOnBlur} /> )} {item.showTime && ( From 12c3434f90f3694d40c32427a31086d994e32f86 Mon Sep 17 00:00:00 2001 From: Sergey Date: Wed, 11 Oct 2023 14:30:52 +0100 Subject: [PATCH 07/14] Fix actions --- src/regions/ParagraphsRegion.js | 5 +++++ src/regions/RichTextRegion.js | 5 +++++ src/tags/object/AudioNext/model.js | 4 ++-- src/tags/object/AudioUltra/model.js | 6 +++--- src/tags/object/Paragraphs/HtxParagraphs.js | 2 +- src/tags/object/Paragraphs/model.js | 6 +++--- src/tags/object/RichText/model.js | 2 +- 7 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/regions/ParagraphsRegion.js b/src/regions/ParagraphsRegion.js index ce2c020026..66608af291 100644 --- a/src/regions/ParagraphsRegion.js +++ b/src/regions/ParagraphsRegion.js @@ -27,6 +27,7 @@ const Model = types .volatile(() => ({ text: '', hideable: true, + _range: null, })) .views(self => ({ get parent() { @@ -45,6 +46,10 @@ const Model = types self.text = text; }, + setRange(range) { + self._range = range; + }, + fixOffsets(startOffset, endOffset) { self.startOffset = startOffset; self.endOffset = endOffset; diff --git a/src/regions/RichTextRegion.js b/src/regions/RichTextRegion.js index 9ea34353b8..436f7c7524 100644 --- a/src/regions/RichTextRegion.js +++ b/src/regions/RichTextRegion.js @@ -40,6 +40,7 @@ const Model = types .volatile(() => ({ hideable: true, cachedRange: null, + _range: null, })) .views(self => ({ get parent() { @@ -61,6 +62,10 @@ const Model = types } }, + setRange(range) { + self._range = range; + }, + serialize() { const res = { value: {}, diff --git a/src/tags/object/AudioNext/model.js b/src/tags/object/AudioNext/model.js index 8d2f6fcf9c..ef118a0cc0 100644 --- a/src/tags/object/AudioNext/model.js +++ b/src/tags/object/AudioNext/model.js @@ -240,7 +240,7 @@ export const AudioModel = types.compose( if (find_r) { find_r.applyCSSClass(wsRegion); - find_r._ws_region = wsRegion; + find_r.setWSRegion(wsRegion); return find_r; } @@ -255,7 +255,7 @@ export const AudioModel = types.compose( const labels = { [control.valueType]: control.selectedValues() }; const r = self.annotation.createResult(wsRegion, labels, control, self); - r._ws_region = wsRegion; + r.setWSRegion(wsRegion); r.updateAppearenceFromState(); return r; }, diff --git a/src/tags/object/AudioUltra/model.js b/src/tags/object/AudioUltra/model.js index c1028d7288..34272f6ccc 100644 --- a/src/tags/object/AudioUltra/model.js +++ b/src/tags/object/AudioUltra/model.js @@ -385,7 +385,7 @@ export const AudioModel = types.compose( states, }); - r._ws_region = wsRegion; + r.setWSRegion(wsRegion); self.regions.push(r); self.annotation.addRegion(r); @@ -399,7 +399,7 @@ export const AudioModel = types.compose( if (find_r) { - find_r._ws_region = wsRegion; + find_r.setWSRegion(wsRegion); find_r.updateColor(); return find_r; } @@ -420,7 +420,7 @@ export const AudioModel = types.compose( const r = self.annotation.createResult(wsRegion, labels, control, self); const updatedRegion = wsRegion.convertToRegion(labels.labels); - r._ws_region = updatedRegion; + r.setWSRegion(updatedRegion); r.updateColor(); return r; }, diff --git a/src/tags/object/Paragraphs/HtxParagraphs.js b/src/tags/object/Paragraphs/HtxParagraphs.js index 9d884dfc51..d89ca33ff3 100644 --- a/src/tags/object/Paragraphs/HtxParagraphs.js +++ b/src/tags/object/Paragraphs/HtxParagraphs.js @@ -400,7 +400,7 @@ class HtxParagraphsView extends Component { splitBoundaries(range); - r._range = range; + r.setRange(range); const spans = r.createSpans(); r.addEventsToSpans(spans); diff --git a/src/tags/object/Paragraphs/model.js b/src/tags/object/Paragraphs/model.js index 627550db36..d3bcee5426 100644 --- a/src/tags/object/Paragraphs/model.js +++ b/src/tags/object/Paragraphs/model.js @@ -480,7 +480,7 @@ const ParagraphsLoadingModel = types.model() ...p, }); - r._range = p._range; + r.setRange(p._range); self.regions.push(r); self.annotation.addRegion(r); @@ -508,7 +508,7 @@ const ParagraphsLoadingModel = types.model() area.notifyDrawingFinished(); - area._range = range._range; + area.setRange(range._range); areas.push(area); } return areas; @@ -534,7 +534,7 @@ const ParagraphsLoadingModel = types.model() area.notifyDrawingFinished(); - area._range = range._range; + area.setRange(range._range); return area; } }, diff --git a/src/tags/object/RichText/model.js b/src/tags/object/RichText/model.js index 4706720612..5907b4c1b2 100644 --- a/src/tags/object/RichText/model.js +++ b/src/tags/object/RichText/model.js @@ -376,7 +376,7 @@ const Model = types destroyNode(state); }); - area._range = range._range; + area.setRange(range._range); const [soff, eoff] = rangeToGlobalOffset(range._range, root); From 16fbd9364bd14a934a1fd601d43b96dc9bebcdee Mon Sep 17 00:00:00 2001 From: Sergey Date: Wed, 11 Oct 2023 14:47:14 +0100 Subject: [PATCH 08/14] Fix eslint problems --- src/LabelStudio.js | 6 +++--- .../AnnotationsCarousel/__tests__/AnnotationButton.test.tsx | 4 ++-- .../__tests__/AnnotationsCarousel.test.tsx | 4 ++-- src/components/SidePanels/__tests__/PanelBase.test.tsx | 6 +++--- src/tags/control/DateTime.js | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/LabelStudio.js b/src/LabelStudio.js index 5a815699dc..c6ae970d68 100644 --- a/src/LabelStudio.js +++ b/src/LabelStudio.js @@ -78,8 +78,8 @@ export class LabelStudio { store={this.store} panels={registerPanels(this.options.panels) ?? []} /> - - ) + , + ); }; const PERFORM_REACT_CLEANUP = true; @@ -108,7 +108,7 @@ export class LabelStudio { cleanDomAfterReact(childNodes, reactKey); cleanDomAfterReact([rootElement], reactKey); } - } + }; const unmountApp = () => { cleanupReactNodes(() => { diff --git a/src/components/AnnotationsCarousel/__tests__/AnnotationButton.test.tsx b/src/components/AnnotationsCarousel/__tests__/AnnotationButton.test.tsx index 7836f0d753..2495ef50a1 100644 --- a/src/components/AnnotationsCarousel/__tests__/AnnotationButton.test.tsx +++ b/src/components/AnnotationsCarousel/__tests__/AnnotationButton.test.tsx @@ -1,10 +1,10 @@ /* global test, expect, jest, describe */ -import { render } from "@testing-library/react"; +import { render } from '@testing-library/react'; import { AnnotationButton } from '../AnnotationButton'; // eslint-disable-next-line // @ts-ignore import { annotationStore } from './sampleData.js'; -import "@testing-library/jest-dom"; +import '@testing-library/jest-dom'; jest.mock('react', () => ({ ...jest.requireActual('react'), diff --git a/src/components/AnnotationsCarousel/__tests__/AnnotationsCarousel.test.tsx b/src/components/AnnotationsCarousel/__tests__/AnnotationsCarousel.test.tsx index 80332d902a..e44f793bbc 100644 --- a/src/components/AnnotationsCarousel/__tests__/AnnotationsCarousel.test.tsx +++ b/src/components/AnnotationsCarousel/__tests__/AnnotationsCarousel.test.tsx @@ -1,6 +1,6 @@ /* global test, expect, jest */ import React from 'react'; -import { render } from "@testing-library/react"; +import { render } from '@testing-library/react'; import { AnnotationsCarousel } from '../AnnotationsCarousel'; // eslint-disable-next-line // @ts-ignore @@ -16,7 +16,7 @@ test('AnnotationsCarousel', async () => { + />, ); const carouselItems = view.container.querySelectorAll('.dm-annotations-carousel__carosel > *'); diff --git a/src/components/SidePanels/__tests__/PanelBase.test.tsx b/src/components/SidePanels/__tests__/PanelBase.test.tsx index 9e026d3f18..fca4bc4383 100644 --- a/src/components/SidePanels/__tests__/PanelBase.test.tsx +++ b/src/components/SidePanels/__tests__/PanelBase.test.tsx @@ -2,8 +2,8 @@ import { PanelBase, PanelProps } from '../PanelBase'; import { createRef } from 'react'; import { render } from '@testing-library/react'; -import "@testing-library/jest-dom"; -import userEvent from "@testing-library/user-event"; +import '@testing-library/jest-dom'; +import userEvent from '@testing-library/user-event'; describe('PanelBase', () => { test('Panel', async () => { @@ -90,7 +90,7 @@ describe('PanelBase', () => { expect(view.getByText(sampleContent)).toBeInTheDocument(); expect(isCurrentlyExpanded).toBe(true); - await userEvent.click(view.getByTestId("panel-toggle-collapsed")); + await userEvent.click(view.getByTestId('panel-toggle-collapsed')); expect(isCurrentlyExpanded).toBe(false); }); }); diff --git a/src/tags/control/DateTime.js b/src/tags/control/DateTime.js index 98314775df..d29f44e98f 100644 --- a/src/tags/control/DateTime.js +++ b/src/tags/control/DateTime.js @@ -1,5 +1,5 @@ import * as d3 from 'd3'; -import React, { useState } from 'react'; +import React from 'react'; import { inject, observer } from 'mobx-react'; import { types } from 'mobx-state-tree'; From ebe3ffa4bfd973ce3b15f8301511d8c0db03aaff Mon Sep 17 00:00:00 2001 From: Sergey Date: Wed, 11 Oct 2023 15:35:26 +0100 Subject: [PATCH 09/14] Fix DateTime --- src/tags/control/DateTime.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/tags/control/DateTime.js b/src/tags/control/DateTime.js index d29f44e98f..94c6491939 100644 --- a/src/tags/control/DateTime.js +++ b/src/tags/control/DateTime.js @@ -1,5 +1,5 @@ import * as d3 from 'd3'; -import React from 'react'; +import React, { useState } from 'react'; import { inject, observer } from 'mobx-react'; import { types } from 'mobx-state-tree'; @@ -363,14 +363,29 @@ const HtxDateTime = inject('store')( className: 'ant-input', }; const [minTime, maxTime] = [item.min, item.max].map(s => s?.match(/\d?\d:\d\d/)?.[0]); + const [dateInputValue, setDateInputValue] = useState(''); const handleDateInputValueChange = event => { const value = event.target.value; const validDateArray = item.validDateFormat(value); + setDateInputValue(value); if (!value || validDateArray) item.setDate(validDateArray); }; + if (item.updateValue) { + if (item.showDate && (item.date === undefined || item.date !== dateInputValue)) { + setDateInputValue(item.date || ''); + } + item.setNeedsUpdate(false); + } + + const handleDateOnBlur = () => { + const dateWasNotSaved = dateInputValue !== item.date; + + if (dateWasNotSaved) setDateInputValue(item.date || ''); + }; + return (
{item.showMonth && ( @@ -411,10 +426,11 @@ const HtxDateTime = inject('store')( type="date" readOnly={disabled} name={item.name + '-date'} - value={item.date ?? ''} + value={dateInputValue || item.date || ''} min={item.min} max={item.max} onChange={disabled ? undefined : handleDateInputValueChange} + onBlur={disabled ? undefined : handleDateOnBlur} /> )} {item.showTime && ( From f30f81106193c432bafee77880966ad5f4c03898 Mon Sep 17 00:00:00 2001 From: Sergey Date: Wed, 11 Oct 2023 16:04:22 +0100 Subject: [PATCH 10/14] Fix Timeseries --- src/regions/TimeSeriesRegion.js | 5 ++++ src/tags/object/TimeSeries.js | 41 ++++++++++++++------------- src/tags/object/TimeSeries/Channel.js | 2 +- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/regions/TimeSeriesRegion.js b/src/regions/TimeSeriesRegion.js index 524a1b8a9b..b78859a582 100644 --- a/src/regions/TimeSeriesRegion.js +++ b/src/regions/TimeSeriesRegion.js @@ -25,6 +25,7 @@ const Model = types }) .volatile(() => ({ hideable: true, + _brushRef: undefined, })) .views(self => ({ get parent() { @@ -44,6 +45,10 @@ const Model = types })) .actions(self => ({ + setBrushRef(brushRef) { + self._brushRef = brushRef; + }, + growRight(size) { self.end = self.end + size; }, diff --git a/src/tags/object/TimeSeries.js b/src/tags/object/TimeSeries.js index c733dd933f..350c344879 100644 --- a/src/tags/object/TimeSeries.js +++ b/src/tags/object/TimeSeries.js @@ -105,6 +105,7 @@ const Model = types zoomedRange: 0, scale: 1, headers: [], + slices: null, })) .views(self => ({ get regionsTimeRanges() { @@ -259,7 +260,7 @@ const Model = types slices[i] = data.slice(slice * i, slice * i + slice + 1); } slices.push(data.slice(slice * (count - 1))); - self.slices = slices; + self.setSlices(slices); return slices; }, @@ -280,6 +281,21 @@ const Model = types }; }, + get _format() { + const { timedisplayformat: format, isDate } = self; + + if (format === 'date') return formatTrackerTime; + else if (format) return isDate ? d3.utcFormat(format) : d3.format(format); + else return String; + }, + + get _formatDuration() { + const { durationdisplayformat: format, isDate } = self; + + if (format) return isDate ? d3.utcFormat(format) : d3.format(format); + else return String; + }, + states() { return self.annotation.toNames.get(self.name); }, @@ -291,23 +307,10 @@ const Model = types }, formatTime(time) { - if (!self._format) { - const { timedisplayformat: format, isDate } = self; - - if (format === 'date') self._format = formatTrackerTime; - else if (format) self._format = isDate ? d3.utcFormat(format) : d3.format(format); - else self._format = String; - } return self._format(time); }, formatDuration(duration) { - if (!self._formatDuration) { - const { durationdisplayformat: format, isDate } = self; - - if (format) self._formatDuration = isDate ? d3.utcFormat(format) : d3.format(format); - else self._formatDuration = String; - } return self._formatDuration(duration); }, @@ -331,6 +334,10 @@ const Model = types self.scale = scale; }, + setSlices(slices) { + self.slices = slices; + }, + updateView() { self._needsUpdate = self._needsUpdate + 1; }, @@ -801,12 +808,6 @@ const Overview = observer(({ item, data, series }) => { const HtxTimeSeriesViewRTS = ({ item }) => { const ref = React.createRef(); - React.useEffect(() => { - if (item?.brushRange?.length) { - item._nodeReference = ref.current; - } - }, [item, ref]); - // the last thing updated during initialisation if (!item?.brushRange?.length || !item.data) return ( diff --git a/src/tags/object/TimeSeries/Channel.js b/src/tags/object/TimeSeries/Channel.js index d04803a3e0..f9b7106d09 100644 --- a/src/tags/object/TimeSeries/Channel.js +++ b/src/tags/object/TimeSeries/Channel.js @@ -308,7 +308,7 @@ class ChannelD3 extends React.Component { } if (r._brushRef === undefined || !r._brushRef.isConnected) { - r._brushRef = group.select('.selection').node(); + r.setBrushRef(group.select('.selection').node()); } }) .merge(brushSelection) From a08ca1ceef786158db857edad2895a62af965853 Mon Sep 17 00:00:00 2001 From: Sergey Date: Wed, 11 Oct 2023 16:17:45 +0100 Subject: [PATCH 11/14] Fix Paragraphs --- src/mixins/SpanText.js | 2 +- src/tags/object/Paragraphs/HtxParagraphs.js | 2 +- src/tags/object/Paragraphs/model.js | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/mixins/SpanText.js b/src/mixins/SpanText.js index f079858df2..869d0f5e4e 100644 --- a/src/mixins/SpanText.js +++ b/src/mixins/SpanText.js @@ -100,7 +100,7 @@ export default types // skip it to allow another span to be selected if (self.parent._currentSpan !== this) { ev.stopPropagation(); - self.parent._currentSpan = this; + self.parent.setCurrentSpan(this); } }; diff --git a/src/tags/object/Paragraphs/HtxParagraphs.js b/src/tags/object/Paragraphs/HtxParagraphs.js index d89ca33ff3..333435ac38 100644 --- a/src/tags/object/Paragraphs/HtxParagraphs.js +++ b/src/tags/object/Paragraphs/HtxParagraphs.js @@ -305,7 +305,7 @@ class HtxParagraphsView extends Component { return; } - item._currentSpan = null; + item.setCurrentSpan(null); if (isFF(FF_DEV_2918)) { const htxRanges = item.addRegions(selectedRanges); diff --git a/src/tags/object/Paragraphs/model.js b/src/tags/object/Paragraphs/model.js index d3bcee5426..58b19a6dde 100644 --- a/src/tags/object/Paragraphs/model.js +++ b/src/tags/object/Paragraphs/model.js @@ -155,6 +155,11 @@ const Model = types return !self.filterByAuthor.length || self.filterByAuthor.includes(data[self.namekey]); }, + })) + .actions(self => ({ + setCurrentSpan(currentSpan) { + self._currentSpan = currentSpan; + }, })); const PlayableAndSyncable = types.model() From e6cd7a9d9b201cadc3990393ba82cb7522e55f5c Mon Sep 17 00:00:00 2001 From: Sergey Date: Wed, 11 Oct 2023 16:51:27 +0100 Subject: [PATCH 12/14] Fix removeChild --- src/lib/AudioUltra/Visual/Visualizer.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/AudioUltra/Visual/Visualizer.ts b/src/lib/AudioUltra/Visual/Visualizer.ts index 9ea7e3a32c..8e20e370e7 100644 --- a/src/lib/AudioUltra/Visual/Visualizer.ts +++ b/src/lib/AudioUltra/Visual/Visualizer.ts @@ -138,7 +138,9 @@ export class Visualizer extends Events { this._loader = document.createElement('loading-progress-bar'); this._container.appendChild(this._loader); } else { - this._container.removeChild(this._loader); + if (this._loader.parentNode === this._container) { + this._container.removeChild(this._loader); + } } } From 541a270dd51e0714a0b9a6312beb41dd9e0e30cb Mon Sep 17 00:00:00 2001 From: Sergey Date: Thu, 12 Oct 2023 01:31:34 +0100 Subject: [PATCH 13/14] Fix annotation button test --- e2e/tests/regression-tests/annotation-button.test.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/e2e/tests/regression-tests/annotation-button.test.js b/e2e/tests/regression-tests/annotation-button.test.js index 94ed468e84..844e7ddf7f 100644 --- a/e2e/tests/regression-tests/annotation-button.test.js +++ b/e2e/tests/regression-tests/annotation-button.test.js @@ -27,7 +27,9 @@ Scenario('Annotation button should keep border width on hover', async ({ I, Labe ], }); - const borderWidth = await I.executeScript(()=>{ + LabelStudio.waitForObjectsReady(); + I.seeElement('.lsf-annotation-button:nth-child(2)'); + const borderWidth = await I.executeScript(() => { const el = document.querySelector('.lsf-annotation-button:nth-child(2)'); const borderWidth = window.getComputedStyle(el).getPropertyValue('border-width'); @@ -36,7 +38,7 @@ Scenario('Annotation button should keep border width on hover', async ({ I, Labe I.moveCursorTo('.lsf-annotation-button:nth-child(2)'); - const borderWidthHovered = await I.executeScript(()=>{ + const borderWidthHovered = await I.executeScript(() => { const el = document.querySelector('.lsf-annotation-button:nth-child(2)'); const borderWidth = window.getComputedStyle(el).getPropertyValue('border-width'); @@ -48,4 +50,4 @@ Scenario('Annotation button should keep border width on hover', async ({ I, Labe borderWidthHovered, 'Annotation button\'s border width should not change on hover', ); -}); \ No newline at end of file +}); From 2b7557a4b018be54169db464c6b73122a61ce578 Mon Sep 17 00:00:00 2001 From: Sergey Date: Thu, 12 Oct 2023 15:00:17 +0100 Subject: [PATCH 14/14] Update ls-test --- tests/functional/package.json | 2 +- tests/functional/yarn.lock | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/tests/functional/package.json b/tests/functional/package.json index 35d1313997..cd0fe90fcb 100644 --- a/tests/functional/package.json +++ b/tests/functional/package.json @@ -20,7 +20,7 @@ "cvg:summary": "nyc report --temp-dir=.nyc_output --reporter=text-summary --cwd=. --exclude-after-remap false" }, "dependencies": { - "@heartexlabs/ls-test": "git+ssh://git@github.com/heartexlabs/ls-frontend-test#b4c8edbe8f15ac1d6ad0d8bb7bd9aede14dc8e06" + "@heartexlabs/ls-test": "git+ssh://git@github.com/heartexlabs/ls-frontend-test#2e91f442891def184597e3beb85660b0f964602a" }, "devDependencies": { "ts-loader": "^9.4.2", diff --git a/tests/functional/yarn.lock b/tests/functional/yarn.lock index fb7f5ce193..6f56431f59 100644 --- a/tests/functional/yarn.lock +++ b/tests/functional/yarn.lock @@ -264,6 +264,28 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== +"@heartexlabs/ls-test@git+ssh://git@github.com/heartexlabs/ls-frontend-test#2e91f442891def184597e3beb85660b0f964602a": + version "1.0.8" + resolved "git+ssh://git@github.com/heartexlabs/ls-frontend-test#2e91f442891def184597e3beb85660b0f964602a" + dependencies: + "@cypress/code-coverage" "^3.10.0" + "@cypress/webpack-preprocessor" "^5.17.0" + chai "^4.3.7" + cypress "12.17.4" + cypress-image-snapshot "^4.0.1" + cypress-multi-reporters "^1.6.2" + cypress-parallel "^0.12.0" + cypress-plugin-snapshots "^1.4.4" + cypress-terminal-report "^5.1.1" + pixelmatch "^5.3.0" + pngjs "^7.0.0" + proper-lockfile "^4.1.2" + ts-loader "^9.4.2" + typescript "^4.9.5" + webpack "^5.77.0" + webpack-cli "^5.0.1" + yargs "^17.7.1" + "@heartexlabs/ls-test@git+ssh://git@github.com/heartexlabs/ls-frontend-test#b4c8edbe8f15ac1d6ad0d8bb7bd9aede14dc8e06": version "1.0.8" resolved "git+ssh://git@github.com/heartexlabs/ls-frontend-test#b4c8edbe8f15ac1d6ad0d8bb7bd9aede14dc8e06"