From cb5330c94213bf1dbbfb5dfa688aca519e8d6e53 Mon Sep 17 00:00:00 2001 From: Ahmet Can Buyukyilmaz Date: Tue, 25 Feb 2025 09:35:33 +0300 Subject: [PATCH 1/2] chore(deps): updated the react ecosystem packages, fixed 1 failing test --- package.json | 10 +- .../ScriptsUpload/ScriptsUpload.test.tsx | 2 +- yarn.lock | 117 ++++++++---------- 3 files changed, 61 insertions(+), 68 deletions(-) diff --git a/package.json b/package.json index 7e64861e44..c6c150e97f 100644 --- a/package.json +++ b/package.json @@ -71,10 +71,10 @@ "re-reselect": "5.1.0", "react": "18.3.1", "react-dom": "18.3.1", - "react-dropzone": "14.2.3", + "react-dropzone": "14.3.8", "react-ga4": "2.1.0", "react-redux": "8.1.3", - "react-router-dom": "6.24.0", + "react-router-dom": "6.29.0", "react-storage-hooks": "4.0.1", "react-useportal": "1.0.19", "reconnecting-websocket": "4.4.0", @@ -118,9 +118,9 @@ "@types/node": "20.12.12", "@types/path-parse": "1.0.22", "@types/pluralize": "0.0.33", - "@types/react": "18.3.3", - "@types/react-dom": "18.3.0", - "@types/react-redux": "7.1.33", + "@types/react": "18.3.18", + "@types/react-dom": "18.3.5", + "@types/react-redux": "7.1.34", "@types/react-router": "5.1.20", "@types/react-router-dom": "5.3.3", "@types/redux-mock-store": "1.0.6", diff --git a/src/app/settings/views/Scripts/ScriptsUpload/ScriptsUpload.test.tsx b/src/app/settings/views/Scripts/ScriptsUpload/ScriptsUpload.test.tsx index 6a61dff1a0..8c2be3b133 100644 --- a/src/app/settings/views/Scripts/ScriptsUpload/ScriptsUpload.test.tsx +++ b/src/app/settings/views/Scripts/ScriptsUpload/ScriptsUpload.test.tsx @@ -73,7 +73,7 @@ describe("ScriptsUpload", () => { await waitFor(() => expect( - screen.getByText("foo.sh (2000 bytes) ready for upload.") + screen.getByText("./foo.sh (2000 bytes) ready for upload.") ).toBeInTheDocument() ); }); diff --git a/yarn.lock b/yarn.lock index 2115aab767..fe97b9f45b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3530,10 +3530,10 @@ redux-thunk "^2.4.2" reselect "^4.1.8" -"@remix-run/router@1.17.0": - version "1.17.0" - resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.17.0.tgz#fbb0add487478ef42247d5942e7a5d8a2e20095f" - integrity sha512-2D6XaHEVvkCn682XBnipbJjgZUU7xjLtA4dGJRBVUKpEaDYOZMENZoZjAOSb7qirxt5RupjzZxz4fK2FO+EFPw== +"@remix-run/router@1.22.0": + version "1.22.0" + resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.22.0.tgz#dd8096cb055c475a4de6b35322b8d3b118c17b43" + integrity sha512-MBOl8MeOzpK0HQQQshKB7pABXbmyHizdTpqnrIseTbsv0nAepwC2ENZa1aaBExNQcpLoXmWthhak8SABLzvGPw== "@rollup/pluginutils@^4.2.1": version "4.2.1" @@ -5106,10 +5106,15 @@ dependencies: "@types/react" "*" -"@types/react-redux@7.1.33": - version "7.1.33" - resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.33.tgz#53c5564f03f1ded90904e3c90f77e4bd4dc20b15" - integrity sha512-NF8m5AjWCkert+fosDsN3hAlHzpjSiXlVy9EgQEmLoBhaNXbmyeGs/aj5dQzKuF+/q+S7JQagorGDW8pJ28Hmg== +"@types/react-dom@18.3.5": + version "18.3.5" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.5.tgz#45f9f87398c5dcea085b715c58ddcf1faf65f716" + integrity sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q== + +"@types/react-redux@7.1.34": + version "7.1.34" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.34.tgz#83613e1957c481521e6776beeac4fd506d11bd0e" + integrity sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ== dependencies: "@types/hoist-non-react-statics" "^3.3.0" "@types/react" "*" @@ -5148,6 +5153,14 @@ "@types/prop-types" "*" csstype "^3.0.2" +"@types/react@18.3.18": + version "18.3.18" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.18.tgz#9b382c4cd32e13e463f97df07c2ee3bbcd26904b" + integrity sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ== + dependencies: + "@types/prop-types" "*" + csstype "^3.0.2" + "@types/redux-mock-store@1.0.6": version "1.0.6" resolved "https://registry.yarnpkg.com/@types/redux-mock-store/-/redux-mock-store-1.0.6.tgz#0a03b2655028b7cf62670d41ac1de5ca1b1f5958" @@ -6027,10 +6040,10 @@ at-least-node@^1.0.0: resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== -attr-accept@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-2.2.2.tgz#646613809660110749e92f2c10833b70968d929b" - integrity sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg== +attr-accept@^2.2.4: + version "2.2.5" + resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-2.2.5.tgz#d7061d958e6d4f97bf8665c68b75851a0713ab5e" + integrity sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ== available-typed-arrays@^1.0.5: version "1.0.5" @@ -8441,12 +8454,12 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -file-selector@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/file-selector/-/file-selector-0.6.0.tgz#fa0a8d9007b829504db4d07dd4de0310b65287dc" - integrity sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw== +file-selector@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/file-selector/-/file-selector-2.1.2.tgz#fe7c7ee9e550952dfbc863d73b14dc740d7de8b4" + integrity sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig== dependencies: - tslib "^2.4.0" + tslib "^2.7.0" file-system-cache@2.3.0: version "2.3.0" @@ -12046,13 +12059,13 @@ react-dom@18.3.1: loose-envify "^1.1.0" scheduler "^0.23.2" -react-dropzone@14.2.3: - version "14.2.3" - resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-14.2.3.tgz#0acab68308fda2d54d1273a1e626264e13d4e84b" - integrity sha512-O3om8I+PkFKbxCukfIR3QAGftYXDZfOE2N1mr/7qebQJHs7U+/RSL/9xomJNpRg9kM5h9soQSdf0Gc7OHF5Fug== +react-dropzone@14.3.8: + version "14.3.8" + resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-14.3.8.tgz#a7eab118f8a452fe3f8b162d64454e81ba830582" + integrity sha512-sBgODnq+lcA4P296DY4wacOZz3JFpD99fp+hb//iBO2HHnyeZU3FwWyXJ6salNpqQdsZrgMrotuko/BdJMV8Ug== dependencies: - attr-accept "^2.2.2" - file-selector "^0.6.0" + attr-accept "^2.2.4" + file-selector "^2.1.0" prop-types "^15.8.1" react-element-to-jsx-string@^15.0.0: @@ -12130,20 +12143,20 @@ react-remove-scroll@2.5.5: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" -react-router-dom@6.24.0: - version "6.24.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.24.0.tgz#ec49dc38c49bb9bd25b310a8ae849268d3085e1d" - integrity sha512-960sKuau6/yEwS8e+NVEidYQb1hNjAYM327gjEyXlc6r3Skf2vtwuJ2l7lssdegD2YjoKG5l8MsVyeTDlVeY8g== +react-router-dom@6.29.0: + version "6.29.0" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.29.0.tgz#2ffb56b03ef3d6d6daafcfad9f3922132d2ced94" + integrity sha512-pkEbJPATRJ2iotK+wUwHfy0xs2T59YPEN8BQxVCPeBZvK7kfPESRc/nyxzdcxR17hXgUPYx2whMwl+eo9cUdnQ== dependencies: - "@remix-run/router" "1.17.0" - react-router "6.24.0" + "@remix-run/router" "1.22.0" + react-router "6.29.0" -react-router@6.24.0: - version "6.24.0" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.24.0.tgz#aa46648f26b6525e07f908ad3e1ad2e68d131155" - integrity sha512-sQrgJ5bXk7vbcC4BxQxeNa5UmboFm35we1AFK0VvQaz9g0LzxEIuLOhHIoZ8rnu9BO21ishGeL9no1WB76W/eg== +react-router@6.29.0: + version "6.29.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.29.0.tgz#14a329ca838b4de048fc5cca82874b727ee546b7" + integrity sha512-DXZJoE0q+KyeVw75Ck6GkPxFak63C4fGqZGNijnWgzB/HzSP1ZfTlBj5COaGWwhrMQ/R8bXiq5Ooy4KG+ReyjQ== dependencies: - "@remix-run/router" "1.17.0" + "@remix-run/router" "1.22.0" react-storage-hooks@4.0.1: version "4.0.1" @@ -13096,7 +13109,7 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -13114,15 +13127,6 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -13188,7 +13192,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -13202,13 +13206,6 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" -strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -13655,6 +13652,11 @@ tslib@^2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +tslib@^2.7.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" @@ -14400,7 +14402,7 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -14418,15 +14420,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 550596f7e272c7e26c355620a905fa349a220568 Mon Sep 17 00:00:00 2001 From: Ahmet Can Buyukyilmaz Date: Tue, 25 Feb 2025 10:30:01 +0300 Subject: [PATCH 2/2] tests(settings): implemented renderWithProviders, added custom test history support --- .../ScriptsUpload/ScriptsUpload.test.tsx | 29 ++++------- src/testing/utils.tsx | 48 ++++++++++++------- 2 files changed, 41 insertions(+), 36 deletions(-) diff --git a/src/app/settings/views/Scripts/ScriptsUpload/ScriptsUpload.test.tsx b/src/app/settings/views/Scripts/ScriptsUpload/ScriptsUpload.test.tsx index 8c2be3b133..dd727b90e6 100644 --- a/src/app/settings/views/Scripts/ScriptsUpload/ScriptsUpload.test.tsx +++ b/src/app/settings/views/Scripts/ScriptsUpload/ScriptsUpload.test.tsx @@ -3,7 +3,6 @@ import type { FileWithPath } from "react-dropzone"; import { Provider } from "react-redux"; import { MemoryRouter } from "react-router-dom"; import type { Dispatch } from "redux"; -import { HistoryRouter as Router } from "redux-first-history/rr6"; import configureStore from "redux-mock-store"; import ScriptsUpload, { Labels as ScriptsUploadLabels } from "./ScriptsUpload"; @@ -19,7 +18,7 @@ import { render, waitFor, fireEvent, - renderWithMockStore, + renderWithProviders, } from "@/testing/utils"; const mockStore = configureStore(); @@ -61,12 +60,9 @@ describe("ScriptsUpload", () => { it("accepts files of any mimetype", async () => { const files = [createFile("foo.sh", 2000, "")]; - renderWithMockStore( - - - , - { state } - ); + renderWithProviders(, { + state, + }); const upload = screen.getByLabelText(ScriptsUploadLabels.FileUploadArea); await userEvent.upload(upload, files); @@ -212,12 +208,10 @@ describe("ScriptsUpload", () => { const history = createMemoryHistory({ initialEntries: ["/"], }); - renderWithMockStore( - - - , - { state } - ); + renderWithProviders(, { + state, + history, + }); await userEvent.click(screen.getByRole("button", { name: "Cancel" })); expect(history.location.pathname).toBe("/settings/scripts/commissioning"); // linting errors occur if you use settingsUrls.scripts }); @@ -226,12 +220,7 @@ describe("ScriptsUpload", () => { const history = createMemoryHistory({ initialEntries: ["/"], }); - renderWithMockStore( - - - , - { state } - ); + renderWithProviders(, { state, history }); await userEvent.click(screen.getByRole("button", { name: "Cancel" })); expect(history.location.pathname).toBe("/settings/scripts/testing"); // linting errors occur if you use settingsUrls.scripts }); diff --git a/src/testing/utils.tsx b/src/testing/utils.tsx index da688dcf70..b428ee8d77 100644 --- a/src/testing/utils.tsx +++ b/src/testing/utils.tsx @@ -1,4 +1,4 @@ -import { type ReactNode } from "react"; +import { type ReactNode, useEffect } from "react"; import type { ValueOf } from "@canonical/react-components"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; @@ -544,6 +544,7 @@ type TestProviderProps = { queryData?: { queryKey: any; data: Partial> | undefined }[]; store?: MockStoreEnhanced; route?: string; + history?: MemoryHistory; }; /** @@ -553,6 +554,7 @@ type TestProviderProps = { * @param state The app state used for testing * @param store The mock store * @param route The route for the test + * @param history The history object for navigation * @constructor */ export const TestProvider = ({ @@ -560,20 +562,27 @@ export const TestProvider = ({ state = factory.rootState(), store, route = "/", + history = createMemoryHistory({ initialEntries: [route] }), }: TestProviderProps) => { - window.history.pushState({}, "Test page", route); const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false, staleTime: Infinity } }, }); const mockStore = store ?? configureStore()(state); + useEffect(() => { + const stopListening = history.listen(({ location }) => { + window.history.pushState({}, "", location.pathname + location.search); + }); + return () => stopListening(); + }, [history]); + return ( - {children} + {children} @@ -589,20 +598,27 @@ export const TestProvider = ({ */ export const renderWithProviders = ( ui: ReactNode, - options?: Omit & Partial + options?: Omit & + Partial & { history?: MemoryHistory } ) => { - const { state, queryData, store, ...renderOptions } = options ?? {}; - return render(ui, { - wrapper: (props) => ( - - ), - ...renderOptions, - }); + const { state, queryData, store, history, ...renderOptions } = options ?? {}; + const testHistory = history ?? createMemoryHistory(); + + return { + ...render(ui, { + wrapper: (props) => ( + + ), + ...renderOptions, + }), + history: testHistory, + }; }; /**