Skip to content

Commit

Permalink
move to seperate function
Browse files Browse the repository at this point in the history
  • Loading branch information
qdraw committed Dec 8, 2023
1 parent 69cabf4 commit 84aee23
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 82 deletions.
5 changes: 4 additions & 1 deletion starsky/starsky/clientapp/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ const config: StorybookConfig = {
},
docs: {
autodocs: "tag"
}
},
core: {
disableTelemetry: true, // 👈 Disables telemetry
},
};
export default config;
2 changes: 1 addition & 1 deletion starsky/starsky/clientapp/.vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
"editor.formatOnSave": true,
"eslint.alwaysShowStatus": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
"source.fixAll.eslint": "explicit"
}
}
8 changes: 4 additions & 4 deletions starsky/starsky/clientapp/clientapp.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
],
"settings": {
"editor.codeActionsOnSave": {
"source.organizeImports": true,
"source.fixAll": true,
"source.fixAll.eslint": true
},
"source.organizeImports": "explicit",
"source.fixAll": "explicit",
"source.fixAll.eslint": "explicit"
},
"editor.formatOnPaste": true,
"editor.tabSize": 2,
"editor.detectIndentation": false,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import {
render,
fireEvent,
waitFor,
act,
screen
} from "@testing-library/react";
import MenuOptionRotateImage90 from "./menu-option-rotate-image-90.tsx";
import { IDetailView } from "../../../interfaces/IDetailView.ts"; // for expect assertions

