From 616424b2235ccee503c58f7a72efb6e8ab0dd4ee Mon Sep 17 00:00:00 2001 From: lrnselfreliance <33263708+lrnselfreliance@users.noreply.github.com> Date: Sat, 8 Aug 2026 18:01:52 -0600 Subject: [PATCH] fix: repair CI after the dependency bumps, and align it with the Trixie build (#651) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(app): depend on @testing-library/dom directly jest-dom 7 moved @testing-library/dom from a bundled dependency to a peer dependency. Nothing else pulls the top-level copy in — @testing-library/react 13 carries its own nested v8 — so it was present only as a peer, and CI installs with --legacy-peer-deps, which skips peers. Every suite then failed to load setupTests.js with "Cannot find module '@testing-library/dom'". Declare it as a devDependency so it installs under either resolution mode. Co-Authored-By: Claude Opus 5 (1M context) * fix(app): import mount from cypress/react Cypress 14 removed the cypress/react18 subpath; cypress/react mounts React 18 itself. The e2e support file loads commands.js, so the stale import broke bundling for every spec, not just component tests: Module not found: Package path ./react18 is not exported from package cypress Co-Authored-By: Claude Opus 5 (1M context) * ci: install and cache Cypress the way the bump requires The Cypress binary lives in ~/.cache/Cypress, outside node_modules, but only node_modules was cached. A restored cache satisfied npm, so npm skipped the postinstall download and the 15.x binary was never fetched: The cypress npm package is installed, but the Cypress binary is missing. Cache both paths and install the binary explicitly. Also align the JS toolchain with what actually ships. Debian 13 devices run nodejs 20.19.2 and install with a plain `npm install`; the Docker app image does the same. CI pinned older Node and passed --legacy-peer-deps, which skips peer dependencies -- that is why jest-dom 7's peer requirement passed review and broke CI. Match the devices instead. Pin caddy to 2.11.4, the version Debian 13 devices run, rather than latest. Co-Authored-By: Claude Opus 5 (1M context) * ci: test on Python 3.13, the version that ships Debian 13 devices run Python 3.13.5 and the api/controller/help images are python:3.13-trixie, but CI ran 3.11 (and one job on 3.12), so the runtime under test was two minors behind the runtime in production. Verified on 3.13 before switching: backend 1712 passed, 5 skipped; controller 883 passed. The only new warning is SQLAlchemy 1.3.22 reaching Python's deprecated datetime.utcfromtimestamp(), which is noise rather than a break. Drop api-tests-3-12: no workflow referenced it, it duplicated api-tests, and its "Sanic does not yet support 3.12" note is stale now that devices run 3.13. Co-Authored-By: Claude Opus 5 (1M context) --------- Co-authored-by: Claude Opus 5 (1M context) --- .circleci/config.yml | 58 +++++------ .github/workflows/controller-tests.yml | 2 +- .github/workflows/jest-tests.yml | 4 +- app/cypress/support/commands.js | 4 +- app/package-lock.json | 127 +++++++++---------------- app/package.json | 1 + docker/web/Dockerfile | 3 +- 7 files changed, 76 insertions(+), 123 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2c358b7b..174acc91 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,9 +5,9 @@ version: 2.1 # Define a job to be invoked later in a workflow. # See: https://circleci.com/docs/2.0/configuration-reference/#jobs jobs: - api-tests-3-11: + api-tests: docker: - - image: cimg/python:3.11 + - image: cimg/python:3.13 # `large` (4 vCPU, 8 GB) so pytest-xdist's `-nauto` has room to scale. resource_class: large steps: @@ -15,7 +15,7 @@ jobs: - run: sudo apt-get update - run: sudo apt-get install -y ffmpeg catdoc - restore_cache: - key: deps-3.11-{{ checksum "requirements.txt" }}-5 + key: deps-3.13-{{ checksum "requirements.txt" }}-5 - run: name: Install Requirements command: | @@ -23,7 +23,7 @@ jobs: . venv/bin/activate pip install -r requirements.txt - save_cache: - key: deps-3.11-{{ checksum "requirements.txt" }}-5 + key: deps-3.13-{{ checksum "requirements.txt" }}-5 paths: - "venv" # `-nauto` parallelizes across all available cores via pytest-xdist. @@ -35,12 +35,12 @@ jobs: path: test-results.xml api-alembic-migrations: docker: - - image: cimg/python:3.11 + - image: cimg/python:3.13 resource_class: medium steps: - checkout - restore_cache: - key: deps-3.11-{{ checksum "requirements.txt" }}-5 + key: deps-3.13-{{ checksum "requirements.txt" }}-5 - run: name: Install Requirements command: | @@ -56,35 +56,13 @@ jobs: - run: name: Check for Missing Migrations command: MEDIA_DIRECTORY=/tmp/wrolpi-media ./venv/bin/python ./main.py db check - api-tests-3-12: - docker: - - image: cimg/python:3.12 - resource_class: large - steps: - - checkout - - run: sudo apt-get update - - run: sudo apt-get install -y ffmpeg catdoc - - restore_cache: - key: deps-3.12-{{ checksum "requirements.txt" }}-5 - - run: - name: Install Requirements - command: | - python3 -m venv venv - . venv/bin/activate - pip install -r requirements.txt - - save_cache: - key: deps-3.12-{{ checksum "requirements.txt" }}-5 - paths: - - "venv" - - run: - command: './venv/bin/pytest -nauto' sanic-api-start: docker: - - image: cimg/python:3.11 + - image: cimg/python:3.13 steps: - checkout - restore_cache: - key: deps-3.11-{{ checksum "requirements.txt" }}-5 + key: deps-3.13-{{ checksum "requirements.txt" }}-5 - run: name: Install dependencies command: | @@ -108,13 +86,13 @@ jobs: command: pkill -f sanic react-app-start: docker: - - image: cimg/node:20.13 + - image: cimg/node:20.19 resource_class: large steps: - checkout - restore_cache: key: app-{{ checksum "app/package-lock.json" }} - - run: cd app && npm install --legacy-peer-deps + - run: cd app && npm install - save_cache: key: app-{{ checksum "app/package-lock.json" }} paths: @@ -137,7 +115,7 @@ jobs: # Jest tests moved to GitHub Actions (.github/workflows/jest-tests.yml) cypress-e2e-tests: docker: - - image: cimg/node:20.18-browsers + - image: cimg/node:20.19-browsers resource_class: large steps: - checkout @@ -145,11 +123,20 @@ jobs: key: app-browsers-{{ checksum "app/package-lock.json" }} - run: name: Install Dependencies - command: cd app && npm install --legacy-peer-deps + command: cd app && npm install + # The Cypress binary lives outside node_modules, so caching only + # node_modules lets the two drift apart: a restored cache satisfies npm, + # npm skips the postinstall download, and the binary for the new version + # is never fetched. Cache both, and install explicitly (a no-op when the + # binary is already present). + - run: + name: Install Cypress Binary + command: cd app && npx cypress install - save_cache: key: app-browsers-{{ checksum "app/package-lock.json" }} paths: - ./app/node_modules + - ~/.cache/Cypress - run: name: Start React App in Background command: cd app && DISABLE_ESLINT_PLUGIN=true npm start @@ -179,9 +166,8 @@ workflows: wrolpi-api-tests: jobs: - sanic-api-start - - api-tests-3-11 + - api-tests - api-alembic-migrations - # - api-tests-3-12 Sanic does not yet support 3.12. wrolpi-app-test: jobs: - react-app-start diff --git a/.github/workflows/controller-tests.yml b/.github/workflows/controller-tests.yml index d4dfa60d..a1c005ad 100644 --- a/.github/workflows/controller-tests.yml +++ b/.github/workflows/controller-tests.yml @@ -21,7 +21,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v5 with: - python-version: '3.11' + python-version: '3.13' cache: 'pip' cache-dependency-path: controller/requirements.txt diff --git a/.github/workflows/jest-tests.yml b/.github/workflows/jest-tests.yml index 03dd7300..68bfd7aa 100644 --- a/.github/workflows/jest-tests.yml +++ b/.github/workflows/jest-tests.yml @@ -21,12 +21,12 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '20' + node-version: '20.19' cache: 'npm' cache-dependency-path: app/package-lock.json - name: Install dependencies - run: npm install --legacy-peer-deps + run: npm install - name: Run Jest tests run: CI=true npm test -- --watchAll=false --coverage --coverageReporters=text --coverageReporters=lcov diff --git a/app/cypress/support/commands.js b/app/cypress/support/commands.js index 0a5ae0d0..ecda4089 100644 --- a/app/cypress/support/commands.js +++ b/app/cypress/support/commands.js @@ -1,4 +1,4 @@ -import {mount} from 'cypress/react18' +import {mount} from 'cypress/react' -// Use React 18 for all mounts. +// Cypress 14 dropped the separate cypress/react18 entry point; cypress/react mounts React 18 itself. Cypress.Commands.add('mount', mount); diff --git a/app/package-lock.json b/app/package-lock.json index 5f77d429..fc8dd1ac 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -37,6 +37,7 @@ "web-vitals": "^5.3.0" }, "devDependencies": { + "@testing-library/dom": "^10.4.1", "@testing-library/jest-dom": "^7.0.0", "@types/lodash": "^4.17.24", "@types/node": "^26.1.2", @@ -5286,7 +5287,8 @@ "version": "10.4.1", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", - "peer": true, + "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", @@ -20183,6 +20185,7 @@ "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -21520,8 +21523,7 @@ "@artsy/fresnel": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/@artsy/fresnel/-/fresnel-8.5.0.tgz", - "integrity": "sha512-Rt5NfZEJ8/4fQJVtz2wR4KjQbHVdZr/+0uWPZ+W2OXiHTurhcxVijgBq3xP8e/YtjJ06uuJR7034bKpiNVqMAg==", - "requires": {} + "integrity": "sha512-Rt5NfZEJ8/4fQJVtz2wR4KjQbHVdZr/+0uWPZ+W2OXiHTurhcxVijgBq3xP8e/YtjJ06uuJR7034bKpiNVqMAg==" }, "@babel/code-frame": { "version": "7.29.0", @@ -23841,20 +23843,17 @@ "@csstools/postcss-unset-value": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", - "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", - "requires": {} + "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==" }, "@csstools/selector-specificity": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.1.1.tgz", - "integrity": "sha512-jwx+WCqszn53YHOfvFMJJRd/B2GqkCBt+1MJSG6o5/s8+ytHMvDZXsJgUEWLk12UnLd7HYKac4BYU5i/Ron1Cw==", - "requires": {} + "integrity": "sha512-jwx+WCqszn53YHOfvFMJJRd/B2GqkCBt+1MJSG6o5/s8+ytHMvDZXsJgUEWLk12UnLd7HYKac4BYU5i/Ron1Cw==" }, "@cypress/react18": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@cypress/react18/-/react18-2.0.1.tgz", - "integrity": "sha512-T/bhFEvVDIu0lDOKXbEQqVEmmANKWc/pyFDyDoJw3OndRYv9QVEJSsE/VNXIaOQLDjWvQkKBOwd0lLe1hWF/Zg==", - "requires": {} + "integrity": "sha512-T/bhFEvVDIu0lDOKXbEQqVEmmANKWc/pyFDyDoJw3OndRYv9QVEJSsE/VNXIaOQLDjWvQkKBOwd0lLe1hWF/Zg==" }, "@cypress/request": { "version": "4.0.1", @@ -25041,7 +25040,7 @@ "version": "10.4.1", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz", "integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==", - "peer": true, + "dev": true, "requires": { "@babel/code-frame": "7.29.0", "@babel/runtime": "^7.12.5", @@ -25469,8 +25468,7 @@ "@types/react-dom": { "version": "18.3.7", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", - "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", - "requires": {} + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==" }, "@types/react-reconciler": { "version": "0.26.7", @@ -25881,14 +25879,12 @@ "acorn-import-phases": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", - "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "requires": {} + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==" }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "requires": {} + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" }, "acorn-node": { "version": "1.8.2", @@ -25974,8 +25970,7 @@ "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "requires": {} + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" }, "ansi-escapes": { "version": "4.3.2", @@ -26348,8 +26343,7 @@ "babel-plugin-named-asset-import": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", - "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==", - "requires": {} + "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==" }, "babel-plugin-polyfill-corejs2": { "version": "0.3.3", @@ -27114,8 +27108,7 @@ "css-declaration-sorter": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz", - "integrity": "sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w==", - "requires": {} + "integrity": "sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w==" }, "css-has-pseudo": { "version": "3.0.4", @@ -27198,8 +27191,7 @@ "css-prefers-color-scheme": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", - "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", - "requires": {} + "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==" }, "css-select": { "version": "4.3.0", @@ -27304,8 +27296,7 @@ "cssnano-utils": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "requires": {} + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==" }, "csso": { "version": "4.2.0", @@ -28461,8 +28452,7 @@ "eslint-plugin-react-hooks": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "requires": {} + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==" }, "eslint-plugin-testing-library": { "version": "5.10.0", @@ -29632,8 +29622,7 @@ "icss-utils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "requires": {} + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==" }, "idb": { "version": "7.1.1", @@ -30744,8 +30733,7 @@ "jest-pnp-resolver": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "requires": {} + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==" }, "jest-regex-util": { "version": "27.5.1", @@ -32857,8 +32845,7 @@ "postcss-browser-comments": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", - "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==", - "requires": {} + "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==" }, "postcss-calc": { "version": "8.2.4", @@ -32956,26 +32943,22 @@ "postcss-discard-comments": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", - "requires": {} + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==" }, "postcss-discard-duplicates": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "requires": {} + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==" }, "postcss-discard-empty": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "requires": {} + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==" }, "postcss-discard-overridden": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "requires": {} + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==" }, "postcss-double-position-gradients": { "version": "3.1.2", @@ -32997,8 +32980,7 @@ "postcss-flexbugs-fixes": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", - "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", - "requires": {} + "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==" }, "postcss-focus-visible": { "version": "6.0.4", @@ -33019,14 +33001,12 @@ "postcss-font-variant": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", - "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", - "requires": {} + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==" }, "postcss-gap-properties": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", - "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", - "requires": {} + "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==" }, "postcss-image-set-function": { "version": "4.0.7", @@ -33049,8 +33029,7 @@ "postcss-initial": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", - "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", - "requires": {} + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==" }, "postcss-js": { "version": "4.0.0", @@ -33091,14 +33070,12 @@ "postcss-logical": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", - "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", - "requires": {} + "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==" }, "postcss-media-minmax": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", - "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", - "requires": {} + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==" }, "postcss-merge-longhand": { "version": "5.1.7", @@ -33159,8 +33136,7 @@ "postcss-modules-extract-imports": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "requires": {} + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==" }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -33218,8 +33194,7 @@ "postcss-normalize-charset": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "requires": {} + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==" }, "postcss-normalize-display-values": { "version": "5.1.0", @@ -33290,8 +33265,7 @@ "postcss-opacity-percentage": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", - "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", - "requires": {} + "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==" }, "postcss-ordered-values": { "version": "5.1.3", @@ -33313,8 +33287,7 @@ "postcss-page-break": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", - "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", - "requires": {} + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==" }, "postcss-place": { "version": "7.0.5", @@ -33408,8 +33381,7 @@ "postcss-replace-overflow-wrap": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", - "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", - "requires": {} + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==" }, "postcss-selector-not": { "version": "6.0.1", @@ -33762,8 +33734,7 @@ "react-colorful": { "version": "5.8.0", "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.8.0.tgz", - "integrity": "sha512-Wy9OzPfjSN9bF12OB8N7UQvlsZ0I+7wHxpN+bV5BjNQGxOj6IiwkRjevJK9yOBjJWGQvAaf1OXtn8rUeEatAng==", - "requires": {} + "integrity": "sha512-Wy9OzPfjSN9bF12OB8N7UQvlsZ0I+7wHxpN+bV5BjNQGxOj6IiwkRjevJK9yOBjJWGQvAaf1OXtn8rUeEatAng==" }, "react-dev-utils": { "version": "12.0.1", @@ -33883,8 +33854,7 @@ "react-hotkeys-hook": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-5.3.3.tgz", - "integrity": "sha512-aswgyWUnE25hmhzHTfKDmKzsaSE5DJ4LKaU/o6rQSXkDd/1Bh9TfAFQbHkf6fLy11HvlYkp+cDDarGdhmCDhoQ==", - "requires": {} + "integrity": "sha512-aswgyWUnE25hmhzHTfKDmKzsaSE5DJ4LKaU/o6rQSXkDd/1Bh9TfAFQbHkf6fLy11HvlYkp+cDDarGdhmCDhoQ==" }, "react-is": { "version": "17.0.2", @@ -34007,8 +33977,7 @@ "react-semantic-toasts-2": { "version": "0.6.7", "resolved": "https://registry.npmjs.org/react-semantic-toasts-2/-/react-semantic-toasts-2-0.6.7.tgz", - "integrity": "sha512-Mwcwu6DbozO8XOteOOXmicNywLwskX7XV98sG2cSZ02G/RIM2uRUZvx65nqIFp67CSe+tBU1wKVWvNascZQR/w==", - "requires": {} + "integrity": "sha512-Mwcwu6DbozO8XOteOOXmicNywLwskX7XV98sG2cSZ02G/RIM2uRUZvx65nqIFp67CSe+tBU1wKVWvNascZQR/w==" }, "react-stl-viewer": { "version": "2.5.0", @@ -35034,8 +35003,7 @@ "style-loader": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", - "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", - "requires": {} + "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==" }, "stylehacks": { "version": "5.1.1", @@ -35094,8 +35062,7 @@ "suspend-react": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/suspend-react/-/suspend-react-0.1.3.tgz", - "integrity": "sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==", - "requires": {} + "integrity": "sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==" }, "svg-parser": { "version": "2.0.4", @@ -35575,7 +35542,8 @@ "typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true }, "unbox-primitive": { "version": "1.0.2", @@ -36005,8 +35973,7 @@ "ws": { "version": "8.21.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz", - "integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==", - "requires": {} + "integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==" } } }, @@ -36463,8 +36430,7 @@ "ws": { "version": "7.5.12", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.12.tgz", - "integrity": "sha512-1xGnbYN3zbog9CwuNDQULNRrTCLIn46/WmpR1f0w6PsCYQHkylZr5vkd6kfMZYV6pRnQkcPNRyiA8LsrNKyhpg==", - "requires": {} + "integrity": "sha512-1xGnbYN3zbog9CwuNDQULNRrTCLIn46/WmpR1f0w6PsCYQHkylZr5vkd6kfMZYV6pRnQkcPNRyiA8LsrNKyhpg==" }, "xml-name-validator": { "version": "3.0.0", @@ -36536,8 +36502,7 @@ "zustand": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz", - "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==", - "requires": {} + "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==" } } } diff --git a/app/package.json b/app/package.json index 64e37c9e..0d6f8008 100644 --- a/app/package.json +++ b/app/package.json @@ -57,6 +57,7 @@ ] }, "devDependencies": { + "@testing-library/dom": "^10.4.1", "@testing-library/jest-dom": "^7.0.0", "@types/lodash": "^4.17.24", "@types/node": "^26.1.2", diff --git a/docker/web/Dockerfile b/docker/web/Dockerfile index 4b6a6a87..79dbb5e5 100644 --- a/docker/web/Dockerfile +++ b/docker/web/Dockerfile @@ -1,4 +1,5 @@ -FROM caddy:latest +# Pinned to the Caddy that Debian 13 devices run, so Docker matches hardware. +FROM caddy:2.11.4 RUN apk add --no-cache openssl bash