build: uninstall Semantic UI

`semantic-ui-react`, `react-semantic-toasts-2` and `semantic-ui-offline` are
gone from package.json, the lockfile and node_modules -- 19 MB of dependencies
that nothing had imported since the migration finished.

Four things still referenced them and would have broken on uninstall.  None was
caught by a build or by jest:

  Four test files still ran `jest.mock('react-semantic-toasts-2', ...)` for
  components that no longer use it.  A jest.mock of a module that does not exist
  throws, so the packages could not have come out without this.

  `src/components/Download.cy.js` and `cypress/support/component.js` both
  imported semantic.min.css.  The support file now loads what the app loads --
  index.css, the font and token stylesheets, and Mantine's.

The ratchet changes job rather than being deleted.  An import of a missing module
fails loudly now, but three quieter mistakes would not: a `className="ui button"`
that styles nothing, a file reaching back through Theme.tsx, and someone
reinstalling a package to "just use one Semantic component".  It asserts all
three, plus that package.json names nothing matching /semantic/i.

Two pre-existing problems in the cypress component harness surfaced while
checking the uninstall had not broken it, both fixed because that file had to be
edited anyway:

  It imported `react-router-dom`, which is not installed -- this app is on
  react-router v7.  Dates to 5621d473, so the component suite has been
  un-runnable since well before this migration.

  Its mount helper supplied no MantineProvider, so every library component threw
  -- the same gap test-utils.js had for jest.

The component specs now load and four pass; eleven assertions are still written
against markup from before they stopped running.  Repairing those is its own
piece of work, deliberately not bundled in here.  The e2e suite is unaffected:
43/43.
This commit is contained in:
Roland 2026-07-30 14:50:47 -06:00
parent 3c82291db3
commit 8ba73e64cd
No known key found for this signature in database
GPG key ID: 1BA620CE6C9A4680
9 changed files with 48 additions and 322 deletions

View file

