mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ACS-6140] migrate tests to harness (#9071)
* migrate aspect list tests to harness * [ci:force] categories management * [ci:force] fix keyboard handling * [ci:force] fix memory leak * migrate document list * migrate new version uploader dialog * migrate folder dialog * bug fixes for keyboard, remove fake unit tests * [ci:force] migrate and cleanup notification tests * migrate app details cloud * migrate app list cloud * migrate group cloud component * [ci:force] cleanup code based on reviews * [ci:force] migrate people cloud * [ci:force] migrate process list cloud * [ci:force] migrate start process cloud * [ci:force] task form cloud * [ci:force] service task list cloud * [ci:force] task list cloud * [ci:force] process attachment list and apps list * [ci:force] code review changes * [ci:force] app list bug fixes and code cleanup * [ci:force] fix incorrect/missing typings, fix tests * [ci:force] code cleanup
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
(click)="onCheckBoxClick($event)"
|
||||
(change)="onChange($event, aspect?.entry?.id)">
|
||||
<p class="adf-aspect-list-element-title">{{getTitle(aspect)}}</p>
|
||||
</mat-checkbox>
|
||||
</mat-checkbox>
|
||||
</mat-panel-title>
|
||||
<mat-panel-description [id]="'aspect-list-'+colIndex+'-title'"
|
||||
[matTooltip]="getTitle(aspect)">
|
||||
@@ -39,6 +39,6 @@
|
||||
|
||||
<ng-template #loading>
|
||||
<div class="adf-aspect-list-spinner">
|
||||
<mat-spinner id="adf-aspect-spinner"></mat-spinner>
|
||||
<mat-progress-spinner mode="indeterminate" id="adf-aspect-spinner"></mat-progress-spinner>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
@@ -24,86 +24,96 @@ import { AspectListService } from './services/aspect-list.service';
|
||||
import { of } from 'rxjs';
|
||||
import { AspectEntry } from '@alfresco/js-api';
|
||||
import { delay } from 'rxjs/operators';
|
||||
import { HarnessLoader } from '@angular/cdk/testing';
|
||||
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||
import { MatExpansionPanelHarness } from '@angular/material/expansion/testing';
|
||||
import { MatTableHarness } from '@angular/material/table/testing';
|
||||
import { MatCheckboxHarness } from '@angular/material/checkbox/testing';
|
||||
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
|
||||
|
||||
const aspectListMock: AspectEntry[] = [{
|
||||
entry: {
|
||||
parentId: 'frs:aspectZero',
|
||||
id: 'frs:AspectOne',
|
||||
description: 'First Aspect with random description',
|
||||
title: 'FirstAspect',
|
||||
properties: [
|
||||
{
|
||||
id: 'channelPassword',
|
||||
title: 'The authenticated channel password',
|
||||
dataType: 'd:propA'
|
||||
},
|
||||
{
|
||||
id: 'channelUsername',
|
||||
title: 'The authenticated channel username',
|
||||
dataType: 'd:propB'
|
||||
}
|
||||
]
|
||||
const aspectListMock: AspectEntry[] = [
|
||||
{
|
||||
entry: {
|
||||
parentId: 'frs:aspectZero',
|
||||
id: 'frs:AspectOne',
|
||||
description: 'First Aspect with random description',
|
||||
title: 'FirstAspect',
|
||||
properties: [
|
||||
{
|
||||
id: 'channelPassword',
|
||||
title: 'The authenticated channel password',
|
||||
dataType: 'd:propA'
|
||||
},
|
||||
{
|
||||
id: 'channelUsername',
|
||||
title: 'The authenticated channel username',
|
||||
dataType: 'd:propB'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
entry: {
|
||||
parentId: 'frs:AspectZer',
|
||||
id: 'frs:SecondAspect',
|
||||
description: 'Second Aspect description',
|
||||
title: 'SecondAspect',
|
||||
properties: [
|
||||
{
|
||||
id: 'assetId',
|
||||
title: 'Published Asset Id',
|
||||
dataType: 'd:text'
|
||||
},
|
||||
{
|
||||
id: 'assetUrl',
|
||||
title: 'Published Asset URL',
|
||||
dataType: 'd:text'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
entry: {
|
||||
parentId: 'frs:AspectZer',
|
||||
id: 'frs:SecondAspect',
|
||||
description: 'Second Aspect description',
|
||||
title: 'SecondAspect',
|
||||
properties: [
|
||||
{
|
||||
id: 'assetId',
|
||||
title: 'Published Asset Id',
|
||||
dataType: 'd:text'
|
||||
},
|
||||
{
|
||||
id: 'assetUrl',
|
||||
title: 'Published Asset URL',
|
||||
dataType: 'd:text'
|
||||
}
|
||||
]
|
||||
}
|
||||
}];
|
||||
];
|
||||
|
||||
const customAspectListMock: AspectEntry[] = [{
|
||||
entry: {
|
||||
parentId: 'cst:parentAspect',
|
||||
id: 'cst:customAspect',
|
||||
description: 'Custom Aspect with random description',
|
||||
title: 'CustomAspect',
|
||||
properties: [
|
||||
{
|
||||
id: 'channelPassword',
|
||||
title: 'The authenticated channel password',
|
||||
dataType: 'd:propA'
|
||||
},
|
||||
{
|
||||
id: 'channelUsername',
|
||||
title: 'The authenticated channel username',
|
||||
dataType: 'd:propB'
|
||||
}
|
||||
]
|
||||
const customAspectListMock: AspectEntry[] = [
|
||||
{
|
||||
entry: {
|
||||
parentId: 'cst:parentAspect',
|
||||
id: 'cst:customAspect',
|
||||
description: 'Custom Aspect with random description',
|
||||
title: 'CustomAspect',
|
||||
properties: [
|
||||
{
|
||||
id: 'channelPassword',
|
||||
title: 'The authenticated channel password',
|
||||
dataType: 'd:propA'
|
||||
},
|
||||
{
|
||||
id: 'channelUsername',
|
||||
title: 'The authenticated channel username',
|
||||
dataType: 'd:propB'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
entry: {
|
||||
parentId: 'cst:commonaspect',
|
||||
id: 'cst:nonamedAspect',
|
||||
description: '',
|
||||
title: '',
|
||||
properties: [
|
||||
{
|
||||
id: 'channelPassword',
|
||||
title: 'The authenticated channel password',
|
||||
dataType: 'd:propA'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
entry: {
|
||||
parentId: 'cst:commonaspect',
|
||||
id: 'cst:nonamedAspect',
|
||||
description: '',
|
||||
title: '',
|
||||
properties: [
|
||||
{
|
||||
id: 'channelPassword',
|
||||
title: 'The authenticated channel password',
|
||||
dataType: 'd:propA'
|
||||
}
|
||||
]
|
||||
}
|
||||
}];
|
||||
];
|
||||
|
||||
describe('AspectListComponent', () => {
|
||||
|
||||
let loader: HarnessLoader;
|
||||
let component: AspectListComponent;
|
||||
let fixture: ComponentFixture<AspectListComponent>;
|
||||
let aspectListService: AspectListService;
|
||||
@@ -111,36 +121,31 @@ describe('AspectListComponent', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
ContentTestingModule
|
||||
],
|
||||
imports: [TranslateModule.forRoot(), ContentTestingModule],
|
||||
providers: [AspectListService]
|
||||
});
|
||||
});
|
||||
|
||||
describe('Loading', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AspectListComponent);
|
||||
component = fixture.componentInstance;
|
||||
nodeService = TestBed.inject(NodesApiService);
|
||||
aspectListService = TestBed.inject(AspectListService);
|
||||
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
});
|
||||
|
||||
it('should show the loading spinner when result is loading', () => {
|
||||
it('should show the loading spinner when result is loading', async () => {
|
||||
const delayResult = of(null).pipe(delay(0));
|
||||
spyOn(nodeService, 'getNode').and.returnValue(delayResult);
|
||||
spyOn(aspectListService, 'getAspects').and.returnValue(delayResult);
|
||||
fixture.detectChanges();
|
||||
const spinner = fixture.nativeElement.querySelector('#adf-aspect-spinner');
|
||||
expect(spinner).toBeDefined();
|
||||
expect(spinner).not.toBeNull();
|
||||
|
||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('When passing a node id', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AspectListComponent);
|
||||
component = fixture.componentInstance;
|
||||
@@ -152,6 +157,7 @@ describe('AspectListComponent', () => {
|
||||
spyOn(nodeService, 'getNode').and.returnValue(of({ id: 'fake-node-id', aspectNames: ['frs:AspectOne'] } as any));
|
||||
component.nodeId = 'fake-node-id';
|
||||
fixture.detectChanges();
|
||||
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -167,106 +173,80 @@ describe('AspectListComponent', () => {
|
||||
expect(component.hasEqualAspect).toBe(false);
|
||||
});
|
||||
|
||||
it('should show all the aspects', () => {
|
||||
const firstElement = fixture.nativeElement.querySelector('#aspect-list-FirstAspect');
|
||||
const secondElement = fixture.nativeElement.querySelector('#aspect-list-SecondAspect');
|
||||
|
||||
expect(firstElement).not.toBeNull();
|
||||
expect(firstElement).toBeDefined();
|
||||
expect(secondElement).not.toBeNull();
|
||||
expect(secondElement).toBeDefined();
|
||||
it('should show all the aspects', async () => {
|
||||
expect(await loader.hasHarness(MatExpansionPanelHarness.with({ selector: '#aspect-list-FirstAspect' }))).toBe(true);
|
||||
expect(await loader.hasHarness(MatExpansionPanelHarness.with({ selector: '#aspect-list-SecondAspect' }))).toBe(true);
|
||||
});
|
||||
|
||||
it('should show aspect id when name or title is not set', () => {
|
||||
const noNameAspect: HTMLElement = fixture.nativeElement.querySelector('#aspect-list-cst-nonamedAspect .adf-aspect-list-element-title');
|
||||
const noNameAspect = fixture.nativeElement.querySelector('#aspect-list-cst-nonamedAspect .adf-aspect-list-element-title');
|
||||
expect(noNameAspect).toBeDefined();
|
||||
expect(noNameAspect).not.toBeNull();
|
||||
expect(noNameAspect.innerText).toBe('cst:nonamedAspect');
|
||||
});
|
||||
|
||||
it('should show the details when a row is clicked', () => {
|
||||
const firstElement = fixture.nativeElement.querySelector('#aspect-list-FirstAspect');
|
||||
firstElement.click();
|
||||
fixture.detectChanges();
|
||||
const firstElementDesc = fixture.nativeElement.querySelector('#aspect-list-0-description');
|
||||
expect(firstElementDesc).not.toBeNull();
|
||||
expect(firstElementDesc).toBeDefined();
|
||||
it('should show the details when a row is clicked', async () => {
|
||||
const panel = await loader.getHarness(MatExpansionPanelHarness);
|
||||
await panel.expand();
|
||||
expect(await panel.getDescription()).not.toBeNull();
|
||||
|
||||
const firstElementPropertyTable = fixture.nativeElement.querySelector('#aspect-list-0-properties-table');
|
||||
expect(firstElementPropertyTable).not.toBeNull();
|
||||
expect(firstElementPropertyTable).toBeDefined();
|
||||
const nameProperties = fixture.nativeElement.querySelectorAll('#aspect-list-0-properties-table tbody .mat-column-name');
|
||||
expect(nameProperties[0]).not.toBeNull();
|
||||
expect(nameProperties[0]).toBeDefined();
|
||||
expect(nameProperties[0].innerText).toBe('channelPassword');
|
||||
expect(nameProperties[1]).not.toBeNull();
|
||||
expect(nameProperties[1]).toBeDefined();
|
||||
expect(nameProperties[1].innerText).toBe('channelUsername');
|
||||
const table = await panel.getHarness(MatTableHarness);
|
||||
const [row1, row2] = await table.getRows();
|
||||
const [r1c1, r1c2, r1c3] = await row1.getCells();
|
||||
expect(await r1c1.getText()).toBe('channelPassword');
|
||||
expect(await r1c2.getText()).toBe('The authenticated channel password');
|
||||
expect(await r1c3.getText()).toBe('d:propA');
|
||||
|
||||
const titleProperties = fixture.nativeElement.querySelectorAll('#aspect-list-0-properties-table tbody .mat-column-title');
|
||||
expect(titleProperties[0]).not.toBeNull();
|
||||
expect(titleProperties[0]).toBeDefined();
|
||||
expect(titleProperties[0].innerText).toBe('The authenticated channel password');
|
||||
expect(titleProperties[1]).not.toBeNull();
|
||||
expect(titleProperties[1]).toBeDefined();
|
||||
expect(titleProperties[1].innerText).toBe('The authenticated channel username');
|
||||
|
||||
const dataTypeProperties = fixture.nativeElement.querySelectorAll('#aspect-list-0-properties-table tbody .mat-column-dataType');
|
||||
expect(dataTypeProperties[0]).not.toBeNull();
|
||||
expect(dataTypeProperties[0]).toBeDefined();
|
||||
expect(dataTypeProperties[0].innerText).toBe('d:propA');
|
||||
expect(dataTypeProperties[1]).not.toBeNull();
|
||||
expect(dataTypeProperties[1]).toBeDefined();
|
||||
expect(dataTypeProperties[1].innerText).toBe('d:propB');
|
||||
const [r2c1, r2c2, r2c3] = await row2.getCells();
|
||||
expect(await r2c1.getText()).toBe('channelUsername');
|
||||
expect(await r2c2.getText()).toBe('The authenticated channel username');
|
||||
expect(await r2c3.getText()).toBe('d:propB');
|
||||
});
|
||||
|
||||
it('should show as checked the node properties', () => {
|
||||
const firstAspectCheckbox: HTMLInputElement = fixture.nativeElement.querySelector('#aspect-list-0-check-input');
|
||||
expect(firstAspectCheckbox).toBeDefined();
|
||||
expect(firstAspectCheckbox).not.toBeNull();
|
||||
expect(firstAspectCheckbox.checked).toBeTruthy();
|
||||
it('should show as checked the node properties', async () => {
|
||||
const panel = await loader.getHarness(MatExpansionPanelHarness);
|
||||
await panel.expand();
|
||||
|
||||
const checkbox = await panel.getHarness(MatCheckboxHarness);
|
||||
expect(await checkbox.isChecked()).toBe(true);
|
||||
});
|
||||
|
||||
it('should remove aspects unchecked', (done) => {
|
||||
const secondElement = fixture.nativeElement.querySelector('#aspect-list-1-check-input');
|
||||
expect(secondElement).toBeDefined();
|
||||
expect(secondElement).not.toBeNull();
|
||||
expect(secondElement.checked).toBeFalsy();
|
||||
secondElement.click();
|
||||
fixture.detectChanges();
|
||||
it('should remove aspects unchecked', async () => {
|
||||
const panel = await loader.getAllHarnesses(MatExpansionPanelHarness);
|
||||
await panel[1].expand();
|
||||
|
||||
const checkbox = await panel[1].getHarness(MatCheckboxHarness);
|
||||
expect(await checkbox.isChecked()).toBe(false);
|
||||
|
||||
await checkbox.toggle();
|
||||
|
||||
expect(component.nodeAspects.length).toBe(2);
|
||||
expect(component.nodeAspects[1]).toBe('frs:SecondAspect');
|
||||
component.valueChanged.subscribe((aspects) => {
|
||||
expect(aspects.length).toBe(1);
|
||||
expect(aspects[0]).toBe('frs:AspectOne');
|
||||
done();
|
||||
});
|
||||
secondElement.click();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should reset the properties on reset', (done) => {
|
||||
const secondElement = fixture.nativeElement.querySelector('#aspect-list-1-check-input');
|
||||
expect(secondElement).toBeDefined();
|
||||
expect(secondElement).not.toBeNull();
|
||||
expect(secondElement.checked).toBeFalsy();
|
||||
secondElement.click();
|
||||
fixture.detectChanges();
|
||||
expect(component.nodeAspects.length).toBe(2);
|
||||
component.valueChanged.subscribe((aspects) => {
|
||||
expect(aspects.length).toBe(1);
|
||||
done();
|
||||
});
|
||||
component.reset();
|
||||
});
|
||||
await checkbox.toggle();
|
||||
|
||||
it('should clear all the properties on clear', (done) => {
|
||||
expect(component.nodeAspects.length).toBe(1);
|
||||
component.valueChanged.subscribe((aspects) => {
|
||||
expect(aspects.length).toBe(0);
|
||||
done();
|
||||
});
|
||||
expect(component.nodeAspects[0]).toBe('frs:AspectOne');
|
||||
});
|
||||
|
||||
it('should reset the properties on reset', async () => {
|
||||
const panel = await loader.getAllHarnesses(MatExpansionPanelHarness);
|
||||
await panel[1].expand();
|
||||
|
||||
const checkbox = await panel[1].getHarness(MatCheckboxHarness);
|
||||
expect(await checkbox.isChecked()).toBe(false);
|
||||
|
||||
await checkbox.toggle();
|
||||
|
||||
expect(component.nodeAspects.length).toBe(2);
|
||||
component.reset();
|
||||
expect(component.nodeAspects.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should clear all the properties on clear', async () => {
|
||||
expect(component.nodeAspects.length).toBe(1);
|
||||
component.clear();
|
||||
expect(component.nodeAspects.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -277,21 +257,16 @@ describe('AspectListComponent', () => {
|
||||
aspectListService = TestBed.inject(AspectListService);
|
||||
spyOn(aspectListService, 'getAspects').and.returnValue(of(aspectListMock));
|
||||
fixture.detectChanges();
|
||||
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should show all the aspects', () => {
|
||||
const firstElement = fixture.nativeElement.querySelector('#aspect-list-FirstAspect');
|
||||
const secondElement = fixture.nativeElement.querySelector('#aspect-list-SecondAspect');
|
||||
|
||||
expect(firstElement).not.toBeNull();
|
||||
expect(firstElement).toBeDefined();
|
||||
expect(secondElement).not.toBeNull();
|
||||
expect(secondElement).toBeDefined();
|
||||
it('should show all the aspects', async () => {
|
||||
expect(await loader.hasHarness(MatExpansionPanelHarness.with({ selector: '#aspect-list-FirstAspect' }))).toBe(true);
|
||||
expect(await loader.hasHarness(MatExpansionPanelHarness.with({ selector: '#aspect-list-SecondAspect' }))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -71,7 +71,8 @@
|
||||
[value]="category">
|
||||
{{ category.name }}
|
||||
</mat-list-option>
|
||||
<p *ngIf="!existingCategories?.length && !existingCategoriesLoading">
|
||||
<p *ngIf="!existingCategories?.length && !existingCategoriesLoading"
|
||||
data-automation-id="no-categories-message">
|
||||
{{ 'CATEGORIES_MANAGEMENT.NO_EXISTING_CATEGORIES' | translate }}
|
||||
</p>
|
||||
</mat-selection-list>
|
||||
|
@@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
import { Category, CategoryPaging, ResultNode, ResultSetPaging } from '@alfresco/js-api';
|
||||
import { DebugElement } from '@angular/core';
|
||||
import { ComponentFixture, discardPeriodicTasks, fakeAsync, flush, TestBed, tick } from '@angular/core/testing';
|
||||
import { Validators } from '@angular/forms';
|
||||
import { MatError } from '@angular/material/form-field';
|
||||
@@ -28,8 +27,12 @@ import { ContentTestingModule } from '../../testing/content.testing.module';
|
||||
import { CategoriesManagementMode } from './categories-management-mode';
|
||||
import { CategoryService } from '../services/category.service';
|
||||
import { CategoriesManagementComponent } from './categories-management.component';
|
||||
import { HarnessLoader } from '@angular/cdk/testing';
|
||||
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
|
||||
|
||||
describe('CategoriesManagementComponent', () => {
|
||||
let loader: HarnessLoader;
|
||||
let component: CategoriesManagementComponent;
|
||||
let fixture: ComponentFixture<CategoriesManagementComponent>;
|
||||
let categoryService: CategoryService;
|
||||
@@ -38,18 +41,15 @@ describe('CategoriesManagementComponent', () => {
|
||||
const category2 = new Category({ id: 'test2', name: 'testCat2' });
|
||||
const category3 = new Category({ id: 'test3', name: 'testCat3' });
|
||||
const category4 = new Category({ id: 'test4', name: 'testCat4' });
|
||||
const resultCat1 = new ResultNode({ id: 'test', name: 'testCat', path: { name: 'general/categories' }});
|
||||
const resultCat2 = new ResultNode({ id: 'test2', name: 'testCat2', path: { name: 'general/categories' }});
|
||||
const categoryPagingResponse: CategoryPaging = { list: { pagination: {}, entries: [ { entry: category1 }, { entry: category2 }]}};
|
||||
const categorySearchResponse: ResultSetPaging = { list: { pagination: {}, entries: [ { entry: resultCat1 }, { entry: resultCat2 }]}};
|
||||
const resultCat1 = new ResultNode({ id: 'test', name: 'testCat', path: { name: 'general/categories' } });
|
||||
const resultCat2 = new ResultNode({ id: 'test2', name: 'testCat2', path: { name: 'general/categories' } });
|
||||
const categoryPagingResponse: CategoryPaging = { list: { pagination: {}, entries: [{ entry: category1 }, { entry: category2 }] } };
|
||||
const categorySearchResponse: ResultSetPaging = { list: { pagination: {}, entries: [{ entry: resultCat1 }, { entry: resultCat2 }] } };
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [CategoriesManagementComponent],
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
ContentTestingModule
|
||||
],
|
||||
imports: [TranslateModule.forRoot(), ContentTestingModule],
|
||||
providers: [
|
||||
{
|
||||
provide: CategoryService,
|
||||
@@ -65,6 +65,7 @@ describe('CategoriesManagementComponent', () => {
|
||||
fixture = TestBed.createComponent(CategoriesManagementComponent);
|
||||
component = fixture.componentInstance;
|
||||
categoryService = TestBed.inject(CategoryService);
|
||||
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -138,7 +139,9 @@ describe('CategoriesManagementComponent', () => {
|
||||
* @returns list of native elements
|
||||
*/
|
||||
function getRemoveCategoryButtons(): HTMLButtonElement[] {
|
||||
return fixture.debugElement.queryAll(By.css(`[data-automation-id="categories-remove-category-button"]`)).map((debugElem) => debugElem.nativeElement);
|
||||
return fixture.debugElement
|
||||
.queryAll(By.css(`[data-automation-id="categories-remove-category-button"]`))
|
||||
.map((debugElem) => debugElem.nativeElement);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,39 +264,28 @@ describe('CategoriesManagementComponent', () => {
|
||||
});
|
||||
|
||||
describe('Spinner', () => {
|
||||
/**
|
||||
* Get the spinner element
|
||||
*
|
||||
* @returns debug element
|
||||
*/
|
||||
function getSpinner(): DebugElement {
|
||||
return fixture.debugElement.query(By.css(`.mat-progress-spinner`));
|
||||
}
|
||||
it('should not be displayed when existing categories stopped loading', async () => {
|
||||
component.categoryNameControlVisible = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
it('should be displayed with correct diameter when existing categories are loading', fakeAsync(() => {
|
||||
typeCategory('Category 1', 0);
|
||||
const categoryControlInput = getCategoryControlInput();
|
||||
categoryControlInput.value = 'Category 1';
|
||||
categoryControlInput.dispatchEvent(new InputEvent('input'));
|
||||
|
||||
const spinner = getSpinner();
|
||||
expect(spinner).toBeTruthy();
|
||||
expect(spinner.componentInstance.diameter).toBe(50);
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
discardPeriodicTasks();
|
||||
flush();
|
||||
}));
|
||||
|
||||
it('should not be displayed when existing categories stopped loading', fakeAsync(() => {
|
||||
typeCategory('Category 1');
|
||||
|
||||
const spinner = getSpinner();
|
||||
expect(spinner).toBeFalsy();
|
||||
}));
|
||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('should display correct message when there are no existing categories', fakeAsync(() => {
|
||||
spyOn(categoryService, 'getSubcategories').and.returnValue(of({list: { pagination: {}, entries: []}}));
|
||||
spyOn(categoryService, 'getSubcategories').and.returnValue(of({ list: { pagination: {}, entries: [] } }));
|
||||
typeCategory('test');
|
||||
|
||||
const noExistingCategoriesMsg = fixture.debugElement.query(By.css('mat-selection-list p'))?.nativeElement.textContent.trim();
|
||||
const noExistingCategoriesMsg = fixture.debugElement
|
||||
.query(By.css(`[data-automation-id="no-categories-message"]`))
|
||||
?.nativeElement.textContent.trim();
|
||||
expect(noExistingCategoriesMsg).toBe('CATEGORIES_MANAGEMENT.NO_EXISTING_CATEGORIES');
|
||||
}));
|
||||
});
|
||||
@@ -328,7 +320,9 @@ describe('CategoriesManagementComponent', () => {
|
||||
|
||||
it('should have correct remove category title', () => {
|
||||
const removeButtons = getRemoveCategoryButtons();
|
||||
const isTitleCorrect = removeButtons.every((removeBtn) => removeBtn.attributes.getNamedItem('title').textContent === 'CATEGORIES_MANAGEMENT.UNASSIGN_CATEGORY');
|
||||
const isTitleCorrect = removeButtons.every(
|
||||
(removeBtn) => removeBtn.attributes.getNamedItem('title').textContent === 'CATEGORIES_MANAGEMENT.UNASSIGN_CATEGORY'
|
||||
);
|
||||
expect(isTitleCorrect).toBeTrue();
|
||||
});
|
||||
|
||||
@@ -434,7 +428,9 @@ describe('CategoriesManagementComponent', () => {
|
||||
|
||||
it('should have correct remove category title', () => {
|
||||
const removeButtons = getRemoveCategoryButtons();
|
||||
const isTitleCorrect = removeButtons.every((removeBtn) => removeBtn.attributes.getNamedItem('title').textContent === 'CATEGORIES_MANAGEMENT.DELETE_CATEGORY');
|
||||
const isTitleCorrect = removeButtons.every(
|
||||
(removeBtn) => removeBtn.attributes.getNamedItem('title').textContent === 'CATEGORIES_MANAGEMENT.DELETE_CATEGORY'
|
||||
);
|
||||
expect(isTitleCorrect).toBeTrue();
|
||||
});
|
||||
|
||||
|
@@ -15,9 +15,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Component, Inject, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { Component, Inject, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { TranslationService, NotificationService} from '@alfresco/adf-core';
|
||||
import { TranslationService, NotificationService } from '@alfresco/adf-core';
|
||||
import { Node } from '@alfresco/js-api';
|
||||
import { AllowableOperationsEnum } from '../common/models/allowable-operations.enum';
|
||||
import { ContentService } from '../common/services/content.service';
|
||||
@@ -26,6 +26,8 @@ import { ContentNodeSelectorComponentData } from './content-node-selector.compon
|
||||
import { NodeEntryEvent } from '../document-list/components/node.event';
|
||||
import { NodeAction } from '../document-list/models/node-action.enum';
|
||||
import { OverlayContainer } from '@angular/cdk/overlay';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-content-node-selector',
|
||||
@@ -33,7 +35,9 @@ import { OverlayContainer } from '@angular/cdk/overlay';
|
||||
styleUrls: ['./content-node-selector.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class ContentNodeSelectorComponent implements OnInit {
|
||||
export class ContentNodeSelectorComponent implements OnInit, OnDestroy {
|
||||
private onDestroy$ = new Subject<void>();
|
||||
|
||||
title: string;
|
||||
action: NodeAction;
|
||||
buttonActionName: string;
|
||||
@@ -48,13 +52,15 @@ export class ContentNodeSelectorComponent implements OnInit {
|
||||
emptyFolderImageUrl: string = './assets/images/empty_doc_lib.svg';
|
||||
breadcrumbFolderNode: Node;
|
||||
|
||||
constructor(private translation: TranslationService,
|
||||
private contentService: ContentService,
|
||||
private notificationService: NotificationService,
|
||||
private uploadService: UploadService,
|
||||
private dialog: MatDialogRef<ContentNodeSelectorComponent>,
|
||||
private overlayContainer: OverlayContainer,
|
||||
@Inject(MAT_DIALOG_DATA) public data: ContentNodeSelectorComponentData) {
|
||||
constructor(
|
||||
private translation: TranslationService,
|
||||
private contentService: ContentService,
|
||||
private notificationService: NotificationService,
|
||||
private uploadService: UploadService,
|
||||
private dialog: MatDialogRef<ContentNodeSelectorComponent>,
|
||||
private overlayContainer: OverlayContainer,
|
||||
@Inject(MAT_DIALOG_DATA) public data: ContentNodeSelectorComponentData
|
||||
) {
|
||||
this.action = data.actionName ?? NodeAction.CHOOSE;
|
||||
this.buttonActionName = `NODE_SELECTOR.${this.action}`;
|
||||
this.title = data.title;
|
||||
@@ -62,28 +68,41 @@ export class ContentNodeSelectorComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.dialog.keydownEvents().subscribe(event => {
|
||||
// Esc
|
||||
if (event.keyCode === 27) {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
this.dialog
|
||||
.keydownEvents()
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe((event) => {
|
||||
if (event?.key === 'Escape') {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
|
||||
this.dialog
|
||||
.backdropClick()
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(() => {
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
this.dialog.backdropClick().subscribe(() => {
|
||||
this.close();
|
||||
});
|
||||
this.dialog
|
||||
.afterOpened()
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe(() => {
|
||||
this.overlayContainer.getContainerElement().setAttribute('role', 'main');
|
||||
});
|
||||
|
||||
this.dialog.afterOpened().subscribe(() => {
|
||||
this.overlayContainer.getContainerElement().setAttribute('role', 'main');
|
||||
});
|
||||
|
||||
this.uploadService.fileUploadStarting.subscribe(() => {
|
||||
this.uploadService.fileUploadStarting.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
|
||||
this.uploadStarted = true;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next();
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
close() {
|
||||
this.dialog.close();
|
||||
this.overlayContainer.getContainerElement().setAttribute('role', 'region');
|
||||
@@ -179,16 +198,17 @@ export class ContentNodeSelectorComponent implements OnInit {
|
||||
}
|
||||
|
||||
getWarningMessage(): string {
|
||||
return this.showingSearch ? 'NODE_SELECTOR.UPLOAD_BUTTON_SEARCH_WARNING_MESSAGE' :
|
||||
(this.hasNoPermissionToUpload() ? 'NODE_SELECTOR.UPLOAD_BUTTON_PERMISSION_WARNING_MESSAGE' : '');
|
||||
if (this.showingSearch) {
|
||||
return 'NODE_SELECTOR.UPLOAD_BUTTON_SEARCH_WARNING_MESSAGE';
|
||||
}
|
||||
return this.hasNoPermissionToUpload() ? 'NODE_SELECTOR.UPLOAD_BUTTON_PERMISSION_WARNING_MESSAGE' : '';
|
||||
}
|
||||
|
||||
hasNoPermissionToUpload(): boolean {
|
||||
return (!this.hasAllowableOperations && !this.showingSearch) && !this.isLoading;
|
||||
return !this.hasAllowableOperations && !this.showingSearch && !this.isLoading;
|
||||
}
|
||||
|
||||
hasUploadError(): boolean {
|
||||
return this.showingSearch || this.hasNoPermissionToUpload();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -48,6 +48,8 @@ describe('FolderDialogComponent', () => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
const getTitle = () => fixture.debugElement.query(By.css('[data-automation-id="adf-folder-dialog-title"]'));
|
||||
|
||||
describe('Edit', () => {
|
||||
beforeEach(() => {
|
||||
component.data = {
|
||||
@@ -70,8 +72,8 @@ describe('FolderDialogComponent', () => {
|
||||
});
|
||||
|
||||
it('should have the proper title', () => {
|
||||
const title = fixture.debugElement.query(By.css('[mat-dialog-title]'));
|
||||
expect(title === null).toBe(false);
|
||||
const title = getTitle();
|
||||
expect(title).not.toBeNull();
|
||||
expect(title.nativeElement.innerText.trim()).toBe('CORE.FOLDER_DIALOG.EDIT_FOLDER_TITLE');
|
||||
});
|
||||
|
||||
@@ -165,8 +167,8 @@ describe('FolderDialogComponent', () => {
|
||||
});
|
||||
|
||||
it('should have the proper title', () => {
|
||||
const title = fixture.debugElement.query(By.css(`[data-automation-id="adf-folder-dialog-title"]`));
|
||||
expect(title === null).toBe(false);
|
||||
const title = getTitle();
|
||||
expect(title).not.toBeNull();
|
||||
expect(title.nativeElement.innerText.trim()).toBe('CORE.FOLDER_DIALOG.CREATE_FOLDER_TITLE');
|
||||
});
|
||||
|
||||
|
@@ -62,12 +62,16 @@ import { domSanitizerMock } from '../../testing/dom-sanitizer-mock';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { FileAutoDownloadComponent } from './file-auto-download/file-auto-download.component';
|
||||
import { ShareDataTableAdapter } from '../data/share-datatable-adapter';
|
||||
import { HarnessLoader } from '@angular/cdk/testing';
|
||||
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
||||
import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing';
|
||||
|
||||
const mockDialog = {
|
||||
open: jasmine.createSpy('open')
|
||||
};
|
||||
|
||||
describe('DocumentList', () => {
|
||||
let loader: HarnessLoader;
|
||||
let documentList: DocumentListComponent;
|
||||
let documentListService: DocumentListService;
|
||||
let customResourcesService: CustomResourcesService;
|
||||
@@ -116,6 +120,8 @@ describe('DocumentList', () => {
|
||||
spyFavorite = spyOn(customResourcesService.favoritesApi, 'listFavorites').and.returnValue(
|
||||
Promise.resolve(new FavoritePaging({ list: new FavoritePagingList({ entries: [] }) }))
|
||||
);
|
||||
|
||||
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -219,7 +225,7 @@ describe('DocumentList', () => {
|
||||
|
||||
it('should show the header when there are no records in the table but filter is active', () => {
|
||||
documentList.data = new ShareDataTableAdapter(thumbnailService, contentService, []);
|
||||
documentList.filterValue = { $thumbnail: 'TYPE:"cm:folder"' };
|
||||
documentList.filterValue = { $thumbnail: 'TYPE:"cm:folder"' };
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
@@ -1075,10 +1081,11 @@ describe('DocumentList', () => {
|
||||
expect(fixture.debugElement.query(By.css('.adf-no-permission__template'))).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should display loading template when data is loading', () => {
|
||||
it('should display loading template when data is loading', async () => {
|
||||
documentList.loading = true;
|
||||
fixture.detectChanges();
|
||||
expect(fixture.debugElement.query(By.css('mat-progress-spinner'))).not.toBeNull();
|
||||
|
||||
expect(await loader.hasHarness(MatProgressSpinnerHarness)).toBe(true);
|
||||
});
|
||||
|
||||
it('should empty folder NOT show the pagination', () => {
|
||||
@@ -1406,14 +1413,16 @@ describe('DocumentList', () => {
|
||||
expect(documentList.reload).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not show loading state if pagination is updated with merge setting as true', fakeAsync (() => {
|
||||
it('should not show loading state if pagination is updated with merge setting as true', fakeAsync(() => {
|
||||
spyFolderNode = spyOn(documentListService, 'loadFolderByNodeId').and.callFake(() =>
|
||||
of(new DocumentLoaderNode(null, {
|
||||
list: {
|
||||
pagination: {},
|
||||
entries: mockPreselectedNodes
|
||||
}
|
||||
}))
|
||||
of(
|
||||
new DocumentLoaderNode(null, {
|
||||
list: {
|
||||
pagination: {},
|
||||
entries: mockPreselectedNodes
|
||||
}
|
||||
})
|
||||
)
|
||||
);
|
||||
fixture.detectChanges();
|
||||
const fakeDatatableRows = [
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<h1 mat-dialog-title>{{ title | translate }}</h1>
|
||||
<h1 mat-dialog-title data-automation-id="new-version-uploader-dialog-title">{{ title | translate }}</h1>
|
||||
<section mat-dialog-content *ngIf="!data.showVersionsOnly">
|
||||
<adf-version-comparison id="adf-version-comparison" [newFileVersion]="data.file" [node]="data.node"></adf-version-comparison>
|
||||
<adf-version-upload
|
||||
|
@@ -28,13 +28,13 @@ import { NewVersionUploaderDialogComponent } from './new-version-uploader.dialog
|
||||
describe('NewVersionUploaderDialog', () => {
|
||||
let component: NewVersionUploaderDialogComponent;
|
||||
let fixture: ComponentFixture<NewVersionUploaderDialogComponent>;
|
||||
let nativeElement;
|
||||
let nativeElement: HTMLElement;
|
||||
|
||||
const cssSelectors = {
|
||||
adfVersionUploadButton: '#adf-version-upload-button',
|
||||
adfVersionComparison: '#adf-version-comparison',
|
||||
adfVersionList: '.adf-version-list',
|
||||
matDialogTitle: '.mat-dialog-title'
|
||||
title: '[data-automation-id="new-version-uploader-dialog-title"]'
|
||||
};
|
||||
|
||||
const mockDialogRef = {
|
||||
@@ -45,10 +45,7 @@ describe('NewVersionUploaderDialog', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
ContentTestingModule
|
||||
],
|
||||
imports: [TranslateModule.forRoot(), ContentTestingModule],
|
||||
declarations: [
|
||||
NewVersionUploaderDialogComponent,
|
||||
VersionListComponent,
|
||||
@@ -59,7 +56,8 @@ describe('NewVersionUploaderDialog', () => {
|
||||
providers: [
|
||||
{ provide: MAT_DIALOG_DATA, useValue: { node: mockNode, showVersionsOnly, file: mockFile } },
|
||||
{
|
||||
provide: MatDialogRef, useValue: mockDialogRef
|
||||
provide: MatDialogRef,
|
||||
useValue: mockDialogRef
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -72,12 +70,7 @@ describe('NewVersionUploaderDialog', () => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('Upload New Version', () => {
|
||||
|
||||
const expectedUploadNewVersionTitle = 'ADF-NEW-VERSION-UPLOADER.DIALOG_UPLOAD.TITLE';
|
||||
|
||||
it('should display adf version upload button if showVersionsOnly is passed as false from parent component', () => {
|
||||
@@ -104,7 +97,7 @@ describe('NewVersionUploaderDialog', () => {
|
||||
it('should show default title if title is not provided from parent component', () => {
|
||||
component.data.showVersionsOnly = false;
|
||||
fixture.detectChanges();
|
||||
const matDialogTitle = nativeElement.querySelector(cssSelectors.matDialogTitle);
|
||||
const matDialogTitle = nativeElement.querySelector(cssSelectors.title);
|
||||
expect(matDialogTitle.innerHTML).toEqual(expectedUploadNewVersionTitle);
|
||||
});
|
||||
|
||||
@@ -112,7 +105,7 @@ describe('NewVersionUploaderDialog', () => {
|
||||
component.data.showVersionsOnly = false;
|
||||
component.data.title = '';
|
||||
fixture.detectChanges();
|
||||
const matDialogTitle = nativeElement.querySelector(cssSelectors.matDialogTitle);
|
||||
const matDialogTitle = nativeElement.querySelector(cssSelectors.title);
|
||||
expect(matDialogTitle.innerHTML).toEqual(expectedUploadNewVersionTitle);
|
||||
});
|
||||
|
||||
@@ -120,7 +113,7 @@ describe('NewVersionUploaderDialog', () => {
|
||||
component.data.showVersionsOnly = false;
|
||||
component.data.title = 'TEST_TITLE';
|
||||
fixture.detectChanges();
|
||||
const matDialogTitle = nativeElement.querySelector(cssSelectors.matDialogTitle);
|
||||
const matDialogTitle = nativeElement.querySelector(cssSelectors.title);
|
||||
expect(matDialogTitle.innerHTML).toEqual('TEST_TITLE');
|
||||
});
|
||||
|
||||
@@ -150,11 +143,9 @@ describe('NewVersionUploaderDialog', () => {
|
||||
component.handleCancel();
|
||||
expect(mockDialogRef.close).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Manage Versions', () => {
|
||||
|
||||
const expectedManageVersionsTitle = 'ADF-NEW-VERSION-UPLOADER.DIALOG_LIST.TITLE';
|
||||
|
||||
it('should display adf version list if showVersionsOnly is passed as true from parent component', () => {
|
||||
@@ -182,7 +173,7 @@ describe('NewVersionUploaderDialog', () => {
|
||||
component.data.showVersionsOnly = true;
|
||||
component.data.title = undefined;
|
||||
fixture.detectChanges();
|
||||
const matDialogTitle = nativeElement.querySelector(cssSelectors.matDialogTitle);
|
||||
const matDialogTitle = nativeElement.querySelector(cssSelectors.title);
|
||||
expect(matDialogTitle.innerHTML).toEqual(expectedManageVersionsTitle);
|
||||
});
|
||||
|
||||
@@ -190,7 +181,7 @@ describe('NewVersionUploaderDialog', () => {
|
||||
component.data.showVersionsOnly = true;
|
||||
component.data.title = '';
|
||||
fixture.detectChanges();
|
||||
const matDialogTitle = nativeElement.querySelector(cssSelectors.matDialogTitle);
|
||||
const matDialogTitle = nativeElement.querySelector(cssSelectors.title);
|
||||
expect(matDialogTitle.innerHTML).toEqual(expectedManageVersionsTitle);
|
||||
});
|
||||
|
||||
@@ -198,10 +189,8 @@ describe('NewVersionUploaderDialog', () => {
|
||||
component.data.showVersionsOnly = true;
|
||||
component.data.title = 'TEST_TITLE';
|
||||
fixture.detectChanges();
|
||||
const matDialogTitle = nativeElement.querySelector(cssSelectors.matDialogTitle);
|
||||
const matDialogTitle = nativeElement.querySelector(cssSelectors.title);
|
||||
expect(matDialogTitle.innerHTML).toEqual('TEST_TITLE');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
Reference in New Issue
Block a user