diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.html b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.html index 57f6e2e62d5..5c9522ac86b 100644 --- a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.html +++ b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.html @@ -100,7 +100,9 @@
- {{ tag }} + + {{ tag }} +
{{ 'METADATA.BASIC.NO_TAGS_ADDED' | translate }} diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.scss b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.scss index 918041ac9ee..ca3636fbf0b 100644 --- a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.scss +++ b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.scss @@ -64,17 +64,9 @@ $panel-properties-height: 56px !default; color: var(--adf-theme-foreground-text-color-054); } - .adf-metadata-properties-tag { - min-height: 32px; - display: inline-flex; - align-items: center; - border-radius: 16px; - width: fit-content; + #{$mat-chip} { background: var(--adf-metadata-buttons-background-color); - padding: 6px 12px; - justify-content: center; - margin-left: 8px; - overflow-wrap: anywhere; + padding: 6px; } .adf-metadata-no-item-added { diff --git a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts index fb0cabdc30b..64b1db09665 100644 --- a/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts +++ b/lib/content-services/src/lib/content-metadata/components/content-metadata/content-metadata.component.spec.ts @@ -16,12 +16,22 @@ */ import { ComponentFixture, discardPeriodicTasks, fakeAsync, flush, TestBed, tick } from '@angular/core/testing'; -import { DebugElement, SimpleChange } from '@angular/core'; +import { SimpleChange } from '@angular/core'; import { By } from '@angular/platform-browser'; import { Category, CategoryPaging, ClassesApi, Node, Tag, TagBody, TagEntry, TagPaging, TagPagingList } from '@alfresco/js-api'; import { ContentMetadataComponent } from './content-metadata.component'; import { ContentMetadataService } from '../../services/content-metadata.service'; -import { AppConfigService, AuthModule, CardViewBaseItemModel, CardViewComponent, NotificationService, PipeModule, TranslationMock, TranslationService, UpdateNotification } from '@alfresco/adf-core'; +import { + AppConfigService, + AuthModule, + CardViewBaseItemModel, + CardViewComponent, + NotificationService, + PipeModule, + TranslationMock, + TranslationService, + UpdateNotification +} from '@alfresco/adf-core'; import { NodesApiService } from '../../../common/services/nodes-api.service'; import { EMPTY, of, throwError } from 'rxjs'; import { TranslateModule } from '@ngx-translate/core'; @@ -43,6 +53,8 @@ import { MatDialogModule } from '@angular/material/dialog'; import { MatSnackBarModule } from '@angular/material/snack-bar'; import { MatProgressBarModule } from '@angular/material/progress-bar'; import { MatTooltipModule } from '@angular/material/tooltip'; +import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; +import { MatChipHarness } from '@angular/material/chips/testing'; describe('ContentMetadataComponent', () => { let component: ContentMetadataComponent; @@ -79,7 +91,16 @@ describe('ContentMetadataComponent', () => { const category2 = new Category({ id: 'test2', name: 'testCat2' }); const categoryPagingResponse: CategoryPaging = { list: { pagination: {}, entries: [{ entry: category1 }, { entry: category2 }] } }; - const findTagElements = (): DebugElement[] => fixture.debugElement.queryAll(By.css('.adf-metadata-properties .adf-metadata-properties-tag')); + const findTagElements = async (): Promise => { + const matChipHarnessList = await TestbedHarnessEnvironment.loader(fixture).getAllHarnesses( + MatChipHarness.with({ selector: '[data-automation-id="metadata-properties-tag-chip"]' }) + ); + const tags = []; + for (const matChip of matChipHarnessList) { + tags.push(await matChip.getText()); + } + return tags; + }; const findCancelButton = (): HTMLButtonElement => fixture.debugElement.query(By.css('[data-automation-id=reset-metadata]')).nativeElement; const findCancelTagsButton = (): HTMLButtonElement => @@ -165,15 +186,17 @@ describe('ContentMetadataComponent', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), - NoopAnimationsModule, - AuthModule.forRoot({ useHash: true }), - HttpClientModule, - MatDialogModule, - MatSnackBarModule, - MatProgressBarModule, - MatTooltipModule, - PipeModule], + imports: [ + TranslateModule.forRoot(), + NoopAnimationsModule, + AuthModule.forRoot({ useHash: true }), + HttpClientModule, + MatDialogModule, + MatSnackBarModule, + MatProgressBarModule, + MatTooltipModule, + PipeModule + ], providers: [ { provide: TranslationService, useClass: TranslationMock }, { @@ -286,11 +309,15 @@ describe('ContentMetadataComponent', () => { })); it('should save changedProperties on save click', fakeAsync(() => { - getGroupedPropertiesSpy.and.returnValue(of([{ - editable: true, - title: 'test', - properties: [] - }])); + getGroupedPropertiesSpy.and.returnValue( + of([ + { + editable: true, + title: 'test', + properties: [] + } + ]) + ); updateService.itemUpdated$.next({ changed: {} } as UpdateNotification); @@ -375,7 +402,6 @@ describe('ContentMetadataComponent', () => { sub.unsubscribe(); }); - fixture.detectChanges(); toggleEditModeForGeneralInfo(); fixture.whenStable().then(() => clickOnGeneralInfoSave()); @@ -471,11 +497,15 @@ describe('ContentMetadataComponent', () => { beforeEach(() => { showErrorSpy = spyOn(notificationService, 'showError').and.stub(); - getGroupedPropertiesSpy.and.returnValue(of([{ - editable: true, - title: 'test', - properties: [] - }])); + getGroupedPropertiesSpy.and.returnValue( + of([ + { + editable: true, + title: 'test', + properties: [] + } + ]) + ); component.displayCategories = true; component.displayTags = true; component.ngOnInit(); @@ -623,11 +653,15 @@ describe('ContentMetadataComponent', () => { }); it('should reset group edit ability on reset click', () => { - getGroupedPropertiesSpy.and.returnValue(of([{ - editable: true, - title: 'test', - properties: [] - }])); + getGroupedPropertiesSpy.and.returnValue( + of([ + { + editable: true, + title: 'test', + properties: [] + } + ]) + ); component.ngOnInit(); component.readOnly = false; fixture.detectChanges(); @@ -786,11 +820,15 @@ describe('ContentMetadataComponent', () => { }); it('should reload properties for group panel on cancel', () => { - getGroupedPropertiesSpy.and.returnValue(of([{ - editable: true, - title: 'test', - properties: [] - }])); + getGroupedPropertiesSpy.and.returnValue( + of([ + { + editable: true, + title: 'test', + properties: [] + } + ]) + ); component.ngOnChanges({ node: new SimpleChange(node, expectedNode, false) }); component.readOnly = false; fixture.detectChanges(); @@ -1204,32 +1242,32 @@ describe('ContentMetadataComponent', () => { component.displayTags = true; }); - it('should render tags after loading tags in ngOnInit', () => { + it('should render tags after loading tags in ngOnInit', async () => { spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging)); component.ngOnInit(); fixture.detectChanges(); expandTagsPanel(); - const tagElements = findTagElements(); + const tagElements = await findTagElements(); expect(tagElements).toHaveSize(2); - expect(tagElements[0].nativeElement.textContent).toBe(tagPaging.list.entries[0].entry.tag); - expect(tagElements[1].nativeElement.textContent).toBe(tagPaging.list.entries[1].entry.tag); + expect(tagElements[0]).toBe(tagPaging.list.entries[0].entry.tag); + expect(tagElements[1]).toBe(tagPaging.list.entries[1].entry.tag); expect(tagService.getTagsByNodeId).toHaveBeenCalledWith(node.id); }); - it('should not render tags after loading tags in ngOnInit if displayTags is false', () => { + it('should not render tags after loading tags in ngOnInit if displayTags is false', async () => { component.displayTags = false; spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging)); component.ngOnInit(); fixture.detectChanges(); expandTagsPanel(); - const tagElements = findTagElements(); + const tagElements = await findTagElements(); expect(tagElements).toHaveSize(0); expect(tagService.getTagsByNodeId).not.toHaveBeenCalled(); }); - it('should render tags after loading tags in ngOnChanges', () => { + it('should render tags after loading tags in ngOnChanges', async () => { spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging)); component.ngOnChanges({ @@ -1238,14 +1276,14 @@ describe('ContentMetadataComponent', () => { fixture.detectChanges(); expandTagsPanel(); - const tagElements = findTagElements(); + const tagElements = await findTagElements(); expect(tagElements).toHaveSize(2); - expect(tagElements[0].nativeElement.textContent).toBe(tagPaging.list.entries[0].entry.tag); - expect(tagElements[1].nativeElement.textContent).toBe(tagPaging.list.entries[1].entry.tag); + expect(tagElements[0]).toBe(tagPaging.list.entries[0].entry.tag); + expect(tagElements[1]).toBe(tagPaging.list.entries[1].entry.tag); expect(tagService.getTagsByNodeId).toHaveBeenCalledWith(node.id); }); - it('should not render tags after loading tags in ngOnChanges if displayTags is false', () => { + it('should not render tags after loading tags in ngOnChanges if displayTags is false', async () => { component.displayTags = false; spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging)); component.ngOnChanges({ @@ -1254,23 +1292,23 @@ describe('ContentMetadataComponent', () => { expandTagsPanel(); fixture.detectChanges(); - const tagElements = findTagElements(); + const tagElements = await findTagElements(); expect(tagElements).toHaveSize(0); expect(tagService.getTagsByNodeId).not.toHaveBeenCalled(); }); - it('should not render tags after loading tags in ngOnChanges if node is not changed', () => { + it('should not render tags after loading tags in ngOnChanges if node is not changed', async () => { spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging)); component.ngOnChanges({}); expandTagsPanel(); fixture.detectChanges(); - const tagElements = findTagElements(); + const tagElements = await findTagElements(); expect(tagElements).toHaveSize(0); expect(tagService.getTagsByNodeId).not.toHaveBeenCalled(); }); - it('should not render tags after loading tags in ngOnChanges if node is changed first time', () => { + it('should not render tags after loading tags in ngOnChanges if node is changed first time', async () => { spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging)); component.ngOnChanges({ node: new SimpleChange(undefined, node, true) @@ -1278,12 +1316,12 @@ describe('ContentMetadataComponent', () => { expandTagsPanel(); fixture.detectChanges(); - const tagElements = findTagElements(); + const tagElements = await findTagElements(); expect(tagElements).toHaveSize(0); expect(tagService.getTagsByNodeId).not.toHaveBeenCalled(); }); - it('should render tags after loading tags after clicking on Cancel button', fakeAsync(() => { + it('should render tags after loading tags after clicking on Cancel button', fakeAsync(async () => { component.readOnly = false; fixture.detectChanges(); toggleEditModeForTags(); @@ -1297,14 +1335,14 @@ describe('ContentMetadataComponent', () => { fixture.detectChanges(); expandTagsPanel(); - const tagElements = findTagElements(); + const tagElements = await findTagElements(); expect(tagElements).toHaveSize(2); - expect(tagElements[0].nativeElement.textContent).toBe(tagPaging.list.entries[0].entry.tag); - expect(tagElements[1].nativeElement.textContent).toBe(tagPaging.list.entries[1].entry.tag); + expect(tagElements[0]).toBe(tagPaging.list.entries[0].entry.tag); + expect(tagElements[1]).toBe(tagPaging.list.entries[1].entry.tag); expect(tagService.getTagsByNodeId).toHaveBeenCalledOnceWith(node.id); })); - it('should be hidden when editable is true', () => { + it('should be hidden when editable is true', async () => { spyOn(tagService, 'getTagsByNodeId').and.returnValue(of(tagPaging)); component.ngOnInit(); component.readOnly = false; @@ -1312,7 +1350,7 @@ describe('ContentMetadataComponent', () => { toggleEditModeForTags(); fixture.detectChanges(); - expect(findTagElements()).toHaveSize(0); + expect(await findTagElements()).toHaveSize(0); }); }); diff --git a/lib/content-services/src/lib/tag/tags-creator/tags-creator.component.spec.ts b/lib/content-services/src/lib/tag/tags-creator/tags-creator.component.spec.ts index a54846c990f..ecf8ccb9f27 100644 --- a/lib/content-services/src/lib/tag/tags-creator/tags-creator.component.spec.ts +++ b/lib/content-services/src/lib/tag/tags-creator/tags-creator.component.spec.ts @@ -34,6 +34,8 @@ import { MatListModule } from '@angular/material/list'; import { HarnessLoader } from '@angular/cdk/testing'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { MatProgressSpinnerHarness } from '@angular/material/progress-spinner/testing'; +import { MatChipOptionHarness } from '@angular/material/chips/testing'; +import { MatChipsModule } from '@angular/material/chips'; describe('TagsCreatorComponent', () => { let fixture: ComponentFixture; @@ -53,6 +55,7 @@ describe('TagsCreatorComponent', () => { MatInputModule, MatProgressSpinnerModule, MatListModule, + MatChipsModule, NoopAnimationsModule, ReactiveFormsModule, TranslateModule.forRoot() @@ -121,9 +124,13 @@ describe('TagsCreatorComponent', () => { * * @returns list of tags */ - function getAddedTags(): string[] { - const tagElements = fixture.debugElement.queryAll(By.css(`.adf-tags-creation .adf-tags-chip`)); - return tagElements.map((el) => el.nativeElement.firstChild.nodeValue.trim()); + async function getAddedTags(): Promise { + const matChipHarness = await loader.getAllHarnesses(MatChipOptionHarness.with({ selector: '.adf-tags-chip' })); + const tagElements = []; + for (const matChip of matChipHarness) { + tagElements.push(await matChip.getText()); + } + return tagElements; } /** @@ -179,52 +186,52 @@ describe('TagsCreatorComponent', () => { expect(message).toBe('TAG.TAGS_CREATOR.NO_TAGS_CREATED'); }); - it('should display all tags which have been typed in input and accepted using enter', fakeAsync(() => { + it('should display all tags which have been typed in input and accepted using enter', fakeAsync(async () => { const tag1 = 'Tag 1'; const tag2 = 'Tag 2'; addTagToAddedList(tag1, true); addTagToAddedList(tag2, true); - const tagElements = getAddedTags(); + const tagElements = await getAddedTags(); expect(tagElements.length).toBe(2); expect(tagElements[0]).toBe(tag1); expect(tagElements[1]).toBe(tag2); })); - it('should display all tags which have been typed in input and accepted by clicking at create label', fakeAsync(() => { + it('should display all tags which have been typed in input and accepted by clicking at create label', fakeAsync(async () => { const tag1 = 'Tag 1'; const tag2 = 'Tag 2'; addTagToAddedList(tag1); addTagToAddedList(tag2); - const tagElements = getAddedTags(); + const tagElements = await getAddedTags(); expect(tagElements).toEqual([tag1, tag2]); })); - it('should not add tag if contains only spaces', fakeAsync(() => { + it('should not add tag if contains only spaces', fakeAsync(async () => { addTagToAddedList(' ', true); - expect(getAddedTags().length).toBe(0); + expect((await getAddedTags()).length).toBe(0); })); - it('should not add tag if field is empty', fakeAsync(() => { + it('should not add tag if field is empty', fakeAsync(async () => { addTagToAddedList('', true); - expect(getAddedTags().length).toBe(0); + expect((await getAddedTags()).length).toBe(0); })); - it('should not duplicate already added tag', fakeAsync(() => { + it('should not duplicate already added tag', fakeAsync(async () => { const tag = 'Some tag'; addTagToAddedList(tag, true); addTagToAddedList(tag, true); - expect(getAddedTags().length).toBe(1); + expect((await getAddedTags()).length).toBe(1); })); - it('should not duplicate already existing tag', fakeAsync(() => { + it('should not duplicate already existing tag', fakeAsync(async () => { const tag = 'Tag'; spyOn(tagService, 'findTagByName').and.returnValue( @@ -237,15 +244,15 @@ describe('TagsCreatorComponent', () => { ); addTagToAddedList(tag, true); - expect(getAddedTags().length).toBe(0); + expect((await getAddedTags()).length).toBe(0); })); - it('should not add tag if hit enter during tags loading', fakeAsync(() => { + it('should not add tag if hit enter during tags loading', fakeAsync(async () => { addTagToAddedList('Tag', true, 0); - expect(getAddedTags().length).toBe(0); + expect((await getAddedTags()).length).toBe(0); })); - it('should remove specific tag after clicking at remove icon', fakeAsync(() => { + it('should remove specific tag after clicking at remove icon', fakeAsync(async () => { const tag1 = 'Tag 1'; const tag2 = 'Tag 2'; @@ -257,7 +264,7 @@ describe('TagsCreatorComponent', () => { tick(); fixture.detectChanges(); - const tagElements = getAddedTags(); + const tagElements = await getAddedTags(); expect(tagElements).toEqual([tag2]); })); @@ -281,10 +288,10 @@ describe('TagsCreatorComponent', () => { expect(getRemoveTagButtons()[0].hasAttribute('hidden')).toBeFalse(); })); - it('should display tags passed by tags input', () => { + it('should display tags passed by tags input', async () => { component.tags = ['Passed tag 1', 'Passed tag 2']; fixture.detectChanges(); - expect(getAddedTags()).toEqual(component.tags); + expect(await getAddedTags()).toEqual(component.tags); }); }); @@ -710,7 +717,7 @@ describe('TagsCreatorComponent', () => { expect(component.isOnlyCreateMode()).toBeFalse(); })); - it('should select existing tag when selectionChange event emits', fakeAsync(() => { + it('should select existing tag when selectionChange event emits', fakeAsync(async () => { const selectedTag = { entry: { tag: 'tag1' } as any }; const leftTag = 'tag2'; component.mode = TagsCreatorMode.CREATE_AND_ASSIGN; @@ -728,7 +735,7 @@ describe('TagsCreatorComponent', () => { component.addExistingTagToTagsToAssign(selectedTag); fixture.detectChanges(); - expect(getAddedTags()).toEqual([selectedTag.entry.tag]); + expect(await getAddedTags()).toEqual([selectedTag.entry.tag]); expect(getExistingTags()).toEqual([leftTag]); })); });