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

Iris: Add clear chat session button #6894

Merged
merged 139 commits into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from 132 commits
Commits
Show all changes
139 commits
Select commit Hold shift + click to select a range
c34b5bb
Chatbot full screen initialization -not complete
eceeeren May 29, 2023
c794781
draggable & resizable features added
asliayk May 29, 2023
564ac59
minor design updates
asliayk May 29, 2023
4cfe422
popup window moved into widget
asliayk May 31, 2023
f4217c7
Chatbot full screen design fix
eceeeren Jun 1, 2023
48240cc
Scroll to bottom button is added
eceeeren Jun 3, 2023
e57829d
Multiline support is added to the input field
eceeeren Jun 3, 2023
c2b40cf
Robot and info button is added
eceeeren Jun 3, 2023
9e13f46
design updates
asliayk Jun 6, 2023
5174ba7
design updates
asliayk Jun 9, 2023
d84b143
Multiline new line formatting fix
eceeeren Jun 10, 2023
4f49879
refactor
asliayk Jun 10, 2023
065a745
Merge remote-tracking branch 'origin/feature/advanced-chatbot-ui' int…
asliayk Jun 10, 2023
5483ec9
Code refactoring
eceeeren Jun 11, 2023
dc6ff60
Remove @extend
eceeeren Jun 11, 2023
8336747
Merge branch 'develop-iris' into feature/advanced-chatbot-ui
bassner Jun 12, 2023
61acf1f
Remove new window support & unnecessary import
eceeeren Jun 12, 2023
4158688
Merge remote-tracking branch 'origin/feature/advanced-chatbot-ui' int…
eceeeren Jun 12, 2023
eff247b
Maximize & minimize screen is added
eceeeren Jun 12, 2023
89a1cf1
design updates & shift button function
asliayk Jun 13, 2023
a4342a2
added client tests
asliayk Jun 13, 2023
0b1584e
input drag bug fixed
asliayk Jun 13, 2023
510b109
Chatbot textarea expansion fix
eceeeren Jun 15, 2023
1d76455
new style for message boxes added
asliayk Jun 15, 2023
922cd01
resize/fullscreen bug fixed
asliayk Jun 15, 2023
757f0d2
animation added
asliayk Jun 16, 2023
92f3d45
information page added
asliayk Jun 16, 2023
f2a6940
moved files for merging
asliayk Jun 17, 2023
12612ec
merge develop-iris into feature/advanced-chatbot-ui
asliayk Jun 18, 2023
b695a41
Merge branch 'develop-iris' into feature/advanced-chatbot-ui
asliayk Jun 18, 2023
088228c
fix merge bugs
asliayk Jun 18, 2023
575d871
Fix codacy issues
eceeeren Jun 19, 2023
41fdcb5
Bug & style fixes
eceeeren Jun 19, 2023
ea7913a
Remove uppercase
eceeeren Jun 19, 2023
0d2d669
Merge branch 'develop-iris' into feature/advanced-chatbot-ui
eceeeren Jun 19, 2023
72a5f57
Merge branch 'develop-iris' into feature/advanced-chatbot-ui
eceeeren Jun 19, 2023
269502c
Merge branch 'develop-iris' into feature/advanced-chatbot-ui
eceeeren Jun 19, 2023
aa087bd
refactor
asliayk Jun 20, 2023
44e9bec
Codacy fix
eceeeren Jun 20, 2023
c51f644
Remove unused parts from .spec files
eceeeren Jun 20, 2023
5e1cbc4
Fix path error
eceeeren Jun 20, 2023
4412aef
refactor
asliayk Jun 20, 2023
eafe658
Merge remote-tracking branch 'origin/feature/advanced-chatbot-ui' int…
asliayk Jun 20, 2023
67b4cf3
bugs fixed
asliayk Jun 21, 2023
a17611b
ref
asliayk Jun 21, 2023
e24b7b1
Fix textarea resizing & multiline formatting & full screen bug
eceeeren Jun 21, 2023
6b68ec7
Fix scroll button position after multiline
eceeeren Jun 21, 2023
3654255
Fix scroll button position after multiline 2 & fix scroll to bottom o…
eceeeren Jun 21, 2023
18686e1
updated client tests
asliayk Jun 22, 2023
dff7f77
refactor
asliayk Jun 22, 2023
db11c4d
refactor
asliayk Jun 22, 2023
a82bf32
refactor
asliayk Jun 22, 2023
08565b1
bug fix
asliayk Jun 22, 2023
d3e8405
Codacy fix
eceeeren Jun 22, 2023
cc1d095
Merge branch 'feature/advanced-chatbot-ui' into feature/advanced-chat…
eceeeren Jun 22, 2023
2875ec2
Change info button & code refactoring
eceeeren Jun 22, 2023
9bc30cf
bug fix
asliayk Jun 23, 2023
bfe0cec
Add new line
asliayk Jun 23, 2023
b887f56
Add new line
asliayk Jun 23, 2023
97b8a73
Add new line
asliayk Jun 23, 2023
e0708cd
refactor
asliayk Jun 23, 2023
82903f8
Disable text area when loading & user not accepted
eceeeren Jun 24, 2023
5cdce42
Store chatbot size to use later --not complete
eceeeren Jun 24, 2023
0b527ec
Header made clickable & button color changed
eceeeren Jun 25, 2023
269e203
Store chatbot size to use later --completed
eceeeren Jun 25, 2023
5f3c207
multiline continued (not complete)
asliayk Jun 26, 2023
4a1a34c
Header draggable fix
eceeeren Jun 26, 2023
856565b
Refactoring package.json
eceeeren Jun 26, 2023
75edeb8
About Iris path change
eceeeren Jun 27, 2023
52d3b69
Resizable css file removed from the root
eceeeren Jun 27, 2023
42eb565
Multiline whitespace problem fixed
eceeeren Jun 27, 2023
c9761b1
Remove unused event
eceeeren Jun 27, 2023
5e0f50d
Merge branch 'develop-iris' into feature/advanced-chatbot-ui
asliayk Jul 2, 2023
98c869c
refactor
asliayk Jul 2, 2023
cfb84ac
Resizable.css added back to angular.json
eceeeren Jul 3, 2023
e47f3eb
refactor + client tests
asliayk Jul 4, 2023
9565f63
bug fixed
asliayk Jul 4, 2023
adf096d
Merge branch 'develop-iris' into feature/advanced-chatbot-ui
eceeeren Jul 4, 2023
78be0c3
Adjust chatbot widget size
eceeeren Jul 4, 2023
ba21c11
Disable chatbot while receiving an answer
eceeeren Jul 4, 2023
5ef79a5
Empty message can't be sent -not complete
eceeeren Jul 4, 2023
dfd78cb
Prevent esc to close the modal
eceeeren Jul 4, 2023
a5ed52a
Fix chatbot button -not complete
eceeeren Jul 5, 2023
d27c2e0
Update About Iris page -not complete
eceeeren Jul 9, 2023
f960158
bug fixes (not complete)
asliayk Jul 9, 2023
b456eb8
Merge remote-tracking branch 'origin/feature/advanced-chatbot-ui' int…
asliayk Jul 9, 2023
60146a1
Full screen - icon dysfunction is fixed --completed
eceeeren Jul 10, 2023
e75102a
Fix new lines in new messages
eceeeren Jul 10, 2023
593263f
Add the remaining About Iris lines --complete
eceeeren Jul 10, 2023
1a27319
Enable textarea and disable Enter button --complete
eceeeren Jul 10, 2023
c4c4405
Fix resetChatBodyHeight
eceeeren Jul 10, 2023
84e3864
Merge branch 'develop-iris' into feature/advanced-chatbot-ui
asliayk Jul 10, 2023
04c0128
refactor
asliayk Jul 10, 2023
d8557c8
fix autofocus issue
undernagruzez Jul 10, 2023
33620eb
comments added
asliayk Jul 11, 2023
a4e2ad9
fix client-test failed(part)
RY997 Jul 11, 2023
83cd6bf
Merge branch 'feature/advanced-chatbot-ui' of https://github.com/ls1i…
RY997 Jul 11, 2023
0986de3
Fix sending first message issue
eceeeren Jul 11, 2023
90374d1
fix client-test failed(complete)
RY997 Jul 11, 2023
c916769
Merge remote-tracking branch 'origin/feature/advanced-chatbot-ui' int…
RY997 Jul 11, 2023
5a1d0f0
refactor
asliayk Jul 11, 2023
38d76ae
Merge remote-tracking branch 'origin/feature/advanced-chatbot-ui' int…
asliayk Jul 11, 2023
73c17a9
Local storage is removed from the code
eceeeren Jul 11, 2023
9e183e2
Add clear chat history button
dakennguyen Jul 13, 2023
e85a241
Fix Codacy issue
eceeeren Jul 13, 2023
a979e21
Merge branch 'develop-iris' into feature/advanced-chatbot-ui
asliayk Jul 13, 2023
3128534
refactor
asliayk Jul 13, 2023
abac26b
Fix test
dakennguyen Jul 13, 2023
b10a1a0
Merge branch 'feature/advanced-chatbot-ui' into feature/clear-chat-se…
dakennguyen Jul 13, 2023
f98de79
Fix missing imports
dakennguyen Jul 13, 2023
2571dcd
Merge branch 'feature/advanced-chatbot-ui' into feature/clear-chat-se…
dakennguyen Jul 13, 2023
a92e6d9
Fix send button
eceeeren Jul 13, 2023
6383280
refactor
asliayk Jul 13, 2023
f5e8280
Merge remote-tracking branch 'origin/feature/advanced-chatbot-ui' int…
asliayk Jul 13, 2023
1866622
add client tests
asliayk Jul 13, 2023
dbfe2bb
refactor
asliayk Jul 13, 2023
c6cdeec
refactor
asliayk Jul 13, 2023
2aa0cf4
add client tests
asliayk Jul 13, 2023
f0bb1b3
add client tests
asliayk Jul 13, 2023
4f2ed58
refactor
asliayk Jul 13, 2023
8e4abf2
refactor
asliayk Jul 13, 2023
af188fa
refactor
asliayk Jul 13, 2023
4c2f460
refactor
asliayk Jul 13, 2023
c9d51aa
Merge remote-tracking branch 'origin/feature/advanced-chatbot-ui' int…
dakennguyen Jul 14, 2023
221bcb6
Use state variable
dakennguyen Jul 14, 2023
576b422
Add test
dakennguyen Jul 14, 2023
965df35
Merge remote-tracking branch 'origin/develop-iris' into feature/clear…
dakennguyen Jul 14, 2023
638cda7
Disabled clear chat if empty
dakennguyen Jul 14, 2023
8bf6915
Add confirm modal
dakennguyen Jul 14, 2023
d3e1c00
Fix and add tests
dakennguyen Jul 14, 2023
01415c4
Fix type checking
dakennguyen Jul 14, 2023
cbcee52
Render modal on top and resize icon
dakennguyen Jul 14, 2023
f564473
Change text translation
dakennguyen Jul 16, 2023
f2444ab
Merge remote-tracking branch 'origin/develop-iris' into feature/clear…
dakennguyen Jul 16, 2023
b4ed082
Merge remote-tracking branch 'origin/develop-iris' into feature/clear…
dakennguyen Jul 17, 2023
b355d5c
Add clear chat history instruction for About Iris
dakennguyen Jul 17, 2023
2988939
Merge remote-tracking branch 'origin/develop-iris' into feature/clear…
dakennguyen Jul 18, 2023
83ac157
Merge branch 'develop-iris' into feature/clear-chat-session-ui
dakennguyen Jul 18, 2023
efe1138
Merge remote-tracking branch 'origin/develop-iris' into feature/clear…
dakennguyen Jul 18, 2023
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 @@ -109,6 +109,8 @@ export class ExerciseChatbotComponent implements OnInit, OnDestroy {
disableClose: true,
data: {
stateStore: this.stateStore,
exerciseId: this.exerciseId,
sessionService: this.sessionService,
widgetWidth: localStorage.getItem('widgetWidth') || `${this.initialWidth}px`,
widgetHeight: localStorage.getItem('widgetHeight') || `${this.initialHeight}px`,
fullSize: localStorage.getItem('fullSize') === 'true',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,13 @@ <h3 class="header-start">
</a>
</h3>
<div class="button-container">
<button *ngIf="isClearChatEnabled()" id="clear-chat-session" (click)="onClearSession(clearConfirmModal)" class="header-icon">
<fa-icon [icon]="faTrash"></fa-icon>
</button>
<button *ngIf="!fullSize; else compressButton" (click)="maximizeScreen()" class="header-icon">
<fa-icon [icon]="faExpand"></fa-icon></button
><ng-template #compressButton>
<fa-icon [icon]="faExpand"></fa-icon>
</button>
<ng-template #compressButton>
<button (click)="minimizeScreen()" class="header-icon">
<fa-icon [icon]="faCompress"></fa-icon>
</button>
Expand All @@ -39,6 +43,23 @@ <h3 class="header-start">
</div>
</div>

<ng-template #clearConfirmModal let-modal>
<div class="modal-header">
<h4 class="modal-title">
<span>{{ 'artemisApp.exerciseChatbot.clearSession.title' | artemisTranslate }}</span>
</h4>
<button type="button" class="btn-close" aria-label="Close" (click)="modal.dismiss()"></button>
</div>
<div class="modal-body">
<p>{{ 'artemisApp.exerciseChatbot.clearSession.text' | artemisTranslate }}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" (click)="modal.close('confirm')">
<span>{{ 'artemisApp.exerciseChatbot.clearSession.submit' | artemisTranslate }}</span>
</button>
dakennguyen marked this conversation as resolved.
Show resolved Hide resolved
</div>
</ng-template>

<!-- main chat section -->
<div class="chat-body" #chatBody (scroll)="checkChatScroll()">
<div *ngFor="let message of messages; let i = index">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,11 @@ pre {
.shake-animation {
animation: shake 0.3s cubic-bezier(0.36, 0.07, 0.19, 0.97);
}

::ng-deep ngb-modal-backdrop {
z-index: 9999 !important;
}

::ng-deep ngb-modal-window {
z-index: 9999 !important;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import { faArrowDown, faCircle, faCircleInfo, faCompress, faExpand, faPaperPlane, faRedo, faRobot, faThumbsDown, faThumbsUp, faXmark } from '@fortawesome/free-solid-svg-icons';
import {
faArrowDown,
faCircle,
faCircleInfo,
faCompress,
faExpand,
faPaperPlane,
faRedo,
faRobot,
faThumbsDown,
faThumbsUp,
faTrash,
faXmark,
} from '@fortawesome/free-solid-svg-icons';
import { ActivatedRoute, NavigationStart, Router } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { LocalStorageService } from 'ngx-webstorage';
import { AccountService } from 'app/core/auth/account.service';
import { ButtonType } from 'app/shared/components/button.component';
Expand Down Expand Up @@ -29,6 +43,7 @@ import { Subscription } from 'rxjs';
import { ResizeSensor } from 'css-element-queries';
import { Overlay } from '@angular/cdk/overlay';
import { SharedService } from 'app/iris/shared.service';
import { IrisSessionService } from 'app/iris/session.service';
import { IrisErrorMessageKey, IrisErrorType } from 'app/entities/iris/iris-errors.model';
import dayjs from 'dayjs';
import { AnimationEvent, animate, state, style, transition, trigger } from '@angular/animations';
Expand Down Expand Up @@ -57,6 +72,7 @@ import { AnimationEvent, animate, state, style, transition, trigger } from '@ang
})
export class ExerciseChatWidgetComponent implements OnInit, OnDestroy, AfterViewInit {
// Icons
faTrash = faTrash;
faCircle = faCircle;
faPaperPlane = faPaperPlane;
faExpand = faExpand;
Expand Down Expand Up @@ -98,6 +114,8 @@ export class ExerciseChatWidgetComponent implements OnInit, OnDestroy, AfterView
isGreetingMessage = false;
shouldLoadGreetingMessage = true;
fadeState = '';
exerciseId: number;
sessionService: IrisSessionService;

Copy link
Contributor

Choose a reason for hiding this comment

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

Why don't you use dependency injection like for the rest of the services?

Copy link
Author

Choose a reason for hiding this comment

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

inject IrisSessionService as a result will inject IrisStateStore (it would create a new instance of IrisStateStore), but I need to use the IrisStateStore that has already been injected in src/main/webapp/app/iris/exercise-chatbot/exercise-chatbot.component.ts so we can have the same state

// User preferences
userAccepted = false;
Expand All @@ -123,8 +141,11 @@ export class ExerciseChatWidgetComponent implements OnInit, OnDestroy, AfterView
private overlay: Overlay,
private router: Router,
private sharedService: SharedService,
private modalService: NgbModal,
) {
this.stateStore = data.stateStore;
this.exerciseId = data.exerciseId;
this.sessionService = data.sessionService;
this.navigationSubscription = this.router.events.subscribe((event) => {
if (event instanceof NavigationStart) {
this.dialog.closeAll();
Expand Down Expand Up @@ -261,6 +282,17 @@ export class ExerciseChatWidgetComponent implements OnInit, OnDestroy, AfterView
this.resetChatBodyHeight();
}

/**
* Clear session and start a new conversation.
*/
onClearSession(content: any) {
this.modalService.open(content).result.then((result: string) => {
if (result === 'confirm') {
this.createNewSession();
}
});
}

/**
* Scrolls to the unread message.
*/
Expand Down Expand Up @@ -482,6 +514,11 @@ export class ExerciseChatWidgetComponent implements OnInit, OnDestroy, AfterView
return isServerSentMessage(message);
}

/**
* Checks if a message is a welcome message generated by the client.
* @param message - The message to check.
* @returns A boolean indicating if the message is a client-sent message.
*/
isArtemisClientSentMessage(message: IrisMessage): message is IrisServerMessage {
return isArtemisClientSentMessage(message);
}
Expand Down Expand Up @@ -558,4 +595,12 @@ export class ExerciseChatWidgetComponent implements OnInit, OnDestroy, AfterView
this.fadeState = 'end';
}
}

isClearChatEnabled(): boolean {
return this.messages.length > 1 || (this.messages.length === 1 && !isArtemisClientSentMessage(this.messages[0]));
}

createNewSession() {
this.sessionService.createNewSession(this.exerciseId);
}
}
2 changes: 1 addition & 1 deletion src/main/webapp/app/iris/session.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export class IrisSessionService {
* Creates a new session for the given exercise ID.
* @param exerciseId The exercise ID for which to create a new session.
*/
private createNewSession(exerciseId: number): void {
createNewSession(exerciseId: number): void {
this.httpSessionService.createSessionForProgrammingExercise(exerciseId).subscribe(
(irisSessionResponse: any) => {
this.stateStore.dispatch(new SessionReceivedAction(irisSessionResponse.id, []));
Expand Down
5 changes: 5 additions & 0 deletions src/main/webapp/i18n/de/exerciseChatbot.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
"supportText": "(Wenn du Probleme mit dem Iris-Widget oder bei der Interaktion mit Iris hast, erstelle bitte einen Issue auf GitHub https://github.com/ls1intum/Artemis)",
"unreadMessages": "Ungelesene Nachrichten",
"buttonTooltip": "Beginne mit Iris zu chatten!",
"clearSession": {
"title": "Chatverlauf löschen",
"text": "Bist du sicher, dass du den Chatverlauf löschen möchtest?",
"submit": "Absenden"
dakennguyen marked this conversation as resolved.
Show resolved Hide resolved
},
"errors": {
"invalidSessionState": "Der Zustand der Iris Session ist ungültig. Es ist nicht möglich, in diesem Zustand Nachrichten zu senden.",
"historyLoadFailed": "Der Chatverlauf konnte nicht abgerufen werden.",
Expand Down
5 changes: 5 additions & 0 deletions src/main/webapp/i18n/en/exerciseChatbot.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
"supportText": "(If you have any problems using the widget or messaging Iris, please create an issue on GitHub: https://github.com/ls1intum/Artemis)",
"unreadMessages": "Unread messages",
"buttonTooltip": "Start chatting with Iris!",
"clearSession": {
"title": "Clear chat history",
"text": "Are you sure you want to clear the chat history?",
"submit": "Submit"
dakennguyen marked this conversation as resolved.
Show resolved Hide resolved
},
"errors": {
"invalidSessionState": "Iris session state is invalid. It is impossible to send messages in this state.",
"historyLoadFailed": "Could not fetch messages.",
Expand Down
33 changes: 33 additions & 0 deletions src/test/javascript/spec/component/iris/session.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,39 @@ describe('IrisSessionService', () => {
jest.restoreAllMocks();
});

describe('createNewSession', () => {
it('should create a new session if success', async () => {
// given
const exerciseId = 123;
const sessionId = 456;
const createSessionForProgrammingExerciseMock = jest.spyOn(mockHttpSessionService, 'createSessionForProgrammingExercise').mockReturnValueOnce(of({ id: sessionId }));
const dispatchSpy = jest.spyOn(stateStore, 'dispatch');

// when
await irisSessionService.createNewSession(exerciseId);

// then
expect(createSessionForProgrammingExerciseMock).toHaveBeenCalledWith(exerciseId);
expect(dispatchSpy).toHaveBeenCalledWith(new SessionReceivedAction(sessionId, []));
});

it('should dispatch error if fail', async () => {
// given
const exerciseId = 123;
const createSessionForProgrammingExerciseMock = jest
.spyOn(mockHttpSessionService, 'createSessionForProgrammingExercise')
.mockReturnValueOnce(throwError(new HttpErrorResponse({ status: 500 })));
const dispatchSpy = jest.spyOn(stateStore, 'dispatch');

// when
await irisSessionService.createNewSession(exerciseId);

// then
expect(createSessionForProgrammingExerciseMock).toHaveBeenCalledWith(exerciseId);
expect(dispatchSpy).toHaveBeenCalledWith(new ConversationErrorOccurredAction(IrisErrorMessageKey.SESSION_CREATION_FAILED));
});
});

it('should create a new session if getCurrentSession returns 404 and createSession is successful', async () => {
// given
const exerciseId = 123;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { MockPipe } from 'ng-mocks';
import { ExerciseChatWidgetComponent } from 'app/iris/exercise-chatbot/exercise-chatwidget/exercise-chat-widget.component';
import { IrisStateStore } from 'app/iris/state-store.service';
Expand All @@ -18,7 +19,7 @@ import {
StudentMessageSentAction,
} from 'app/iris/state-store.model';
import { throwError } from 'rxjs';
import { mockClientMessage, mockServerMessage } from '../../../helpers/sample/iris-sample-data';
import { mockArtemisClientMessage, mockClientMessage, mockServerMessage } from '../../../helpers/sample/iris-sample-data';
import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe';
import { LocalStorageService, SessionStorageService } from 'ngx-webstorage';
import { MockTranslateService } from '../../../helpers/mocks/service/mock-translate.service';
Expand All @@ -29,13 +30,16 @@ import { MockAccountService } from '../../../helpers/mocks/service/mock-account.
import { IrisMessageContentType } from 'app/entities/iris/iris-content-type.model';
import { IrisClientMessage, IrisSender } from 'app/entities/iris/iris-message.model';
import { IrisErrorMessageKey } from 'app/entities/iris/iris-errors.model';
import { IrisSessionService } from 'app/iris/session.service';

describe('ExerciseChatWidgetComponent', () => {
let component: ExerciseChatWidgetComponent;
let fixture: ComponentFixture<ExerciseChatWidgetComponent>;
let stateStore: IrisStateStore;
let mockHttpMessageService: IrisHttpMessageService;
let mockSessionService: IrisSessionService;
let mockDialog: MatDialog;
let mockModalService: NgbModal;

beforeEach(async () => {
mockDialog = {
Expand All @@ -50,14 +54,22 @@ describe('ExerciseChatWidgetComponent', () => {
createMessage: jest.fn(),
} as any;

mockSessionService = {
createNewSession: jest.fn(),
} as any;

stateStore = new IrisStateStore();
mockModalService = {
open: jest.fn(),
} as any;

await TestBed.configureTestingModule({
imports: [FormsModule, FontAwesomeModule, MatDialogModule],
declarations: [ExerciseChatWidgetComponent, MockPipe(ArtemisTranslatePipe), MockPipe(HtmlForMarkdownPipe)],
providers: [
{ provide: MAT_DIALOG_DATA, useValue: { stateStore: stateStore } },
{ provide: MAT_DIALOG_DATA, useValue: { stateStore: stateStore, sessionService: mockSessionService } },
{ provide: IrisHttpMessageService, useValue: mockHttpMessageService },
{ provide: NgbModal, useValue: mockModalService },
{ provide: MatDialog, useValue: mockDialog },
{ provide: ActivatedRoute, useValue: {} },
{ provide: LocalStorageService, useValue: {} },
Expand Down Expand Up @@ -437,4 +449,55 @@ describe('ExerciseChatWidgetComponent', () => {
component.error = { key: IrisErrorMessageKey.SEND_MESSAGE_FAILED, fatal: false };
expect(component.deactivateSubmitButton()).toBeFalsy();
});

describe('clear chat session', () => {
it('should call service to clear old session and create a new one', () => {
jest.spyOn(mockSessionService, 'createNewSession');
component.exerciseId = 18;

component.createNewSession();

expect(mockSessionService.createNewSession).toHaveBeenCalledWith(18);
});

it('should open confirm modal when click on the clear button', () => {
stateStore.dispatch(new SessionReceivedAction(123, [mockClientMessage, mockServerMessage]));
fixture.detectChanges();
const button: HTMLInputElement = fixture.debugElement.nativeElement.querySelector('#clear-chat-session');

button.click();

const openModalStub = jest.spyOn(mockModalService, 'open');
expect(openModalStub).toHaveBeenCalledOnce();
});

it('should not render clear chat button if the history is empty', () => {
const button: HTMLInputElement = fixture.debugElement.nativeElement.querySelector('#clear-chat-session');
expect(button).toBeNull();
});

it('should not render clear chat button if the history has only one message from the client', () => {
stateStore.dispatch(new SessionReceivedAction(123, [mockArtemisClientMessage]));
fixture.detectChanges();
const button: HTMLInputElement = fixture.debugElement.nativeElement.querySelector('#clear-chat-session');

expect(button).toBeNull();
});

it('should render clear chat button if the history has one message from server', () => {
stateStore.dispatch(new SessionReceivedAction(123, [mockServerMessage]));
fixture.detectChanges();
const button: HTMLInputElement = fixture.debugElement.nativeElement.querySelector('#clear-chat-session');

expect(button).not.toBeNull();
});

it('should render clear chat button if the history has one message from user', () => {
stateStore.dispatch(new SessionReceivedAction(123, [mockClientMessage]));
fixture.detectChanges();
const button: HTMLInputElement = fixture.debugElement.nativeElement.querySelector('#clear-chat-session');

expect(button).not.toBeNull();
});
});
});
8 changes: 7 additions & 1 deletion src/test/javascript/spec/helpers/sample/iris-sample-data.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import dayjs from 'dayjs';
import { ExerciseType } from 'app/entities/exercise.model';
import { ProgrammingExercise } from 'app/entities/programming-exercise.model';
import { IrisClientMessage, IrisSender, IrisServerMessage } from 'app/entities/iris/iris-message.model';
import { IrisArtemisClientMessage, IrisClientMessage, IrisSender, IrisServerMessage } from 'app/entities/iris/iris-message.model';
import { IrisMessageContent, IrisMessageContentType } from 'app/entities/iris/iris-content-type.model';
import { IrisSession } from 'app/entities/iris/iris-session.model';

Expand All @@ -19,6 +19,12 @@ export const mockServerMessage = {
sentAt: dayjs(),
} as IrisServerMessage;

export const mockArtemisClientMessage = {
sender: IrisSender.ARTEMIS_CLIENT,
content: [mockMessageContent],
sentAt: dayjs(),
} as IrisArtemisClientMessage;

export const mockClientMessage = {
sender: IrisSender.USER,
content: [mockMessageContent],
Expand Down
Loading