[ACS-8833] Displaying error page when there is no selected nodes (#4142)

This commit is contained in:
AleksanderSklorz 2024-09-27 09:49:47 +02:00 committed by GitHub
parent 34e494e8e6
commit a93722bea6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 53 additions and 5 deletions

View File

@ -27,7 +27,7 @@ import { SearchAiResultsComponent } from './search-ai-results.component';
import { ActivatedRoute, Params, Router } from '@angular/router'; import { ActivatedRoute, Params, Router } from '@angular/router';
import { of, Subject, throwError } from 'rxjs'; import { of, Subject, throwError } from 'rxjs';
import { MatSnackBarModule } from '@angular/material/snack-bar'; import { MatSnackBarModule } from '@angular/material/snack-bar';
import { EmptyContentComponent, UserPreferencesService } from '@alfresco/adf-core'; import { EmptyContentComponent, UnsavedChangesGuard, UserPreferencesService } from '@alfresco/adf-core';
import { MatDialogModule } from '@angular/material/dialog'; import { MatDialogModule } from '@angular/material/dialog';
import { AppTestingModule } from '../../../../testing/app-testing.module'; import { AppTestingModule } from '../../../../testing/app-testing.module';
import { MatIconTestingModule } from '@angular/material/icon/testing'; import { MatIconTestingModule } from '@angular/material/icon/testing';
@ -40,6 +40,7 @@ import { SearchAiInputComponent } from '../search-ai-input/search-ai-input.compo
import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { MockStore, provideMockStore } from '@ngrx/store/testing';
import { getAppSelection, getCurrentFolder, ViewNodeAction } from '@alfresco/aca-shared/store'; import { getAppSelection, getCurrentFolder, ViewNodeAction } from '@alfresco/aca-shared/store';
import { ViewerService } from '@alfresco/aca-content/viewer'; import { ViewerService } from '@alfresco/aca-content/viewer';
import { DebugElement } from '@angular/core';
const questionMock: QuestionModel = { question: 'test', questionId: 'testId', restrictionQuery: { nodesIds: [] } }; const questionMock: QuestionModel = { question: 'test', questionId: 'testId', restrictionQuery: { nodesIds: [] } };
const aiAnswerMock: AiAnswer = { answer: 'Some answer', questionId: 'some id', references: [] }; const aiAnswerMock: AiAnswer = { answer: 'Some answer', questionId: 'some id', references: [] };
@ -57,6 +58,7 @@ describe('SearchAiResultsComponent', () => {
let searchAiService: SearchAiService; let searchAiService: SearchAiService;
let store: MockStore; let store: MockStore;
let viewerService: ViewerService; let viewerService: ViewerService;
let unsavedChangesGuard: UnsavedChangesGuard;
afterEach(() => { afterEach(() => {
store.resetSelectors(); store.resetSelectors();
@ -92,6 +94,7 @@ describe('SearchAiResultsComponent', () => {
searchAiService = TestBed.inject(SearchAiService); searchAiService = TestBed.inject(SearchAiService);
userPreferencesService = TestBed.inject(UserPreferencesService); userPreferencesService = TestBed.inject(UserPreferencesService);
viewerService = TestBed.inject(ViewerService); viewerService = TestBed.inject(ViewerService);
unsavedChangesGuard = TestBed.inject(UnsavedChangesGuard);
store = TestBed.inject(MockStore); store = TestBed.inject(MockStore);
store.overrideSelector(getAppSelection, { store.overrideSelector(getAppSelection, {
nodes: [], nodes: [],
@ -107,6 +110,8 @@ describe('SearchAiResultsComponent', () => {
}); });
describe('query params change', () => { describe('query params change', () => {
const getEmptyContentElement = (): DebugElement => fixture.debugElement.query(By.directive(EmptyContentComponent));
it('should perform ai search and sets agents on query params change', () => { it('should perform ai search and sets agents on query params change', () => {
spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes); spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes);
mockQueryParams.next({ query: 'test', agentId: 'agentId1' }); mockQueryParams.next({ query: 'test', agentId: 'agentId1' });
@ -212,6 +217,27 @@ describe('SearchAiResultsComponent', () => {
expect(component.hasAnsweringError).toBeFalse(); expect(component.hasAnsweringError).toBeFalse();
})); }));
it('should render empty content when there are not selected nodes', () => {
mockQueryParams.next({
query: 'test',
agentId: 'agentId1'
});
fixture.detectChanges();
expect(getEmptyContentElement()).not.toBeNull();
});
it('should not render empty content when there are selected nodes', () => {
spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes);
mockQueryParams.next({
query: 'test',
agentId: 'agentId1'
});
fixture.detectChanges();
expect(getEmptyContentElement()).toBeNull();
});
describe('when query params contains location', () => { describe('when query params contains location', () => {
let params: Params; let params: Params;
@ -236,7 +262,7 @@ describe('SearchAiResultsComponent', () => {
}); });
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.debugElement.query(By.directive(EmptyContentComponent))).toBeNull(); expect(getEmptyContentElement()).toBeNull();
}); });
it('should not display search query', () => { it('should not display search query', () => {
@ -368,5 +394,26 @@ describe('SearchAiResultsComponent', () => {
expect(nodesOrder).toEqual(['node1', 'node2']); expect(nodesOrder).toEqual(['node1', 'node2']);
}); });
it('should set unsaved on UnsavedChangesGuard to false when there are no selected nodes', () => {
mockQueryParams.next({
query: 'test',
agentId: 'agentId1'
});
component.ngOnInit();
expect(unsavedChangesGuard.unsaved).toBeFalse();
});
it('should set unsaved on UnsavedChangesGuard to true when there are selected nodes', () => {
spyOn(userPreferencesService, 'get').and.returnValue(knowledgeRetrievalNodes);
mockQueryParams.next({
query: 'test',
agentId: 'agentId1'
});
component.ngOnInit();
expect(unsavedChangesGuard.unsaved).toBeTrue();
});
}); });
}); });

View File

@ -147,16 +147,17 @@ export class SearchAiResultsComponent extends PageComponent implements OnInit, O
.subscribe((params) => { .subscribe((params) => {
this._agentId = params.agentId; this._agentId = params.agentId;
this._searchQuery = params.query ? decodeURIComponent(params.query) : ''; this._searchQuery = params.query ? decodeURIComponent(params.query) : '';
if (!this.searchQuery || !this.agentId) { const selectedNodesState = this.userPreferencesService.get('knowledgeRetrievalNodes');
if (!this.searchQuery || !this.agentId || !selectedNodesState) {
this._hasError = true; this._hasError = true;
return; return;
} }
this._selectedNodesState = JSON.parse(this.userPreferencesService.get('knowledgeRetrievalNodes')); this._selectedNodesState = JSON.parse(selectedNodesState);
this.performAiSearch(); this.performAiSearch();
}); });
super.ngOnInit(); super.ngOnInit();
this.unsavedChangesGuard.unsaved = this.route.snapshot?.queryParams?.query?.length > 0; this.unsavedChangesGuard.unsaved = this.route.snapshot?.queryParams?.query?.length > 0 && !this.hasError;
this.unsavedChangesGuard.data = { this.unsavedChangesGuard.data = {
descriptionText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.CONVERSATION_DISCARDED', descriptionText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.CONVERSATION_DISCARDED',
confirmButtonText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.OKAY', confirmButtonText: 'KNOWLEDGE_RETRIEVAL.SEARCH.DISCARD_CHANGES.OKAY',