From e090eca7f016e4879bf99015c4753195c5e824b2 Mon Sep 17 00:00:00 2001
From: Pavel Vostretsov
Date: Tue, 16 Jan 2024 15:23:24 +0500
Subject: [PATCH] use @skbkontur/react-selenium-testing package
---
db-viewer-ui/index.tsx | 4 +-
db-viewer-ui/package.json | 1 +
db-viewer-ui/react-selenium-prep.ts | 30 +
db-viewer-ui/react-selenium-testing.js | 558 ------------------
.../DateTimeRangePicker/TimePicker.tsx | 1 -
db-viewer-ui/vite.config.ts | 2 +-
db-viewer-ui/yarn.lock | 38 ++
7 files changed, 73 insertions(+), 561 deletions(-)
create mode 100644 db-viewer-ui/react-selenium-prep.ts
delete mode 100644 db-viewer-ui/react-selenium-testing.js
diff --git a/db-viewer-ui/index.tsx b/db-viewer-ui/index.tsx
index b0de0439..ce1edeab 100644
--- a/db-viewer-ui/index.tsx
+++ b/db-viewer-ui/index.tsx
@@ -1,4 +1,6 @@
-import "./react-selenium-testing";
+import "./react-selenium-prep";
+import "@skbkontur/react-selenium-testing";
+
import React from "react";
import ReactDom from "react-dom";
import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
diff --git a/db-viewer-ui/package.json b/db-viewer-ui/package.json
index 42518ec6..1aeb463f 100644
--- a/db-viewer-ui/package.json
+++ b/db-viewer-ui/package.json
@@ -56,6 +56,7 @@
},
"devDependencies": {
"@skbkontur/icons": "^1.3.0",
+ "@skbkontur/react-selenium-testing": "^0.2.1",
"@skbkontur/react-ui": "^4.1.0",
"@storybook/addon-actions": "^7.0.7",
"@storybook/addons": "^7.0.7",
diff --git a/db-viewer-ui/react-selenium-prep.ts b/db-viewer-ui/react-selenium-prep.ts
new file mode 100644
index 00000000..186a0947
--- /dev/null
+++ b/db-viewer-ui/react-selenium-prep.ts
@@ -0,0 +1,30 @@
+import type { ReactSeleniumTestingType } from "@skbkontur/react-selenium-testing";
+
+const customization: ReactSeleniumTestingType = {
+ attributeWhiteList: {
+ error: [/.*/],
+ warning: [/.*/],
+ disabled: [/.*/],
+ "data-page-number": [/.*/],
+ disablePortal: ["ComboBoxRenderer"],
+ checked: [/.*/],
+ items: ["RadioGroup"],
+ value: [/Input|Textarea|RadioGroup|FilteredInput/],
+ activePage: ["Paging"],
+ pagesCount: ["Paging"],
+ trigger: [/Tooltip|ValidationTooltip|ValidationWrapper|ValidationWrapperV1/],
+ active: [/.*/],
+ className: [/.*/],
+ "data-active": [/.*/],
+ },
+ acceptAttribute: (prevAcceptResult, componentName, propName) => {
+ if (componentName === "Select" && propName === "items") {
+ return true;
+ }
+ return prevAcceptResult;
+ },
+};
+
+window.global ||= window;
+
+global.ReactSeleniumTesting = customization;
diff --git a/db-viewer-ui/react-selenium-testing.js b/db-viewer-ui/react-selenium-testing.js
deleted file mode 100644
index 2a48bb9e..00000000
--- a/db-viewer-ui/react-selenium-testing.js
+++ /dev/null
@@ -1,558 +0,0 @@
-let customAcceptAttribute = prevResult => prevResult;
-let attributeWhiteList = null;
-
-// Inlined from ReactTypeOfSideEffect
-const PerformedWork = 1;
-
-if (typeof ReactSeleniumTesting !== 'undefined') {
- if (
- ReactSeleniumTesting &&
- ReactSeleniumTesting.acceptAttribute &&
- typeof ReactSeleniumTesting.acceptAttribute === 'function'
- ) {
- customAcceptAttribute = ReactSeleniumTesting.acceptAttribute;
- }
-
- if (
- ReactSeleniumTesting &&
- ReactSeleniumTesting.attributeWhiteList &&
- typeof ReactSeleniumTesting.attributeWhiteList === 'object'
- ) {
- attributeWhiteList = ReactSeleniumTesting.attributeWhiteList;
- }
-}
-
-function extendStaticObject(base, overrides) {
- const oldBase = Object.assign({}, base);
- for (const overrideKey of Object.keys(overrides)) {
- base[overrideKey] = overrides[overrideKey](oldBase);
- }
-}
-
-function injectReactDevToolsHook(injectModule, injectFiberHanlers) {
- if (!global.__REACT_DEVTOOLS_GLOBAL_HOOK__) {
- global.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {
- inject: () => {},
- supportsFiber: true,
- onCommitFiberRoot: () => {},
- };
- }
- const oldInject = global.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject;
- global.__REACT_DEVTOOLS_GLOBAL_HOOK__.inject = x => {
- const ReactMount = x.Mount;
- if (oldInject) {
- var id = oldInject.call(global.__REACT_DEVTOOLS_GLOBAL_HOOK__, x);
- }
- injectModule(x);
- // Return id for React Dev Tools
- return id;
- };
- injectFiberHanlers(global.__REACT_DEVTOOLS_GLOBAL_HOOK__);
-}
-
-if (process.env.enableReactTesting) {
- global.ReactTesting = {
- addRenderContainer: () => {},
- removeRenderContainer: () => {},
- };
- injectReactDevToolsHook(exposeReactInternalsIntoDomHook, injectFiberHanlers);
-}
-
-// ====================================================
-// ==================== COMMON =========================
-// ====================================================
-
-function appendToSet(attrContainer, name, value) {
- if (value === null) return;
- const attributeStringValue = attrContainer[name];
- const set = (attributeStringValue || '').split(' ').filter(x => x !== '');
- if (!set.includes(value)) {
- attrContainer[name] = (attributeStringValue ? attributeStringValue + ' ' : '') + value;
- }
-}
-
-function acceptProp(componentName, propName, propValue) {
- let result =
- !propName.startsWith('$$') &&
- !propName.startsWith('on') &&
- propName !== 'children' &&
- propName !== 'data-tid' &&
- typeof propValue !== 'function';
- if (!result) {
- return false;
- }
- if (attributeWhiteList != null) {
- if (attributeWhiteList[propName] == null) {
- result = false;
- } else {
- if (
- !attributeWhiteList[propName].every(componentNamePattern => acceptPattern(componentNamePattern, componentName))
- ) {
- result = false;
- }
- }
- }
- if (customAcceptAttribute != null) {
- result = customAcceptAttribute(result, componentName, propName);
- }
- return result;
-}
-
-function acceptPattern(pattern, value) {
- if (pattern == null) {
- return false;
- }
- if (typeof pattern === 'string') {
- return value === pattern;
- }
- if (typeof pattern.test === 'function') {
- return pattern.test(value);
- }
- return false;
-}
-
-function stringifySafe(value) {
- if (typeof value === 'string') {
- return value;
- }
- if (value === undefined || value === null) {
- return '';
- }
- try {
- return JSON.stringify(value);
- } catch (e) {
- try {
- if (Array.isArray(value) && value.length > 0 && Array.isArray(value[0])) {
- return JSON.stringify(value.map(x => x[0]));
- }
- } catch (e) {
- return '';
- }
- return '';
- }
-}
-
-// ====================================================
-// ==================== FIBER =========================
-// ====================================================
-
-const ReactWorkTypes = {
- FunctionComponent: 'FunctionComponent',
- ClassComponent: 'ClassComponent',
- HostPortal: 'HostPortal',
- HostComponent: 'HostComponent',
- Fragment: 'Fragment',
- ContextConsumer: 'ContextConsumer',
- ContextProvider: 'ContextProvider',
-};
-
-const WorkTagsByReactVersion = {
- ['<16.5']: {
- [ReactWorkTypes.FunctionComponent]: 1,
- [ReactWorkTypes.ClassComponent]: 2,
- [ReactWorkTypes.HostPortal]: 4,
- [ReactWorkTypes.HostComponent]: 5,
- [ReactWorkTypes.Fragment]: 10,
- [ReactWorkTypes.ContextConsumer]: 12,
- [ReactWorkTypes.ContextProvider]: 13,
- },
- ['>=16.5 <16.6']: {
- [ReactWorkTypes.FunctionComponent]: 0,
- [ReactWorkTypes.ClassComponent]: 2,
- [ReactWorkTypes.HostPortal]: 6,
- [ReactWorkTypes.HostComponent]: 7,
- [ReactWorkTypes.Fragment]: 9,
- [ReactWorkTypes.ContextConsumer]: 11,
- [ReactWorkTypes.ContextProvider]: 12,
- },
- ['>=16.6']: {
- [ReactWorkTypes.FunctionComponent]: 0,
- [ReactWorkTypes.ClassComponent]: 1,
- [ReactWorkTypes.HostPortal]: 4,
- [ReactWorkTypes.HostComponent]: 5,
- [ReactWorkTypes.Fragment]: 7,
- [ReactWorkTypes.ContextConsumer]: 9,
- [ReactWorkTypes.ContextProvider]: 10,
- },
-};
-
-function isFiberNodeOfType(node, type) {
- if (!node) return false;
- const reactVersion = node.hasOwnProperty('elementType')
- ? '>=16.6'
- : node.hasOwnProperty('firstContextDependency')
- ? '>=16.5 <16.6'
- : '<16.5';
- const ReactWorkTags = WorkTagsByReactVersion[reactVersion];
- const tag = ReactWorkTags ? ReactWorkTags[type] : null;
- return node.tag === tag;
-}
-function injectFiberHanlers(hook) {
- extendStaticObject(hook, {
- onCommitFiberRoot: base => (...args) => {
- handleCommitFiberRoot(...args);
- if (base.onCommitFiberRoot) {
- base.onCommitFiberRoot(...args);
- }
- },
- });
-}
-
-function handleCommitFiberRoot(rendererID, root) {
- const current = root.current;
- const alternate = current.alternate;
- if (alternate) {
- const wasMounted = alternate.memoizedState != null && alternate.memoizedState.element != null;
- const isMounted = current.memoizedState != null && current.memoizedState.element != null;
- if (!wasMounted && isMounted) {
- handleMountFiber(current);
- } else if (wasMounted && isMounted) {
- handleUpdateFiber(current, alternate);
- } else if (wasMounted && !isMounted) {
- // Skip unmounting
- }
- } else {
- handleMountFiber(current);
- }
-}
-
-function handleUpdateFiber(nextFiber, prevFiber) {
- let hasChildOrderChanged = false;
- if (nextFiber.child !== prevFiber.child) {
- let nextChild = nextFiber.child;
- let prevChildAtSameIndex = prevFiber.child;
- while (nextChild) {
- if (nextChild.alternate) {
- const prevChild = nextChild.alternate;
- handleUpdateFiber(nextChild, prevChild);
- if (!hasChildOrderChanged && prevChild !== prevChildAtSameIndex) {
- hasChildOrderChanged = true;
- }
- } else {
- handleMountFiber(nextChild);
- if (!hasChildOrderChanged) {
- hasChildOrderChanged = true;
- }
- }
- nextChild = nextChild.sibling;
- if (!hasChildOrderChanged && prevChildAtSameIndex != null) {
- prevChildAtSameIndex = prevChildAtSameIndex.sibling;
- }
- }
- if (!hasChildOrderChanged && prevChildAtSameIndex != null) {
- hasChildOrderChanged = true;
- }
- }
- updateIfNecessaryFiberNode(nextFiber, hasChildOrderChanged);
-}
-
-function handleMountFiber(fiber) {
- let node = fiber;
- outer: while (true) {
- if (node.child) {
- node.child.return = node;
- node = node.child;
- continue;
- }
- mountFiberNode(node);
- if (node == fiber) {
- return;
- }
- if (node.sibling) {
- node.sibling.return = node.return;
- node = node.sibling;
- continue;
- }
- while (node.return) {
- node = node.return;
- mountFiberNode(node);
- if (node == fiber) {
- return;
- }
- if (node.sibling) {
- node.sibling.return = node.return;
- node = node.sibling;
- continue outer;
- }
- }
- return;
- }
-}
-
-function mountFiberNode(node) {
- syncDomNodeWithFiberNode(node);
-}
-
-function updateIfNecessaryFiberNode(node, hasChildOrderChanged) {
- if (!hasChildOrderChanged && !hasDataChanged(node.alternate, node)) {
- return;
- }
- syncDomNodeWithFiberNode(node);
-}
-
-function syncDomNodeWithFiberNode(node) {
- const attrs = {};
- const visitedNodes = [];
- if (isFiberNodeOfType(node, ReactWorkTypes.HostPortal) && node.sibling) {
- const domElement = findDomElementByFiberNode(node.sibling);
- const targetDomElement = findDomElementByFiberNode(node.sibling.return);
- fillAttrsForDomElementByFiberNodeRecursive(attrs, node.sibling, visitedNodes, domElement);
- fillAttrsForDomElementByFiberNodeRecursive(attrs, node.sibling.return, visitedNodes, targetDomElement);
- if (domElement != null) {
- if (typeof domElement.setAttribute === 'function') {
- for (var attrName in attrs) {
- domElement.setAttribute(attrName, attrs[attrName]);
- }
- }
- }
- } else {
- const domElement = findDomElementByFiberNode(node);
- fillAttrsForDomElementByFiberNodeRecursive(attrs, node, visitedNodes, domElement);
- if (domElement != null) {
- if (typeof domElement.setAttribute === 'function') {
- for (var attrName in attrs) {
- domElement.setAttribute(attrName, attrs[attrName]);
- }
- }
- }
- }
-}
-
-function hasDataChanged(prevFiber, nextFiber) {
- if (isFiberNodeOfType(prevFiber, ReactWorkTypes.ClassComponent)) {
- if ((nextFiber.effectTag & PerformedWork) !== PerformedWork) {
- return false;
- }
- if (prevFiber.stateNode.context !== nextFiber.stateNode.context) {
- return true;
- }
- if (nextFiber.updateQueue != null && nextFiber.updateQueue.hasForceUpdate) {
- return true;
- }
- }
- return (
- prevFiber.memoizedProps !== nextFiber.memoizedProps ||
- prevFiber.memoizedState !== nextFiber.memoizedState ||
- prevFiber.ref !== nextFiber.ref ||
- prevFiber._debugSource !== nextFiber._debugSource
- );
-}
-
-function findDomElementByFiberNode(node) {
- let result = null;
- if (typeof node.setAttribute === 'function') {
- return node;
- }
- if (result == null && node.stateNode) {
- result = findDomElementByFiberNode(node.stateNode);
- }
- if (result == null && node.child) {
- result = findDomElementByFiberNode(node.child);
- }
- return result;
-}
-
-function fillAttrsForDomElementByFiberNodeRecursive(attrContainer, node, visitedNodes, domElement) {
- if (node == null || visitedNodes.includes(node)) {
- return;
- }
- visitedNodes.push(node);
- fillAttrsForDomElementByFiberNode(attrContainer, node);
- if (
- isFiberNodeOfType(node, ReactWorkTypes.FunctionComponent) ||
- isFiberNodeOfType(node, ReactWorkTypes.ClassComponent) ||
- isFiberNodeOfType(node, ReactWorkTypes.ContextConsumer) ||
- isFiberNodeOfType(node, ReactWorkTypes.ContextProvider) ||
- isFiberNodeOfType(node, ReactWorkTypes.Fragment)
- ) {
- fillAttrsForDomElementByFiberNodeRecursive(attrContainer, node.child, visitedNodes);
- } else if (isFiberNodeOfType(node, ReactWorkTypes.HostComponent)) {
- // I dont know what does it mean
- } else if (isFiberNodeOfType(node, ReactWorkTypes.HostPortal)) {
- // I dont know what does it mean
- } else {
- }
- if (node.return) {
- const parentDomElement = findDomElementByFiberNode(node.return);
- if (parentDomElement == domElement) {
- fillAttrsForDomElementByFiberNodeRecursive(attrContainer, node.return, visitedNodes, domElement);
- }
- }
- if (node && node.memoizedProps && node.key === 'portal-ref') {
- if (node.return) {
- const parentDomElement = findDomElementByFiberNode(node.return);
- fillAttrsForDomElementByFiberNodeRecursive(attrContainer, node.return, visitedNodes, parentDomElement);
- }
- }
-}
-
-function fillAttrsForDomElementByFiberNode(attrContainer, node) {
- const instanceProps = node.memoizedProps;
- const componentName = getFiberComponentName(node);
- if (componentName) {
- appendToSet(attrContainer, 'data-comp-name', componentName);
- }
- if (instanceProps != null) {
- if (instanceProps['data-tid']) {
- appendToSet(attrContainer, 'data-tid', instanceProps['data-tid']);
- }
- for (const prop in instanceProps) {
- if (acceptProp(componentName, prop, instanceProps[prop])) {
- attrContainer[`data-prop-${prop}`] = stringifySafe(instanceProps[prop]);
- }
- }
- } else {
- }
-}
-
-function getFiberComponentName(node) {
- if (node.type) {
- return node.type.name;
- }
-}
-
-// ====================================================
-// =============== REACT (<16.0.0) ====================
-// ====================================================
-
-function exposeReactInternalsIntoDomHook({ Mount, Reconciler }) {
- const ReactMount = Mount;
- if (Reconciler == null) {
- return;
- }
- extendStaticObject(Reconciler, {
- receiveComponent: base => (instance, nextElement, transaction, context) => {
- base.receiveComponent(instance, nextElement, transaction, context);
-
- const prevElement = instance._currentElement;
- if (nextElement === prevElement && context === instance._context) {
- return;
- }
-
- if (instance._currentElement && instance._currentElement.type) {
- const domElement = getTargetNode(instance, ReactMount);
- updateDomElement(domElement, instance, false);
- }
- },
-
- mountComponent: base => (instance, tr, host, hostParent, hostContainerInfo, context, ...rest) => {
- const result = base.mountComponent(instance, tr, host, hostParent, hostContainerInfo, context, ...rest);
- if (typeof result === 'string') {
- // React 0.14.*
- const resultDomElement = createDomFromString(result);
- if (!resultDomElement) {
- return result;
- }
- updateDomElement(resultDomElement, instance, true);
- return resultDomElement.outerHTML;
- } else if (result.node) {
- // React 15.*
- updateDomElement(result.node, instance, true);
- }
- return result;
- },
- });
-}
-
-function createDomFromString(s) {
- let rootDomElement;
- if (s.startsWith(' {
: {
"process.env.API": isDevMode ? "'fake'" : "'real'",
"process.env.enableReactTesting": "true",
- global: "window",
},
server: {
+ host: "0.0.0.0",
proxy: {
"/db-viewer": "http://localhost:5000",
},
diff --git a/db-viewer-ui/yarn.lock b/db-viewer-ui/yarn.lock
index 0e725e75..aea5f768 100644
--- a/db-viewer-ui/yarn.lock
+++ b/db-viewer-ui/yarn.lock
@@ -2650,6 +2650,7 @@ __metadata:
resolution: "@skbkontur/db-viewer-ui@workspace:."
dependencies:
"@skbkontur/icons": "npm:^1.3.0"
+ "@skbkontur/react-selenium-testing": "npm:^0.2.1"
"@skbkontur/react-stack-layout": "npm:^1.0.3"
"@skbkontur/react-ui": "npm:^4.1.0"
"@skbkontur/react-ui-validations": "npm:^1.8.3"
@@ -2705,6 +2706,32 @@ __metadata:
languageName: node
linkType: hard
+"@skbkontur/react-selenium-testing@npm:^0.2.1":
+ version: 0.2.1
+ resolution: "@skbkontur/react-selenium-testing@npm:0.2.1"
+ dependencies:
+ "@skbkontur/react-sorge": "npm:^0.2.1"
+ checksum: cb0bade94b68b95f22611f5f3bd17f3ff6d36cc8f499b40bdc0894ad5fa98259c687844386af4cdec18f4c9b94088d06e5eb4647794742fcac6e7daaeef81e7f
+ languageName: node
+ linkType: hard
+
+"@skbkontur/react-sorge@npm:^0.2.1":
+ version: 0.2.1
+ resolution: "@skbkontur/react-sorge@npm:0.2.1"
+ dependencies:
+ semver: "npm:7.3.5"
+ peerDependencies:
+ react: ">=16.7 <=17.0"
+ react-dom: ">=16.7 <=17.0"
+ peerDependenciesMeta:
+ react:
+ optional: true
+ react-dom:
+ optional: true
+ checksum: c29a029c2cfff29c1e067a7c5e9477692a3759d222eeb15a5c9d5bfdab666605b179d39430283d872acececf0142bcdccf3e942124ee75a26a680a7c485b2afb
+ languageName: node
+ linkType: hard
+
"@skbkontur/react-stack-layout@npm:^1.0.3":
version: 1.2.0
resolution: "@skbkontur/react-stack-layout@npm:1.2.0"
@@ -10107,6 +10134,17 @@ __metadata:
languageName: node
linkType: hard
+"semver@npm:7.3.5":
+ version: 7.3.5
+ resolution: "semver@npm:7.3.5"
+ dependencies:
+ lru-cache: "npm:^6.0.0"
+ bin:
+ semver: bin/semver.js
+ checksum: 22854378594943f2988ee853c02a7471dd02eba7bf75e286b98538114590a148dd59b22775edf42fcfb354438f304b8f32a53c136d228e99068ac52c60259324
+ languageName: node
+ linkType: hard
+
"semver@npm:^6.0.0, semver@npm:^6.3.1":
version: 6.3.1
resolution: "semver@npm:6.3.1"