From 54c6e3aebf9708e377819c2bad39eb302f1dbbd0 Mon Sep 17 00:00:00 2001 From: Dion Date: Wed, 6 Mar 2024 22:18:51 +0100 Subject: [PATCH 1/3] fix some code smells --- .../Helpers/ArgsHelper.cs | 12 ++- .../internal/remove-cache.spec.ts | 74 +++++++++++++++++++ .../internal/remove-cache.ts | 47 ++++++++++++ .../modal-archive-synchronize-manually.tsx | 44 ++++------- 4 files changed, 144 insertions(+), 33 deletions(-) create mode 100644 starsky/starsky/clientapp/src/components/organisms/modal-archive-synchronize-manually/internal/remove-cache.spec.ts create mode 100644 starsky/starsky/clientapp/src/components/organisms/modal-archive-synchronize-manually/internal/remove-cache.ts diff --git a/starsky/starsky.foundation.platform/Helpers/ArgsHelper.cs b/starsky/starsky.foundation.platform/Helpers/ArgsHelper.cs index 808894fde7..030ff415fb 100644 --- a/starsky/starsky.foundation.platform/Helpers/ArgsHelper.cs +++ b/starsky/starsky.foundation.platform/Helpers/ArgsHelper.cs @@ -554,7 +554,7 @@ public List GetPathListFormArgs(IReadOnlyList args) var path = GetUserInputPathFromArg(args); // To use only with -p or --path > current directory - if ( ( args.Contains("-p") || args.Contains("--path") ) && + if ( ( args.Contains("-p") || args.Contains(PathCommandLineArgLong) ) && ( path == string.Empty || path[0] == "-"[0] ) ) { path = Directory.GetCurrentDirectory(); @@ -572,6 +572,8 @@ public List GetPathListFormArgs(IReadOnlyList args) return dotCommaRegex.Split(path).Where(p => !string.IsNullOrWhiteSpace(p)).ToList(); } + private const string PathCommandLineArgLong = "--path"; + /// /// Get the user input from -p or --path /// @@ -582,7 +584,8 @@ private static string GetUserInputPathFromArg(IReadOnlyList args) var path = string.Empty; for ( var arg = 0; arg < args.Count; arg++ ) { - if ( ( args[arg].Equals("--path", StringComparison.CurrentCultureIgnoreCase) || + if ( ( args[arg].Equals(PathCommandLineArgLong, + StringComparison.CurrentCultureIgnoreCase) || args[arg].Equals("-p", StringComparison.CurrentCultureIgnoreCase) ) && ( arg + 1 ) != args.Count ) { @@ -671,7 +674,7 @@ public string GetPathFormArgs(IReadOnlyList args, bool dbStyle = true) var path = GetUserInputPathFromArg(args); // To use only with -p or --path > current directory - if ( ( args.Contains("-p") || args.Contains("--path") ) && + if ( ( args.Contains("-p") || args.Contains(PathCommandLineArgLong) ) && ( path == string.Empty || path[0] == "-"[0] ) ) { var currentDirectory = Directory.GetCurrentDirectory(); @@ -760,7 +763,8 @@ public static bool IsSubPathOrPath(IReadOnlyList args) { // To use only with -p or --path > current directory if ( args.Any(arg => - ( arg.Equals("--path", StringComparison.CurrentCultureIgnoreCase) || + ( arg.Equals(PathCommandLineArgLong, + StringComparison.CurrentCultureIgnoreCase) || arg.Equals("-p", StringComparison.CurrentCultureIgnoreCase) )) ) { return false; diff --git a/starsky/starsky/clientapp/src/components/organisms/modal-archive-synchronize-manually/internal/remove-cache.spec.ts b/starsky/starsky/clientapp/src/components/organisms/modal-archive-synchronize-manually/internal/remove-cache.spec.ts new file mode 100644 index 0000000000..1c001145eb --- /dev/null +++ b/starsky/starsky/clientapp/src/components/organisms/modal-archive-synchronize-manually/internal/remove-cache.spec.ts @@ -0,0 +1,74 @@ +import { FileListCache } from "../../../../shared/filelist-cache"; +import { RemoveCache } from "./remove-cache"; + +describe("RemoveCache function", () => { + beforeEach(() => { + jest.useFakeTimers(); + }); + + afterEach(() => { + jest.clearAllTimers(); + }); + + it("should call setIsLoading with true", () => { + const setIsLoading = jest.fn(); + RemoveCache(setIsLoading, "/parent", "search", jest.fn(), jest.fn()); + expect(setIsLoading).toHaveBeenCalledWith(true); + }); + + it("should call CacheCleanEverything", () => { + const cacheCleanEverything = jest.spyOn(FileListCache.prototype, "CacheCleanEverything"); + RemoveCache(jest.fn(), "/parent", "search", jest.fn(), jest.fn()); + expect(cacheCleanEverything).toHaveBeenCalled(); + cacheCleanEverything.mockRestore(); + }); + + it("should call FetchGet with the correct URL to remove cache", () => { + const fetchGet = jest.spyOn(global, "FetchGet").mockResolvedValue(); + const parentFolder = "/parent"; + RemoveCache(jest.fn(), parentFolder, "search", jest.fn(), jest.fn()); + expect(fetchGet).toHaveBeenCalledWith(expect.any(String)); + expect(fetchGet.mock.calls[0][0]).toContain("/remove-cache"); + expect(fetchGet.mock.calls[0][0]).toContain(encodeURIComponent(parentFolder)); + fetchGet.mockRestore(); + }); + + it("should call FetchGet with the correct URL to index server API after setTimeout", () => { + const fetchGet = jest.spyOn(global, "FetchGet").mockResolvedValue(); + const setTimeoutSpy = jest.spyOn(global, "setTimeout"); + const parentFolder = "/parent"; + const historyLocationSearch = "search"; + RemoveCache(jest.fn(), parentFolder, historyLocationSearch, jest.fn(), jest.fn()); + + expect(setTimeoutSpy).toHaveBeenCalledWith(expect.any(Function), 600); + jest.runAllTimers(); + + expect(fetchGet).toHaveBeenCalledWith(expect.any(String)); + expect(fetchGet.mock.calls[1][0]).toContain("/index-server-api"); + expect(fetchGet.mock.calls[1][0]).toContain(historyLocationSearch); + + fetchGet.mockRestore(); + setTimeoutSpy.mockRestore(); + }); + + it("should dispatch force-reset action when payload has fileIndexItems", async () => { + const dispatch = jest.fn(); + const mediaArchiveData = { + data: { + fileIndexItems: [{}, {}] // Mocking fileIndexItems + } + }; + const fetchGet = jest.spyOn(global, "FetchGet").mockResolvedValue(mediaArchiveData); + await RemoveCache(jest.fn(), "/parent", "search", dispatch, jest.fn()); + + expect(dispatch).toHaveBeenCalledWith({ type: "force-reset", payload: mediaArchiveData.data }); + fetchGet.mockRestore(); + }); + + it("should call propsHandleExit after completing", async () => { + const propsHandleExit = jest.fn(); + const dispatch = jest.fn(); + await RemoveCache(jest.fn(), "/parent", "search", dispatch, propsHandleExit); + expect(propsHandleExit).toHaveBeenCalled(); + }); +}); diff --git a/starsky/starsky/clientapp/src/components/organisms/modal-archive-synchronize-manually/internal/remove-cache.ts b/starsky/starsky/clientapp/src/components/organisms/modal-archive-synchronize-manually/internal/remove-cache.ts new file mode 100644 index 0000000000..181f6cef1a --- /dev/null +++ b/starsky/starsky/clientapp/src/components/organisms/modal-archive-synchronize-manually/internal/remove-cache.ts @@ -0,0 +1,47 @@ +import { ArchiveAction } from "../../../../contexts/archive-context.tsx"; +import { FileListCache } from "../../../../shared/filelist-cache.ts"; +import FetchGet from "../../../../shared/fetch/fetch-get.ts"; +import { UrlQuery } from "../../../../shared/url/url-query.ts"; +import { URLPath } from "../../../../shared/url/url-path.ts"; +import { CastToInterface } from "../../../../shared/cast-to-interface.ts"; +import { IArchiveProps } from "../../../../interfaces/IArchiveProps.ts"; +import { Dispatch, SetStateAction } from "react"; + +/** + * Remove Folder cache + */ +export function RemoveCache( + setIsLoading: Dispatch>, + propsParentFolder: string, + historyLocationSearch: string, + dispatch: Dispatch, + propsHandleExit: () => {} +) { + setIsLoading(true); + new FileListCache().CacheCleanEverything(); + const parentFolder = propsParentFolder ?? "/"; + FetchGet(new UrlQuery().UrlRemoveCache(new URLPath().encodeURI(parentFolder))) + .then(() => { + return new Promise((resolve) => { + setTimeout(() => { + resolve( + new UrlQuery().UrlIndexServerApi(new URLPath().StringToIUrl(historyLocationSearch)) + ); + }, 600); + }); + }) + .then((url: string) => { + return FetchGet(url, { "Cache-Control": "no-store, max-age=0" }); + }) + .then((connectionResult) => { + const removeCacheResult = new CastToInterface().MediaArchive(connectionResult.data); + const payload = removeCacheResult.data as IArchiveProps; + if (payload.fileIndexItems) { + dispatch({ type: "force-reset", payload }); + } + propsHandleExit(); + }) + .catch((error) => { + console.error("Error:", error); + }); +} diff --git a/starsky/starsky/clientapp/src/components/organisms/modal-archive-synchronize-manually/modal-archive-synchronize-manually.tsx b/starsky/starsky/clientapp/src/components/organisms/modal-archive-synchronize-manually/modal-archive-synchronize-manually.tsx index 3f54e08648..b3f954bda4 100644 --- a/starsky/starsky/clientapp/src/components/organisms/modal-archive-synchronize-manually/modal-archive-synchronize-manually.tsx +++ b/starsky/starsky/clientapp/src/components/organisms/modal-archive-synchronize-manually/modal-archive-synchronize-manually.tsx @@ -3,22 +3,20 @@ import { ArchiveContext } from "../../../contexts/archive-context"; import useGlobalSettings from "../../../hooks/use-global-settings"; import useInterval from "../../../hooks/use-interval"; import useLocation from "../../../hooks/use-location/use-location"; -import { IArchiveProps } from "../../../interfaces/IArchiveProps"; import localization from "../../../localization/localization.json"; -import { CastToInterface } from "../../../shared/cast-to-interface"; import FetchGet from "../../../shared/fetch/fetch-get"; import FetchPost from "../../../shared/fetch/fetch-post"; -import { FileListCache } from "../../../shared/filelist-cache"; import { Language } from "../../../shared/language"; import { URLPath } from "../../../shared/url/url-path"; import { UrlQuery } from "../../../shared/url/url-query"; import Modal from "../../atoms/modal/modal"; import Preloader from "../../atoms/preloader/preloader"; import ForceSyncWaitButton from "../../molecules/force-sync-wait-button/force-sync-wait-button"; +import { RemoveCache } from "./internal/remove-cache.ts"; interface IModalDisplayOptionsProps { isOpen: boolean; - handleExit: Function; + handleExit: () => {}; parentFolder?: string; } @@ -53,30 +51,6 @@ const ModalArchiveSynchronizeManually: React.FunctionComponent { - setTimeout(() => { - const url = new UrlQuery().UrlIndexServerApi( - new URLPath().StringToIUrl(history.location.search) - ); - FetchGet(url, { "Cache-Control": "no-store, max-age=0" }).then((connectionResult) => { - const removeCacheResult = new CastToInterface().MediaArchive(connectionResult.data); - const payload = removeCacheResult.data as IArchiveProps; - if (payload.fileIndexItems) { - dispatch({ type: "force-reset", payload }); - } - props.handleExit(); - }); - }, 600); - }); - } - const [geoSyncPercentage, setGeoSyncPercentage] = useState(0); function geoSync() { @@ -139,7 +113,19 @@ const ModalArchiveSynchronizeManually: React.FunctionComponent props.handleExit()} dispatch={dispatch} > -