Merge remote-tracking branch 'origin/dev' into node-shortcuts-refactor
This commit is contained in:
commit
1b3d62c5ca
151 changed files with 6035 additions and 2674 deletions
4
src/frontend/.gitignore
vendored
4
src/frontend/.gitignore
vendored
|
|
@ -28,3 +28,7 @@ yarn-error.log*
|
|||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#baseline
|
||||
FROM --platform=linux/amd64 node:19-bullseye-slim AS base
|
||||
FROM --platform=linux/amd64 node:21-bookworm-slim AS base
|
||||
RUN mkdir -p /home/node/app
|
||||
RUN chown -R node:node /home/node && chmod -R 770 /home/node
|
||||
RUN apt-get update && apt-get install -y jq curl
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#baseline
|
||||
FROM node:19-bullseye-slim AS base
|
||||
FROM node:21-bookworm-slim AS base
|
||||
RUN mkdir -p /home/node/app
|
||||
RUN chown -R node:node /home/node && chmod -R 770 /home/node
|
||||
RUN apt-get update && apt-get install -y jq
|
||||
|
|
|
|||
615
src/frontend/package-lock.json
generated
615
src/frontend/package-lock.json
generated
|
|
@ -31,6 +31,7 @@
|
|||
"@tailwindcss/line-clamp": "^0.4.4",
|
||||
"@types/axios": "^0.14.0",
|
||||
"ace-builds": "^1.24.1",
|
||||
"ag-grid-react": "^31.2.1",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"axios": "^1.5.0",
|
||||
"base64-js": "^1.5.1",
|
||||
|
|
@ -38,12 +39,15 @@
|
|||
"clsx": "^1.2.1",
|
||||
"cmdk": "^1.0.0",
|
||||
"dompurify": "^3.0.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"esbuild": "^0.17.19",
|
||||
"file-saver": "^2.0.5",
|
||||
"framer-motion": "^11.0.6",
|
||||
"lodash": "^4.17.21",
|
||||
"lucide-react": "^0.331.0",
|
||||
"million": "^3.0.6",
|
||||
"moment": "^2.29.4",
|
||||
"openseadragon": "^4.1.1",
|
||||
"playwright": "^1.42.0",
|
||||
"react": "^18.2.0",
|
||||
"react-ace": "^10.1.0",
|
||||
|
|
@ -54,6 +58,7 @@
|
|||
"react-icons": "^5.0.1",
|
||||
"react-laag": "^2.0.5",
|
||||
"react-markdown": "^8.0.7",
|
||||
"react-pdf": "^7.7.1",
|
||||
"react-router-dom": "^6.15.0",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"react18-json-view": "^0.2.3",
|
||||
|
|
@ -71,7 +76,7 @@
|
|||
"zustand": "^4.4.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.42.0",
|
||||
"@playwright/test": "^1.43.1",
|
||||
"@swc/cli": "^0.1.62",
|
||||
"@swc/core": "^1.3.80",
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
|
|
@ -1059,6 +1064,59 @@
|
|||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
|
||||
"integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.0",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"make-dir": "^3.1.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"nopt": "^5.0.0",
|
||||
"npmlog": "^5.0.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"semver": "^7.3.5",
|
||||
"tar": "^6.1.11"
|
||||
},
|
||||
"bin": {
|
||||
"node-pre-gyp": "bin/node-pre-gyp"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp/node_modules/semver": {
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
|
||||
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@mapbox/node-pre-gyp/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/@million/lint": {
|
||||
"version": "0.0.73",
|
||||
"resolved": "https://registry.npmjs.org/@million/lint/-/lint-0.0.73.tgz",
|
||||
|
|
@ -1759,12 +1817,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.42.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.42.1.tgz",
|
||||
"integrity": "sha512-Gq9rmS54mjBL/7/MvBaNOBwbfnh7beHvS6oS4srqXFcQHpQCV1+c8JXWE8VLPyRDhgS3H8x8A7hztqI9VnwrAQ==",
|
||||
"version": "1.43.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.43.1.tgz",
|
||||
"integrity": "sha512-HgtQzFgNEEo4TE22K/X7sYTYNqEMMTZmFS8kTq6m8hXj+m1D8TgwgIbumHddJa9h4yl4GkKb8/bgAl2+g7eDgA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"playwright": "1.42.1"
|
||||
"playwright": "1.43.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
|
|
@ -4283,6 +4341,12 @@
|
|||
"integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
|
||||
"deprecated": "Use your platform's native atob() and btoa() methods instead"
|
||||
},
|
||||
"node_modules/abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/ace-builds": {
|
||||
"version": "1.32.9",
|
||||
"resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.32.9.tgz",
|
||||
|
|
@ -4325,6 +4389,24 @@
|
|||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ag-grid-community": {
|
||||
"version": "31.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-31.2.1.tgz",
|
||||
"integrity": "sha512-D+gnUQ4dHZ/EQJmupQnDqcEKiCEeuK5ZxlsIpdPKgHg/23dmW+aEdivtB9nLpSc2IEK0RUpchcSxeUT37Boo5A=="
|
||||
},
|
||||
"node_modules/ag-grid-react": {
|
||||
"version": "31.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ag-grid-react/-/ag-grid-react-31.2.1.tgz",
|
||||
"integrity": "sha512-9UH3xxXRwZfW97oz58KboyCJl4t+zdetopieeHVcttsXX1DvGFDUIEz7A1sQaG8e1DAXLMf3IxoIPrfWheH4XA==",
|
||||
"dependencies": {
|
||||
"ag-grid-community": "31.2.1",
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.3.0 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^16.3.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
|
|
@ -4402,6 +4484,12 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/aproba": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
|
||||
"integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/arch": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz",
|
||||
|
|
@ -4422,6 +4510,19 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"node_modules/are-we-there-yet": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
|
||||
"integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"delegates": "^1.0.0",
|
||||
"readable-stream": "^3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/arg": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
|
||||
|
|
@ -4907,6 +5008,21 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"node_modules/canvas": {
|
||||
"version": "2.11.2",
|
||||
"resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz",
|
||||
"integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==",
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@mapbox/node-pre-gyp": "^1.0.0",
|
||||
"nan": "^2.17.0",
|
||||
"simple-get": "^3.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/ccount": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
|
||||
|
|
@ -4990,6 +5106,15 @@
|
|||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/chownr": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
|
||||
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/class-variance-authority": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.6.1.tgz",
|
||||
|
|
@ -5095,6 +5220,15 @@
|
|||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
|
||||
},
|
||||
"node_modules/color-support": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
|
||||
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
|
||||
"optional": true,
|
||||
"bin": {
|
||||
"color-support": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
|
|
@ -5128,7 +5262,13 @@
|
|||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
||||
"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/content-disposition": {
|
||||
"version": "0.5.4",
|
||||
|
|
@ -5583,6 +5723,12 @@
|
|||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/delegates": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/dequal": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
|
||||
|
|
@ -5591,6 +5737,15 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
|
||||
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-node-es": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
|
||||
|
|
@ -5672,6 +5827,17 @@
|
|||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.4.5",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
|
||||
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
|
|
@ -6427,6 +6593,11 @@
|
|||
"node": "^10.12.0 || >=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/file-saver": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
|
||||
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
|
||||
},
|
||||
"node_modules/file-type": {
|
||||
"version": "17.1.6",
|
||||
"resolved": "https://registry.npmjs.org/file-type/-/file-type-17.1.6.tgz",
|
||||
|
|
@ -6671,11 +6842,41 @@
|
|||
"node": ">=14.14"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-minipass": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
|
||||
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-minipass/node_modules/minipass": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-minipass/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
|
|
@ -6707,6 +6908,46 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/gauge": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
|
||||
"integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"aproba": "^1.0.3 || ^2.0.0",
|
||||
"color-support": "^1.1.2",
|
||||
"console-control-strings": "^1.0.0",
|
||||
"has-unicode": "^2.0.1",
|
||||
"object-assign": "^4.1.1",
|
||||
"signal-exit": "^3.0.0",
|
||||
"string-width": "^4.2.3",
|
||||
"strip-ansi": "^6.0.1",
|
||||
"wide-align": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/gauge/node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/gauge/node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/gensync": {
|
||||
"version": "1.0.0-beta.2",
|
||||
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
||||
|
|
@ -6755,7 +6996,7 @@
|
|||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
|
|
@ -6786,7 +7027,7 @@
|
|||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
|
@ -6796,7 +7037,7 @@
|
|||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
|
|
@ -6928,6 +7169,12 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-unicode": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
|
||||
"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
|
|
@ -7233,7 +7480,7 @@
|
|||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
|
|
@ -8242,6 +8489,37 @@
|
|||
"lz-string": "bin/bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/make-cancellable-promise": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/make-cancellable-promise/-/make-cancellable-promise-1.3.2.tgz",
|
||||
"integrity": "sha512-GCXh3bq/WuMbS+Ky4JBPW1hYTOU+znU+Q5m9Pu+pI8EoUqIHk9+tviOKC6/qhHh8C4/As3tzJ69IF32kdz85ww==",
|
||||
"funding": {
|
||||
"url": "https://github.com/wojtekmaj/make-cancellable-promise?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/make-dir": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
|
||||
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"semver": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/make-event-props": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/make-event-props/-/make-event-props-1.6.2.tgz",
|
||||
"integrity": "sha512-iDwf7mA03WPiR8QxvcVHmVWEPfMY1RZXerDVNCRYW7dUr2ppH3J58Rwb39/WG39yTZdRSxr3x+2v22tvI0VEvA==",
|
||||
"funding": {
|
||||
"url": "https://github.com/wojtekmaj/make-event-props?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/markdown-table": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz",
|
||||
|
|
@ -8490,6 +8768,22 @@
|
|||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/merge-refs": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/merge-refs/-/merge-refs-1.2.2.tgz",
|
||||
"integrity": "sha512-RwcT7GsQR3KbuLw1rRuodq4Nt547BKEBkliZ0qqsrpyNne9bGTFtsFIsIpx82huWhcl3kOlOlH4H0xkPk/DqVw==",
|
||||
"funding": {
|
||||
"url": "https://github.com/wojtekmaj/merge-refs?sponsor=1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
|
|
@ -9175,6 +9469,37 @@
|
|||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/minizlib": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
|
||||
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0",
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/minizlib/node_modules/minipass": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
|
||||
"integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/minizlib/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/mj-context-menu": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz",
|
||||
|
|
@ -9225,6 +9550,12 @@
|
|||
"thenify-all": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nan": {
|
||||
"version": "2.19.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz",
|
||||
"integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.7",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||
|
|
@ -9299,6 +9630,21 @@
|
|||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
|
||||
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw=="
|
||||
},
|
||||
"node_modules/nopt": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
|
||||
"integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"abbrev": "1"
|
||||
},
|
||||
"bin": {
|
||||
"nopt": "bin/nopt.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
|
|
@ -9349,6 +9695,18 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/npmlog": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
|
||||
"integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"are-we-there-yet": "^2.0.0",
|
||||
"console-control-strings": "^1.1.0",
|
||||
"gauge": "^3.0.0",
|
||||
"set-blocking": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nwsapi": {
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz",
|
||||
|
|
@ -9426,7 +9784,7 @@
|
|||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
|
@ -9445,6 +9803,14 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/openseadragon": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/openseadragon/-/openseadragon-4.1.1.tgz",
|
||||
"integrity": "sha512-owU9gsasAcobLN+LM8lN58Xc2VDSDotY9mkrwS/NB6g9KX/PcusV4RZvhHng2RF/Q0pMziwldf62glwXoGnuzg==",
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/openseadragon"
|
||||
}
|
||||
},
|
||||
"node_modules/optionator": {
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
|
||||
|
|
@ -9674,7 +10040,7 @@
|
|||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -9723,6 +10089,27 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/path2d-polyfill": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path2d-polyfill/-/path2d-polyfill-2.0.1.tgz",
|
||||
"integrity": "sha512-ad/3bsalbbWhmBo0D6FZ4RNMwsLsPpL6gnvhuSaU5Vm7b06Kr5ubSltQQ0T7YKsiJQO+g22zJ4dJKNTXIyOXtA==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/pdfjs-dist": {
|
||||
"version": "3.11.174",
|
||||
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-3.11.174.tgz",
|
||||
"integrity": "sha512-TdTZPf1trZ8/UFu5Cx/GXB7GZM30LT+wWUNfsi6Bq8ePLnb+woNKtDymI2mxZYBpMbonNFqKmiz684DIfnd8dA==",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"canvas": "^2.11.2",
|
||||
"path2d-polyfill": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/peek-readable": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz",
|
||||
|
|
@ -9769,11 +10156,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"version": "1.42.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.1.tgz",
|
||||
"integrity": "sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg==",
|
||||
"version": "1.43.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.43.1.tgz",
|
||||
"integrity": "sha512-V7SoH0ai2kNt1Md9E3Gwas5B9m8KR2GVvwZnAI6Pg0m3sh7UvgiYhRrhsziCmqMJNouPckiOhk8T+9bSAK0VIA==",
|
||||
"dependencies": {
|
||||
"playwright-core": "1.42.1"
|
||||
"playwright-core": "1.43.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
|
|
@ -9786,9 +10173,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.42.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.1.tgz",
|
||||
"integrity": "sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA==",
|
||||
"version": "1.43.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.43.1.tgz",
|
||||
"integrity": "sha512-EI36Mto2Vrx6VF7rm708qSnesVQKbxEWvPrfA1IPY6HgczBplDx7ENtx+K2n4kJ41sLLkuGfmb0ZLSSXlDhqPg==",
|
||||
"bin": {
|
||||
"playwright-core": "cli.js"
|
||||
},
|
||||
|
|
@ -10542,6 +10929,43 @@
|
|||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
|
||||
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
|
||||
},
|
||||
"node_modules/react-pdf": {
|
||||
"version": "7.7.1",
|
||||
"resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-7.7.1.tgz",
|
||||
"integrity": "sha512-cbbf/PuRtGcPPw+HLhMI1f6NSka8OJgg+j/yPWTe95Owf0fK6gmVY7OXpTxMeh92O3T3K3EzfE0ML0eXPGwR5g==",
|
||||
"dependencies": {
|
||||
"clsx": "^2.0.0",
|
||||
"dequal": "^2.0.3",
|
||||
"make-cancellable-promise": "^1.3.1",
|
||||
"make-event-props": "^1.6.0",
|
||||
"merge-refs": "^1.2.1",
|
||||
"pdfjs-dist": "3.11.174",
|
||||
"prop-types": "^15.6.2",
|
||||
"tiny-invariant": "^1.0.0",
|
||||
"warning": "^4.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/wojtekmaj/react-pdf?sponsor=1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-pdf/node_modules/clsx": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/react-reconciler": {
|
||||
"version": "0.29.0",
|
||||
"resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.29.0.tgz",
|
||||
|
|
@ -10965,7 +11389,7 @@
|
|||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
|
|
@ -11140,6 +11564,12 @@
|
|||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/set-function-length": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||
|
|
@ -11419,6 +11849,61 @@
|
|||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
||||
},
|
||||
"node_modules/simple-concat": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
|
||||
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/simple-get": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
|
||||
"integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"decompress-response": "^4.2.0",
|
||||
"once": "^1.3.1",
|
||||
"simple-concat": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-get/node_modules/decompress-response": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
|
||||
"integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"mimic-response": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/simple-get/node_modules/mimic-response": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
|
||||
"integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/sisteransi": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
||||
|
|
@ -11873,6 +12358,50 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
|
||||
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"chownr": "^2.0.0",
|
||||
"fs-minipass": "^2.0.0",
|
||||
"minipass": "^5.0.0",
|
||||
"minizlib": "^2.1.1",
|
||||
"mkdirp": "^1.0.3",
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/tar/node_modules/minipass": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
|
||||
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/tar/node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||
"optional": true,
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/tar/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/text-table": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||
|
|
@ -11898,6 +12427,11 @@
|
|||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/tiny-invariant": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
|
||||
"integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="
|
||||
},
|
||||
"node_modules/tiny-warning": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
|
||||
|
|
@ -12855,6 +13389,14 @@
|
|||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/warning": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
|
||||
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wcwidth": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
|
||||
|
|
@ -13016,6 +13558,35 @@
|
|||
"resolved": "https://registry.npmjs.org/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz",
|
||||
"integrity": "sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw=="
|
||||
},
|
||||
"node_modules/wide-align": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
|
||||
"integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"string-width": "^1.0.2 || 2 || 3 || 4"
|
||||
}
|
||||
},
|
||||
"node_modules/wide-align/node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/wide-align/node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
|
||||
|
|
@ -13137,7 +13708,7 @@
|
|||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true
|
||||
"devOptional": true
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.16.0",
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
"@tailwindcss/line-clamp": "^0.4.4",
|
||||
"@types/axios": "^0.14.0",
|
||||
"ace-builds": "^1.24.1",
|
||||
"ag-grid-react": "^31.2.1",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"axios": "^1.5.0",
|
||||
"base64-js": "^1.5.1",
|
||||
|
|
@ -33,12 +34,15 @@
|
|||
"clsx": "^1.2.1",
|
||||
"cmdk": "^1.0.0",
|
||||
"dompurify": "^3.0.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"esbuild": "^0.17.19",
|
||||
"file-saver": "^2.0.5",
|
||||
"framer-motion": "^11.0.6",
|
||||
"lodash": "^4.17.21",
|
||||
"lucide-react": "^0.331.0",
|
||||
"million": "^3.0.6",
|
||||
"moment": "^2.29.4",
|
||||
"openseadragon": "^4.1.1",
|
||||
"playwright": "^1.42.0",
|
||||
"react": "^18.2.0",
|
||||
"react-ace": "^10.1.0",
|
||||
|
|
@ -49,6 +53,7 @@
|
|||
"react-icons": "^5.0.1",
|
||||
"react-laag": "^2.0.5",
|
||||
"react-markdown": "^8.0.7",
|
||||
"react-pdf": "^7.7.1",
|
||||
"react-router-dom": "^6.15.0",
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"react18-json-view": "^0.2.3",
|
||||
|
|
@ -93,7 +98,7 @@
|
|||
},
|
||||
"proxy": "http://127.0.0.1:7860",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.42.0",
|
||||
"@playwright/test": "^1.43.1",
|
||||
"@swc/cli": "^0.1.62",
|
||||
"@swc/core": "^1.3.80",
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
import { defineConfig, devices } from "@playwright/test";
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
dotenv.config();
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
|
||||
/**
|
||||
* Read environment variables from file.
|
||||
* https://github.com/motdotla/dotenv
|
||||
*/
|
||||
// require('dotenv').config();
|
||||
|
||||
/**
|
||||
* See https://playwright.dev/docs/test-configuration.
|
||||
*/
|
||||
|
||||
export default defineConfig({
|
||||
testDir: "./tests",
|
||||
/* Run tests in files in parallel */
|
||||
|
|
@ -18,7 +21,7 @@ export default defineConfig({
|
|||
/* Retry on CI only */
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
/* Opt out of parallel tests on CI. */
|
||||
workers: 3,
|
||||
workers: 1,
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
timeout: 120 * 1000,
|
||||
// reporter: [
|
||||
|
|
@ -40,24 +43,32 @@ export default defineConfig({
|
|||
projects: [
|
||||
{
|
||||
name: "chromium",
|
||||
use: { ...devices["Desktop Chrome"] },
|
||||
use: {
|
||||
...devices["Desktop Chrome"],
|
||||
contextOptions: {
|
||||
// chromium-specific permissions
|
||||
permissions: ["clipboard-read", "clipboard-write"],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "firefox",
|
||||
use: { ...devices["Desktop Firefox"] },
|
||||
use: {
|
||||
...devices["Desktop Firefox"],
|
||||
launchOptions: {
|
||||
firefoxUserPrefs: {
|
||||
"dom.events.asyncClipboard.readText": true,
|
||||
"dom.events.testing.asyncClipboard": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// {
|
||||
// name: "webkit",
|
||||
// use: { ...devices["Desktop Safari"] },
|
||||
// },
|
||||
],
|
||||
/* Run your local dev server before starting the tests */
|
||||
webServer: [
|
||||
{
|
||||
command:
|
||||
"poetry run uvicorn --factory langflow.main:create_app --host 127.0.0.1 --port 7860",
|
||||
"poetry run uvicorn --factory langflow.main:create_app --host 127.0.0.1 --port 7860 --loop asyncio",
|
||||
port: 7860,
|
||||
env: {
|
||||
LANGFLOW_DATABASE_URL: "sqlite:///./temp",
|
||||
|
|
@ -65,7 +76,7 @@ export default defineConfig({
|
|||
},
|
||||
stdout: "ignore",
|
||||
|
||||
reuseExistingServer: !process.env.CI,
|
||||
reuseExistingServer: true,
|
||||
timeout: 120 * 1000,
|
||||
},
|
||||
{
|
||||
|
|
|
|||
141
src/frontend/src/components/ImageViewer/index.tsx
Normal file
141
src/frontend/src/components/ImageViewer/index.tsx
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
import { useEffect, useRef, useState } from "react";
|
||||
import ForwardedIconComponent from "../genericIconComponent";
|
||||
import useFlowStore from "../../stores/flowStore";
|
||||
import OpenSeadragon from 'openseadragon';
|
||||
import { Separator } from "../ui/separator";
|
||||
import { saveAs } from 'file-saver'
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import { IMGViewErrorMSG, IMGViewErrorTitle } from "../../constants/constants";
|
||||
|
||||
export default function ImageViewer({image }) {
|
||||
const viewerRef = useRef(null);
|
||||
const [errorDownloading, setErrordownloading] = useState(false)
|
||||
const setErrorList = useAlertStore(state => state.setErrorData);
|
||||
const [initialMsg, setInicialMsg] = useState("Please build your flow");
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
try {
|
||||
if (viewerRef.current) {
|
||||
// Initialize OpenSeadragon viewer
|
||||
const viewer = OpenSeadragon({
|
||||
element: viewerRef.current,
|
||||
prefixUrl: 'https://cdnjs.cloudflare.com/ajax/libs/openseadragon/2.4.2/images/', // Optional: Set the path to OpenSeadragon images
|
||||
tileSources: {type: 'image', url: image},
|
||||
defaultZoomLevel: 1,
|
||||
maxZoomPixelRatio: 4,
|
||||
showNavigationControl: false,
|
||||
});
|
||||
const zoomInButton = document.getElementById('zoom-in-button');
|
||||
const zoomOutButton = document.getElementById('zoom-out-button');
|
||||
const homeButton = document.getElementById('home-button');
|
||||
const fullPageButton = document.getElementById('full-page-button');
|
||||
|
||||
zoomInButton!.addEventListener('click', () => viewer.viewport.zoomBy(1.2));
|
||||
zoomOutButton!.addEventListener('click', () => viewer.viewport.zoomBy(0.8));
|
||||
homeButton!.addEventListener('click', () => viewer.viewport.goHome());
|
||||
fullPageButton!.addEventListener('click', () => viewer.setFullScreen(true));
|
||||
|
||||
// Optionally, you can set additional viewer options here
|
||||
|
||||
// Cleanup function
|
||||
return () => {
|
||||
viewer.destroy();
|
||||
zoomInButton!.removeEventListener('click', () => viewer.viewport.zoomBy(1.2));
|
||||
zoomOutButton!.removeEventListener('click', () => viewer.viewport.zoomBy(0.8));
|
||||
homeButton!.removeEventListener('click', () => viewer.viewport.goHome());
|
||||
fullPageButton!.removeEventListener('click', () => viewer.setFullScreen(true));
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error initializing OpenSeadragon:', error);
|
||||
}
|
||||
}, [image]);
|
||||
|
||||
function download() {
|
||||
const imageUrl = image;
|
||||
// Fetch the image data
|
||||
fetch(imageUrl)
|
||||
.then(response => response.blob())
|
||||
.then(blob => {
|
||||
// Save the image using FileSaver.js
|
||||
saveAs(blob, 'image.jpg');
|
||||
})
|
||||
.catch(error => {
|
||||
setErrorList({title: "There was an error downloading your image"})
|
||||
console.error('Error downloading image:', error)
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
image === "" ? (
|
||||
<div className="w-full h-full bg-muted rounded-md flex align-center justify-center flex-col gap-5 border border-border">
|
||||
<div className="flex gap-2 align-center justify-center ">
|
||||
<ForwardedIconComponent
|
||||
name="Image"
|
||||
/>
|
||||
{IMGViewErrorTitle}
|
||||
</div>
|
||||
<div className="flex align-center justify-center">
|
||||
<div className="langflow-chat-desc flex align-center justify-center">
|
||||
<div className="langflow-chat-desc-span">
|
||||
{IMGViewErrorMSG}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="w-full flex align-center justify-center my-2 mb-4">
|
||||
<div className="shadow-round-btn-shadow hover:shadow-round-btn-shadow flex items-center justify-center rounded-sm border bg-muted shadow-md transition-all w-[50%]">
|
||||
<button id="zoom-in-button" className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all w-full transition-all duration-500 ease-in-out ease-in-out hover:bg-hover">
|
||||
<ForwardedIconComponent
|
||||
name="ZoomIn"
|
||||
className={"text-secondary-foreground w-5 h-5"}
|
||||
/>
|
||||
</button>
|
||||
<div>
|
||||
<Separator orientation="vertical" />
|
||||
</div>
|
||||
<button id="zoom-out-button" className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover">
|
||||
<ForwardedIconComponent
|
||||
name="ZoomOut"
|
||||
className={"text-secondary-foreground w-5 h-5"}
|
||||
/>
|
||||
</button>
|
||||
<div>
|
||||
<Separator orientation="vertical" />
|
||||
</div>
|
||||
<button id="home-button" className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover">
|
||||
<ForwardedIconComponent
|
||||
name="RotateCcw"
|
||||
className={"text-secondary-foreground w-5 h-5"}
|
||||
/>
|
||||
</button>
|
||||
<div>
|
||||
<Separator orientation="vertical" />
|
||||
</div>
|
||||
<button id="full-page-button" className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover">
|
||||
<ForwardedIconComponent
|
||||
name="Maximize2"
|
||||
className={"text-secondary-foreground w-5 h-5"}
|
||||
/>
|
||||
</button>
|
||||
<div>
|
||||
<Separator orientation="vertical" />
|
||||
</div>
|
||||
|
||||
<button onClick={download} className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover">
|
||||
<ForwardedIconComponent
|
||||
name="ArrowDownToLine"
|
||||
className={"text-secondary-foreground w-5 h-5"}
|
||||
/>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div id="canvas" ref={viewerRef} className={`w-full h-[90%] `} />
|
||||
</>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
export const convertCSVToData = (csvFile, csvSeparator: string) => {
|
||||
const lines = csvFile.data.trim().split("\n");
|
||||
const headers = lines[0].trim().split(csvSeparator);
|
||||
|
||||
|
||||
const initialRowData: any = [];
|
||||
const initialColDefs = headers.map((header) => ({
|
||||
field: header.trim(),
|
||||
wrapText: true,
|
||||
autoHeight: true,
|
||||
height: "100%",
|
||||
}));
|
||||
|
||||
for (let i = 1; i < lines.length; i++) {
|
||||
const data = lines[i].trim().split(csvSeparator);
|
||||
const rowDataEntry: any = {};
|
||||
|
||||
for (let j = 0; j < headers.length; j++) {
|
||||
const value = isNaN(data[j]) ? data[j] : parseFloat(data[j]);
|
||||
rowDataEntry[headers[j].trim()] = value;
|
||||
}
|
||||
|
||||
initialRowData.push(rowDataEntry);
|
||||
}
|
||||
|
||||
return { rowData: initialRowData, colDefs: initialColDefs };
|
||||
};
|
||||
182
src/frontend/src/components/csvOutputComponent/index.tsx
Normal file
182
src/frontend/src/components/csvOutputComponent/index.tsx
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
import "ag-grid-community/styles/ag-grid.css"; // Mandatory CSS required by the grid
|
||||
import "ag-grid-community/styles/ag-theme-balham.css"; // Optional Theme applied to the grid
|
||||
import { AgGridReact } from "ag-grid-react";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import {
|
||||
CSVError,
|
||||
CSVNoDataError,
|
||||
CSVViewErrorTitle,
|
||||
} from "../../constants/constants";
|
||||
import { useDarkStore } from "../../stores/darkStore";
|
||||
import { FlowPoolObjectType } from "../../types/chat";
|
||||
import { NodeType } from "../../types/flow";
|
||||
import ForwardedIconComponent from "../genericIconComponent";
|
||||
import Loading from "../ui/loading";
|
||||
import { convertCSVToData } from "./helpers/convert-data-function";
|
||||
|
||||
function CsvOutputComponent({
|
||||
csvNode,
|
||||
flowPool,
|
||||
}: {
|
||||
csvNode: NodeType;
|
||||
flowPool: FlowPoolObjectType;
|
||||
}) {
|
||||
const csvNodeArtifacts = flowPool?.data?.artifacts?.repr;
|
||||
const jsonString = csvNodeArtifacts?.replace(/'/g, '"');
|
||||
let file = null;
|
||||
try {
|
||||
file = JSON?.parse(jsonString) || "";
|
||||
} catch (e) {
|
||||
console.log("Error parsing JSON");
|
||||
}
|
||||
|
||||
if (!file) {
|
||||
return (
|
||||
<div className=" align-center flex h-full w-full flex-col items-center justify-center gap-5">
|
||||
<div className="align-center flex w-full justify-center gap-2">
|
||||
<ForwardedIconComponent name="Table" />
|
||||
{CSVViewErrorTitle}
|
||||
</div>
|
||||
<div className="align-center flex w-full justify-center">
|
||||
<div className="langflow-chat-desc align-center flex justify-center px-6 py-8">
|
||||
<div className="langflow-chat-desc-span">{CSVError}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const separator = csvNode?.data?.node?.template?.separator?.value || ",";
|
||||
|
||||
const dark = useDarkStore.getState().dark;
|
||||
|
||||
const [rowData, setRowData] = useState([]);
|
||||
const [colDefs, setColDefs] = useState([]);
|
||||
|
||||
const [status, setStatus] = useState("loading");
|
||||
var currentRowHeight: number;
|
||||
var minRowHeight = 25;
|
||||
const defaultColDef = useMemo(() => {
|
||||
return {
|
||||
width: 200,
|
||||
editable: true,
|
||||
filter: true,
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setStatus("loading");
|
||||
if (file) {
|
||||
const { rowData: data, colDefs: columns } = convertCSVToData(
|
||||
file,
|
||||
separator
|
||||
);
|
||||
setRowData(data);
|
||||
setColDefs(columns);
|
||||
|
||||
setTimeout(() => {
|
||||
setStatus("loaded");
|
||||
}, 1000);
|
||||
} else {
|
||||
setStatus("nodata");
|
||||
}
|
||||
}, [separator]);
|
||||
|
||||
const getRowHeight = useCallback(() => {
|
||||
return currentRowHeight;
|
||||
}, []);
|
||||
|
||||
const onGridReady = useCallback((params: any) => {
|
||||
minRowHeight = params.api.getSizesForCurrentTheme().rowHeight;
|
||||
currentRowHeight = minRowHeight;
|
||||
}, []);
|
||||
|
||||
const updateRowHeight = (params: { api: any }) => {
|
||||
const bodyViewport = document.querySelector(".ag-body-viewport");
|
||||
if (!bodyViewport) {
|
||||
return;
|
||||
}
|
||||
var gridHeight = bodyViewport.clientHeight;
|
||||
var renderedRowCount = params.api.getDisplayedRowCount();
|
||||
|
||||
if (renderedRowCount * minRowHeight >= gridHeight) {
|
||||
if (currentRowHeight !== minRowHeight) {
|
||||
currentRowHeight = minRowHeight;
|
||||
params.api.resetRowHeights();
|
||||
}
|
||||
} else {
|
||||
currentRowHeight = Math.floor(gridHeight / renderedRowCount);
|
||||
params.api.resetRowHeights();
|
||||
}
|
||||
};
|
||||
|
||||
const onFirstDataRendered = useCallback(
|
||||
(params: any) => {
|
||||
updateRowHeight(params);
|
||||
},
|
||||
[updateRowHeight]
|
||||
);
|
||||
|
||||
const onGridSizeChanged = useCallback(
|
||||
(params: any) => {
|
||||
updateRowHeight(params);
|
||||
},
|
||||
[updateRowHeight]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className=" h-full rounded-md border bg-muted">
|
||||
{status === "nodata" && (
|
||||
<div className=" align-center flex h-full w-full flex-col items-center justify-center gap-5">
|
||||
<div className="align-center flex w-full justify-center gap-2">
|
||||
<ForwardedIconComponent name="Table" />
|
||||
{CSVViewErrorTitle}
|
||||
</div>
|
||||
<div className="align-center flex w-full justify-center">
|
||||
<div className="langflow-chat-desc align-center flex justify-center px-6 py-8">
|
||||
<div className="langflow-chat-desc-span">{CSVNoDataError}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{status === "error" && (
|
||||
<div className=" align-center flex h-full w-full flex-col items-center justify-center gap-5">
|
||||
<div className="align-center flex w-full justify-center gap-2">
|
||||
<ForwardedIconComponent name="Table" />
|
||||
{CSVViewErrorTitle}
|
||||
</div>
|
||||
<div className="align-center flex w-full justify-center">
|
||||
<div className="langflow-chat-desc align-center flex justify-center px-6 py-8">
|
||||
<div className="langflow-chat-desc-span">{CSVError}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{status === "loaded" && (
|
||||
<div
|
||||
className={`${dark ? "ag-theme-balham-dark" : "ag-theme-balham"}`}
|
||||
style={{ height: "100%", width: "100%" }}
|
||||
>
|
||||
<AgGridReact
|
||||
rowData={rowData}
|
||||
columnDefs={colDefs}
|
||||
defaultColDef={defaultColDef}
|
||||
getRowHeight={getRowHeight}
|
||||
onGridReady={onGridReady}
|
||||
onFirstDataRendered={onFirstDataRendered}
|
||||
onGridSizeChanged={onGridSizeChanged}
|
||||
scrollbarWidth={8}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{status === "loading" && (
|
||||
<div className=" flex h-full w-full items-center justify-center align-middle">
|
||||
<Loading />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default CsvOutputComponent;
|
||||
|
|
@ -83,7 +83,9 @@ export const MenuBar = ({
|
|||
<DropdownMenuTrigger asChild>
|
||||
<Button asChild variant="primary" size="sm">
|
||||
<div className="header-menu-bar-display">
|
||||
<div className="header-menu-flow-name">{currentFlow.name}</div>
|
||||
<div className="header-menu-flow-name" data-testid="flow_name">
|
||||
{currentFlow.name}
|
||||
</div>
|
||||
<IconComponent name="ChevronDown" className="h-4 w-4" />
|
||||
</div>
|
||||
</Button>
|
||||
|
|
|
|||
23
src/frontend/src/components/pdfViewer/Error/index.tsx
Normal file
23
src/frontend/src/components/pdfViewer/Error/index.tsx
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { CHAT_FIRST_INITIAL_TEXT, CHAT_SECOND_INITIAL_TEXT, PDFCheckFlow, PDFLoadErrorTitle } from "../../../constants/constants";
|
||||
import IconComponent from "../../genericIconComponent";
|
||||
|
||||
|
||||
export default function Error(): JSX.Element {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center h-full w-full bg-muted">
|
||||
<div className="chat-alert-box">
|
||||
<span className="flex gap-2">
|
||||
<IconComponent name="FileX2" />
|
||||
<span className="langflow-chat-span">{PDFLoadErrorTitle}</span>
|
||||
</span>
|
||||
<br />
|
||||
<div className="langflow-chat-desc">
|
||||
<span className="langflow-chat-desc-span">
|
||||
{PDFCheckFlow}{" "}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
155
src/frontend/src/components/pdfViewer/index.tsx
Normal file
155
src/frontend/src/components/pdfViewer/index.tsx
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
import { useEffect, useRef, useState } from "react";
|
||||
import { Document, Page, pdfjs } from "react-pdf";
|
||||
import "react-pdf/dist/esm/Page/AnnotationLayer.css";
|
||||
import "react-pdf/dist/esm/Page/TextLayer.css";
|
||||
import IconComponent from "../genericIconComponent";
|
||||
import Loading from "../ui/loading";
|
||||
import Error from "./Error";
|
||||
import NoDataPdf from "./noData";
|
||||
|
||||
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.js`;
|
||||
|
||||
export default function PdfViewer({ pdf }: { pdf: string }): JSX.Element {
|
||||
const [numPages, setNumPages] = useState(-1);
|
||||
const [pageNumber, setPageNumber] = useState(1);
|
||||
const [scale, setScale] = useState(1);
|
||||
const [width, setWidth] = useState<number | undefined>(undefined);
|
||||
const [showControl, setShowControl] = useState(false);
|
||||
const container = useRef<null | HTMLDivElement>(null);
|
||||
|
||||
//shortcuts to change page
|
||||
useEffect(() => {
|
||||
function handleKeyDown(event: KeyboardEvent) {
|
||||
if (event.key === "ArrowLeft") {
|
||||
if (pageNumber > 1) previousPage();
|
||||
} else if (event.key === "ArrowRight") {
|
||||
if (pageNumber < numPages) nextPage();
|
||||
}
|
||||
}
|
||||
document.addEventListener("keydown", handleKeyDown);
|
||||
return () => {
|
||||
document.removeEventListener("keydown", handleKeyDown);
|
||||
};
|
||||
}, [pageNumber]);
|
||||
|
||||
function onDocumentLoadSuccess({ numPages }) {
|
||||
setNumPages(numPages);
|
||||
setPageNumber(1);
|
||||
}
|
||||
|
||||
function changePage(offset) {
|
||||
setPageNumber((prevPageNumber) => prevPageNumber + offset);
|
||||
}
|
||||
|
||||
function previousPage() {
|
||||
changePage(-1);
|
||||
}
|
||||
|
||||
function nextPage() {
|
||||
changePage(1);
|
||||
}
|
||||
|
||||
//set handle scale in % to real number
|
||||
function handleScaleChange(e) {
|
||||
//check if e is a number
|
||||
if (isNaN(e) || e < 0.1) return;
|
||||
// round to 2 decimal places
|
||||
e = Math.round(e * 10) / 10;
|
||||
|
||||
setScale(e);
|
||||
}
|
||||
|
||||
function zoomIn() {
|
||||
handleScaleChange(scale + 0.1);
|
||||
}
|
||||
function zoomOut() {
|
||||
if (scale > 0.1) handleScaleChange(scale - 0.1);
|
||||
}
|
||||
|
||||
function handlePageLoad(page) {
|
||||
if (!container.current) return;
|
||||
const containerWidth = container.current.clientWidth;
|
||||
const pageWidth = page.width;
|
||||
if (containerWidth > pageWidth) {
|
||||
setWidth(containerWidth - 10);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={container}
|
||||
onMouseEnter={(_) => setShowControl(true)}
|
||||
onMouseLeave={(_) => setShowControl(false)}
|
||||
className="flex h-full w-full flex-col items-center justify-end overflow-clip rounded-lg border border-border"
|
||||
>
|
||||
<div className={"h-full min-h-0 w-full overflow-auto custom-scroll"}>
|
||||
<Document
|
||||
loading={
|
||||
<div className="flex h-full w-full items-center justify-center align-middle">
|
||||
<Loading />
|
||||
</div>
|
||||
}
|
||||
onLoadSuccess={onDocumentLoadSuccess}
|
||||
file={pdf}
|
||||
noData={<NoDataPdf />}
|
||||
error={<Error />}
|
||||
className="h-full w-full"
|
||||
>
|
||||
<Page
|
||||
width={width}
|
||||
onLoadSuccess={handlePageLoad}
|
||||
scale={scale}
|
||||
renderTextLayer
|
||||
pageNumber={pageNumber}
|
||||
className={"h-full max-h-0 w-full"}
|
||||
/>
|
||||
</Document>
|
||||
</div>
|
||||
<div
|
||||
className={
|
||||
"absolute z-50 pb-5 " + (showControl && numPages > 0 ? "" : " hidden")
|
||||
}
|
||||
>
|
||||
<div className=" flex w-min items-center justify-center gap-0.5 rounded-xl bg-secondary px-2 align-middle">
|
||||
<button
|
||||
type="button"
|
||||
disabled={pageNumber <= 1}
|
||||
onClick={previousPage}
|
||||
>
|
||||
<IconComponent
|
||||
name={"ChevronLeft"}
|
||||
className="h-6 w-6"
|
||||
></IconComponent>
|
||||
</button>
|
||||
<p>
|
||||
{pageNumber || (numPages ? 1 : "--")}/{numPages || "--"}
|
||||
</p>
|
||||
<button
|
||||
type="button"
|
||||
disabled={pageNumber >= numPages}
|
||||
onClick={nextPage}
|
||||
>
|
||||
<IconComponent
|
||||
name={"ChevronRight"}
|
||||
className="h-6 w-6"
|
||||
></IconComponent>
|
||||
</button>
|
||||
<p className="px-2">|</p>
|
||||
<button type="button" onClick={zoomOut}>
|
||||
<IconComponent name={"ZoomOut"} className="h-6 w-6"></IconComponent>
|
||||
</button>
|
||||
<input
|
||||
type="number"
|
||||
step={0.1}
|
||||
className="w-6 border-b bg-transparent text-center arrow-hide"
|
||||
onChange={(e) => handleScaleChange(e.target.value)}
|
||||
value={scale}
|
||||
/>
|
||||
<button type="button" onClick={zoomIn}>
|
||||
<IconComponent name={"ZoomIn"} className="h-6 w-6"></IconComponent>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
17
src/frontend/src/components/pdfViewer/noData/index.tsx
Normal file
17
src/frontend/src/components/pdfViewer/noData/index.tsx
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { PDFErrorTitle, PDFLoadError } from "../../../constants/constants";
|
||||
|
||||
export default function NoDataPdf(): JSX.Element {
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col items-center justify-center bg-muted">
|
||||
<div className="chat-alert-box">
|
||||
<span>
|
||||
📄 <span className="langflow-chat-span">{PDFErrorTitle}</span>
|
||||
</span>
|
||||
<br />
|
||||
<div className="langflow-chat-desc">
|
||||
<span className="langflow-chat-desc-span">{PDFLoadError} </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -161,6 +161,29 @@ export const IMPORT_DIALOG_SUBTITLE =
|
|||
*/
|
||||
export const TOOLTIP_EMPTY = "No compatible components found.";
|
||||
|
||||
export const CSVViewErrorTitle = "CSV output";
|
||||
|
||||
export const CSVNoDataError = "No data available";
|
||||
|
||||
export const PDFViewConstant = "Expand the ouptut to see the PDF";
|
||||
|
||||
export const CSVError = "Error loading CSV";
|
||||
|
||||
export const PDFLoadErrorTitle = "Error loading PDF";
|
||||
|
||||
export const PDFCheckFlow = "Please check your flow and try again";
|
||||
|
||||
export const PDFErrorTitle = "PDF Output";
|
||||
|
||||
export const PDFLoadError = "Run the flow to see the pdf";
|
||||
|
||||
export const IMGViewConstant = "Expand the view to see the image";
|
||||
|
||||
export const IMGViewErrorMSG =
|
||||
"Run the flow or inform a valid url to see your image";
|
||||
|
||||
export const IMGViewErrorTitle = "Image output";
|
||||
|
||||
/**
|
||||
* The base text for subtitle of code dialog
|
||||
* @constant
|
||||
|
|
@ -688,8 +711,14 @@ export const LANGFLOW_SUPPORTED_TYPES = new Set([
|
|||
|
||||
export const priorityFields = new Set(["code", "template"]);
|
||||
|
||||
export const INPUT_TYPES = new Set(["ChatInput", "TextInput"]);
|
||||
export const OUTPUT_TYPES = new Set(["ChatOutput", "TextOutput"]);
|
||||
export const INPUT_TYPES = new Set(["ChatInput", "TextInput", "KeyPairInput"]);
|
||||
export const OUTPUT_TYPES = new Set([
|
||||
"ChatOutput",
|
||||
"TextOutput",
|
||||
"PDFOutput",
|
||||
"ImageOutput",
|
||||
"CSVOutput",
|
||||
]);
|
||||
|
||||
export const CHAT_FIRST_INITIAL_TEXT =
|
||||
"Start a conversation and click the agent's thoughts";
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ function ApiInterceptor() {
|
|||
async (error: AxiosError) => {
|
||||
if (error.response?.status === 403 || error.response?.status === 401) {
|
||||
if (!autoLogin) {
|
||||
if (error?.config?.url?.includes("github")) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
const stillRefresh = checkErrorCount();
|
||||
if (!stillRefresh) {
|
||||
return Promise.reject(error);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,17 @@
|
|||
import { cloneDeep } from "lodash";
|
||||
import ImageViewer from "../../../../components/ImageViewer";
|
||||
import CsvOutputComponent from "../../../../components/csvOutputComponent";
|
||||
import PdfViewer from "../../../../components/pdfViewer";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "../../../../components/ui/select";
|
||||
import { Textarea } from "../../../../components/ui/textarea";
|
||||
import { PDFViewConstant } from "../../../../constants/constants";
|
||||
import { InputOutput } from "../../../../constants/enums";
|
||||
import useFlowStore from "../../../../stores/flowStore";
|
||||
import { IOFieldViewProps } from "../../../../types/components";
|
||||
|
|
@ -15,6 +27,19 @@ export default function IOFieldView({
|
|||
const setNode = useFlowStore((state) => state.setNode);
|
||||
const flowPool = useFlowStore((state) => state.flowPool);
|
||||
const node = nodes.find((node) => node.id === fieldId);
|
||||
const flowPoolNode = (flowPool[node!.id] ?? [])[
|
||||
(flowPool[node!.id]?.length ?? 1) - 1
|
||||
];
|
||||
const handleChangeSelect = (e) => {
|
||||
if (node) {
|
||||
let newNode = cloneDeep(node);
|
||||
if (newNode.data.node.template.separator) {
|
||||
newNode.data.node.template.separator.value = e;
|
||||
setNode(newNode.id, newNode);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function handleOutputType() {
|
||||
if (!node) return <>"No node found!"</>;
|
||||
switch (type) {
|
||||
|
|
@ -91,6 +116,58 @@ export default function IOFieldView({
|
|||
readOnly
|
||||
/>
|
||||
);
|
||||
case "PDFOutput":
|
||||
return left ? (
|
||||
<div>{PDFViewConstant}</div>
|
||||
) : (
|
||||
<PdfViewer pdf={flowPoolNode?.params ?? ""} />
|
||||
);
|
||||
case "CSVOutput":
|
||||
return left ? (
|
||||
<>
|
||||
<div className="flex justify-between">
|
||||
Expand the ouptut to see the CSV
|
||||
</div>
|
||||
<div className="flex items-center justify-between pt-5">
|
||||
<span>CSV separator </span>
|
||||
<Select
|
||||
value={node.data.node.template.separator.value}
|
||||
onValueChange={(e) => handleChangeSelect(e)}
|
||||
>
|
||||
<SelectTrigger className="w-[70px]">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
{node?.data?.node?.template?.separator?.options.map(
|
||||
(separator) => (
|
||||
<SelectItem key={separator} value={separator}>
|
||||
{separator}
|
||||
</SelectItem>
|
||||
)
|
||||
)}
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<CsvOutputComponent csvNode={node} flowPool={flowPoolNode} />
|
||||
</>
|
||||
);
|
||||
case "ImageOutput":
|
||||
return left ? (
|
||||
<div>Expand the view to see the image</div>
|
||||
) : (
|
||||
<ImageViewer
|
||||
image={
|
||||
(flowPool[node.id] ?? [])[
|
||||
(flowPool[node.id]?.length ?? 1) - 1
|
||||
]?.params ?? ""
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
default:
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -135,7 +135,12 @@ export default function ChatMessage({
|
|||
alt={!chat.isSend ? "robot_image" : "male_technology"}
|
||||
/>
|
||||
</div>
|
||||
<span className="max-w-24 truncate text-xs">
|
||||
<span
|
||||
className="max-w-24 truncate text-xs"
|
||||
data-testid={
|
||||
"sender_name_" + chat.sender_name?.toLocaleLowerCase()
|
||||
}
|
||||
>
|
||||
{chat.sender_name}
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import { getTagsIds } from "../../utils/storeUtils";
|
|||
import ConfirmationModal from "../ConfirmationModal";
|
||||
import BaseModal from "../baseModal";
|
||||
import { useHotkeys } from "react-hotkeys-hook";
|
||||
import ExportModal from "../exportModal";
|
||||
|
||||
export default function ShareModal({
|
||||
component,
|
||||
|
|
@ -215,9 +216,8 @@ export default function ShareModal({
|
|||
{children ? children : <></>}
|
||||
</BaseModal.Trigger>
|
||||
<BaseModal.Header
|
||||
description={`Publish ${
|
||||
is_component ? "your component" : "workflow"
|
||||
} to the Langflow Store.`}
|
||||
description={`Publish ${is_component ? "your component" : "workflow"
|
||||
} to the Langflow Store.`}
|
||||
>
|
||||
<span className="pr-2">Share</span>
|
||||
<IconComponent
|
||||
|
|
@ -246,6 +246,7 @@ export default function ShareModal({
|
|||
onCheckedChange={(event: boolean) => {
|
||||
setSharePublic(event);
|
||||
}}
|
||||
data-testid="public-checkbox"
|
||||
/>
|
||||
<label htmlFor="public" className="export-modal-save-api text-sm ">
|
||||
Set {nameComponent} status to public
|
||||
|
|
@ -259,18 +260,34 @@ export default function ShareModal({
|
|||
|
||||
<BaseModal.Footer>
|
||||
<div className="flex w-full justify-between gap-2">
|
||||
<Button
|
||||
{!is_component && <ExportModal>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="gap-2"
|
||||
onClick={() => {
|
||||
// (setOpen || internalSetOpen)(false);
|
||||
}}
|
||||
>
|
||||
<IconComponent name="Download" className="h-4 w-4" />
|
||||
Export
|
||||
</Button>
|
||||
</ExportModal>
|
||||
}
|
||||
{is_component && <Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
className="gap-2"
|
||||
onClick={() => {
|
||||
handleExportComponent();
|
||||
(setOpen || internalSetOpen)(false);
|
||||
handleExportComponent();
|
||||
}}
|
||||
>
|
||||
<IconComponent name="Download" className="h-4 w-4" />
|
||||
Export
|
||||
</Button>
|
||||
|
||||
}
|
||||
<Button
|
||||
disabled={loadingNames}
|
||||
type="button"
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
|
|||
<a
|
||||
target={"_blank"}
|
||||
href="https://medium.com/logspace/langflow-datastax-better-together-1b7462cebc4d"
|
||||
className="logspace-page-icon"
|
||||
className="langflow-page-icon"
|
||||
>
|
||||
{version && <div className="mt-1">Langflow 🤝 DataStax</div>}
|
||||
<div className={version ? "mt-2" : "mt-1"}>⛓️ v{version}</div>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,11 @@ export const useDarkStore = create<DarkStoreType>((set, get) => ({
|
|||
});
|
||||
},
|
||||
refreshStars: () => {
|
||||
if (import.meta.env.CI) {
|
||||
window.localStorage.setItem("githubStars", "0");
|
||||
set(() => ({ stars: 0, lastUpdated: new Date() }));
|
||||
return;
|
||||
}
|
||||
let lastUpdated = window.localStorage.getItem("githubStarsLastUpdated");
|
||||
let diff = 0;
|
||||
// check if lastUpdated actually exists
|
||||
|
|
@ -27,7 +32,7 @@ export const useDarkStore = create<DarkStoreType>((set, get) => ({
|
|||
|
||||
// if lastUpdated is null or the difference is greater than 2 hours
|
||||
if (lastUpdated === null || diff > 7200000) {
|
||||
getRepoStars("logspace-ai", "langflow").then((res) => {
|
||||
getRepoStars("langflow-ai", "langflow").then((res) => {
|
||||
window.localStorage.setItem("githubStars", res.toString());
|
||||
window.localStorage.setItem(
|
||||
"githubStarsLastUpdated",
|
||||
|
|
|
|||
|
|
@ -205,11 +205,11 @@
|
|||
.flow-page-positioning {
|
||||
@apply h-full w-full overflow-hidden;
|
||||
}
|
||||
.logspace-page-icon {
|
||||
.langflow-page-icon {
|
||||
@apply absolute bottom-2 left-7 flex h-6 cursor-pointer flex-col items-center justify-start overflow-hidden rounded-lg bg-foreground px-2 text-center font-sans text-xs tracking-wide text-secondary transition-all duration-500 ease-in-out;
|
||||
}
|
||||
|
||||
.logspace-page-icon:hover {
|
||||
.langflow-page-icon:hover {
|
||||
@apply hover:h-12;
|
||||
}
|
||||
|
||||
|
|
|
|||
1
src/frontend/tests/end-to-end/assets/test_file.txt
Normal file
1
src/frontend/tests/end-to-end/assets/test_file.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
this is a test file
|
||||
|
|
@ -2,12 +2,12 @@ import { test } from "@playwright/test";
|
|||
|
||||
test.describe("Auto_login tests", () => {
|
||||
test("auto_login sign in", async ({ page }) => {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
});
|
||||
|
||||
test("auto_login block_admin", async ({ page }) => {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
|
|
|
|||
149
src/frontend/tests/end-to-end/chatInputOutput.spec.ts
Normal file
149
src/frontend/tests/end-to-end/chatInputOutput.spec.ts
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import * as dotenv from "dotenv";
|
||||
import { readFileSync } from "fs";
|
||||
import path from "path";
|
||||
|
||||
test("user must interact with chat with Input/Output", async ({ page }) => {
|
||||
if (!process.env.CI) {
|
||||
dotenv.config();
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
|
||||
await page.goto("/");
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
if (!process.env.OPENAI_API_KEY) {
|
||||
//You must set the OPENAI_API_KEY on .env file to run this test
|
||||
expect(false).toBe(true);
|
||||
}
|
||||
|
||||
await page
|
||||
.getByTestId("input-openai_api_key")
|
||||
.fill(process.env.OPENAI_API_KEY ?? "");
|
||||
await page.getByText("Run", { exact: true }).click();
|
||||
await page.getByPlaceholder("Send a message...").fill("Hello, how are you?");
|
||||
await page.getByTestId("icon-LucideSend").click();
|
||||
let valueUser = await page.getByTestId("sender_name_user").textContent();
|
||||
let valueAI = await page.getByTestId("sender_name_ai").textContent();
|
||||
|
||||
expect(valueUser).toBe("User");
|
||||
expect(valueAI).toBe("AI");
|
||||
|
||||
await page.keyboard.press("Escape");
|
||||
|
||||
await page
|
||||
.getByTestId("textarea-input_value")
|
||||
.nth(1)
|
||||
.fill(
|
||||
"testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!"
|
||||
);
|
||||
await page.getByTestId("input-sender_name").nth(1).fill("TestSenderNameUser");
|
||||
await page.getByTestId("input-sender_name").nth(0).fill("TestSenderNameAI");
|
||||
|
||||
await page.getByText("Run", { exact: true }).click();
|
||||
await page.getByTestId("icon-LucideSend").click();
|
||||
|
||||
valueUser = await page
|
||||
.getByTestId("sender_name_testsendernameuser")
|
||||
.textContent();
|
||||
valueAI = await page
|
||||
.getByTestId("sender_name_testsendernameai")
|
||||
.textContent();
|
||||
|
||||
expect(valueUser).toBe("TestSenderNameUser");
|
||||
expect(valueAI).toBe("TestSenderNameAI");
|
||||
|
||||
expect(
|
||||
await page
|
||||
.getByText(
|
||||
"testtesttesttesttesttestte;.;.,;,.;,.;.,;,..,;;;;;;;;;;;;;;;;;;;;;,;.;,.;,.,;.,;.;.,~~çççççççççççççççççççççççççççççççççççççççisdajfdasiopjfaodisjhvoicxjiovjcxizopjviopasjioasfhjaiohf23432432432423423sttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttestççççççççççççççççççççççççççççççççç,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,!",
|
||||
{ exact: true }
|
||||
)
|
||||
.isVisible()
|
||||
);
|
||||
});
|
||||
|
||||
test("chat_io_teste", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
|
||||
// Read your file into a buffer.
|
||||
const jsonContent = readFileSync(
|
||||
"tests/end-to-end/assets/ChatTest.json",
|
||||
"utf-8"
|
||||
);
|
||||
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
// Create the DataTransfer and File
|
||||
const dataTransfer = await page.evaluateHandle((data) => {
|
||||
const dt = new DataTransfer();
|
||||
// Convert the buffer to a hex array
|
||||
const file = new File([data], "ChatTest.json", {
|
||||
type: "application/json",
|
||||
});
|
||||
dt.items.add(file);
|
||||
return dt;
|
||||
}, jsonContent);
|
||||
|
||||
// Now dispatch
|
||||
await page.dispatchEvent(
|
||||
'//*[@id="react-flow-id"]/div[1]/div[1]/div',
|
||||
"drop",
|
||||
{
|
||||
dataTransfer,
|
||||
}
|
||||
);
|
||||
await page.getByLabel("fit view").click();
|
||||
await page.getByText("Run", { exact: true }).click();
|
||||
await page.getByPlaceholder("Send a message...").click();
|
||||
await page.getByPlaceholder("Send a message...").fill("teste");
|
||||
await page.getByRole("button").nth(1).click();
|
||||
const chat_output = page.getByTestId("chat-message-AI-teste");
|
||||
const chat_input = page.getByTestId("chat-message-User-teste");
|
||||
await expect(chat_output).toHaveText("teste");
|
||||
await expect(chat_input).toHaveText("teste");
|
||||
});
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import { readFileSync } from "fs";
|
||||
|
||||
test("chat_io_teste", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
|
||||
// Read your file into a buffer.
|
||||
const jsonContent = readFileSync(
|
||||
"tests/end-to-end/assets/ChatTest.json",
|
||||
"utf-8"
|
||||
);
|
||||
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
// Create the DataTransfer and File
|
||||
const dataTransfer = await page.evaluateHandle((data) => {
|
||||
const dt = new DataTransfer();
|
||||
// Convert the buffer to a hex array
|
||||
const file = new File([data], "ChatTest.json", {
|
||||
type: "application/json",
|
||||
});
|
||||
dt.items.add(file);
|
||||
return dt;
|
||||
}, jsonContent);
|
||||
|
||||
// Now dispatch
|
||||
await page.dispatchEvent(
|
||||
'//*[@id="react-flow-id"]/div[1]/div[1]/div',
|
||||
"drop",
|
||||
{
|
||||
dataTransfer,
|
||||
}
|
||||
);
|
||||
await page.getByLabel("fit view").click();
|
||||
await page.getByText("Run", { exact: true }).click();
|
||||
await page.getByPlaceholder("Send a message...").click();
|
||||
await page.getByPlaceholder("Send a message...").fill("teste");
|
||||
await page.getByRole("button").nth(1).click();
|
||||
const chat_output = page.getByTestId("chat-message-AI-teste");
|
||||
const chat_input = page.getByTestId("chat-message-User-teste");
|
||||
await expect(chat_output).toHaveText("teste");
|
||||
await expect(chat_input).toHaveText("teste");
|
||||
});
|
||||
|
|
@ -1,67 +1,82 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import { test } from "@playwright/test";
|
||||
|
||||
test("CodeAreaModalComponent", async ({ page }) => {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByTestId("extended-disclosure").click();
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("pythonfunctiontool");
|
||||
await page.getByPlaceholder("Search").fill("python function");
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page
|
||||
.getByTestId("toolsPythonFunctionTool")
|
||||
.getByTestId("experimentalPython Function")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTestId("div-generic-node").click();
|
||||
await page.getByTestId("code-button-modal").click();
|
||||
|
||||
let value = await page.locator('//*[@id="codeValue"]').inputValue();
|
||||
const code =
|
||||
'def python_function(text: str) -> str:\n """This is a default python function that returns the input text"""\n return text';
|
||||
const wCode =
|
||||
'def python_function(text: str) -> st: """This is a default python function that returns the input text""" return text';
|
||||
const assertCode =
|
||||
'def python_function(text: str) -> str: """This is a default python function that returns the input text""" return text';
|
||||
|
||||
const customComponentCode = `from typing import Callable
|
||||
from langflow.field_typing import Code
|
||||
from langflow.interface.custom.custom_component import CustomComponent
|
||||
from langflow.interface.custom.utils import get_function
|
||||
|
||||
class PythonFunctionComponent(CustomComponent):
|
||||
def python_function(text: str) -> str:
|
||||
"""This is a default python function that returns the input text"""
|
||||
return text`;
|
||||
|
||||
await page
|
||||
.locator("#CodeEditor div")
|
||||
.filter({ hasText: "def python_function(text: str" })
|
||||
.filter({ hasText: "PythonFunctionComponent" })
|
||||
.nth(1)
|
||||
.click();
|
||||
await page.locator("textarea").press("Control+a");
|
||||
await page.locator("textarea").fill(wCode);
|
||||
await page.locator('//*[@id="checkAndSaveBtn"]').click();
|
||||
await page.waitForTimeout(1000);
|
||||
expect(
|
||||
await page.getByText("invalid syntax (<unknown>, line 1)").isVisible()
|
||||
).toBeTruthy();
|
||||
// expect(
|
||||
// await page.getByText("invalid syntax (<unknown>, line 1)").isVisible()
|
||||
// ).toBeTruthy();
|
||||
await page.locator("textarea").press("Control+a");
|
||||
await page.locator("textarea").fill(wCode);
|
||||
await page.locator("textarea").fill(code);
|
||||
await page.locator("textarea").fill(customComponentCode);
|
||||
await page.locator('//*[@id="checkAndSaveBtn"]').click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
expect(await page.getByText("Code is ready to run").isVisible()).toBeTruthy();
|
||||
await page.getByTestId("code-button-modal").click();
|
||||
expect(await page.locator('//*[@id="codeValue"]').inputValue()).toBe(
|
||||
assertCode
|
||||
);
|
||||
// await page.getByTestId("code-button-modal").click();
|
||||
// const inputCodeValue = await page
|
||||
// .locator('//*[@id="codeValue"]')
|
||||
// .inputValue();
|
||||
|
||||
// expect(inputCodeValue).toContain("def python_function(text: str) -> str");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,9 +1,22 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("curl_api_generation", async ({ page, context }) => {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await context.grantPermissions(["clipboard-read", "clipboard-write"]);
|
||||
await page.goto("/");
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByText("API", { exact: true }).click();
|
||||
|
|
|
|||
|
|
@ -4,7 +4,25 @@ import { readFileSync } from "fs";
|
|||
test.describe("drag and drop test", () => {
|
||||
/// <reference lib="dom"/>
|
||||
test("drop collection", async ({ page }) => {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.goto("/");
|
||||
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
await page.locator("span").filter({ hasText: "Close" }).first().click();
|
||||
|
||||
await page.locator("span").filter({ hasText: "My Collection" }).isVisible();
|
||||
// Read your file into a buffer.
|
||||
const jsonContent = readFileSync(
|
||||
|
|
@ -36,7 +54,7 @@ test.describe("drag and drop test", () => {
|
|||
await page.waitForTimeout(1000);
|
||||
|
||||
const genericNoda = page.getByTestId("div-generic-node");
|
||||
const elementCount = await genericNoda.count();
|
||||
const elementCount = await genericNoda?.count();
|
||||
if (elementCount > 0) {
|
||||
expect(true).toBeTruthy();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,24 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("dropDownComponent", async ({ page }) => {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
|
|
@ -22,17 +36,10 @@ test("dropDownComponent", async ({ page }) => {
|
|||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTestId("title-Amazon Bedrock").click();
|
||||
|
||||
await page.getByTestId("dropdown-model_id").click();
|
||||
|
|
|
|||
88
src/frontend/tests/end-to-end/fileUploadComponent.spec.ts
Normal file
88
src/frontend/tests/end-to-end/fileUploadComponent.spec.ts
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import path from "path";
|
||||
|
||||
test("dropDownComponent", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("extended-disclosure").click();
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("file");
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page
|
||||
.getByTestId("dataFile")
|
||||
.first()
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
const fileChooserPromise = page.waitForEvent("filechooser");
|
||||
await page.getByTestId("icon-FileSearch2").click();
|
||||
const fileChooser = await fileChooserPromise;
|
||||
await fileChooser.setFiles(path.join(__dirname, "/assets/test_file.txt"));
|
||||
await page.getByText("test_file.txt").isVisible();
|
||||
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("text output");
|
||||
|
||||
await page
|
||||
.getByTestId("outputsText Output")
|
||||
.first()
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
// Click and hold on the first element
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[1]/div/div[2]/div[6]/button/div/div'
|
||||
)
|
||||
.hover();
|
||||
await page.mouse.down();
|
||||
|
||||
// Move to the second element
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[3]/div/button/div/div'
|
||||
)
|
||||
.hover();
|
||||
|
||||
// Release the mouse
|
||||
await page.mouse.up();
|
||||
|
||||
await page.getByText("Run", { exact: true }).click();
|
||||
await page.getByText("Run Flow", { exact: true }).click();
|
||||
await page.waitForTimeout(3000);
|
||||
const textOutput = await page.getByPlaceholder("Empty").first().inputValue();
|
||||
|
||||
expect(textOutput).toContain("this is a test file");
|
||||
});
|
||||
|
|
@ -1,11 +1,24 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("LLMChain - Tooltip", async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(1000);
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
|
@ -20,18 +33,10 @@ test("LLMChain - Tooltip", async ({ page }) => {
|
|||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
await page
|
||||
.locator(
|
||||
|
|
@ -39,26 +44,20 @@ test("LLMChain - Tooltip", async ({ page }) => {
|
|||
)
|
||||
.hover()
|
||||
.then(async () => {
|
||||
await expect(
|
||||
page.getByTestId("available-input-model_specs").first()
|
||||
).toBeVisible();
|
||||
await expect(page.getByTestId("tooltip-Chains").first()).toBeVisible();
|
||||
|
||||
await expect(page.getByTestId("tooltip-Models").first()).toBeVisible();
|
||||
await expect(page.getByTestId("tooltip-Inputs").first()).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.getByTestId("tooltip-AzureOpenAIModel").first()
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.getByTestId("tooltip-Model Specs").first()
|
||||
).toBeVisible();
|
||||
await expect(page.getByTestId("tooltip-Outputs").first()).toBeVisible();
|
||||
|
||||
await page.getByTestId("icon-X").click();
|
||||
await page.waitForTimeout(500);
|
||||
});
|
||||
|
||||
await page.getByTitle("fit view").click();
|
||||
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[4]/div/button/div/div'
|
||||
|
|
@ -66,18 +65,14 @@ test("LLMChain - Tooltip", async ({ page }) => {
|
|||
.hover()
|
||||
.then(async () => {
|
||||
await expect(
|
||||
page.getByTestId("available-input-memories").first()
|
||||
page.getByTestId("tooltip-Model Specs").first()
|
||||
).toBeVisible();
|
||||
|
||||
await expect(page.getByTestId("tooltip-Memories").first()).toBeVisible();
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await expect(
|
||||
page
|
||||
.getByTestId(
|
||||
"tooltip-ConversationBufferMemory, ConversationBufferWindowMemory, ConversationEntityMemory, ConversationKGMemory, ConversationSummaryMemory, MotorheadMemory, VectorStoreRetrieverMemory"
|
||||
)
|
||||
.first()
|
||||
page.getByTestId("tooltip-Model Specs").first()
|
||||
).toBeVisible();
|
||||
|
||||
await page.getByTestId("icon-Search").click();
|
||||
|
||||
await page.waitForTimeout(500);
|
||||
|
|
@ -97,11 +92,29 @@ test("LLMChain - Tooltip", async ({ page }) => {
|
|||
});
|
||||
|
||||
test("LLMChain - Filter", async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByTestId(
|
||||
"input-list-plus-btn-edit_metadata_indexing_include-2"
|
||||
);
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
|
@ -115,43 +128,22 @@ test("LLMChain - Filter", async ({ page }) => {
|
|||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page.getByTitle("fit view").click();
|
||||
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[3]/div/button/div/div'
|
||||
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[4]/div/button/div/div'
|
||||
)
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[3]/div/button/div/div'
|
||||
)
|
||||
.click();
|
||||
await page.getByTestId("icon-Search").click();
|
||||
|
||||
await expect(page.getByTestId("disclosure-models")).toBeVisible();
|
||||
await expect(page.getByTestId("disclosure-model specs")).toBeVisible();
|
||||
|
||||
await expect(page.getByTestId("modelsAzure OpenAI")).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsAnthropic").first()).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsAmazon Bedrock")).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsAnthropic")).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsAnthropicLLM")).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsAzureChatOpenAI")).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsChatAnthropic")).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsChatLiteLLM")).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsChatOllama")).toBeVisible();
|
||||
await expect(page.getByTestId("model_specsChatOpenAI")).toBeVisible();
|
||||
|
|
@ -176,8 +168,6 @@ test("LLMChain - Filter", async ({ page }) => {
|
|||
await expect(page.getByTestId("model_specsCTransformers")).not.toBeVisible();
|
||||
await expect(page.getByTestId("model_specsAmazon Bedrock")).not.toBeVisible();
|
||||
await expect(page.getByTestId("modelsAzure OpenAI")).not.toBeVisible();
|
||||
await expect(page.getByTestId("model_specsAnthropic")).not.toBeVisible();
|
||||
await expect(page.getByTestId("model_specsAnthropicLLM")).not.toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("model_specsAzureChatOpenAI")
|
||||
).not.toBeVisible();
|
||||
|
|
@ -190,52 +180,19 @@ test("LLMChain - Filter", async ({ page }) => {
|
|||
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[4]/div/button/div/div'
|
||||
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[7]/button/div/div'
|
||||
)
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div[1]/div[1]/div/div/div[2]/div/div/div[2]/div[4]/div/button/div/div'
|
||||
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div/div/div[2]/div[7]/button/div/div'
|
||||
)
|
||||
.click();
|
||||
|
||||
await expect(page.getByTestId("disclosure-memories")).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("memoriesConversationBufferMemory")
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("memoriesConversationBufferWindowMemory")
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("memoriesConversationEntityMemory")
|
||||
).toBeVisible();
|
||||
await expect(page.getByTestId("memoriesConversationKGMemory")).toBeVisible();
|
||||
await expect(page.getByTestId("memoriesConversationKGMemory")).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("memoriesConversationSummaryMemory")
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("memoriesVectorStoreRetrieverMemory")
|
||||
).toBeVisible();
|
||||
|
||||
await page.getByTestId("rf__wrapper").click();
|
||||
|
||||
await expect(
|
||||
page.getByTestId("memoriesConversationBufferMemory")
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("memoriesConversationBufferWindowMemory")
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("memoriesConversationEntityMemory")
|
||||
).toBeVisible();
|
||||
await expect(page.getByTestId("memoriesConversationKGMemory")).toBeVisible();
|
||||
await expect(page.getByTestId("memoriesConversationKGMemory")).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("memoriesConversationSummaryMemory")
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId("memoriesVectorStoreRetrieverMemory")
|
||||
).toBeVisible();
|
||||
await expect(page.getByTestId("inputsChat Input")).toBeVisible();
|
||||
await expect(page.getByTestId("outputsChat Output")).toBeVisible();
|
||||
await expect(page.getByTestId("helpersID Generator")).toBeVisible();
|
||||
await expect(page.getByTestId("vectorstoresChroma")).toBeVisible();
|
||||
await expect(page.getByTestId("disclosure-vector stores")).toBeVisible();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,10 +1,24 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("FloatComponent", async ({ page }) => {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
|
|
@ -20,28 +34,10 @@ test("FloatComponent", async ({ page }) => {
|
|||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
await page.locator('//*[@id="float-input"]').click();
|
||||
await page.locator('//*[@id="float-input"]').fill("3");
|
||||
|
|
@ -145,7 +141,7 @@ test("FloatComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
const plusButtonLocator = page.locator('//*[@id="float-input"]');
|
||||
const elementCount = await plusButtonLocator.count();
|
||||
const elementCount = await plusButtonLocator?.count();
|
||||
if (elementCount === 0) {
|
||||
expect(true).toBeTruthy();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,25 @@
|
|||
import { Page, test } from "@playwright/test";
|
||||
import { test } from "@playwright/test";
|
||||
|
||||
test.describe("Flow Page tests", () => {
|
||||
async function goToFlowPage(page: Page) {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.getByRole("button", { name: "New Project" }).click();
|
||||
}
|
||||
|
||||
test("save", async ({ page }) => {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(1000);
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
|
@ -26,18 +34,9 @@ test.describe("Flow Page tests", () => {
|
|||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
// await page.getByTestId("icon-ExternalLink").click();
|
||||
// await page.locator('//*[@id="checkAndSaveBtn"]').click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
73
src/frontend/tests/end-to-end/flowSettings.spec.ts
Normal file
73
src/frontend/tests/end-to-end/flowSettings.spec.ts
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("flowSettings", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("flow_name").click();
|
||||
await page.getByText("Settings").first().click();
|
||||
await page
|
||||
.getByPlaceholder("Flow name")
|
||||
.fill(
|
||||
"Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test"
|
||||
);
|
||||
|
||||
await page.getByText("Character limit reached").isVisible();
|
||||
|
||||
await page.getByPlaceholder("Flow name").click();
|
||||
const randomName = Math.random().toString(36).substring(2);
|
||||
await page.getByPlaceholder("Flow name").fill(randomName);
|
||||
await page.getByPlaceholder("Flow name").click();
|
||||
await page
|
||||
.getByPlaceholder("Flow description")
|
||||
.fill(
|
||||
"Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test"
|
||||
);
|
||||
|
||||
await page.getByText("Save").last().click();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByText("Changes saved successfully").isVisible();
|
||||
|
||||
await page.getByTestId("flow_name").click();
|
||||
await page.getByText("Settings").first().click();
|
||||
|
||||
const flowName = await page.getByPlaceholder("Flow name").inputValue();
|
||||
const flowDescription = await page
|
||||
.getByPlaceholder("Flow description")
|
||||
.inputValue();
|
||||
|
||||
if (flowName != randomName) {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
||||
if (
|
||||
flowDescription !=
|
||||
"Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test Flow Name Test"
|
||||
) {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
await page.getByText("Saved").first().isVisible();
|
||||
await page.getByTestId("icon-CheckCircle2").first().isVisible();
|
||||
});
|
||||
79
src/frontend/tests/end-to-end/globalVariables.spec.ts
Normal file
79
src/frontend/tests/end-to-end/globalVariables.spec.ts
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("GlobalVariables", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByTestId("extended-disclosure").click();
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("openai");
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page
|
||||
.getByTestId("modelsOpenAI")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
const genericName = Math.random().toString();
|
||||
const credentialName = Math.random().toString();
|
||||
|
||||
await page.getByTestId("icon-Globe").nth(1).click();
|
||||
await page.getByText("Add New Variable", { exact: true }).click();
|
||||
await page
|
||||
.getByPlaceholder("Insert a name for the variable...")
|
||||
.fill(genericName);
|
||||
await page.getByTestId("icon-ChevronsUpDown").nth(1).click();
|
||||
await page.getByText("Generic", { exact: true }).click();
|
||||
await page
|
||||
.getByPlaceholder("Insert a value for the variable...")
|
||||
.fill("This is a test of generic variable value");
|
||||
await page.getByText("Save Variable", { exact: true }).click();
|
||||
expect(page.getByText(genericName, { exact: true })).not.toBeNull();
|
||||
await page.getByText(genericName, { exact: true }).isVisible();
|
||||
|
||||
await page.getByText("Add New Variable", { exact: true }).click();
|
||||
await page
|
||||
.getByPlaceholder("Insert a name for the variable...")
|
||||
.fill(credentialName);
|
||||
await page.getByTestId("icon-ChevronsUpDown").nth(1).click();
|
||||
await page.getByText("Credential", { exact: true }).click();
|
||||
await page
|
||||
.getByPlaceholder("Insert a value for the variable...")
|
||||
.fill("This is a test of credential variable value");
|
||||
await page.getByText("Save Variable", { exact: true }).click();
|
||||
expect(page.getByText(credentialName, { exact: true })).not.toBeNull();
|
||||
await page.getByText(credentialName, { exact: true }).isVisible();
|
||||
await page
|
||||
.getByText(credentialName, { exact: true })
|
||||
.hover()
|
||||
.then(async () => {
|
||||
await page.getByTestId("icon-Trash2").last().click();
|
||||
await page.getByText("Delete", { exact: true }).nth(1).click();
|
||||
});
|
||||
});
|
||||
|
|
@ -4,7 +4,21 @@ test.describe("group node test", () => {
|
|||
/// <reference lib="dom"/>
|
||||
test("group and ungroup updating values", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
|
||||
await page
|
||||
.getByRole("heading", { name: "Basic Prompting" })
|
||||
|
|
@ -13,8 +27,6 @@ test.describe("group node test", () => {
|
|||
await page.waitForTimeout(2000);
|
||||
await page.getByLabel("fit view").first().click();
|
||||
await page.getByTestId("title-OpenAI").click({ modifiers: ["Control"] });
|
||||
await page.getByTestId("title-Prompt").click({ modifiers: ["Control"] });
|
||||
await page.getByTestId("title-OpenAI").click({ modifiers: ["Control"] });
|
||||
|
||||
await page.getByRole("button", { name: "Group" }).click();
|
||||
await page.getByTestId("title-Group").dblclick();
|
||||
|
|
|
|||
|
|
@ -1,10 +1,24 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("InputComponent", async ({ page }) => {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
|
|
@ -20,17 +34,10 @@ test("InputComponent", async ({ page }) => {
|
|||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTestId("input-collection_name").click();
|
||||
await page
|
||||
.getByTestId("input-collection_name")
|
||||
|
|
@ -132,7 +139,7 @@ test("InputComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
const plusButtonLocator = page.getByTestId("input-collection_name");
|
||||
const elementCount = await plusButtonLocator.count();
|
||||
const elementCount = await plusButtonLocator?.count();
|
||||
if (elementCount === 0) {
|
||||
expect(true).toBeTruthy();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,36 +1,41 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("InputListComponent", async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(1000);
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByTestId("extended-disclosure").click();
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("astradb search");
|
||||
await page.getByPlaceholder("Search").fill("astradb");
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
await page
|
||||
.getByTestId("vectorsearchAstraDB Search")
|
||||
.getByTestId("vectorsearchAstra DB Search")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTestId("div-generic-node").click();
|
||||
await page.getByTestId("more-options-modal").click();
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
|
@ -90,7 +95,7 @@ test("InputListComponent", async ({ page }) => {
|
|||
const plusButtonLocator = page.getByTestId(
|
||||
"input-list-plus-btn_metadata_indexing_include-1"
|
||||
);
|
||||
const elementCount = await plusButtonLocator.count();
|
||||
const elementCount = await plusButtonLocator?.count();
|
||||
|
||||
if (elementCount > 0) {
|
||||
expect(false).toBeTruthy();
|
||||
|
|
@ -161,12 +166,12 @@ test("InputListComponent", async ({ page }) => {
|
|||
const plusButtonLocatorEdit0 = await page.getByTestId(
|
||||
"input-list-plus-btn-edit_metadata_indexing_include-0"
|
||||
);
|
||||
const elementCountEdit0 = await plusButtonLocatorEdit0.count();
|
||||
const elementCountEdit0 = await plusButtonLocatorEdit0?.count();
|
||||
|
||||
const plusButtonLocatorEdit2 = await page.getByTestId(
|
||||
"input-list-plus-btn-edit_metadata_indexing_include-2"
|
||||
);
|
||||
const elementCountEdit2 = await plusButtonLocatorEdit2.count();
|
||||
const elementCountEdit2 = await plusButtonLocatorEdit2?.count();
|
||||
|
||||
if (elementCountEdit0 > 0 || elementCountEdit2 > 0) {
|
||||
expect(false).toBeTruthy();
|
||||
|
|
@ -176,13 +181,13 @@ test("InputListComponent", async ({ page }) => {
|
|||
"input-list-minus-btn-edit_metadata_indexing_include-1"
|
||||
);
|
||||
|
||||
const elementCountMinusEdit1 = await minusButtonLocatorEdit1.count();
|
||||
const elementCountMinusEdit1 = await minusButtonLocatorEdit1?.count();
|
||||
|
||||
const minusButtonLocatorEdit2 = await page.getByTestId(
|
||||
"input-list-minus-btn-edit_metadata_indexing_include-2"
|
||||
);
|
||||
|
||||
const elementCountMinusEdit2 = await minusButtonLocatorEdit2.count();
|
||||
const elementCountMinusEdit2 = await minusButtonLocatorEdit2?.count();
|
||||
|
||||
if (elementCountMinusEdit1 > 0 || elementCountMinusEdit2 > 0) {
|
||||
expect(false).toBeTruthy();
|
||||
|
|
|
|||
|
|
@ -1,10 +1,24 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("IntComponent", async ({ page }) => {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
|
|
@ -21,17 +35,10 @@ test("IntComponent", async ({ page }) => {
|
|||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTestId("int-input-max_tokens").click();
|
||||
await page
|
||||
.getByTestId("int-input-max_tokens")
|
||||
|
|
@ -53,17 +60,10 @@ test("IntComponent", async ({ page }) => {
|
|||
}
|
||||
|
||||
await page.getByTestId("title-ChatOpenAI").click();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
await page.getByTestId("more-options-modal").click();
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
|
@ -157,7 +157,7 @@ test("IntComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
const plusButtonLocator = page.getByTestId("int-input-max_tokens");
|
||||
const elementCount = await plusButtonLocator.count();
|
||||
const elementCount = await plusButtonLocator?.count();
|
||||
if (elementCount === 0) {
|
||||
expect(true).toBeTruthy();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,36 +1,43 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("KeypairListComponent", async ({ page }) => {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByTestId("extended-disclosure").click();
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("csv");
|
||||
await page.getByPlaceholder("Search").fill("amazon bedrock");
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page
|
||||
.getByTestId("documentloadersCSVLoader")
|
||||
.getByTestId("model_specsAmazon Bedrock")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.locator('//*[@id="keypair0"]').click();
|
||||
await page.locator('//*[@id="keypair0"]').fill("testtesttesttest");
|
||||
await page.locator('//*[@id="keypair100"]').click();
|
||||
|
|
@ -48,7 +55,7 @@ test("KeypairListComponent", async ({ page }) => {
|
|||
}
|
||||
|
||||
const plusButtonLocatorNode = page.locator('//*[@id="plusbtn0"]');
|
||||
const elementCountNode = await plusButtonLocatorNode.count();
|
||||
const elementCountNode = await plusButtonLocatorNode?.count();
|
||||
if (elementCountNode > 0) {
|
||||
await plusButtonLocatorNode.click();
|
||||
}
|
||||
|
|
@ -59,7 +66,7 @@ test("KeypairListComponent", async ({ page }) => {
|
|||
await page.getByTestId("div-generic-node").click();
|
||||
|
||||
const keyPairVerification = page.locator('//*[@id="keypair100"]');
|
||||
const elementKeyCount = await keyPairVerification.count();
|
||||
const elementKeyCount = await keyPairVerification?.count();
|
||||
|
||||
if (elementKeyCount === 1) {
|
||||
expect(true).toBeTruthy();
|
||||
|
|
@ -70,16 +77,16 @@ test("KeypairListComponent", async ({ page }) => {
|
|||
await page.getByTestId("more-options-modal").click();
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
||||
await page.locator('//*[@id="showfile_path"]').click();
|
||||
await page.locator('//*[@id="showcache"]').click();
|
||||
expect(await page.locator('//*[@id="showcache"]').isChecked()).toBeFalsy();
|
||||
await page.locator('//*[@id="showcredentials_profile_name"]').click();
|
||||
expect(
|
||||
await page.locator('//*[@id="showfile_path"]').isChecked()
|
||||
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked()
|
||||
).toBeFalsy();
|
||||
await page.locator('//*[@id="showmetadata"]').click();
|
||||
expect(await page.locator('//*[@id="showmetadata"]').isChecked()).toBeFalsy();
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
const plusButtonLocator = page.locator('//*[@id="plusbtn0"]');
|
||||
const elementCount = await plusButtonLocator.count();
|
||||
const elementCount = await plusButtonLocator?.count();
|
||||
if (elementCount === 0) {
|
||||
expect(true).toBeTruthy();
|
||||
await page.getByTestId("div-generic-node").click();
|
||||
|
|
@ -87,20 +94,18 @@ test("KeypairListComponent", async ({ page }) => {
|
|||
await page.getByTestId("more-options-modal").click();
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
||||
await page.locator('//*[@id="showfile_path"]').click();
|
||||
await page.locator('//*[@id="showcredentials_profile_name"]').click();
|
||||
expect(
|
||||
await page.locator('//*[@id="showfile_path"]').isChecked()
|
||||
).toBeTruthy();
|
||||
await page.locator('//*[@id="showmetadata"]').click();
|
||||
expect(
|
||||
await page.locator('//*[@id="showmetadata"]').isChecked()
|
||||
await page.locator('//*[@id="showcredentials_profile_name"]').isChecked()
|
||||
).toBeTruthy();
|
||||
await page.locator('//*[@id="showcache"]').click();
|
||||
expect(await page.locator('//*[@id="showcache"]').isChecked()).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="editNodekeypair0"]').click();
|
||||
await page.locator('//*[@id="editNodekeypair0"]').fill("testtesttesttest");
|
||||
|
||||
const keyPairVerification = page.locator('//*[@id="editNodekeypair0"]');
|
||||
const elementKeyCount = await keyPairVerification.count();
|
||||
const elementKeyCount = await keyPairVerification?.count();
|
||||
|
||||
if (elementKeyCount === 1) {
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import uaParser from "ua-parser-js";
|
||||
test("LangflowShortcuts", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
const getUA = await page.evaluate(() => navigator.userAgent);
|
||||
const userAgentInfo = uaParser(getUA);
|
||||
let control = "Control";
|
||||
|
|
@ -9,11 +10,23 @@ test("LangflowShortcuts", async ({ page }) => {
|
|||
control = "Meta";
|
||||
}
|
||||
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(1000);
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
|
@ -30,17 +43,10 @@ test("LangflowShortcuts", async ({ page }) => {
|
|||
await page.mouse.down();
|
||||
|
||||
await page.locator('//*[@id="react-flow-id"]/div/div[2]/button[3]').click();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTestId("title-Ollama").click();
|
||||
await page.keyboard.press(`${control}+Shift+A`);
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
|
@ -48,7 +54,7 @@ test("LangflowShortcuts", async ({ page }) => {
|
|||
await page.getByTestId("title-Ollama").click();
|
||||
await page.keyboard.press(`${control}+d`);
|
||||
|
||||
let numberOfNodes = await page.getByTestId("title-Ollama").count();
|
||||
let numberOfNodes = await page.getByTestId("title-Ollama")?.count();
|
||||
if (numberOfNodes != 2) {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
|
@ -60,7 +66,7 @@ test("LangflowShortcuts", async ({ page }) => {
|
|||
.click();
|
||||
await page.keyboard.press("Backspace");
|
||||
|
||||
numberOfNodes = await page.getByTestId("title-Ollama").count();
|
||||
numberOfNodes = await page.getByTestId("title-Ollama")?.count();
|
||||
if (numberOfNodes != 1) {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
|
@ -71,7 +77,7 @@ test("LangflowShortcuts", async ({ page }) => {
|
|||
await page.getByTestId("title-Ollama").click();
|
||||
await page.keyboard.press(`${control}+v`);
|
||||
|
||||
numberOfNodes = await page.getByTestId("title-Ollama").count();
|
||||
numberOfNodes = await page.getByTestId("title-Ollama")?.count();
|
||||
if (numberOfNodes != 2) {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
|
@ -86,12 +92,12 @@ test("LangflowShortcuts", async ({ page }) => {
|
|||
await page.getByTestId("title-Ollama").click();
|
||||
await page.keyboard.press(`${control}+x`);
|
||||
|
||||
numberOfNodes = await page.getByTestId("title-Ollama").count();
|
||||
numberOfNodes = await page.getByTestId("title-Ollama")?.count();
|
||||
if (numberOfNodes != 0) {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
await page.keyboard.press(`${control}+v`);
|
||||
numberOfNodes = await page.getByTestId("title-Ollama").count();
|
||||
numberOfNodes = await page.getByTestId("title-Ollama")?.count();
|
||||
if (numberOfNodes != 1) {
|
||||
expect(false).toBeTruthy();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,24 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("NestedComponent", async ({ page }) => {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(1000);
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
|
|
|||
|
|
@ -1,11 +1,24 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("PromptTemplateComponent", async ({ page }) => {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(1000);
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
|
@ -20,17 +33,10 @@ test("PromptTemplateComponent", async ({ page }) => {
|
|||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTestId("prompt-input-template").click();
|
||||
|
||||
await page
|
||||
|
|
|
|||
|
|
@ -2,8 +2,21 @@ import { expect, test } from "@playwright/test";
|
|||
|
||||
test("python_api_generation", async ({ page, context }) => {
|
||||
await page.goto("/");
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await context.grantPermissions(["clipboard-read", "clipboard-write"]);
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByText("API", { exact: true }).click();
|
||||
|
|
|
|||
|
|
@ -1,19 +1,26 @@
|
|||
import { Page, expect, test } from "@playwright/test";
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { readFileSync } from "fs";
|
||||
|
||||
test.describe("save component tests", () => {
|
||||
async function saveComponent(page: Page, pattern: RegExp, n: number) {
|
||||
for (let i = 0; i < n; i++) {
|
||||
await page.getByTestId(pattern).click();
|
||||
await page.getByLabel("Save").click();
|
||||
}
|
||||
}
|
||||
|
||||
/// <reference lib="dom"/>
|
||||
test("save group component tests", async ({ page }) => {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.goto("/");
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
|
|
@ -46,7 +53,7 @@ test.describe("save component tests", () => {
|
|||
);
|
||||
|
||||
const genericNoda = page.getByTestId("div-generic-node");
|
||||
const elementCount = await genericNoda.count();
|
||||
const elementCount = await genericNoda?.count();
|
||||
if (elementCount > 0) {
|
||||
expect(true).toBeTruthy();
|
||||
}
|
||||
|
|
@ -68,13 +75,13 @@ test.describe("save component tests", () => {
|
|||
await page.getByRole("button", { name: "Group" }).click();
|
||||
|
||||
let textArea = page.getByTestId("div-textarea-description");
|
||||
let elementCountText = await textArea.count();
|
||||
let elementCountText = await textArea?.count();
|
||||
if (elementCountText > 0) {
|
||||
expect(true).toBeTruthy();
|
||||
}
|
||||
|
||||
let groupNode = page.getByTestId("title-Group");
|
||||
let elementGroup = await groupNode.count();
|
||||
let elementGroup = await groupNode?.count();
|
||||
if (elementGroup > 0) {
|
||||
expect(true).toBeTruthy();
|
||||
}
|
||||
|
|
@ -98,25 +105,18 @@ test.describe("save component tests", () => {
|
|||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
textArea = page.getByTestId("div-textarea-description");
|
||||
elementCountText = await textArea.count();
|
||||
elementCountText = await textArea?.count();
|
||||
if (elementCountText > 0) {
|
||||
expect(true).toBeTruthy();
|
||||
}
|
||||
|
||||
groupNode = page.getByTestId("title-Group");
|
||||
elementGroup = await groupNode.count();
|
||||
elementGroup = await groupNode?.count();
|
||||
if (elementGroup > 0) {
|
||||
expect(true).toBeTruthy();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("should exists Store", async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("button-store").isVisible();
|
||||
|
|
@ -9,7 +9,7 @@ test("should exists Store", async ({ page }) => {
|
|||
});
|
||||
|
||||
test("should not have an API key", async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("button-store").click();
|
||||
|
|
@ -19,7 +19,7 @@ test("should not have an API key", async ({ page }) => {
|
|||
});
|
||||
|
||||
test("should find a searched Component on Store", async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("button-store").click();
|
||||
|
|
@ -39,7 +39,7 @@ test("should find a searched Component on Store", async ({ page }) => {
|
|||
});
|
||||
|
||||
test("should filter by tag", async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("button-store").click();
|
||||
|
|
@ -66,7 +66,7 @@ test("should filter by tag", async ({ page }) => {
|
|||
});
|
||||
|
||||
test("should order the visualization", async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("button-store").click();
|
||||
|
|
@ -75,6 +75,7 @@ test("should order the visualization", async ({ page }) => {
|
|||
await page.getByText("Basic RAG").isVisible();
|
||||
|
||||
await page.getByTestId("select-order-store").click();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByText("Alphabetical").click();
|
||||
|
||||
await page.getByText("Album Cover Builder").isVisible();
|
||||
|
|
@ -86,7 +87,7 @@ test("should order the visualization", async ({ page }) => {
|
|||
});
|
||||
|
||||
test("should filter by type", async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("button-store").click();
|
||||
|
|
@ -97,7 +98,7 @@ test("should filter by type", async ({ page }) => {
|
|||
await page.getByTestId("flows-button-store").click();
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
let iconGroup = await page.getByTestId("icon-Group").count();
|
||||
let iconGroup = await page.getByTestId("icon-Group")?.count();
|
||||
expect(iconGroup).not.toBe(0);
|
||||
|
||||
await page.getByText("icon-ToyBrick").isHidden();
|
||||
|
|
@ -106,14 +107,14 @@ test("should filter by type", async ({ page }) => {
|
|||
await page.waitForTimeout(3000);
|
||||
|
||||
await page.getByTestId("icon-Group").isHidden();
|
||||
let toyBrick = await page.getByTestId("icon-ToyBrick").count();
|
||||
let toyBrick = await page.getByTestId("icon-ToyBrick")?.count();
|
||||
expect(toyBrick).not.toBe(0);
|
||||
|
||||
await page.getByTestId("all-button-store").click();
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
iconGroup = await page.getByTestId("icon-Group").count();
|
||||
toyBrick = await page.getByTestId("icon-ToyBrick").count();
|
||||
iconGroup = await page.getByTestId("icon-Group")?.count();
|
||||
toyBrick = await page.getByTestId("icon-ToyBrick")?.count();
|
||||
|
||||
if (iconGroup === 0 || toyBrick === 0) {
|
||||
expect(false).toBe(true);
|
||||
|
|
@ -121,7 +122,7 @@ test("should filter by type", async ({ page }) => {
|
|||
});
|
||||
|
||||
test("should add API-KEY", async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("button-store").click();
|
||||
|
|
@ -154,7 +155,7 @@ test("should add API-KEY", async ({ page }) => {
|
|||
});
|
||||
|
||||
test("should like and add components and flows", async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("button-store").click();
|
||||
|
|
@ -216,3 +217,60 @@ test("should like and add components and flows", async ({ page }) => {
|
|||
await page.getByTestId("sidebar-nav-Components").click();
|
||||
await page.getByText("Basic RAG").first().isVisible();
|
||||
});
|
||||
|
||||
test("should share component with share button", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page.waitForTimeout(1000);
|
||||
const flowName = await page.getByTestId("flow_name").innerText();
|
||||
await page.getByTestId("flow_name").click();
|
||||
await page.getByText("Settings").click();
|
||||
const flowDescription = await page
|
||||
.getByPlaceholder("Flow description")
|
||||
.inputValue();
|
||||
await page.getByText("Save").last().click();
|
||||
|
||||
await page.getByTestId("icon-Share3").first().click();
|
||||
await page.getByText("Name:").isVisible();
|
||||
await page.getByText("Description:").isVisible();
|
||||
await page.getByText("Set workflow status to public").isVisible();
|
||||
await page
|
||||
.getByText(
|
||||
"Attention: API keys in specified fields are automatically removed upon sharing."
|
||||
)
|
||||
.isVisible();
|
||||
await page.getByText("Export").first().isVisible();
|
||||
await page.getByText("Share Flow").first().isVisible();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
await page.getByText("Agent").first().isVisible();
|
||||
await page.getByText("Memory").first().isVisible();
|
||||
await page.getByText("Chain").first().isVisible();
|
||||
await page.getByText("Vector Store").first().isVisible();
|
||||
await page.getByText("Prompt").last().isVisible();
|
||||
await page.getByTestId("public-checkbox").isChecked();
|
||||
await page.getByText(flowName).last().isVisible();
|
||||
await page.getByText(flowDescription).last().isVisible();
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByText("Flow shared successfully").last().isVisible();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,13 +1,25 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("TextAreaModalComponent", async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(1000);
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByTestId("extended-disclosure").click();
|
||||
|
|
@ -21,17 +33,10 @@ test("TextAreaModalComponent", async ({ page }) => {
|
|||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTestId("prompt-input-template").click();
|
||||
|
||||
await page.getByTestId("modal-prompt-input-template").fill("{text}");
|
||||
|
|
|
|||
153
src/frontend/tests/end-to-end/textInputOutput.spec.ts
Normal file
153
src/frontend/tests/end-to-end/textInputOutput.spec.ts
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
|
||||
test("TextInputOutputComponent", async ({ page }) => {
|
||||
if (!process.env.CI) {
|
||||
dotenv.config();
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByTestId("extended-disclosure").click();
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("text input");
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page
|
||||
.getByTestId("inputsText Input")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("openai");
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page
|
||||
.getByTestId("modelsOpenAI")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
// Click and hold on the first element
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[1]/div/div[2]/div[6]/button/div/div'
|
||||
)
|
||||
.hover();
|
||||
await page.mouse.down();
|
||||
|
||||
// Move to the second element
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[9]/div/button/div/div'
|
||||
)
|
||||
.hover();
|
||||
|
||||
// Release the mouse
|
||||
await page.mouse.up();
|
||||
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("text output");
|
||||
|
||||
await page
|
||||
.getByTestId("outputsText Output")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
// Click and hold on the first element
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[2]/div/div[2]/div[13]/button/div/div'
|
||||
)
|
||||
.hover();
|
||||
await page.mouse.down();
|
||||
|
||||
// Move to the second element
|
||||
await page
|
||||
.locator(
|
||||
'//*[@id="react-flow-id"]/div/div[1]/div[1]/div/div[2]/div[3]/div/div[2]/div[3]/div/button/div/div'
|
||||
)
|
||||
.hover();
|
||||
|
||||
// Release the mouse
|
||||
await page.mouse.up();
|
||||
|
||||
if (!process.env.OPENAI_API_KEY) {
|
||||
//You must set the OPENAI_API_KEY on .env file to run this test
|
||||
expect(false).toBe(true);
|
||||
}
|
||||
|
||||
await page.getByTestId("input-input_value").nth(0).fill("This is a test!");
|
||||
|
||||
await page
|
||||
.getByTestId("input-openai_api_key")
|
||||
.fill(process.env.OPENAI_API_KEY ?? "");
|
||||
await page.getByText("Run", { exact: true }).click();
|
||||
await page.getByText("Run Flow", { exact: true }).click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
let textInputContent = await page
|
||||
.getByPlaceholder("Enter text...")
|
||||
.textContent();
|
||||
expect(textInputContent).toBe("This is a test!");
|
||||
|
||||
await page.getByText("Outputs", { exact: true }).nth(1).click();
|
||||
await page.getByText("Text Output", { exact: true }).nth(2).click();
|
||||
let contentOutput = await page.getByPlaceholder("Empty").inputValue();
|
||||
expect(contentOutput).not.toBe(null);
|
||||
|
||||
await page.keyboard.press("Escape");
|
||||
|
||||
await page
|
||||
.getByTestId("input-input_value")
|
||||
.nth(0)
|
||||
.fill("This is a test, again just to be sure!");
|
||||
await page.getByText("Run", { exact: true }).click();
|
||||
await page.getByText("Run Flow", { exact: true }).click();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
textInputContent = await page.getByPlaceholder("Enter text...").textContent();
|
||||
expect(textInputContent).toBe("This is a test, again just to be sure!");
|
||||
|
||||
await page.getByText("Outputs", { exact: true }).nth(1).click();
|
||||
await page.getByText("Text Output", { exact: true }).nth(2).click();
|
||||
contentOutput = await page.getByPlaceholder("Empty").inputValue();
|
||||
expect(contentOutput).not.toBe(null);
|
||||
});
|
||||
|
|
@ -1,36 +1,42 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
|
||||
test("ToggleComponent", async ({ page }) => {
|
||||
await page.goto("http:localhost:3000/");
|
||||
await page.goto("/");
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(1000);
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
|
||||
await page.getByTestId("blank-flow").click();
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByTestId("extended-disclosure").click();
|
||||
await page.getByPlaceholder("Search").click();
|
||||
await page.getByPlaceholder("Search").fill("directoryLoader");
|
||||
await page.getByPlaceholder("Search").fill("directory");
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
await page
|
||||
.getByTestId("documentloadersDirectoryLoader")
|
||||
.getByTestId("dataDirectory")
|
||||
.dragTo(page.locator('//*[@id="react-flow-id"]'));
|
||||
await page.mouse.up();
|
||||
await page.mouse.down();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
|
||||
await page
|
||||
.locator('//*[@id="react-flow-id"]/div[1]/div[2]/button[2]')
|
||||
.click();
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
await page.getByTestId("div-generic-node").click();
|
||||
|
||||
|
|
@ -44,8 +50,7 @@ test("ToggleComponent", async ({ page }) => {
|
|||
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeFalsy();
|
||||
await page.getByTitle("fit view").click();
|
||||
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeTruthy();
|
||||
|
|
@ -59,15 +64,20 @@ test("ToggleComponent", async ({ page }) => {
|
|||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeFalsy();
|
||||
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeTruthy();
|
||||
|
||||
await page.getByTestId("div-generic-node").click();
|
||||
|
||||
await page.getByTitle("fit view").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
await page.getByTitle("zoom out").click();
|
||||
|
||||
await page.getByTestId("more-options-modal").click();
|
||||
await page.getByTestId("edit-button-modal").click();
|
||||
|
||||
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="showglob"]').click();
|
||||
expect(await page.locator('//*[@id="showglob"]').isChecked()).toBeFalsy();
|
||||
expect(await page.getByTestId("toggle-load_hidden").isChecked()).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="showload_hidden"]').click();
|
||||
expect(
|
||||
|
|
@ -79,9 +89,6 @@ test("ToggleComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="showmax_concurrency"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="showmetadata"]').click();
|
||||
expect(await page.locator('//*[@id="showmetadata"]').isChecked()).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="showpath"]').click();
|
||||
expect(await page.locator('//*[@id="showpath"]').isChecked()).toBeFalsy();
|
||||
|
||||
|
|
@ -100,19 +107,11 @@ test("ToggleComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="showuse_multithreading"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="showglob"]').click();
|
||||
expect(await page.locator('//*[@id="showglob"]').isChecked()).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="showmax_concurrency"]').click();
|
||||
expect(
|
||||
await page.locator('//*[@id="showmax_concurrency"]').isChecked()
|
||||
).toBeFalsy();
|
||||
|
||||
await page.locator('//*[@id="showmetadata"]').click();
|
||||
expect(
|
||||
await page.locator('//*[@id="showmetadata"]').isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="showpath"]').click();
|
||||
expect(await page.locator('//*[@id="showpath"]').isChecked()).toBeTruthy();
|
||||
|
||||
|
|
@ -134,7 +133,7 @@ test("ToggleComponent", async ({ page }) => {
|
|||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
const plusButtonLocator = page.getByTestId("toggle-load_hidden");
|
||||
const elementCount = await plusButtonLocator.count();
|
||||
const elementCount = await plusButtonLocator?.count();
|
||||
if (elementCount === 0) {
|
||||
expect(true).toBeTruthy();
|
||||
|
||||
|
|
@ -150,15 +149,10 @@ test("ToggleComponent", async ({ page }) => {
|
|||
|
||||
expect(
|
||||
await page.getByTestId("toggle-edit-load_hidden").isChecked()
|
||||
).toBeFalsy();
|
||||
).toBeTruthy();
|
||||
|
||||
await page.locator('//*[@id="saveChangesBtn"]').click();
|
||||
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(
|
||||
await page.getByTestId("toggle-load_hidden").isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(
|
||||
await page.getByTestId("toggle-load_hidden").isChecked()
|
||||
|
|
@ -178,5 +172,10 @@ test("ToggleComponent", async ({ page }) => {
|
|||
expect(
|
||||
await page.getByTestId("toggle-load_hidden").isChecked()
|
||||
).toBeTruthy();
|
||||
|
||||
await page.getByTestId("toggle-load_hidden").click();
|
||||
expect(
|
||||
await page.getByTestId("toggle-load_hidden").isChecked()
|
||||
).toBeFalsy();
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,8 +2,22 @@ import { expect, test } from "@playwright/test";
|
|||
|
||||
test("curl_api_generation", async ({ page, context }) => {
|
||||
await page.goto("/");
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await context.grantPermissions(["clipboard-read", "clipboard-write"]);
|
||||
let modalCount = 0;
|
||||
try {
|
||||
const modalTitleElement = await page?.getByTestId("modal-title");
|
||||
if (modalTitleElement) {
|
||||
modalCount = await modalTitleElement.count();
|
||||
}
|
||||
} catch (error) {
|
||||
modalCount = 0;
|
||||
}
|
||||
|
||||
while (modalCount === 0) {
|
||||
await page.locator('//*[@id="new-project-btn"]').click();
|
||||
await page.waitForTimeout(5000);
|
||||
modalCount = await page.getByTestId("modal-title")?.count();
|
||||
}
|
||||
|
||||
await page.getByRole("heading", { name: "Basic Prompting" }).click();
|
||||
await page.waitForTimeout(2000);
|
||||
await page.getByText("API", { exact: true }).click();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue