Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: keep in history list after history deleted #26

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions public/tabs/history/__tests__/chat_history_page.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { act, fireEvent, render, waitFor } from '@testing-library/react';
import { BehaviorSubject } from 'rxjs';
import { I18nProvider } from '@osd/i18n/react';

import * as useChatStateExports from '../../../hooks/use_chat_state';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: we should barrel this stuff in like

public/tabs/history/index.ts

and then export those files in there so that we can just import with a single line.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that means we create a public/tabs/history/index.ts file and exports all references in it like these

export * from './../hooks/use_chat_state';
export *  from '../../../contexts/chat_context';

then we can import them in single line like this

import * as historyExports from "../";

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah and i think if you need to import you can be like

import { useChatState } from '../history'

depending on where you are importing it. I would export * like how you are doing and then be specific.

Our build system is like a custom implementation of babel and webpack so importing everything with * could potentially not support tree-shaking. So just in general probably better to import what you need to ensure a smaller bundle size.

import * as chatContextExports from '../../../contexts/chat_context';
import * as coreContextExports from '../../../contexts/core_context';

import { ChatHistoryPage } from '../chat_history_page';

const setup = () => {
const useCoreMock = {
services: {
sessions: {
sessions$: new BehaviorSubject({
objects: [
{
id: '1',
title: 'foo',
},
],
total: 1,
}),
status$: new BehaviorSubject('idle'),
load: jest.fn(),
},
sessionLoad: {},
},
};
const useChatStateMock = {
chatStateDispatch: jest.fn(),
};
const useChatContextMock = {
sessionId: '1',
setSessionId: jest.fn(),
setTitle: jest.fn(),
};
jest.spyOn(coreContextExports, 'useCore').mockReturnValue(useCoreMock);
jest.spyOn(useChatStateExports, 'useChatState').mockReturnValue(useChatStateMock);
jest.spyOn(chatContextExports, 'useChatContext').mockReturnValue(useChatContextMock);

const renderResult = render(
<I18nProvider>
<ChatHistoryPage shouldRefresh={false} />
</I18nProvider>
);

return {
useCoreMock,
useChatStateMock,
useChatContextMock,
renderResult,
};
};

describe('<ChatHistoryPage />', () => {
it('should clear old session data after current session deleted', async () => {
const { renderResult, useChatStateMock, useChatContextMock } = setup();

act(() => {
fireEvent.click(renderResult.getByLabelText('Delete conversation'));
});

expect(useChatContextMock.setSessionId).not.toHaveBeenCalled();
expect(useChatContextMock.setTitle).not.toHaveBeenCalled();
expect(useChatStateMock.chatStateDispatch).not.toHaveBeenCalled();

act(() => {
fireEvent.click(renderResult.getByTestId('confirmModalConfirmButton'));
});

expect(useChatContextMock.setSessionId).toHaveBeenLastCalledWith(undefined);
expect(useChatContextMock.setTitle).toHaveBeenLastCalledWith(undefined);
expect(useChatStateMock.chatStateDispatch).toHaveBeenLastCalledWith({ type: 'reset' });
});
});
18 changes: 14 additions & 4 deletions public/tabs/history/chat_history_page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { FormattedMessage } from '@osd/i18n/react';
import { useDebounce, useObservable } from 'react-use';
import cs from 'classnames';
import { useChatActions } from '../../hooks/use_chat_actions';
import { useChatState } from '../../hooks/use_chat_state';
import { useChatContext } from '../../contexts/chat_context';
import { useCore } from '../../contexts/core_context';
import { ChatHistorySearchList } from './chat_history_search_list';
Expand All @@ -33,7 +34,14 @@ interface ChatHistoryPageProps {
export const ChatHistoryPage: React.FC<ChatHistoryPageProps> = React.memo((props) => {
const { services } = useCore();
const { loadChat } = useChatActions();
const { setSelectedTabId, flyoutFullScreen, sessionId } = useChatContext();
const { chatStateDispatch } = useChatState();
const {
setSelectedTabId,
flyoutFullScreen,
sessionId,
setSessionId,
setTitle,
} = useChatContext();
const [pageIndex, setPageIndex] = useState(0);
const [pageSize, setPageSize] = useState(10);
const [searchName, setSearchName] = useState<string>();
Expand Down Expand Up @@ -70,11 +78,13 @@ export const ChatHistoryPage: React.FC<ChatHistoryPageProps> = React.memo((props
const handleHistoryDeleted = useCallback(
(id: string) => {
if (sessionId === id) {
// Switch to new conversation when current session be deleted
loadChat();
// Clear old session chat states
setTitle(undefined);
setSessionId(undefined);
chatStateDispatch({ type: 'reset' });
}
},
[sessionId, loadChat]
[sessionId, setSessionId, setTitle, chatStateDispatch]
);

useDebounce(
Expand Down
8 changes: 4 additions & 4 deletions public/tabs/history/chat_history_search_list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export const ChatHistorySearchList = ({
} | null>(null);
const [deletingConversation, setDeletingConversation] = useState<{ id: string } | null>(null);

const handleEditConversationCancel = useCallback(
const handleEditConversationModalClose = useCallback(
(status: 'updated' | string) => {
if (status === 'updated') {
onRefresh();
Expand All @@ -61,7 +61,7 @@ export const ChatHistorySearchList = ({
[setEditingConversation, onRefresh]
);

const handleDeleteConversationCancel = useCallback(
const handleDeleteConversationConfirmModalClose = useCallback(
(status: 'deleted' | string) => {
if (status === 'deleted') {
onRefresh();
Expand Down Expand Up @@ -108,15 +108,15 @@ export const ChatHistorySearchList = ({
/>
{editingConversation && (
<EditConversationNameModal
onClose={handleEditConversationCancel}
onClose={handleEditConversationModalClose}
sessionId={editingConversation.id}
defaultTitle={editingConversation.title}
/>
)}
{deletingConversation && (
<DeleteConversationConfirmModal
sessionId={deletingConversation.id}
onClose={handleDeleteConversationCancel}
onClose={handleDeleteConversationConfirmModalClose}
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const DeleteConversationConfirmModal = ({
onClose,
sessionId,
}: DeleteConversationConfirmModalProps) => {
const { loading, data, deleteSession, abortController } = useDeleteSession();
const { loading, deleteSession, abortController } = useDeleteSession();

const handleCancel = useCallback(() => {
abortController?.abort();
Expand Down
6 changes: 6 additions & 0 deletions test/__mocks__/fileMock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

module.exports = 'file-stub';
6 changes: 6 additions & 0 deletions test/__mocks__/styleMock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

module.exports = {};