describe("MenuOptionRotateImage90", () => {
const mockState = {
subPath: "/path/to/image.jpg",
fileIndexItem: {
fileHash: "abc123",
filePath: "/path/to/image.jpg",
orientation: "Horizontal"
// Add any other necessary properties for your test case
},
breadcrumb: {},
pageType: "detailView",
colorClassUsage: [],
relativeObjects: {},
colorClassActiveList: [],
colorClassSelect: [],
isReadOnly: false,
dateCache: {}
// Add any other necessary properties for your test case
} as unknown as IDetailView;

it("renders without crashing", () => {
const container = render(
<MenuOptionRotateImage90
state={mockState}
setIsLoading={jest.fn()}
dispatch={jest.fn()}
isMarkedAsDeleted={false}
isReadOnly={false}
/>
);
expect(container.container).toBeTruthy();

container.unmount();
});

it("calls rotateImage90 function on click", async () => {
const setIsLoadingMock = jest.fn();
const container = render(
<MenuOptionRotateImage90
state={mockState}
setIsLoading={setIsLoadingMock}
dispatch={jest.fn()}
isMarkedAsDeleted={false}
isReadOnly={false}
/>
);

fireEvent.click(container.getByTestId("rotate")); // Assuming you have "data-testid" attribute in your MenuOption component

// You might need to wait for async operations to complete before asserting
await waitFor(() => {
expect(setIsLoadingMock).toHaveBeenCalledWith(true);
// Add more assertions based on the expected behavior of your component
});
});

it("handles timeouts correctly", async () => {
const setIsLoadingMock = jest.fn();

const component = render(
<MenuOptionRotateImage90
state={mockState}
setIsLoading={setIsLoadingMock}
dispatch={jest.fn()}
isMarkedAsDeleted={false}
isReadOnly={false}
/>
);

fireEvent.click(screen.getByTestId("rotate"));

// Manually advance the timer to the first setTimeout
act(() => {
jest.advanceTimersByTime(3000);
});

expect(setIsLoadingMock).toHaveBeenCalled();

// Manually advance the timer to the second setTimeout
act(() => {
jest.advanceTimersByTime(7000);
});

expect(setIsLoadingMock).toHaveBeenCalledWith(true);

component.unmount();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Meta } from "@storybook/react";
import { action } from "@storybook/addon-actions";
import MenuOptionRotateImage90 from "./menu-option-rotate-image-90.tsx";
import { IDetailView } from "../../../interfaces/IDetailView.ts";

export default {
component: MenuOptionRotateImage90,
title: "Menu/MenuOptionRotateImage90",
decorators: [
(Story) => (
<div style={{ padding: "20px", maxWidth: "300px" }}>
<Story />
</div>
)
]
} as Meta;

const Template = () => (
<MenuOptionRotateImage90
state={{} as IDetailView}
setIsLoading={action("setIsLoading")}
dispatch={() => {}}
isMarkedAsDeleted={false}
isReadOnly={false}
/>
);

export const Default = Template.bind({});
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import React, { Dispatch, memo } from "react";
import localization from "../../../localization/localization.json";
import FetchPost from "../../../shared/fetch-post";
import { UrlQuery } from "../../../shared/url-query";
import MenuOption from "../../atoms/menu-option/menu-option.tsx";
import FetchGet from "../../../shared/fetch-get.ts";
import { CastToInterface } from "../../../shared/cast-to-interface.ts";
import { Orientation } from "../../../interfaces/IFileIndexItem.ts";
import { IDetailView } from "../../../interfaces/IDetailView.ts";
import { DetailViewAction } from "../../../contexts/detailview-context.tsx";

interface IMenuOptionMenuOptionRotateImage90Props {
state: IDetailView;
setIsLoading: React.Dispatch<React.SetStateAction<boolean>>;
dispatch: Dispatch<DetailViewAction>;
isMarkedAsDeleted: boolean;
isReadOnly: boolean;
}

/**
* Used from DetailView
*/
const MenuOptionRotateImage90: React.FunctionComponent<IMenuOptionMenuOptionRotateImage90Props> =
memo(({ state, setIsLoading, dispatch, isMarkedAsDeleted, isReadOnly }) => {
/**
* Create body params to do url queries
*/
function newBodyParams(): URLSearchParams {
const bodyParams = new URLSearchParams();
bodyParams.set("f", state.subPath);
return bodyParams;
}

/**
* Checks if the hash is changes and update Context: orientation + fileHash
*/
async function requestNewFileHash(): Promise<boolean | null> {
const resultGet = await FetchGet(
new UrlQuery().UrlIndexServerApi({ f: state.subPath })
);
if (!resultGet) return null;
if (resultGet.statusCode !== 200) {
console.error(resultGet);
setIsLoading(false);
return null;
}
const media = new CastToInterface().MediaDetailView(resultGet.data).data;
const orientation = media?.fileIndexItem?.orientation
? media.fileIndexItem.orientation
: Orientation.Horizontal;

// the hash changes if you rotate an image
if (media.fileIndexItem.fileHash === state.fileIndexItem.fileHash)
return false;

dispatch({
type: "update",
orientation,
fileHash: media.fileIndexItem.fileHash,
filePath: media.fileIndexItem.filePath
});
setIsLoading(false);
return true;
}

/**
* Update the rotation status
*/
async function rotateImage90() {
if (isMarkedAsDeleted || isReadOnly) return;
setIsLoading(true);

const bodyParams = newBodyParams();
bodyParams.set("rotateClock", "1");
const resultPost = await FetchPost(
new UrlQuery().UrlUpdateApi(),
bodyParams.toString()
);
if (resultPost.statusCode !== 200) {
console.error(resultPost);
return;
}

// there is an async backend event triggered, sometimes there is an que
setTimeout(() => {
requestNewFileHash().then((result) => {
if (result === false) {
setTimeout(() => {
requestNewFileHash().then(() => {
// when it didn't change after two tries
setIsLoading(false);
});
}, 7000);
}
});
}, 3000);
}

return (
<MenuOption
isReadOnly={isReadOnly}
onClickKeydown={rotateImage90}
localization={localization.MessageRotateToRight}
testName="rotate"
/>
);
});

export default MenuOptionRotateImage90;
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,11 @@ import useKeyboardEvent from "../../../hooks/use-keyboard/use-keyboard-event";
import useLocation from "../../../hooks/use-location/use-location";
import { IDetailView } from "../../../interfaces/IDetailView";
import { IExifStatus } from "../../../interfaces/IExifStatus";
import {
IFileIndexItem,
Orientation
} from "../../../interfaces/IFileIndexItem";
import { IFileIndexItem } from "../../../interfaces/IFileIndexItem";
import { INavigateState } from "../../../interfaces/INavigateState";
import localization from "../../../localization/localization.json";
import { CastToInterface } from "../../../shared/cast-to-interface";
import { Comma } from "../../../shared/comma";
import { IsEditedNow } from "../../../shared/date";
import FetchGet from "../../../shared/fetch-get";
import FetchPost from "../../../shared/fetch-post";
import { FileListCache } from "../../../shared/filelist-cache";
import { Keyboard } from "../../../shared/keyboard";
Expand All @@ -33,6 +28,7 @@ import ModalDownload from "../modal-download/modal-download";
import ModalMoveFile from "../modal-move-file/modal-move-file";
import ModalPublishToggleWrapper from "../modal-publish/modal-publish-toggle-wrapper";
import { GoToParentFolder } from "./shared/go-to-parent-folder";
import MenuOptionRotateImage90 from "../../molecules/menu-option-rotate-image-90/menu-option-rotate-image-90.tsx";

export interface MenuDetailViewProps {
state: IDetailView;
Expand Down Expand Up @@ -235,71 +231,6 @@ const MenuDetailView: React.FunctionComponent<MenuDetailViewProps> = ({
new FileListCache().CacheCleanEverything();
}

/**
* Checks if the hash is changes and update Context: orientation + fileHash
*/
async function requestNewFileHash(): Promise<boolean | null> {
const resultGet = await FetchGet(
new UrlQuery().UrlIndexServerApi({ f: state.subPath })
);
if (!resultGet) return null;
if (resultGet.statusCode !== 200) {
console.error(resultGet);
setIsLoading(false);
return null;
}
const media = new CastToInterface().MediaDetailView(resultGet.data).data;
const orientation = media?.fileIndexItem?.orientation
? media.fileIndexItem.orientation
: Orientation.Horizontal;

// the hash changes if you rotate an image
if (media.fileIndexItem.fileHash === state.fileIndexItem.fileHash)
return false;

dispatch({
type: "update",
orientation,
fileHash: media.fileIndexItem.fileHash,
filePath: media.fileIndexItem.filePath
});
setIsLoading(false);
return true;
}

/**
* Update the rotation status
*/
async function rotateImage90() {
if (isMarkedAsDeleted || isReadOnly) return;
setIsLoading(true);

const bodyParams = newBodyParams();
bodyParams.set("rotateClock", "1");
const resultPost = await FetchPost(
new UrlQuery().UrlUpdateApi(),
bodyParams.toString()
);
if (resultPost.statusCode !== 200) {
console.error(resultPost);
return;
}

// there is an async backend event triggered, sometimes there is an que
setTimeout(() => {
requestNewFileHash().then((result) => {
if (result === false) {
setTimeout(() => {
requestNewFileHash().then(() => {
// when it didn't change after two tries
setIsLoading(false);
});
}, 7000);
}
});
}, 3000);
}

useKeyboardEvent(/(Delete)/, (event: KeyboardEvent) => {
if (new Keyboard().isInForm(event)) return;
event.preventDefault();
Expand Down Expand Up @@ -459,12 +390,13 @@ const MenuDetailView: React.FunctionComponent<MenuDetailViewProps> = ({
) : null}
</MenuOption>

<MenuOption
<MenuOptionRotateImage90
setIsLoading={setIsLoading}
state={state}
dispatch={dispatch}
isMarkedAsDeleted={isMarkedAsDeleted}
isReadOnly={isReadOnly}
onClickKeydown={rotateImage90}
localization={localization.MessageRotateToRight}
testName="rotate"
/>
></MenuOptionRotateImage90>

<MenuOptionModal
isReadOnly={false}
Expand Down

0 comments on commit 84aee23

Please sign in to comment.