@ -14,10 +14,17 @@
// ***********************************************************
import './commands'
import 'semantic-ui-offline/semantic.min.css';
import {MemoryRouter, Route, Routes} from "react-router-dom";
// Component tests mount real components, so they need the same styles the app loads.
import '../../src/index.css';
import '../../src/themes/fonts.css';
import '../../src/themes/tokens.css';
import '@mantine/core/styles.css';
// react-router v7 ships these directly; `react-router-dom` is not installed.
import {MemoryRouter, Route, Routes} from "react-router";
import {QueryProvider} from "../../src/hooks/customHooks";
import {TagsProvider} from "../../src/Tags";
import {MantineProvider} from "@mantine/core";
import {cssVariablesResolver, mantineTheme} from "../../src/themes/mantine";
import React from "react";
Cypress.on('uncaught:exception', (err, runnable) => {
@ -31,8 +38,14 @@ Cypress.on('uncaught:exception', (err, runnable) => {
Cypress.Commands.add('mountWithRouter', (component, options) => {
options = options || {};
const initialEntries = options?.initialEntries || ['/'];
/*
* MantineProvider, configured exactly as ThemeProvider configures it. Every component
* in src/components/ui renders Mantine internals and throws without it -- the same
* thing that had to be added to test-utils.js for jest.
*/
return cy.mount(
<MemoryRouter initialEntries={initialEntries}>
<MantineProvider theme={mantineTheme} cssVariablesResolver={cssVariablesResolver}>
<QueryProvider>
<Routes>
<Route path='/videos/channels/new' element={component}/>
@ -41,6 +54,7 @@ Cypress.Commands.add('mountWithRouter', (component, options) => {
<Route path='*' element={component}/>
</Routes>
</QueryProvider>
</MantineProvider>
</MemoryRouter>,
options
);

287
app/package-lock.json generated
View file

@ -33,10 +33,7 @@
"react-qr-code": "^2.2.0",
"react-router": "^7.18.2",
"react-scripts": "5.0.1",
"react-semantic-toasts-2": "^0.6.7",
"react-stl-viewer": "^2.5.0",
"semantic-ui-offline": "^2.5.1",
"semantic-ui-react": "^2.1.5",
"three": "^0.185",
"web-vitals": "^5.3.0"
},
@ -3799,36 +3796,6 @@
"integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==",
"license": "MIT"
},
"node_modules/@fluentui/react-component-event-listener": {
"version": "0.63.1",
"resolved": "https://registry.npmjs.org/@fluentui/react-component-event-listener/-/react-component-event-listener-0.63.1.tgz",
"integrity": "sha512-gSMdOh6tI3IJKZFqxfQwbTpskpME0CvxdxGM2tdglmf6ZPVDi0L4+KKIm+2dN8nzb8Ya1A8ZT+Ddq0KmZtwVQg==",
"dependencies": {
"@babel/runtime": "^7.10.4"
},
"peerDependencies": {
"react": "^16.8.0 || ^17 || ^18",
"react-dom": "^16.8.0 || ^17 || ^18"
}
},
"node_modules/@fluentui/react-component-ref": {
"version": "0.63.1",
"resolved": "https://registry.npmjs.org/@fluentui/react-component-ref/-/react-component-ref-0.63.1.tgz",
"integrity": "sha512-8MkXX4+R3i80msdbD4rFpEB4WWq2UDvGwG386g3ckIWbekdvN9z2kWAd9OXhRGqB7QeOsoAGWocp6gAMCivRlw==",
"dependencies": {
"@babel/runtime": "^7.10.4",
"react-is": "^16.6.3"
},
"peerDependencies": {
"react": "^16.8.0 || ^17 || ^18",
"react-dom": "^16.8.0 || ^17 || ^18"
}
},
"node_modules/@fluentui/react-component-ref/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.8",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
@ -4905,16 +4872,6 @@
"url": "https://opencollective.com/webpack"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.6",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==",
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@react-three/fiber": {
"version": "8.16.5",
"resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.16.5.tgz",
@ -5153,19 +5110,6 @@
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz",
"integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg=="
},
"node_modules/@semantic-ui-react/event-stack": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/@semantic-ui-react/event-stack/-/event-stack-3.1.3.tgz",
"integrity": "sha512-FdTmJyWvJaYinHrKRsMLDrz4tTMGdFfds299Qory53hBugiDvGC0tEJf+cHsi5igDwWb/CLOgOiChInHwq8URQ==",
"dependencies": {
"exenv": "^1.2.2",
"prop-types": "^15.6.2"
},
"peerDependencies": {
"react": "^16.0.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/@sinclair/typebox": {
"version": "0.24.51",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz",
@ -7937,14 +7881,6 @@
"wrap-ansi": "^7.0.0"
}
},
"node_modules/clsx": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
"engines": {
"node": ">=6"
}
},
"node_modules/co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@ -10453,11 +10389,6 @@
"node": ">=4"
}
},
"node_modules/exenv": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
"integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw=="
},
"node_modules/exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@ -14520,11 +14451,6 @@
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
"node_modules/jquery": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg=="
},
"node_modules/js-sdsl": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
@ -14706,11 +14632,6 @@
"integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==",
"license": "ISC"
},
"node_modules/keyboard-key": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/keyboard-key/-/keyboard-key-1.1.0.tgz",
"integrity": "sha512-qkBzPTi3rlAKvX7k0/ub44sqOfXeLc/jcnGGmj5c7BJpU8eDrEVPyhCvNYAaoubbsLm9uGWwQJO1ytQK1a9/dQ=="
},
"node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@ -14934,11 +14855,6 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="
},
"node_modules/lodash-es": {
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz",
"integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A=="
},
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@ -17592,7 +17508,6 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"peer": true,
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
@ -18016,11 +17931,6 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
},
"node_modules/react-fast-compare": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
},
"node_modules/react-hotkeys-hook": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-5.3.3.tgz",
@ -18045,20 +17955,6 @@
"react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/react-popper": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz",
"integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==",
"dependencies": {
"react-fast-compare": "^3.0.1",
"warning": "^4.0.2"
},
"peerDependencies": {
"@popperjs/core": "^2.0.0",
"react": "^16.8.0 || ^17 || ^18",
"react-dom": "^16.8.0 || ^17 || ^18"
}
},
"node_modules/react-qr-code": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.2.0.tgz",
@ -18252,16 +18148,6 @@
}
}
},
"node_modules/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==",
"peerDependencies": {
"prop-types": "^15.7.2",
"react": "16.x.x || 17.x.x || 18.x.x",
"semantic-ui-react": "*"
}
},
"node_modules/react-stl-viewer": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/react-stl-viewer/-/react-stl-viewer-2.5.0.tgz",
@ -18978,39 +18864,6 @@
"node": ">=10"
}
},
"node_modules/semantic-ui-offline": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/semantic-ui-offline/-/semantic-ui-offline-2.5.1.tgz",
"integrity": "sha512-uwykZ0AF8rbKSsm6GIbQtAwLCKUexqKVX4qbbB1hvYNvOqhYdWqWMbTfrb3JLHYb19g9m6CEV6n+077AoVTUNg==",
"dependencies": {
"jquery": "^3.7.1"
}
},
"node_modules/semantic-ui-react": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/semantic-ui-react/-/semantic-ui-react-2.1.5.tgz",
"integrity": "sha512-nIqmmUNpFHfovEb+RI2w3E2/maZQutd8UIWyRjf1SLse+XF51hI559xbz/sLN3O6RpLjr/echLOOXwKCirPy3Q==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.10.5",
"@fluentui/react-component-event-listener": "~0.63.0",
"@fluentui/react-component-ref": "~0.63.0",
"@popperjs/core": "^2.6.0",
"@semantic-ui-react/event-stack": "^3.1.3",
"clsx": "^1.1.1",
"keyboard-key": "^1.1.0",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"prop-types": "^15.7.2",
"react-is": "^16.8.6 || ^17.0.0 || ^18.0.0",
"react-popper": "^2.3.0",
"shallowequal": "^1.1.0"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/semver": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
@ -19210,11 +19063,6 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
"node_modules/shallowequal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@ -20872,14 +20720,6 @@
"makeerror": "1.0.12"
}
},
"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/watchpack": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz",
@ -24434,30 +24274,6 @@
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz",
"integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww=="
},
"@fluentui/react-component-event-listener": {
"version": "0.63.1",
"resolved": "https://registry.npmjs.org/@fluentui/react-component-event-listener/-/react-component-event-listener-0.63.1.tgz",
"integrity": "sha512-gSMdOh6tI3IJKZFqxfQwbTpskpME0CvxdxGM2tdglmf6ZPVDi0L4+KKIm+2dN8nzb8Ya1A8ZT+Ddq0KmZtwVQg==",
"requires": {
"@babel/runtime": "^7.10.4"
}
},
"@fluentui/react-component-ref": {
"version": "0.63.1",
"resolved": "https://registry.npmjs.org/@fluentui/react-component-ref/-/react-component-ref-0.63.1.tgz",
"integrity": "sha512-8MkXX4+R3i80msdbD4rFpEB4WWq2UDvGwG386g3ckIWbekdvN9z2kWAd9OXhRGqB7QeOsoAGWocp6gAMCivRlw==",
"requires": {
"@babel/runtime": "^7.10.4",
"react-is": "^16.6.3"
},
"dependencies": {
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
}
}
},
"@humanwhocodes/config-array": {
"version": "0.11.8",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
@ -25238,12 +25054,6 @@
}
}
},
"@popperjs/core": {
"version": "2.11.6",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==",
"peer": true
},
"@react-three/fiber": {
"version": "8.16.5",
"resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.16.5.tgz",
@ -25394,15 +25204,6 @@
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz",
"integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg=="
},
"@semantic-ui-react/event-stack": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/@semantic-ui-react/event-stack/-/event-stack-3.1.3.tgz",
"integrity": "sha512-FdTmJyWvJaYinHrKRsMLDrz4tTMGdFfds299Qory53hBugiDvGC0tEJf+cHsi5igDwWb/CLOgOiChInHwq8URQ==",
"requires": {
"exenv": "^1.2.2",
"prop-types": "^15.6.2"
}
},
"@sinclair/typebox": {
"version": "0.24.51",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz",
@ -27424,11 +27225,6 @@
"wrap-ansi": "^7.0.0"
}
},
"clsx": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg=="
},
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@ -29229,11 +29025,6 @@
"pify": "^2.2.0"
}
},
"exenv": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
"integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw=="
},
"exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@ -32124,11 +31915,6 @@
}
}
},
"jquery": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg=="
},
"js-sdsl": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
@ -32266,11 +32052,6 @@
"resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz",
"integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA=="
},
"keyboard-key": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/keyboard-key/-/keyboard-key-1.1.0.tgz",
"integrity": "sha512-qkBzPTi3rlAKvX7k0/ub44sqOfXeLc/jcnGGmj5c7BJpU8eDrEVPyhCvNYAaoubbsLm9uGWwQJO1ytQK1a9/dQ=="
},
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@ -32428,11 +32209,6 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="
},
"lodash-es": {
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz",
"integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A=="
},
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@ -34132,7 +33908,6 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"peer": true,
"requires": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
@ -34443,11 +34218,6 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
},
"react-fast-compare": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
},
"react-hotkeys-hook": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-5.3.3.tgz",
@ -34465,15 +34235,6 @@
"integrity": "sha512-y8O2yHHj3w0aE9XO8d2BCcUOOdQTRSVq+WIuMlLVucAm5XNjJAy+BoOJiuQMldVYVOKTMyvVNfnbl2Oqp+YxGw==",
"requires": {}
},
"react-popper": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz",
"integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==",
"requires": {
"react-fast-compare": "^3.0.1",
"warning": "^4.0.2"
}
},
"react-qr-code": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.2.0.tgz",
@ -34600,12 +34361,6 @@
"workbox-webpack-plugin": "^6.4.1"
}
},
"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": {}
},
"react-stl-viewer": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/react-stl-viewer/-/react-stl-viewer-2.5.0.tgz",
@ -35081,35 +34836,6 @@
"node-forge": "^1"
}
},
"semantic-ui-offline": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/semantic-ui-offline/-/semantic-ui-offline-2.5.1.tgz",
"integrity": "sha512-uwykZ0AF8rbKSsm6GIbQtAwLCKUexqKVX4qbbB1hvYNvOqhYdWqWMbTfrb3JLHYb19g9m6CEV6n+077AoVTUNg==",
"requires": {
"jquery": "^3.7.1"
}
},
"semantic-ui-react": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/semantic-ui-react/-/semantic-ui-react-2.1.5.tgz",
"integrity": "sha512-nIqmmUNpFHfovEb+RI2w3E2/maZQutd8UIWyRjf1SLse+XF51hI559xbz/sLN3O6RpLjr/echLOOXwKCirPy3Q==",
"peer": true,
"requires": {
"@babel/runtime": "^7.10.5",
"@fluentui/react-component-event-listener": "~0.63.0",
"@fluentui/react-component-ref": "~0.63.0",
"@popperjs/core": "^2.6.0",
"@semantic-ui-react/event-stack": "^3.1.3",
"clsx": "^1.1.1",
"keyboard-key": "^1.1.0",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"prop-types": "^15.7.2",
"react-is": "^16.8.6 || ^17.0.0 || ^18.0.0",
"react-popper": "^2.3.0",
"shallowequal": "^1.1.0"
}
},
"semver": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
@ -35282,11 +35008,6 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
"shallowequal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
},
"shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@ -36437,14 +36158,6 @@
"makeerror": "1.0.12"
}
},
"warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"requires": {
"loose-envify": "^1.0.0"
}
},
"watchpack": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz",

