diff --git a/.github/workflows/frontend-build-and-packaging.yml b/.github/workflows/frontend-build-and-packaging.yml new file mode 100644 index 00000000..f41cb0aa --- /dev/null +++ b/.github/workflows/frontend-build-and-packaging.yml @@ -0,0 +1,29 @@ +name: frontend-build-and-packaging + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build-and-packaging: + runs-on: ubuntu-22.04 + steps: + - name: Checkout frontend sources + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '20' + + - name: Display Node version + run: node -v && npm -v + + - name: Install frontend dependencies + working-directory: frontend + run: npm ci + + - name: Run build and package + working-directory: frontend + run: npm run package \ No newline at end of file diff --git a/.github/workflows/frontend-e2e-tests.yml b/.github/workflows/frontend-e2e-tests.yml new file mode 100644 index 00000000..be5cf1d6 --- /dev/null +++ b/.github/workflows/frontend-e2e-tests.yml @@ -0,0 +1,86 @@ +name: frontend-e2e-tests + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + e2e: + runs-on: ubuntu-22.04 + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + + - name: Display Python version + run: python -c "import sys; print(sys.version)" + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '20' + + - name: Install dependencies + working-directory: frontend + run: npm ci + + - name: Install Xvfb + run: sudo apt-get update && sudo apt-get install -y xvfb + + - name: Define dataset list and cache key + id: datasets + run: | + urls=($(cat zenodo_datasets.txt)) + echo "files=${urls[*]}" >> $GITHUB_OUTPUT + + # Generate a hash key from the URLs list, this is used for caching + key=$(echo "${urls[*]}" | sha256sum | cut -d ' ' -f1) + echo "key=${key}" >> $GITHUB_OUTPUT + + - name: Cache Zenodo datasets + id: cache-datasets + uses: actions/cache/restore@v4 + with: + path: e2e_datasets + key: ${{ steps.datasets.outputs.key }} + + - if: ${{ steps.cache-datasets.outputs.cache-hit != 'true' }} + name: Download datasets if not cached + run: | + mkdir -p e2e_datasets + for url in ${{ steps.datasets.outputs.files }}; do + echo "Downloading $(basename $url) ..." + wget -P e2e_datasets/ "$url" + done + + - name: Always save Zenodo datasets (even if pytest would fail) + id: cache-datasets-save + if: always() && steps.cache-datasets.outputs.cache-hit != 'true' + uses: actions/cache/save@v4 + with: + key: ${{ steps.cache-datasets.outputs.cache-primary-key }} + path: e2e_datasets + + - name: Run E2E tests + working-directory: frontend + run: | + xvfb-run --auto-servernum --server-args="-screen 0 1920x1080x24" bash -c " + python3 -m venv ../ibex_venv + source ../ibex_venv/bin/activate + pip install --upgrade pip setuptools wheel + cd ../backend + pip install -e . + cd ../frontend + npm run start:e2e & + npx wait-on tcp:9222 + npx wait-on http://127.0.0.1:8000/docs/ + sleep 5 + npm run test:e2e + " \ No newline at end of file diff --git a/.github/workflows/frontend-linting.yml b/.github/workflows/frontend-linting.yml new file mode 100644 index 00000000..1bf4f54f --- /dev/null +++ b/.github/workflows/frontend-linting.yml @@ -0,0 +1,33 @@ +name: frontend-linting-and-formatting + +on: + push: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + lint: + runs-on: ubuntu-22.04 + steps: + - name: Checkout frontend sources + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: '20' + + - name: Display Node version + run: node -v && npm -v + + - name: Install frontend dependencies + working-directory: frontend + run: npm ci + + - name: Run code formatting + working-directory: frontend + run: npm run format + + - name: Run linting + working-directory: frontend + run: npm run lint \ No newline at end of file diff --git a/.gitignore b/.gitignore index 79f635bc..66674af6 100644 --- a/.gitignore +++ b/.gitignore @@ -105,4 +105,7 @@ saxon*.jar # ASV folder /.asv -.idea/ \ No newline at end of file +.idea/ + +# Local folder for E2E tests +e2e_datasets \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 247f579c..ae1bda1c 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -16,6 +16,7 @@ "@mantine/notifications": "7.17.7", "@tabler/icons-react": "3.23.0", "@tensorflow/tfjs": "4.22.0", + "axios": "1.13.6", "dotenv": "16.4.7", "electron-default-menu": "1.0.2", "electron-squirrel-startup": "1.0.1", @@ -50,7 +51,6 @@ "@types/selenium-webdriver": "4.1.28", "@vercel/webpack-asset-relocator-loader": "1.7.3", "chai": "4.3.10", - "chromedriver": "134.0.5", "cross-env": "7.0.3", "css-loader": "6.0.0", "electron": "35.7.5", @@ -1967,12 +1967,6 @@ "node": ">=10" } }, - "node_modules/@testim/chrome-version": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.4.tgz", - "integrity": "sha512-kIhULpw9TrGYnHp/8VfdcneIcxKnLixmADtukQRtJUmsVlMg0niMkwV0xZmi8hqa57xqilIHjWFA0GKvEjVU5g==", - "dev": true - }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -1982,12 +1976,6 @@ "node": ">= 10" } }, - "node_modules/@tootallnate/quickjs-emscripten": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", - "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", - "dev": true - }, "node_modules/@tsconfig/node10": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", @@ -3432,18 +3420,6 @@ "node": "*" } }, - "node_modules/ast-types": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", - "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", - "dev": true, - "dependencies": { - "tslib": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/async-function": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", @@ -3492,13 +3468,12 @@ } }, "node_modules/axios": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", - "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", - "dev": true, + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz", + "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, @@ -3545,15 +3520,6 @@ "baseline-browser-mapping": "dist/cli.js" } }, - "node_modules/basic-ftp": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", - "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -4096,28 +4062,6 @@ "node": ">=6.0" } }, - "node_modules/chromedriver": { - "version": "134.0.5", - "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-134.0.5.tgz", - "integrity": "sha512-edXbiuShAvH6Elx8Hobl4NQkgNRMIozcW7ZlEiE8TBynZHRazrepO9hfftQzZgztPvjMQiSWeWjZaDV3SecYaw==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@testim/chrome-version": "^1.1.4", - "axios": "^1.7.4", - "compare-versions": "^6.1.0", - "extract-zip": "^2.0.1", - "proxy-agent": "^6.4.0", - "proxy-from-env": "^1.1.0", - "tcp-port-used": "^1.0.2" - }, - "bin": { - "chromedriver": "bin/chromedriver" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/clamp": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz", @@ -4445,12 +4389,6 @@ "node": ">=0.10.0" } }, - "node_modules/compare-versions": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", - "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==", - "dev": true - }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -5031,15 +4969,6 @@ "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==", "peer": true }, - "node_modules/data-uri-to-buffer": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", - "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, "node_modules/data-view-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", @@ -5321,20 +5250,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/degenerator": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", - "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", - "dev": true, - "dependencies": { - "ast-types": "^0.13.4", - "escodegen": "^2.1.0", - "esprima": "^4.0.1" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -6647,6 +6562,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "peer": true, "dependencies": { "esprima": "^4.0.1", "estraverse": "^5.2.0", @@ -6936,6 +6852,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "peer": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -7505,7 +7422,6 @@ "version": "1.15.11", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "dev": true, "funding": [ { "type": "individual", @@ -7963,20 +7879,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-uri": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", - "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", - "dev": true, - "dependencies": { - "basic-ftp": "^5.0.2", - "data-uri-to-buffer": "^6.0.2", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/gl-mat4": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gl-mat4/-/gl-mat4-1.2.0.tgz", @@ -9053,15 +8955,6 @@ "node": ">= 12" } }, - "node_modules/ip-regex": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", - "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -9557,12 +9450,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "dev": true - }, "node_modules/is-weakmap": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", @@ -9618,20 +9505,6 @@ "node": ">=8" } }, - "node_modules/is2": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.9.tgz", - "integrity": "sha512-rZkHeBn9Zzq52sd9IUIV3a5mfwBY+o2HePMh0wkGBM4z4qjvy2GwVxQ6nNXSfw6MmVP6gf1QIlWjiOavhM3x5g==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "ip-regex": "^4.1.0", - "is-url": "^1.2.4" - }, - "engines": { - "node": ">=v0.10.0" - } - }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -10831,15 +10704,6 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "dev": true, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/next-tick": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", @@ -11429,87 +11293,6 @@ "node": ">=4" } }, - "node_modules/pac-proxy-agent": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", - "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", - "dev": true, - "dependencies": { - "@tootallnate/quickjs-emscripten": "^0.23.0", - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "get-uri": "^6.0.1", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.6", - "pac-resolver": "^7.0.1", - "socks-proxy-agent": "^8.0.5" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-proxy-agent/node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-proxy-agent/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-proxy-agent/node_modules/socks-proxy-agent": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", - "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/pac-resolver": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", - "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", - "dev": true, - "dependencies": { - "degenerator": "^5.0.0", - "netmask": "^2.0.2" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -12252,79 +12035,10 @@ "node": ">= 0.10" } }, - "node_modules/proxy-agent": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", - "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.1", - "https-proxy-agent": "^7.0.6", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.1.0", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.5" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/proxy-agent/node_modules/socks-proxy-agent": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", - "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, "node_modules/pump": { "version": "3.0.3", @@ -14638,39 +14352,6 @@ "node": ">=8" } }, - "node_modules/tcp-port-used": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz", - "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", - "dev": true, - "dependencies": { - "debug": "4.3.1", - "is2": "^2.0.6" - } - }, - "node_modules/tcp-port-used/node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/tcp-port-used/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/temp": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", diff --git a/frontend/package.json b/frontend/package.json index f5809eff..afa3fe86 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -36,7 +36,6 @@ "@types/selenium-webdriver": "4.1.28", "@vercel/webpack-asset-relocator-loader": "1.7.3", "chai": "4.3.10", - "chromedriver": "134.0.5", "cross-env": "7.0.3", "css-loader": "6.0.0", "electron": "35.7.5", @@ -72,6 +71,7 @@ "@mantine/notifications": "7.17.7", "@tabler/icons-react": "3.23.0", "@tensorflow/tfjs": "4.22.0", + "axios": "1.13.6", "dotenv": "16.4.7", "electron-default-menu": "1.0.2", "electron-squirrel-startup": "1.0.1", diff --git a/frontend/src/config/bridge.ts b/frontend/src/config/bridge.ts index f73011e3..51310935 100644 --- a/frontend/src/config/bridge.ts +++ b/frontend/src/config/bridge.ts @@ -4,5 +4,8 @@ import { API } from '../preload'; declare global { interface Window { api: typeof API; + env: { + E2E_TEST: string; + }; } } diff --git a/frontend/src/config/config.ts b/frontend/src/config/config.ts index 5550c975..df5726cf 100644 --- a/frontend/src/config/config.ts +++ b/frontend/src/config/config.ts @@ -8,35 +8,12 @@ export type TConfig = { LOGGER_PORT: number; }; -const defaultConfig: TConfig = { - API_URL: 'http://localhost:8000', - WEBPACK_PORT: 3001, - LOGGER_PORT: 9013, -}; - -const getConfigPath = (): string => { - const configDir = path.join(os.homedir(), '.config', 'ibex'); - const configPath = path.join(configDir, 'config.json'); - - if (!fs.existsSync(configDir)) { - fs.mkdirSync(configDir, { recursive: true }); - } - - return configPath; -}; - -export const getConfigSync = (): TConfig => { - // Check if backend URL is provided by Electron main process - const backendUrl = process.env.IBEX_BACKEND_URL; - - if (backendUrl) { - console.info(`Using backend URL from Electron: ${backendUrl}`); - return { - ...defaultConfig, - API_URL: backendUrl, - }; - } - +const createDefaultConfig = (): TConfig => { + const defaultConfig = { + API_URL: 'http://localhost:8000', + WEBPACK_PORT: 3001, + LOGGER_PORT: Math.floor(49152 + Math.random() * (65535 - 49152)), + } as TConfig; const configPath = getConfigPath(); try { @@ -49,7 +26,7 @@ export const getConfigSync = (): TConfig => { } const data = fs.readFileSync(configPath, 'utf-8'); - const parsed = JSON.parse(data); + const parsed = JSON.parse(data) as TConfig; if ( typeof parsed.API_URL === 'string' && @@ -59,10 +36,33 @@ export const getConfigSync = (): TConfig => { return parsed; } - console.warn('Configuration invalide, retour à la config par défaut.'); - return defaultConfig; + console.warn('Read invalid configuration, get the default configuration.'); + return defaultConfig as TConfig; } catch (err) { - console.error('Erreur de lecture de config:', err); + console.error('Error reading the configuration file:', err); return defaultConfig; } }; + +const getConfigPath = (): string => { + const configDir = path.join(os.homedir(), '.config', 'ibex'); + const configPath = path.join(configDir, 'config.json'); + if (!fs.existsSync(configDir)) { + fs.mkdirSync(configDir, { recursive: true }); + } + return configPath; +}; + +export const getConfigSync = (): TConfig => { + // Check if backend URL is provided by Electron main process + const backendUrl = process.env.IBEX_BACKEND_URL; + if (backendUrl) { + console.info(`Using backend URL from Electron: ${backendUrl}`); + return { + ...createDefaultConfig(), + API_URL: backendUrl, + }; + } else { + return { ...createDefaultConfig() }; + } +}; diff --git a/frontend/src/main/ipc.ts b/frontend/src/main/ipc.ts index 647940fb..0d4161f9 100644 --- a/frontend/src/main/ipc.ts +++ b/frontend/src/main/ipc.ts @@ -147,11 +147,11 @@ export default { return app.getPath('home'); }); - ipcMain.handle('getDefaultTemplatesPath', () => { + ipcMain.handle('getPathFromRessources', (event, folderSteps: string[]) => { const templatesPath = process.env.NODE_ENV === 'development' - ? path.join(app.getAppPath(), '..', 'templates') // root in dev - : path.join(process.resourcesPath, 'templates'); // resources/ in prod + ? path.join(app.getAppPath(), '..', ...folderSteps) // root in dev + : path.join(process.resourcesPath, ...folderSteps); // resources/ in prod return templatesPath; }); }, diff --git a/frontend/src/preload.ts b/frontend/src/preload.ts index 0c4dd73b..9710d84c 100644 --- a/frontend/src/preload.ts +++ b/frontend/src/preload.ts @@ -65,7 +65,10 @@ export const API = { getHomePath: async () => await ipcRenderer.invoke('getHomePath'), getDefaultTemplatesPath: async () => - await ipcRenderer.invoke('getDefaultTemplatesPath'), + await ipcRenderer.invoke('getPathFromRessources', ['templates']), + + getZenodoDataPath: async () => + await ipcRenderer.invoke('getPathFromRessources', ['e2e_datasets']), }, preferences: { @@ -107,3 +110,6 @@ export const API = { contextBridge.exposeInMainWorld('api', API); contextBridge.exposeInMainWorld('stubDataStorage', stubDataStorage); +contextBridge.exposeInMainWorld('env', { + E2E_TEST: process.env.E2E_TEST, +}); diff --git a/frontend/src/renderer/components/configuration/ConfigCreateModal.tsx b/frontend/src/renderer/components/configuration/ConfigCreateModal.tsx index 8bd85a40..728a2fac 100644 --- a/frontend/src/renderer/components/configuration/ConfigCreateModal.tsx +++ b/frontend/src/renderer/components/configuration/ConfigCreateModal.tsx @@ -212,6 +212,9 @@ export function ConfigCreateModal({ title="Create config" size="sm" data-testid="config-create-modal" + {...(window.env.E2E_TEST === 'true' && { + transitionProps: { duration: 0 }, + })} >