Stabilising unit test for ACA (#2015)

* Stabilising unit test for ACA part 1

* Stabilising unit test for ACA
This commit is contained in:
Vito
2021-02-24 17:31:15 +00:00
committed by GitHub
parent 2626f46295
commit 60607c1305
11 changed files with 381 additions and 213 deletions
@@ -24,10 +24,10 @@
*/
import { TestBed, fakeAsync, tick, ComponentFixture } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { NO_ERRORS_SCHEMA, SimpleChange, SimpleChanges } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { NodeFavoriteDirective, DataTableComponent, UploadService, AppConfigModule, DataTableModule, PaginationModule } from '@alfresco/adf-core';
import { DocumentListComponent, FilterSearch } from '@alfresco/adf-content-services';
import { DocumentListComponent, DocumentListService, FilterSearch } from '@alfresco/adf-content-services';
import { NodeActionsService } from '../../services/node-actions.service';
import { FilesComponent } from './files.component';
import { AppTestingModule } from '../../testing/app-testing.module';
@@ -35,6 +35,7 @@ import { ContentApiService, SharedDirectivesModule } from '@alfresco/aca-shared'
import { of, throwError } from 'rxjs';
import { By } from '@angular/platform-browser';
import { DirectivesModule } from '../../directives/directives.module';
import { NodeEntry, NodePaging } from '@alfresco/js-api';
describe('FilesComponent', () => {
let node;
@@ -48,6 +49,8 @@ describe('FilesComponent', () => {
navigate: jasmine.createSpy('navigate')
};
let spyContent = null;
function verifyEmptyFilterTemplate() {
const template = fixture.debugElement.query(By.css('.empty-search__block')).nativeElement as HTMLElement;
expect(template).toBeDefined();
@@ -83,24 +86,32 @@ describe('FilesComponent', () => {
fixture = TestBed.createComponent(FilesComponent);
component = fixture.componentInstance;
const documentListService = TestBed.inject(DocumentListService);
const fakeNodeEntry: NodeEntry = { entry: { id: 'fake-node-entry' } } as NodeEntry;
const fakeNodePaging: NodePaging = { list: { pagination: { count: 10, maxItems: 10, skipCount: 0 } } };
const documentLoaderNode = { children: fakeNodePaging, currentNode: fakeNodeEntry };
spyOn(documentListService, 'loadFolderByNodeId').and.returnValue(of(documentLoaderNode));
uploadService = TestBed.inject(UploadService);
router = TestBed.inject(Router);
nodeActionsService = TestBed.inject(NodeActionsService);
contentApi = TestBed.inject(ContentApiService);
spyContent = spyOn(contentApi, 'getNode');
});
beforeEach(() => {
node = { id: 'node-id', isFolder: true };
spyContent.and.returnValue(of({ entry: node }));
});
describe('Current page is valid', () => {
beforeEach(() => {
fixture.detectChanges();
spyOn(component.documentList, 'loadFolder').and.callFake(() => {});
spyContent.and.stub();
});
it('should be a valid current page', fakeAsync(() => {
spyOn(contentApi, 'getNode').and.returnValue(throwError(null));
spyContent.and.returnValue(throwError(null));
component.ngOnInit();
fixture.detectChanges();
@@ -110,9 +121,6 @@ describe('FilesComponent', () => {
}));
it('should set current page as invalid path', fakeAsync(() => {
spyOn(contentApi, 'getNode').and.returnValue(of({ entry: node }));
component.ngOnInit();
fixture.detectChanges();
tick();
@@ -126,14 +134,13 @@ describe('FilesComponent', () => {
});
it('should set current node', () => {
spyOn(contentApi, 'getNode').and.returnValue(of({ entry: node }));
fixture.detectChanges();
expect(component.node).toBe(node);
});
it('should navigate to parent if node is not a folder', () => {
const nodeEntry = { isFolder: false, parentId: 'parent-id' };
spyOn(contentApi, 'getNode').and.returnValue(of({ entry: nodeEntry } as any));
spyContent.and.returnValue(of({ entry: nodeEntry } as any));
fixture.detectChanges();
@@ -143,7 +150,6 @@ describe('FilesComponent', () => {
describe('refresh on events', () => {
beforeEach(() => {
spyOn(contentApi, 'getNode').and.returnValue(of({ entry: node }));
spyOn(component, 'reload');
fixture.detectChanges();
@@ -217,7 +223,6 @@ describe('FilesComponent', () => {
describe('onBreadcrumbNavigate()', () => {
beforeEach(() => {
spyOn(contentApi, 'getNode').and.returnValue(of({ entry: node }));
fixture.detectChanges();
});
@@ -233,7 +238,6 @@ describe('FilesComponent', () => {
describe('Node navigation', () => {
beforeEach(() => {
spyOn(contentApi, 'getNode').and.returnValue(of({ entry: node }));
fixture.detectChanges();
});
@@ -315,7 +319,6 @@ describe('FilesComponent', () => {
describe('empty template', () => {
beforeEach(() => {
fixture.detectChanges();
spyOn(component.documentList, 'loadFolder').and.callFake(() => {});
});
it('should show custom empty template if filter headers are applied', async () => {
@@ -327,8 +330,6 @@ describe('FilesComponent', () => {
});
it('should display custom empty template when no data available', async () => {
spyOn(contentApi, 'getNode').and.returnValue(of({ entry: node }));
fixture.detectChanges();
await fixture.whenStable();
@@ -339,15 +340,15 @@ describe('FilesComponent', () => {
it('[C308041] should have sticky headers', async () => {
fixture.detectChanges();
spyOn(component.documentList, 'loadFolder').and.callFake(() => {});
spyOn(contentApi, 'getNode').and.returnValue(of({ entry: node }));
fixture.componentInstance.nodeResult = {
const nodeResult = {
list: {
entries: [{ entry: { id: '1', isFile: true } } as any, { entry: { id: '2', isFile: true } } as any],
pagination: { count: 2 }
}
};
const changes: SimpleChanges = { nodeResult: new SimpleChange(null, nodeResult, true) };
fixture.componentInstance.ngOnChanges(changes);
fixture.detectChanges();
await fixture.whenStable();
@@ -28,6 +28,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AppTestingModule } from '../../../testing/app-testing.module';
import { NodePermissionService } from '@alfresco/aca-shared';
import { Node } from '@alfresco/js-api';
import { CommentsModule } from '@alfresco/adf-core';
describe('CommentsTabComponent', () => {
let component: CommentsTabComponent;
@@ -37,7 +38,7 @@ describe('CommentsTabComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [AppTestingModule],
imports: [AppTestingModule, CommentsModule],
declarations: [CommentsTabComponent]
});
@@ -30,17 +30,21 @@ import { CustomResourcesService, DocumentListComponent } from '@alfresco/adf-con
import { RecentFilesComponent } from './recent-files.component';
import { AppTestingModule } from '../../testing/app-testing.module';
import { Router } from '@angular/router';
import { PersonEntry, ResultSetPaging } from '@alfresco/js-api';
import { NodePaging, SearchApi } from '@alfresco/js-api';
import { of } from 'rxjs';
describe('RecentFilesComponent', () => {
let fixture: ComponentFixture<RecentFilesComponent>;
let component: RecentFilesComponent;
beforeEach(() => {
TestBed.configureTestingModule({
beforeEach(async () => {
const searchApi = jasmine.createSpyObj('SearchApi', ['search']);
const testBed = TestBed.configureTestingModule({
imports: [AppTestingModule, AppConfigModule],
declarations: [DataTableComponent, NodeFavoriteDirective, DocumentListComponent, RecentFilesComponent],
providers: [
{ provide: SearchApi, useValue: searchApi },
{
provide: Router,
useValue: {
@@ -51,27 +55,48 @@ describe('RecentFilesComponent', () => {
schemas: [NO_ERRORS_SCHEMA]
});
fixture = TestBed.createComponent(RecentFilesComponent);
component = fixture.componentInstance;
await testBed.compileComponents();
const customResourcesService = TestBed.inject(CustomResourcesService);
spyOn(customResourcesService.peopleApi, 'getPerson').and.returnValue(
Promise.resolve({
entry: { id: 'personId' }
} as PersonEntry)
);
const page: ResultSetPaging = {
const page: NodePaging = {
list: {
entries: [
{ entry: { id: '1', name: 'node1', nodeType: 'cm:file', isFile: true, isFolder: false } },
{ entry: { id: '2', name: 'node2', nodeType: 'cm:file', isFile: true, isFolder: false } }
{
entry: {
id: '1',
name: 'node1',
nodeType: 'cm:file',
isFile: true,
isFolder: false,
createdAt: null,
modifiedAt: null,
modifiedByUser: null,
createdByUser: null
}
},
{
entry: {
id: '2',
name: 'node2',
nodeType: 'cm:file',
isFile: true,
isFolder: false,
createdAt: null,
modifiedAt: null,
modifiedByUser: null,
createdByUser: null
}
}
],
pagination: { count: 2, totalItems: 2 }
}
};
spyOn(customResourcesService.searchApi, 'search').and.returnValue(Promise.resolve(page));
spyOn(customResourcesService, 'getRecentFiles').and.returnValue(of(page));
fixture = TestBed.createComponent(RecentFilesComponent);
component = fixture.componentInstance;
});
it('should call showPreview method', () => {
@@ -24,7 +24,7 @@
*/
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { TestBed, ComponentFixture, fakeAsync, tick } from '@angular/core/testing';
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { SearchInputComponent } from './search-input.component';
import { AppTestingModule } from '../../../testing/app-testing.module';
import { Actions, ofType } from '@ngrx/effects';
@@ -74,61 +74,71 @@ describe('SearchInputComponent', () => {
});
describe('onSearchSubmit()', () => {
it('should call search action with correct search options', fakeAsync((done) => {
it('should call search action with correct search options', (done) => {
const searchedTerm = 's';
const currentSearchOptions = [{ key: 'test' }];
actions$.pipe(
ofType<SearchByTermAction>(SearchActionTypes.SearchByTerm),
map((action) => {
expect(action.searchOptions[0].key).toBe(currentSearchOptions[0].key);
component.searchedWord = 'te';
actions$
.pipe(
ofType<SearchByTermAction>(SearchActionTypes.SearchByTerm),
map((action) => {
expect(action.searchOptions[0].key).toBe('SEARCH.INPUT.FILES');
})
)
.subscribe(() => {
done();
})
);
});
component.onSearchSubmit({ target: { value: searchedTerm } });
tick();
}));
fixture.detectChanges();
});
it('should call search action with correct searched term', fakeAsync((done) => {
it('should call search action with correct searched term', (done) => {
const searchedTerm = 's';
actions$.pipe(
ofType<SearchByTermAction>(SearchActionTypes.SearchByTerm),
map((action) => {
expect(action.payload).toBe(searchedTerm);
actions$
.pipe(
ofType<SearchByTermAction>(SearchActionTypes.SearchByTerm),
map((action) => {
expect(action.payload).toBe(searchedTerm);
})
)
.subscribe(() => {
done();
})
);
});
component.onSearchSubmit({ target: { value: searchedTerm } });
tick();
}));
fixture.detectChanges();
});
});
describe('onSearchChange()', () => {
it('should call search action with correct search options', fakeAsync((done) => {
it('should call search action with correct search options', (done) => {
const searchedTerm = 's';
const currentSearchOptions = [{ key: 'test' }];
actions$.pipe(
ofType<SearchByTermAction>(SearchActionTypes.SearchByTerm),
map((action) => {
expect(action.searchOptions[0].key).toBe(currentSearchOptions[0].key);
const currentSearchOptions = [{ key: 'SEARCH.INPUT.FILES' }];
actions$
.pipe(
ofType<SearchByTermAction>(SearchActionTypes.SearchByTerm),
map((action) => {
expect(action.searchOptions[0].key).toBe(currentSearchOptions[0].key);
})
)
.subscribe(() => {
done();
})
);
});
component.onSearchChange(searchedTerm);
tick(1000);
}));
});
it('should call search action with correct searched term', fakeAsync((done) => {
it('should call search action with correct searched term', (done) => {
const searchedTerm = 's';
actions$.pipe(
ofType<SearchByTermAction>(SearchActionTypes.SearchByTerm),
map((action) => {
expect(action.payload).toBe(searchedTerm);
actions$
.pipe(
ofType<SearchByTermAction>(SearchActionTypes.SearchByTerm),
map((action) => {
expect(action.payload).toBe(searchedTerm);
})
)
.subscribe(() => {
done();
})
);
});
component.onSearchChange(searchedTerm);
tick(1000);
}));
});
});
describe('isLibrariesChecked()', () => {
@@ -23,10 +23,41 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { NodeEntry } from '@alfresco/js-api';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CoreModule } from '@angular/flex-layout';
import { TranslateModule } from '@ngx-translate/core';
import { AppTestingModule } from '../../../testing/app-testing.module';
import { AppSearchResultsModule } from '../search-results.module';
import { SearchResultsRowComponent } from './search-results-row.component';
describe('SearchResultsRowComponent', () => {
it('should be defined', () => {
expect(SearchResultsRowComponent).toBeDefined();
let component: SearchResultsRowComponent;
let fixture: ComponentFixture<SearchResultsRowComponent>;
const nodeEntry: NodeEntry = {
entry: {
id: 'fake-node-entry',
modifiedByUser: { displayName: 'IChangeThings' },
modifiedAt: new Date(),
isFile: true,
properties: { 'cm:title': 'BananaRama' }
}
} as NodeEntry;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), CoreModule, AppTestingModule, AppSearchResultsModule]
});
fixture = TestBed.createComponent(SearchResultsRowComponent);
component = fixture.componentInstance;
});
it('should show the current node', () => {
component.context = { row: { node: nodeEntry } };
fixture.detectChanges();
const element = fixture.nativeElement.querySelector('.line');
expect(element).not.toBeNull();
});
});
@@ -24,9 +24,40 @@
*/
import { DocumentDisplayModeComponent } from './document-display-mode.component';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CoreModule } from '@angular/flex-layout';
import { TranslateModule } from '@ngx-translate/core';
import { AppTestingModule } from '../../../testing/app-testing.module';
import { of } from 'rxjs';
describe('DocumentDisplayModeComponent', () => {
it('should be defined', () => {
expect(DocumentDisplayModeComponent).toBeDefined();
let component: DocumentDisplayModeComponent;
let fixture: ComponentFixture<DocumentDisplayModeComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), CoreModule, AppTestingModule]
});
fixture = TestBed.createComponent(DocumentDisplayModeComponent);
component = fixture.componentInstance;
});
it('should show the list button when list', async () => {
component.displayMode$ = of('list');
fixture.detectChanges();
await fixture.whenStable();
const displayButton: HTMLButtonElement = fixture.nativeElement.querySelector('#app-document-display-mode-button');
expect(displayButton.title).toBe('APP.ACTIONS.LIST_MODE');
});
it('should show the gallery button when list', async () => {
component.displayMode$ = of('gallery');
fixture.detectChanges();
await fixture.whenStable();
const displayButton: HTMLButtonElement = fixture.nativeElement.querySelector('#app-document-display-mode-button');
expect(displayButton.title).toBe('APP.ACTIONS.GALLERY_MODE');
});
});
@@ -33,6 +33,7 @@ import { AppStore, ToggleDocumentDisplayMode, getDocumentDisplayMode } from '@al
template: `
<ng-container *ngIf="displayMode$ | async as displayMode">
<button
id="app-document-display-mode-button"
[attr.title]="getTitle(displayMode) | translate"
[attr.aria-label]="getTitle(displayMode) | translate"
mat-icon-button
@@ -24,9 +24,36 @@
*/
import { ToggleInfoDrawerComponent } from './toggle-info-drawer.component';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CoreModule } from '@angular/flex-layout';
import { TranslateModule } from '@ngx-translate/core';
import { AppTestingModule } from '../../../testing/app-testing.module';
import { Subject } from 'rxjs';
import { Store } from '@ngrx/store';
describe('ToggleInfoDrawerComponent', () => {
it('should be defined', () => {
expect(ToggleInfoDrawerComponent).toBeDefined();
let fixture: ComponentFixture<ToggleInfoDrawerComponent>;
const mockStream = new Subject();
const storeMock = {
dispatch: jasmine.createSpy('dispatch'),
select: () => mockStream
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), CoreModule, AppTestingModule],
providers: [{ provide: Store, useValue: storeMock }]
});
fixture = TestBed.createComponent(ToggleInfoDrawerComponent);
});
it('should show info drawer button', async () => {
mockStream.next(true);
fixture.detectChanges();
await fixture.whenStable();
const infoDrawerButton: HTMLButtonElement = fixture.nativeElement.querySelector('.app-toggle-info-drawer button');
expect(infoDrawerButton).not.toBeNull();
});
});
@@ -34,7 +34,6 @@ import {
PurgeDeletedNodesAction,
RestoreDeletedNodesAction,
NavigateToParentFolder,
NavigateRouteAction,
DeleteNodesAction,
MoveNodesAction,
CopyNodesAction,
@@ -42,7 +41,7 @@ import {
SetSelectedNodesAction,
UnlockWriteAction,
SnackbarActionTypes,
RouterActionTypes
NodeActionTypes
} from '@alfresco/aca-shared/store';
import { map } from 'rxjs/operators';
import { NodeEffects } from '../store/effects/node.effects';
@@ -768,61 +767,67 @@ describe('ContentManagementService', () => {
});
describe('Delete action', () => {
it('should raise info message on successful single file deletion', fakeAsync((done) => {
it('should raise info message on successful single file deletion', (done) => {
spyOn(contentApi, 'deleteNode').and.returnValue(of(null));
actions$.pipe(
ofType<SnackbarInfoAction>(SnackbarActionTypes.Info),
map(() => done())
);
actions$
.pipe(
ofType<SnackbarInfoAction>(SnackbarActionTypes.Info),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
const selection: any[] = [{ entry: { id: '1', name: 'name1' } }];
store.dispatch(new DeleteNodesAction(selection));
}));
});
it('should raise error message on failed single file deletion', fakeAsync((done) => {
it('should raise error message on failed single file deletion', (done) => {
spyOn(contentApi, 'deleteNode').and.returnValue(throwError(null));
actions$.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map(() => {
done();
})
);
actions$
.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
const selection: any[] = [{ entry: { id: '1', name: 'name1' } }];
store.dispatch(new DeleteNodesAction(selection));
}));
});
it('should raise info message on successful multiple files deletion', fakeAsync((done) => {
it('should raise info message on successful multiple files deletion', (done) => {
spyOn(contentApi, 'deleteNode').and.returnValue(of(null));
actions$.pipe(
ofType<SnackbarInfoAction>(SnackbarActionTypes.Info),
map(() => done())
);
actions$
.pipe(
ofType<SnackbarInfoAction>(SnackbarActionTypes.Info),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
const selection: any[] = [{ entry: { id: '1', name: 'name1' } }, { entry: { id: '2', name: 'name2' } }];
store.dispatch(new DeleteNodesAction(selection));
}));
});
it('should raise error message failed multiple files deletion', fakeAsync((done) => {
it('should raise error message failed multiple files deletion', (done) => {
spyOn(contentApi, 'deleteNode').and.returnValue(throwError(null));
actions$.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map(() => done())
);
actions$
.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
const selection: any[] = [{ entry: { id: '1', name: 'name1' } }, { entry: { id: '2', name: 'name2' } }];
store.dispatch(new DeleteNodesAction(selection));
}));
});
it('should raise warning message when only one file is successful', fakeAsync((done) => {
it('should raise warning message when only one file is successful', (done) => {
spyOn(contentApi, 'deleteNode').and.callFake((id) => {
if (id === '1') {
return throwError(null);
@@ -831,17 +836,19 @@ describe('ContentManagementService', () => {
}
});
actions$.pipe(
ofType<SnackbarWarningAction>(SnackbarActionTypes.Warning),
map(() => done())
);
actions$
.pipe(
ofType<SnackbarWarningAction>(SnackbarActionTypes.Warning),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
const selection: any[] = [{ entry: { id: '1', name: 'name1' } }, { entry: { id: '2', name: 'name2' } }];
store.dispatch(new DeleteNodesAction(selection));
}));
});
it('should raise warning message when some files are successfully deleted', fakeAsync((done) => {
it('should raise warning message when some files are successfully deleted', (done) => {
spyOn(contentApi, 'deleteNode').and.callFake((id) => {
if (id === '1') {
return throwError(null);
@@ -858,15 +865,17 @@ describe('ContentManagementService', () => {
return of(null);
});
actions$.pipe(
ofType<SnackbarWarningAction>(SnackbarActionTypes.Warning),
map(() => done())
);
actions$
.pipe(
ofType<SnackbarWarningAction>(SnackbarActionTypes.Warning),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
const selection: any[] = [{ entry: { id: '1', name: 'name1' } }, { entry: { id: '2', name: 'name2' } }, { entry: { id: '3', name: 'name3' } }];
store.dispatch(new DeleteNodesAction(selection));
}));
});
});
describe('Permanent Delete', () => {
@@ -885,21 +894,23 @@ describe('ContentManagementService', () => {
expect(contentApi.purgeDeletedNode).not.toHaveBeenCalled();
});
it('call purge nodes if selection is not empty', fakeAsync(() => {
it('call purge nodes if selection is not empty', () => {
spyOn(contentApi, 'purgeDeletedNode').and.returnValue(of({}));
const selection: any[] = [{ entry: { id: '1' } }];
store.dispatch(new PurgeDeletedNodesAction(selection));
expect(contentApi.purgeDeletedNode).toHaveBeenCalled();
}));
});
describe('notification', () => {
it('raises warning on multiple fail and one success', fakeAsync((done) => {
actions$.pipe(
ofType<SnackbarWarningAction>(SnackbarActionTypes.Warning),
map(() => done())
);
it('raises warning on multiple fail and one success', (done) => {
actions$
.pipe(
ofType<SnackbarWarningAction>(SnackbarActionTypes.Warning),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
spyOn(contentApi, 'purgeDeletedNode').and.callFake((id) => {
if (id === '1') {
@@ -924,13 +935,15 @@ describe('ContentManagementService', () => {
];
store.dispatch(new PurgeDeletedNodesAction(selection));
}));
});
it('raises warning on multiple success and multiple fail', fakeAsync((done) => {
actions$.pipe(
ofType<SnackbarWarningAction>(SnackbarActionTypes.Warning),
map(() => done())
);
it('raises warning on multiple success and multiple fail', (done) => {
actions$
.pipe(
ofType<SnackbarWarningAction>(SnackbarActionTypes.Warning),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
spyOn(contentApi, 'purgeDeletedNode').and.callFake((id) => {
if (id === '1') {
@@ -960,39 +973,46 @@ describe('ContentManagementService', () => {
];
store.dispatch(new PurgeDeletedNodesAction(selection));
}));
});
it('raises info on one selected node success', fakeAsync((done) => {
actions$.pipe(
ofType<SnackbarInfoAction>(SnackbarActionTypes.Info),
map(() => done())
);
it('raises info on one selected node success', (done) => {
actions$
.pipe(
ofType<SnackbarInfoAction>(SnackbarActionTypes.Info),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
spyOn(contentApi, 'purgeDeletedNode').and.returnValue(of({}));
const selection: any[] = [{ entry: { id: '1', name: 'name1' } }];
store.dispatch(new PurgeDeletedNodesAction(selection));
}));
});
it('raises error on one selected node fail', fakeAsync((done) => {
actions$.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map(() => done())
);
it('raises error on one selected node fail', (done) => {
actions$
.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
spyOn(contentApi, 'purgeDeletedNode').and.returnValue(throwError({}));
const selection: any[] = [{ entry: { id: '1', name: 'name1' } }];
store.dispatch(new PurgeDeletedNodesAction(selection));
}));
});
it('raises info on all nodes success', (done) => {
actions$
.pipe(
ofType<SnackbarInfoAction>(SnackbarActionTypes.Info),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
it('raises info on all nodes success', fakeAsync((done) => {
actions$.pipe(
ofType<SnackbarInfoAction>(SnackbarActionTypes.Info),
map(() => done())
);
spyOn(contentApi, 'purgeDeletedNode').and.callFake((id) => {
if (id === '1') {
return of({});
@@ -1008,13 +1028,16 @@ describe('ContentManagementService', () => {
const selection: any[] = [{ entry: { id: '1', name: 'name1' } }, { entry: { id: '2', name: 'name2' } }];
store.dispatch(new PurgeDeletedNodesAction(selection));
}));
});
it('raises error on all nodes fail', (done) => {
actions$
.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
it('raises error on all nodes fail', fakeAsync((done) => {
actions$.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map(() => done())
);
spyOn(contentApi, 'purgeDeletedNode').and.callFake((id) => {
if (id === '1') {
return throwError({});
@@ -1030,7 +1053,7 @@ describe('ContentManagementService', () => {
const selection: any[] = [{ entry: { id: '1', name: 'name1' } }, { entry: { id: '2', name: 'name2' } }];
store.dispatch(new PurgeDeletedNodesAction(selection));
}));
});
});
});
@@ -1054,7 +1077,7 @@ describe('ContentManagementService', () => {
expect(contentApi.restoreNode).not.toHaveBeenCalled();
});
it('call restore nodes if selection has nodes with path', fakeAsync(() => {
it('call restore nodes if selection has nodes with path', () => {
spyOn(contentApi, 'restoreNode').and.returnValue(of({} as NodeEntry));
spyOn(contentApi, 'getDeletedNodes').and.returnValue(
of({
@@ -1083,9 +1106,9 @@ describe('ContentManagementService', () => {
store.dispatch(new RestoreDeletedNodesAction(selection));
expect(contentApi.restoreNode).toHaveBeenCalled();
}));
});
it('should navigate to library folder when node is a library content', fakeAsync(() => {
it('should navigate to library folder when node is a library content', () => {
spyOn(store, 'dispatch').and.callThrough();
spyOn(contentApi, 'restoreNode').and.returnValue(of({} as NodeEntry));
spyOn(contentApi, 'getDeletedNodes').and.returnValue(
@@ -1119,7 +1142,7 @@ describe('ContentManagementService', () => {
store.dispatch(new RestoreDeletedNodesAction(selection));
expect(store.dispatch['calls'].argsFor(1)[0].userAction.action instanceof NavigateToParentFolder).toBe(true);
}));
});
describe('notification', () => {
beforeEach(() => {
@@ -1130,13 +1153,15 @@ describe('ContentManagementService', () => {
);
});
it('should raise error message on partial multiple fail ', fakeAsync((done) => {
it('should raise error message on partial multiple fail ', (done) => {
const error = { message: '{ "error": {} }' };
actions$.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map(() => done())
);
actions$
.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
spyOn(contentApi, 'restoreNode').and.callFake((id) => {
if (id === '1') {
@@ -1170,16 +1195,18 @@ describe('ContentManagementService', () => {
];
store.dispatch(new RestoreDeletedNodesAction(selection));
}));
});
it('should raise error message when restored node exist, error 409', fakeAsync((done) => {
it('should raise error message when restored node exist, error 409', (done) => {
const error = { message: '{ "error": { "statusCode": 409 } }' };
spyOn(contentApi, 'restoreNode').and.returnValue(throwError(error));
actions$.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map(() => done())
);
actions$
.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
const path = {
elements: [
@@ -1193,17 +1220,19 @@ describe('ContentManagementService', () => {
const selection: any[] = [{ entry: { id: '1', name: 'name1', path } }];
store.dispatch(new RestoreDeletedNodesAction(selection));
}));
});
it('should raise error message when restored node returns different statusCode', fakeAsync((done) => {
it('should raise error message when restored node returns different statusCode', (done) => {
const error = { message: '{ "error": { "statusCode": 404 } }' };
spyOn(contentApi, 'restoreNode').and.returnValue(throwError(error));
actions$.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map(() => done())
);
actions$
.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
const path = {
elements: [
@@ -1217,17 +1246,19 @@ describe('ContentManagementService', () => {
const selection: any[] = [{ entry: { id: '1', name: 'name1', path } }];
store.dispatch(new RestoreDeletedNodesAction(selection));
}));
});
it('should raise error message when restored node location is missing', fakeAsync((done) => {
it('should raise error message when restored node location is missing', (done) => {
const error = { message: '{ "error": { } }' };
spyOn(contentApi, 'restoreNode').and.returnValue(throwError(error));
actions$.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map(() => done())
);
actions$
.pipe(
ofType<SnackbarErrorAction>(SnackbarActionTypes.Error),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
const path = {
elements: [
@@ -1241,9 +1272,9 @@ describe('ContentManagementService', () => {
const selection: any[] = [{ entry: { id: '1', name: 'name1', path } }];
store.dispatch(new RestoreDeletedNodesAction(selection));
}));
});
it('should raise info message when restore multiple nodes', fakeAsync((done) => {
it('should raise info message when restore multiple nodes', (done) => {
spyOn(contentApi, 'restoreNode').and.callFake((id) => {
const entry = {} as NodeEntry;
if (id === '1') {
@@ -1257,10 +1288,12 @@ describe('ContentManagementService', () => {
return of(entry);
});
actions$.pipe(
ofType<SnackbarInfoAction>(SnackbarActionTypes.Info),
map(() => done())
);
actions$
.pipe(
ofType<SnackbarInfoAction>(SnackbarActionTypes.Info),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
const path = {
elements: [
@@ -1274,15 +1307,17 @@ describe('ContentManagementService', () => {
const selection: any[] = [{ entry: { id: '1', name: 'name1', path } }, { entry: { id: '2', name: 'name2', path } }];
store.dispatch(new RestoreDeletedNodesAction(selection));
}));
});
it('should raise info message when restore selected node', fakeAsync((done) => {
it('should raise info message when restore selected node', (done) => {
spyOn(contentApi, 'restoreNode').and.returnValue(of({} as NodeEntry));
actions$.pipe(
ofType<SnackbarInfoAction>(SnackbarActionTypes.Info),
map(() => done())
);
actions$
.pipe(
ofType<SnackbarInfoAction>(SnackbarActionTypes.Info),
map((action) => expect(action).toBeDefined())
)
.subscribe(() => done());
const path = {
elements: [
@@ -1296,16 +1331,10 @@ describe('ContentManagementService', () => {
const selection: any[] = [{ entry: { id: '1', name: 'name1', path } }];
store.dispatch(new RestoreDeletedNodesAction(selection));
}));
});
it('navigate to restore selected node location onAction', fakeAsync((done) => {
it('navigate to restore selected node location onAction', (done) => {
spyOn(contentApi, 'restoreNode').and.returnValue(of({} as NodeEntry));
actions$.pipe(
ofType<NavigateRouteAction>(RouterActionTypes.NavigateRoute),
map(() => done())
);
const path = {
elements: [
{
@@ -1325,8 +1354,17 @@ describe('ContentManagementService', () => {
}
];
actions$
.pipe(
ofType<RestoreDeletedNodesAction>(NodeActionTypes.RestoreDeleted),
map((action) => {
expect(action).toBeDefined();
})
)
.subscribe(() => done());
store.dispatch(new RestoreDeletedNodesAction(selection));
}));
});
});
});
+10 -7
View File
@@ -78,7 +78,7 @@ describe('NodeActionsService', () => {
} else if (nameExistingOnDestination && options && options.name === nameExistingOnDestination) {
reject(conflictError);
} else {
resolve();
resolve('');
}
});
};
@@ -625,7 +625,7 @@ describe('NodeActionsService', () => {
}
];
spyOn(nodesApi, 'getNodeChildren').and.callFake(helper.fakeGetNodeChildren(testFamilyNodes));
spyOn(service, 'getChildByName').and.returnValue(subject);
spyOn(service, 'getChildByName').and.returnValue(of({}) as any);
copyObservable
.toPromise()
@@ -1004,13 +1004,13 @@ describe('NodeActionsService', () => {
];
});
it('emits child node with specified name, when it exists in folder', () => {
it('emits child node with specified name, when it exists in folder', async(() => {
spyOn(nodesApi, 'getNodeChildren').and.callFake(helper.fakeGetNodeChildren(testFamilyNodes));
service.getChildByName(testFamilyNodes[0].parentNodeId, childNode.entry.name).subscribe((value) => {
expect(value).toEqual(childNode);
});
});
}));
it('emits null value when child with specified name is not found in folder', async(() => {
spyOn(nodesApi, 'getNodeChildren').and.callFake(helper.fakeGetNodeChildren(testFamilyNodes));
@@ -1023,9 +1023,12 @@ describe('NodeActionsService', () => {
it('emits error when permission error occurs', async(() => {
spyOn(nodesApi, 'getNodeChildren').and.callFake(helper.fakeGetNodeChildren(testFamilyNodes, actionIsForbidden));
service.getChildByName(testFamilyNodes[0].parentNodeId, notChildNode.entry.name).subscribe((value) => {
expect(value).toEqual(null);
});
service.getChildByName(testFamilyNodes[0].parentNodeId, notChildNode.entry.name).subscribe(
() => {},
(err) => {
expect(err.message).toBe('{"error":{"statusCode":403}}');
}
);
}));
});
+1 -1
View File
@@ -529,7 +529,7 @@ export class NodeActionsService {
}
},
(err) => {
return of(err || 'Server error');
return matchedNodes.error(err);
}
);
return matchedNodes;