View file

@ -28,10 +28,7 @@
"react-qr-code": "^2.2.0",
"react-router": "^7.18.2",
"react-scripts": "5.0.1",
"react-semantic-toasts-2": "^0.6.7",
"react-stl-viewer": "^2.5.0",
"semantic-ui-offline": "^2.5.1",
"semantic-ui-react": "^2.1.5",
"three": "^0.185",
"web-vitals": "^5.3.0"
},

View file

@ -1,6 +1,5 @@
import React from 'react';
import {ArchiveDownloadForm, ChannelDownloadForm, EditRSSDownloadForm} from './Download';
import 'semantic-ui-offline/semantic.min.css';
describe('<ArchiveDownloadForm />', () => {
beforeEach(() => {

View file

@ -11,10 +11,6 @@ jest.mock('../../api', () => ({
getBatchReorganizationStatus: jest.fn(),
}));
// Mock react-semantic-toasts-2
jest.mock('react-semantic-toasts-2', () => ({
toast: jest.fn(),
}));
// Mock the FileWorkerStatusContext
jest.mock('../../contexts/FileWorkerStatusContext', () => ({

View file

@ -11,10 +11,6 @@ jest.mock('../../api', () => ({
getReorganizationStatus: jest.fn(),
}));
// Mock react-semantic-toasts-2
jest.mock('react-semantic-toasts-2', () => ({
toast: jest.fn(),
}));
// Mock the FileWorkerStatusContext - default mock returns inactive state
jest.mock('../../contexts/FileWorkerStatusContext', () => ({

View file

@ -9,10 +9,6 @@ jest.mock('../../api', () => ({
deleteFileGroups: jest.fn(),
}));
// Mock react-semantic-toasts-2
jest.mock('react-semantic-toasts-2', () => ({
toast: jest.fn(),
}));
describe('ConflictResolutionModal', () => {
const mockConflicts = [

View file

@ -17,7 +17,6 @@ jest.mock('../api/controller', () => ({
getControllerStats: jest.fn().mockResolvedValue({}),
}));
jest.mock('react-semantic-toasts-2', () => ({toast: jest.fn()}));
const controllerApi = require('../api/controller');

View file

@ -3,20 +3,20 @@ import path from 'path';
import baseline from './semantic-baseline.json';
/*
* A ratchet for the Semantic UI removal.
* Semantic UI is gone, and this keeps it gone.
*
* semantic-baseline.json lists every file that still imports Semantic UI (or the
* Semantic-based toast library). This test fails if a file not on that list
* starts importing them, and asks for the list to shrink when a file stops.
* It began as a ratchet: semantic-baseline.json listed the 75 files still importing
* Semantic UI, the list only shrank, and adding a file to it failed the build. The list
* reached zero, the three packages are uninstalled, and the baseline is now an empty
* array kept only so a reintroduction has to delete a file rather than edit one.
*
* It replaces an ESLint rule deliberately: `no-restricted-imports` would either
* print 75 warnings on every dev rebuild, or fail the build outright, and CI
* already unsets CI= for the build step so warnings there guard nothing.
* The assertions below are cheap and each one caught something real during the migration,
* so they stay: an import would now fail to resolve, but a `className="ui button"` or a
* reach back through Theme.tsx would not, and neither would reinstalling a package.
*
* The list has reached zero. The test stays as a guard rather than being deleted: it now
* asserts that nothing imports Semantic UI, nothing calls its toast library, nothing leans
* on its stylesheet, and no migrated file reaches back through Theme.tsx. It can go when
* the packages themselves are uninstalled.
* It is a test rather than an ESLint rule deliberately: `no-restricted-imports` would
* either print dozens of warnings on every dev rebuild or fail the build outright, and CI
* unsets CI= for its build step, so warnings there guard nothing.
*/
const SRC = path.join(__dirname);
@ -109,10 +109,26 @@ describe('Semantic UI removal', () => {
expect(leaks).toEqual([]);
});
it('reports how much of the migration is left', () => {
// Not an assertion so much as a progress readout in the test output.
const remaining = importers().length;
expect(remaining).toBeLessThanOrEqual(baseline.length);
console.log(`Semantic UI: ${remaining} files remaining to migrate.`);
it('has no Semantic package installed', () => {
/*
* The three packages are uninstalled. An import of a missing module fails loudly,
* so this guards the quieter mistake: someone reinstalling one -- to "just use a
* Semantic component for this one thing" -- which would drag the whole library and
* its 300kB stylesheet back into the bundle.
*/
const pkg = JSON.parse(
fs.readFileSync(path.join(SRC, '..', 'package.json'), 'utf8'));
const named = [...Object.keys(pkg.dependencies || {}),
...Object.keys(pkg.devDependencies || {})]
.filter(name => /semantic/i.test(name));
expect(named).toEqual([]);
});
it('keeps the baseline empty', () => {
// The migration is finished; the file stays as an empty list so that putting a
// name back requires a deliberate edit.
expect(baseline).toEqual([]);
expect(importers()).toEqual([]);
});
});