Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,20 @@ describe('AIAssistantView', () => {
});

describe('chat event handlers', () => {
describe('onChatCleared', () => {
Comment thread
dmirgaev marked this conversation as resolved.
it('should call clear on aiChatInstance when triggered', () => {
createAIAssistantView();

const aiChatInstance = (AIChat as jest.Mock)
.mock.results[0].value as { clear: jest.Mock };

const aiChatConfig = (AIChat as jest.Mock).mock.calls[0][0] as AIChatOptions;
aiChatConfig.onChatCleared?.();

expect(aiChatInstance.clear).toHaveBeenCalledTimes(1);
});
});

describe('onMessageEntered', () => {
it('should send request to AI with the entered message', () => {
mockAIAssistantController.sendRequestToAI.mockReturnValue(Promise.resolve());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,5 +357,27 @@ describe('AIAssistantViewController', () => {
expect(getMessageStatusClass($messagesAfter.eq(1)))
.toBe(MessageStatus.Success);
});

it('should clear all messages when clear chat button is clicked', async () => {
const { instance, getLastCallbacks } = await createDataGridWithAIAssistant();

sendAIRequest(instance, 'Sort by Name');

getLastCallbacks().onComplete?.({
actions: [{ name: 'sort', args: { column: 'Name' } }],
});
await flushAsync();
await flushAsync();

expect(findMessageElements().length).toBe(1);

const clearButtonEl = document.querySelector(`.${CLASSES.clearChatButton} .dx-button`) as HTMLElement;

clearButtonEl.click();
await flushAsync();
await flushAsync();

expect(findMessageElements().length).toBe(0);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ export class AIAssistantView extends View {
return {
container: this.element(),
createComponent: this._createComponent.bind(this),
onChatCleared: (): void => {},
onChatCleared: (): void => {
this.aiChatInstance.clear();
},
onRegenerate: (): void => {},
popupOptions,
chatOptions,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,15 @@ const mockPopupInstance = {

const mockChatElement = $('<div>');

const mockDataSource = {
store: jest.fn(),
reload: jest.fn(),
};

const mockChatInstance = {
option: jest.fn(),
$element: jest.fn(() => mockChatElement),
getDataSource: jest.fn(() => mockDataSource),
};

const mockClearChatButtonInstance = {
Expand Down Expand Up @@ -130,6 +136,7 @@ const beforeTest = (): void => {
mockChatElement.empty();
mockWidgetInstance.option.mockClear();
mockClearChatButtonInstance.option.mockClear();
mockChatInstance.getDataSource.mockReturnValue(mockDataSource);
};

const afterTest = (): void => {
Expand Down Expand Up @@ -919,4 +926,40 @@ describe('AIChat', () => {
});
});
});

describe('clear', () => {
it('should clear store and reload dataSource', () => {
const mockStore = { clear: jest.fn() };
mockDataSource.store.mockReturnValue(mockStore);

const { aiChat } = createAIChat();
triggerContentTemplate();

aiChat.clear();

expect(mockChatInstance.getDataSource).toHaveBeenCalledTimes(1);
expect(mockDataSource.store).toHaveBeenCalledTimes(1);
expect(mockStore.clear).toHaveBeenCalledTimes(1);
expect(mockDataSource.reload).toHaveBeenCalledTimes(1);
});

it('should not throw when dataSource is undefined', () => {
mockChatInstance.getDataSource.mockReturnValue(undefined as any);

const { aiChat } = createAIChat();
triggerContentTemplate();

expect(() => {
aiChat.clear();
}).not.toThrow();
});

it('should not throw when chatInstance is not initialized', () => {
const { aiChat } = createAIChat();

expect(() => {
aiChat.clear();
}).not.toThrow();
});
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { name as clickEventName } from '@js/common/core/events/click';
import eventsEngine from '@js/common/core/events/core/events_engine';
import messageLocalization from '@js/common/core/localization/message';
import type { ArrayStore } from '@js/common/data';
import type { dxElementWrapper } from '@js/core/renderer';
import $ from '@js/core/renderer';
import type { Message, Properties as ChatProperties } from '@js/ui/chat';
Expand Down Expand Up @@ -333,4 +334,13 @@ export class AIChat {
this.renderMessageHeader($content, message);
this.renderMessageStateContent($content, message);
}

public clear(): void {
const dataSource = this.chatInstance?.getDataSource();
const store = dataSource?.store() as ArrayStore<Message, string>;

store?.clear();
Comment thread
Alyar666 marked this conversation as resolved.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
dataSource?.reload();
Comment thread
Alyar666 marked this conversation as resolved.
}
}
Loading