From 7db410dd8c70a6ab916ff7a1cdd9f1c66fb11d1d Mon Sep 17 00:00:00 2001 From: musicEnfanthen Date: Tue, 17 Dec 2024 17:53:46 +0100 Subject: [PATCH 1/3] refactor(shared): move WE disclaimer into separate component --- .../disclaimer-workeditions.component.html | 3 + .../disclaimer-workeditions.component.scss | 0 .../disclaimer-workeditions.component.spec.ts | 93 +++++++++++++++++++ .../disclaimer-workeditions.component.ts | 45 +++++++++ src/app/shared/shared.module.ts | 3 + 5 files changed, 144 insertions(+) create mode 100644 src/app/shared/disclaimer-workeditions/disclaimer-workeditions.component.html create mode 100644 src/app/shared/disclaimer-workeditions/disclaimer-workeditions.component.scss create mode 100644 src/app/shared/disclaimer-workeditions/disclaimer-workeditions.component.spec.ts create mode 100644 src/app/shared/disclaimer-workeditions/disclaimer-workeditions.component.ts diff --git a/src/app/shared/disclaimer-workeditions/disclaimer-workeditions.component.html b/src/app/shared/disclaimer-workeditions/disclaimer-workeditions.component.html new file mode 100644 index 0000000000..5a5886c093 --- /dev/null +++ b/src/app/shared/disclaimer-workeditions/disclaimer-workeditions.component.html @@ -0,0 +1,3 @@ + + diff --git a/src/app/shared/disclaimer-workeditions/disclaimer-workeditions.component.scss b/src/app/shared/disclaimer-workeditions/disclaimer-workeditions.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/app/shared/disclaimer-workeditions/disclaimer-workeditions.component.spec.ts b/src/app/shared/disclaimer-workeditions/disclaimer-workeditions.component.spec.ts new file mode 100644 index 0000000000..eb7d26788a --- /dev/null +++ b/src/app/shared/disclaimer-workeditions/disclaimer-workeditions.component.spec.ts @@ -0,0 +1,93 @@ +import { DebugElement, NgModule } from '@angular/core'; +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; + +import { IconDefinition } from '@fortawesome/angular-fontawesome'; +import { FontAwesomeTestingModule } from '@fortawesome/angular-fontawesome/testing'; +import { faCalendarXmark } from '@fortawesome/free-solid-svg-icons'; + +import { NgbConfig, NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap'; + +import { expectToBe, expectToContain, expectToEqual, getAndExpectDebugElementByCss } from '@testing/expect-helper'; + +import { DisclaimerWorkeditionsComponent } from './disclaimer-workeditions.component'; + +describe('DisclaimerWorkeditionsComponent', () => { + let component: DisclaimerWorkeditionsComponent; + let fixture: ComponentFixture; + let compDe: DebugElement; + + let expectedDisclaimer: string; + let expectedFaCalendarXmark: IconDefinition; + + // global NgbConfigModule + @NgModule({ imports: [NgbPopoverModule], exports: [NgbPopoverModule] }) + class NgbConfigModule { + constructor(config: NgbConfig) { + // Set animations to false + config.animation = false; + } + } + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [FontAwesomeTestingModule, NgbConfigModule], + declarations: [DisclaimerWorkeditionsComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DisclaimerWorkeditionsComponent); + component = fixture.componentInstance; + compDe = fixture.debugElement; + + // Test data + expectedDisclaimer = + 'Werkeditionen sind aus rechtlichen Gründen frühestens ab 2049 online verfügbar. Bis dahin konsultieren Sie bitte die entsprechende Printausgabe.'; + expectedFaCalendarXmark = faCalendarXmark; + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('BEFORE initial data binding', () => { + it('... should have `disclaimer`', () => { + expectToEqual(component.disclaimer, expectedDisclaimer); + }); + + it('... should have `faCalendarXmark`', () => { + expectToEqual(component.faCalendarXmark, expectedFaCalendarXmark); + }); + + it('... should have correct NgbPopoverConfig', () => { + expectToBe(component.config.placement, 'top'); + expectToBe(component.config.container, 'body'); + expectToBe(component.config.triggers, 'mouseenter:mouseleave'); + }); + }); + + describe('AFTER initial data binding', () => { + beforeEach(() => { + // Trigger initial data binding + fixture.detectChanges(); + }); + + describe('VIEW', () => { + it('... should contain a text-danger span', () => { + const spanDes = getAndExpectDebugElementByCss(compDe, 'span', 1, 1); + const spanEl: HTMLSpanElement = spanDes[0].nativeElement; + + expectToContain(spanEl.classList, 'text-danger'); + }); + + it('... should contain a fa-icon with Xmark in text-danger span', () => { + const spanDes = getAndExpectDebugElementByCss(compDe, 'span', 1, 1); + + const faIconDes = getAndExpectDebugElementByCss(spanDes[0], 'fa-icon', 1, 1); + const faIconIns = faIconDes[0].componentInstance.icon; + + expectToEqual(faIconIns, expectedFaCalendarXmark); + }); + }); + }); +}); diff --git a/src/app/shared/disclaimer-workeditions/disclaimer-workeditions.component.ts b/src/app/shared/disclaimer-workeditions/disclaimer-workeditions.component.ts new file mode 100644 index 0000000000..1267039fcc --- /dev/null +++ b/src/app/shared/disclaimer-workeditions/disclaimer-workeditions.component.ts @@ -0,0 +1,45 @@ +import { Component } from '@angular/core'; + +import { faCalendarXmark } from '@fortawesome/free-solid-svg-icons'; +import { NgbPopoverConfig } from '@ng-bootstrap/ng-bootstrap'; + +/** + * The DisclaimerWorkeditions component. + * + * It contains the disclaimer for work editions. + */ +@Component({ + selector: 'awg-disclaimer-workeditions', + templateUrl: './disclaimer-workeditions.component.html', + styleUrls: ['./disclaimer-workeditions.component.scss'], +}) +export class DisclaimerWorkeditionsComponent { + /** + * Public variable: disclaimer. + * + * + * It keeps the disclaimer for work editions. + */ + disclaimer = + 'Werkeditionen sind aus rechtlichen Gründen frühestens ab 2049 online verfügbar. Bis dahin konsultieren Sie bitte die entsprechende Printausgabe.'; + + /** + * Public variable: faCalendarXmark. + * + * It instantiates fontawesome's faCalendarXmark icon. + */ + faCalendarXmark = faCalendarXmark; + + /** + * Constructor of the DisclaimerWorkeditionsComponent. + * + * It declares an instance of the NgbPopoverConfig. + * + * @param {NgbPopoverConfig} config Instance of the NgbPopoverConfig. + */ + constructor(public config: NgbPopoverConfig) { + config.placement = 'top'; + config.container = 'body'; + config.triggers = 'mouseenter:mouseleave'; + } +} diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index a1f99e84d6..d911be53b8 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -17,6 +17,7 @@ import { CompileHtmlModule } from './compile-html'; import { AddressComponent } from './address/address.component'; import { AlertErrorComponent } from './alert-error/alert-error.component'; import { AlertInfoComponent } from './alert-info/alert-info.component'; +import { DisclaimerWorkeditionsComponent } from './disclaimer-workeditions/disclaimer-workeditions.component'; import { FullscreenToggleComponent } from './fullscreen-toggle/fullscreen-toggle.component'; import { HeadingComponent } from './heading/heading.component'; import { JsonViewerComponent } from './json-viewer/json-viewer.component'; @@ -63,6 +64,7 @@ import { OrderByPipe } from './order-by-pipe/order-by.pipe'; AddressComponent, AlertErrorComponent, AlertInfoComponent, + DisclaimerWorkeditionsComponent, FullscreenToggleComponent, HeadingComponent, JsonViewerComponent, @@ -96,6 +98,7 @@ import { OrderByPipe } from './order-by-pipe/order-by.pipe'; AddressComponent, AlertErrorComponent, AlertInfoComponent, + DisclaimerWorkeditionsComponent, FullscreenToggleComponent, HeadingComponent, JsonViewerComponent, From 7d6c2897ce16e9d69d51a6f4a330d33b4671c6f4 Mon Sep 17 00:00:00 2001 From: musicEnfanthen Date: Tue, 17 Dec 2024 17:57:28 +0100 Subject: [PATCH 2/3] refactor(edition): use disclaimer component in sheets nav --- .../edition-svg-sheet-nav-item.component.html | 9 +--- ...ition-svg-sheet-nav-item.component.spec.ts | 49 ++++--------------- .../edition-svg-sheet-nav-item.component.ts | 17 ------- 3 files changed, 11 insertions(+), 64 deletions(-) diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.html b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.html index 5812dc4c0b..55da343f49 100644 --- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.html +++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.html @@ -1,14 +1,7 @@
{{ navItemLabel }}: @if (navItemLabel === 'Werkeditionen') { -   - + } @else if (!utils.isNotEmptyArray(svgSheets)) { --- } diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.spec.ts index 0e3153f572..a1f112e2ca 100644 --- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.spec.ts +++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.spec.ts @@ -1,11 +1,7 @@ -import { DebugElement, NgModule } from '@angular/core'; +import { Component, DebugElement } from '@angular/core'; import { ComponentFixture, fakeAsync, TestBed, waitForAsync } from '@angular/core/testing'; import Spy = jasmine.Spy; -import { IconDefinition } from '@fortawesome/angular-fontawesome'; -import { FontAwesomeTestingModule } from '@fortawesome/angular-fontawesome/testing'; -import { faCalendarXmark } from '@fortawesome/free-solid-svg-icons'; - import { clickAndAwaitChanges } from '@testing/click-helper'; import { detectChangesOnPush } from '@testing/detect-changes-on-push-helper'; import { @@ -14,14 +10,18 @@ import { expectToContain, expectToEqual, getAndExpectDebugElementByCss, + getAndExpectDebugElementByDirective, } from '@testing/expect-helper'; import { mockEditionData } from '@testing/mock-data'; import { EditionSvgSheet } from '@awg-views/edition-view/models'; -import { NgbConfig, NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap'; import { EditionSvgSheetNavItemComponent } from './edition-svg-sheet-nav-item.component'; +// Mock components +@Component({ selector: 'awg-disclaimer-workeditions', template: '' }) +class DisclaimerWorkeditionsStubComponent {} + describe('EditionSvgSheetNavItemComponent (DONE)', () => { let component: EditionSvgSheetNavItemComponent; let fixture: ComponentFixture; @@ -31,8 +31,7 @@ describe('EditionSvgSheetNavItemComponent (DONE)', () => { let selectSvgSheetRequestEmitSpy: Spy; let expectedComplexId: string; - let expectedDisclaimerWorkEditions: string; - let expectedFaCalendarXmark: IconDefinition; + let expectedNextComplexId: string; let expectedNavItemLabel: string; let expectedSvgSheets: EditionSvgSheet[]; @@ -43,19 +42,9 @@ describe('EditionSvgSheetNavItemComponent (DONE)', () => { let expectedSvgSheetWithPartialA: EditionSvgSheet; let expectedNextSvgSheet: EditionSvgSheet; - // global NgbConfigModule - @NgModule({ imports: [NgbPopoverModule], exports: [NgbPopoverModule] }) - class NgbConfigModule { - constructor(config: NgbConfig) { - // Set animations to false - config.animation = false; - } - } - beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ - imports: [FontAwesomeTestingModule, NgbConfigModule], - declarations: [EditionSvgSheetNavItemComponent], + declarations: [EditionSvgSheetNavItemComponent, DisclaimerWorkeditionsStubComponent], }).compileComponents(); })); @@ -65,9 +54,6 @@ describe('EditionSvgSheetNavItemComponent (DONE)', () => { compDe = fixture.debugElement; // Test data - expectedDisclaimerWorkEditions = - 'Werkeditionen sind aus rechtlichen Gründen frühestens ab 2049 online verfügbar. Bis dahin konsultieren Sie bitte die entsprechende Printausgabe.'; - expectedFaCalendarXmark = faCalendarXmark; expectedNavItemLabel = 'Testeditionslabel'; expectedComplexId = 'testComplex1'; expectedNextComplexId = 'testComplex2'; @@ -105,14 +91,6 @@ describe('EditionSvgSheetNavItemComponent (DONE)', () => { expect(component.selectedSvgSheet).toBeUndefined(); }); - it('... should have disclaimerWorkEditions', () => { - expectToEqual(component.disclaimerWorkEditions, expectedDisclaimerWorkEditions); - }); - - it('... should have faCalendarXmark', () => { - expectToEqual(component.faCalendarXmark, expectedFaCalendarXmark); - }); - describe('VIEW', () => { it('... should contain 1 h6.card-title without navItemLabel (yet)', () => { const hDes = getAndExpectDebugElementByCss(compDe, 'h6.card-title', 1, 1); @@ -159,20 +137,13 @@ describe('EditionSvgSheetNavItemComponent (DONE)', () => { expectToBe(hEl.textContent.trim(), expectedNavItemLabel + ':'); }); - it('... should contain an text-danger xMark icon if navItemLabel=`Werkeditionen` ', () => { + it('... should contain a DisclaimerWorkeditions component if navItemLabel=`Werkeditionen` ', () => { component.navItemLabel = 'Werkeditionen'; detectChangesOnPush(fixture); const hDes = getAndExpectDebugElementByCss(compDe, 'h6.card-title', 1, 1); - const spanDes = getAndExpectDebugElementByCss(hDes[0], 'span', 1, 1); - const spanEl: HTMLSpanElement = spanDes[0].nativeElement; - - expectToContain(spanEl.classList, 'text-danger'); - - const faIconDes = getAndExpectDebugElementByCss(spanDes[0], 'fa-icon', 1, 1); - const faIconIns = faIconDes[0].componentInstance.icon; - expectToEqual(faIconIns, expectedFaCalendarXmark); + getAndExpectDebugElementByDirective(hDes[0], DisclaimerWorkeditionsStubComponent, 1, 1); }); it('... should contain a span in h6.card-title with "---" if svgSheets is empty', () => { diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.ts index 06b6862c8d..f391cec39e 100644 --- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.ts +++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-sheets/edition-accolade/edition-svg-sheet-nav/edition-svg-sheet-nav-item/edition-svg-sheet-nav-item.component.ts @@ -1,5 +1,4 @@ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; -import { faCalendarXmark } from '@fortawesome/free-solid-svg-icons'; import { UtilityService } from '@awg-core/services'; import { EditionSvgSheet } from '@awg-views/edition-view/models'; @@ -50,22 +49,6 @@ export class EditionSvgSheetNavItemComponent { @Output() selectSvgSheetRequest: EventEmitter<{ complexId: string; sheetId: string }> = new EventEmitter(); - /** - * Public variable: disclaimerWorkEditions. - * - * - * It keeps the disclaimer for work editions. - */ - disclaimerWorkEditions = - 'Werkeditionen sind aus rechtlichen Gründen frühestens ab 2049 online verfügbar. Bis dahin konsultieren Sie bitte die entsprechende Printausgabe.'; - - /** - * Public variable: faCalendarXmark. - * - * It instantiates fontawesome's faCalendarXmark icon. - */ - faCalendarXmark = faCalendarXmark; - /** * Constructor of the EditionSvgSheetNavItemComponent. * From bd19a5849a714be4fc76c4af4305fab41a8597b0 Mon Sep 17 00:00:00 2001 From: musicEnfanthen Date: Tue, 17 Dec 2024 18:05:52 +0100 Subject: [PATCH 3/3] feat(edition): add disclaimer button to WE textcritics --- .../textcritics-list.component.html | 22 +- .../textcritics-list.component.spec.ts | 259 ++++++++++++++---- .../textcritics-list.component.ts | 15 + 3 files changed, 231 insertions(+), 65 deletions(-) diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.html b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.html index 1c7b4fc149..3204e85cd3 100644 --- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.html +++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.html @@ -1,6 +1,6 @@ @if (textcriticsData) {
- @for (textcritics of textcriticsData.textcritics; track textcritics) { + @for (textcritics of textcriticsData.textcritics; track textcritics.id) {
diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.spec.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.spec.ts index 153fbfd955..3698e71bc7 100644 --- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.spec.ts +++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.spec.ts @@ -24,6 +24,9 @@ import { TextcriticalCommentBlock, TextcriticsList } from '@awg-views/edition-vi import { TextcriticsListComponent } from './textcritics-list.component'; // Mock components +@Component({ selector: 'awg-disclaimer-workeditions', template: '' }) +class DisclaimerWorkeditionsStubComponent {} + @Component({ selector: 'awg-edition-tka-description', template: '' }) class EditionTkaDescriptionStubComponent { @Input() @@ -98,6 +101,7 @@ describe('TextcriticsListComponent (DONE)', () => { declarations: [ TextcriticsListComponent, CompileHtmlComponent, + DisclaimerWorkeditionsStubComponent, EditionTkaDescriptionStubComponent, EditionTkaLabelStubComponent, EditionTkaTableStubComponent, @@ -172,14 +176,16 @@ describe('TextcriticsListComponent (DONE)', () => { getAndExpectDebugElementByCss(compDe, 'div.accordion', 1, 1); }); - it('... should contain two items in div.accordion', () => { + it('... should contain as many items in div.accordion as there are textcritics', () => { + const totalItems = expectedTextcriticsData.textcritics.length; const accordionDes = getAndExpectDebugElementByCss(compDe, 'div.accordion', 1, 1); - getAndExpectDebugElementByCss(accordionDes[0], 'div.accordion-item', 2, 2); + getAndExpectDebugElementByCss(accordionDes[0], 'div.accordion-item', totalItems, totalItems); }); it('... should contain item header with collapsed body', () => { - const itemDes = getAndExpectDebugElementByCss(compDe, 'div.accordion-item', 2, 2); + const totalItems = expectedTextcriticsData.textcritics.length; + const itemDes = getAndExpectDebugElementByCss(compDe, 'div.accordion-item', totalItems, totalItems); getAndExpectDebugElementByCss( itemDes[0], @@ -213,8 +219,9 @@ describe('TextcriticsListComponent (DONE)', () => { expectToContain(itemBodyEl2.classList, 'collapse'); }); - it('... should contain CompileHtmlComponent in first item header button', () => { - const itemDes = getAndExpectDebugElementByCss(compDe, 'div.accordion-item', 2, 2); + it('... should contain an item header button with CompileHtmlComponent', () => { + const totalItems = expectedTextcriticsData.textcritics.length; + const itemDes = getAndExpectDebugElementByCss(compDe, 'div.accordion-item', totalItems, totalItems); itemDes.forEach((itemDe, index) => { const itemHeaderDes = getAndExpectDebugElementByCss( @@ -227,15 +234,16 @@ describe('TextcriticsListComponent (DONE)', () => { const btnDes = getAndExpectDebugElementByCss( itemHeaderDes[0], 'div.accordion-button > button.btn', - 2, - 2 + 1, + 1 ); getAndExpectDebugElementByDirective(btnDes[0], CompileHtmlComponent, 1, 1); }); }); - it('... should display item header buttons', () => { - const itemDes = getAndExpectDebugElementByCss(compDe, 'div.accordion-item', 2, 2); + it('... should display item header button', () => { + const totalItems = expectedTextcriticsData.textcritics.length; + const itemDes = getAndExpectDebugElementByCss(compDe, 'div.accordion-item', totalItems, totalItems); itemDes.forEach((itemDe, index) => { const itemHeaderDes = getAndExpectDebugElementByCss( @@ -248,27 +256,123 @@ describe('TextcriticsListComponent (DONE)', () => { const btnDes = getAndExpectDebugElementByCss( itemHeaderDes[0], 'div.accordion-button > button.btn', - 2, - 2 + 1, + 1 ); - const btnEl0: HTMLButtonElement = btnDes[0].nativeElement; - const btnEl1: HTMLButtonElement = btnDes[1].nativeElement; + const btnEl: HTMLButtonElement = btnDes[0].nativeElement; + + const expectedButtonLabel = mockDocument.createElement('span'); + expectedButtonLabel.innerHTML = expectedTextcriticsData.textcritics[index].label; + + expect(btnEl).toHaveClass('text-start'); + expectToBe(btnEl.textContent.trim(), expectedButtonLabel.textContent.trim()); + }); + }); + + it('... should contain a button group with sheet button', () => { + const totalItems = expectedTextcriticsData.textcritics.length; + const itemDes = getAndExpectDebugElementByCss(compDe, 'div.accordion-item', totalItems, totalItems); + + itemDes.forEach((itemDe, index) => { + const itemHeaderDes = getAndExpectDebugElementByCss( + itemDe, + `div#${expectedTextcriticsData.textcritics[index].id} > div.accordion-header`, + 1, + 1 + ); + + const btnGrpDes = getAndExpectDebugElementByCss( + itemHeaderDes[0], + 'div.accordion-button > div.btn-group', + 1, + 1 + ); + const btnDes = getAndExpectDebugElementByCss(btnGrpDes[0], 'button.btn', 1, 1); + const btnEl: HTMLButtonElement = btnDes[0].nativeElement; + + const expectedButtonLabel = 'Zum edierten Notentext'; + + expect(btnEl).toHaveClass('btn-outline-info'); + expectToBe(btnEl.disabled, false); + expectToBe(btnEl.textContent.trim(), expectedButtonLabel); + }); + }); + + describe('... if textcritics are related to work edition', () => { + let textcriticsDataWithWorkEdition: TextcriticsList; + + beforeEach(() => { + textcriticsDataWithWorkEdition = JSON.parse(JSON.stringify(expectedTextcriticsData)); + textcriticsDataWithWorkEdition.textcritics[0].id = 'op12_WE'; + textcriticsDataWithWorkEdition.textcritics[1].id = 'op25_WE'; - const expectedButtonLabel0 = mockDocument.createElement('span'); - expectedButtonLabel0.innerHTML = expectedTextcriticsData.textcritics[index].label; + component.textcriticsData = textcriticsDataWithWorkEdition; + detectChangesOnPush(fixture); + }); - const expectedButtonLabel1 = 'Zum edierten Notentext'; + it('... should contain another button with DisclaimerWorkeditions component in button group ', () => { + const totalItems = expectedTextcriticsData.textcritics.length; + const itemDes = getAndExpectDebugElementByCss(compDe, 'div.accordion-item', totalItems, totalItems); - expect(btnEl0).toHaveClass('text-start'); - expectToBe(btnEl0.textContent.trim(), expectedButtonLabel0.textContent.trim()); + itemDes.forEach((itemDe, index) => { + const itemHeaderDes = getAndExpectDebugElementByCss( + itemDe, + `div#${textcriticsDataWithWorkEdition.textcritics[index].id} > div.accordion-header`, + 1, + 1 + ); - expect(btnEl1).toHaveClass('btn-outline-info'); - expectToBe(btnEl1.textContent.trim(), expectedButtonLabel1); + const btnGrpDes = getAndExpectDebugElementByCss( + itemHeaderDes[0], + 'div.accordion-button > div.btn-group', + 1, + 1 + ); + const btnDes = getAndExpectDebugElementByCss(btnGrpDes[0], 'button.btn', 2, 2); + const btnEl1: HTMLButtonElement = btnDes[1].nativeElement; + const expectedButtonLabel = 'Zum edierten Notentext'; + + getAndExpectDebugElementByDirective(btnDes[0], DisclaimerWorkeditionsStubComponent, 1, 1); + + expect(btnEl1).toHaveClass('btn-outline-info'); + expectToBe(btnEl1.textContent.trim(), expectedButtonLabel); + }); + }); + + it('... should disable sheet button', () => { + const totalItems = expectedTextcriticsData.textcritics.length; + const itemDes = getAndExpectDebugElementByCss(compDe, 'div.accordion-item', totalItems, totalItems); + + itemDes.forEach((itemDe, index) => { + const itemHeaderDes = getAndExpectDebugElementByCss( + itemDe, + `div#${textcriticsDataWithWorkEdition.textcritics[index].id} > div.accordion-header`, + 1, + 1 + ); + + const btnGrpDes = getAndExpectDebugElementByCss( + itemHeaderDes[0], + 'div.accordion-button > div.btn-group', + 1, + 1 + ); + const btnDes = getAndExpectDebugElementByCss(btnGrpDes[0], 'button.btn', 2, 2); + const btnEl1: HTMLButtonElement = btnDes[1].nativeElement; + const expectedButtonLabel = 'Zum edierten Notentext'; + + getAndExpectDebugElementByDirective(btnDes[0], DisclaimerWorkeditionsStubComponent, 1, 1); + + expect(btnEl1).toHaveClass('btn-outline-info'); + expectToBe(btnEl1.disabled, true); + expectToBe(btnEl1.textContent.trim(), expectedButtonLabel); + }); }); }); it('... should toggle first item body on click on first header', () => { - const itemDes = getAndExpectDebugElementByCss(compDe, 'div.accordion-item', 2, 2); + const totalItems = expectedTextcriticsData.textcritics.length; + const itemDes = getAndExpectDebugElementByCss(compDe, 'div.accordion-item', totalItems, totalItems); const headerDes0 = getAndExpectDebugElementByCss( itemDes[0], @@ -277,7 +381,7 @@ describe('TextcriticsListComponent (DONE)', () => { 1 ); - const btnDes = getAndExpectDebugElementByCss(headerDes0[0], 'div.accordion-button > button.btn', 2, 2); + const btnDes = getAndExpectDebugElementByCss(headerDes0[0], 'div.accordion-button > button.btn', 1, 1); const btnEl: HTMLButtonElement = btnDes[0].nativeElement; // Item body is closed @@ -326,7 +430,8 @@ describe('TextcriticsListComponent (DONE)', () => { }); it('... should toggle second item body on click on second header', () => { - const itemDes = getAndExpectDebugElementByCss(compDe, 'div.accordion-item', 2, 2); + const totalItems = expectedTextcriticsData.textcritics.length; + const itemDes = getAndExpectDebugElementByCss(compDe, 'div.accordion-item', totalItems, totalItems); const headerDes1 = getAndExpectDebugElementByCss( itemDes[1], @@ -335,7 +440,7 @@ describe('TextcriticsListComponent (DONE)', () => { 1 ); - const btnDes = getAndExpectDebugElementByCss(headerDes1[0], 'div.accordion-button > button.btn', 2, 2); + const btnDes = getAndExpectDebugElementByCss(headerDes1[0], 'div.accordion-button > button.btn', 1, 1); const btnEl: HTMLButtonElement = btnDes[0].nativeElement; // Item body is closed @@ -402,14 +507,14 @@ describe('TextcriticsListComponent (DONE)', () => { const btnDes0 = getAndExpectDebugElementByCss( headerDes0[0], 'div.accordion-button > button.btn', - 2, - 2 + 1, + 1 ); const btnDes1 = getAndExpectDebugElementByCss( headerDes1[0], 'div.accordion-button > button.btn', - 2, - 2 + 1, + 1 ); const btnEl0: HTMLButtonElement = btnDes0[0].nativeElement; const btnEl1: HTMLButtonElement = btnDes1[0].nativeElement; @@ -702,6 +807,44 @@ describe('TextcriticsListComponent (DONE)', () => { }); }); + describe('#isWorkEditionId()', () => { + it('... should have a method `isWorkEditionId`', () => { + expect(component.isWorkEditionId).toBeDefined(); + }); + + describe('... should return false if', () => { + it('... id is undefined', () => { + const result = component.isWorkEditionId(undefined); + + expect(result).toBeFalse(); + }); + + it('... id is null', () => { + const result = component.isWorkEditionId(null); + + expect(result).toBeFalse(); + }); + + it('... id is empty string', () => { + const result = component.isWorkEditionId(''); + + expect(result).toBeFalse(); + }); + + it('... id is not a work edition id', () => { + const result = component.isWorkEditionId('test_id'); + + expect(result).toBeFalse(); + }); + }); + + it('... should return true if id is a work edition id', () => { + const result = component.isWorkEditionId('op12_WE'); + + expect(result).toBeTrue(); + }); + }); + describe('#navigateToReportFragment()', () => { it('... should have a method `navigateToReportFragment`', () => { expect(component.navigateToReportFragment).toBeDefined(); @@ -717,16 +860,16 @@ describe('TextcriticsListComponent (DONE)', () => { 1 ); - const btnDes1 = getAndExpectDebugElementByCss( + const btnDes = getAndExpectDebugElementByCss( headerDes1[0], 'div.accordion-button > button.btn', - 2, - 2 + 1, + 1 ); - const btnEl1: HTMLButtonElement = btnDes1[0].nativeElement; + const btnEl: HTMLButtonElement = btnDes[0].nativeElement; // Click header buttons to open body - click(btnEl1 as HTMLElement); + click(btnEl as HTMLElement); detectChangesOnPush(fixture); const editionTkaDescriptionDes = getAndExpectDebugElementByDirective( @@ -755,16 +898,16 @@ describe('TextcriticsListComponent (DONE)', () => { 1 ); - const btnDes1 = getAndExpectDebugElementByCss( + const btnDes = getAndExpectDebugElementByCss( headerDes1[0], 'div.accordion-button > button.btn', - 2, - 2 + 1, + 1 ); - const btnEl1: HTMLButtonElement = btnDes1[0].nativeElement; + const btnEl: HTMLButtonElement = btnDes[0].nativeElement; // Click header buttons to open body - click(btnEl1 as HTMLElement); + click(btnEl as HTMLElement); detectChangesOnPush(fixture); const editionTkaTableDes = getAndExpectDebugElementByDirective( @@ -855,16 +998,16 @@ describe('TextcriticsListComponent (DONE)', () => { 1 ); - const btnDes1 = getAndExpectDebugElementByCss( + const btnDes = getAndExpectDebugElementByCss( headerDes1[0], 'div.accordion-button > button.btn', - 2, - 2 + 1, + 1 ); - const btnEl1: HTMLButtonElement = btnDes1[0].nativeElement; + const btnEl: HTMLButtonElement = btnDes[0].nativeElement; // Click header buttons to open body - click(btnEl1 as HTMLElement); + click(btnEl as HTMLElement); detectChangesOnPush(fixture); const editionTkaDescriptionDes = getAndExpectDebugElementByDirective( @@ -891,16 +1034,16 @@ describe('TextcriticsListComponent (DONE)', () => { 1 ); - const btnDes1 = getAndExpectDebugElementByCss( + const btnDes = getAndExpectDebugElementByCss( headerDes1[0], 'div.accordion-button > button.btn', - 2, - 2 + 1, + 1 ); - const btnEl1: HTMLButtonElement = btnDes1[0].nativeElement; + const btnEl: HTMLButtonElement = btnDes[0].nativeElement; // Click header buttons to open body - click(btnEl1 as HTMLElement); + click(btnEl as HTMLElement); detectChangesOnPush(fixture); const editionTkaTableDes = getAndExpectDebugElementByDirective( @@ -960,16 +1103,16 @@ describe('TextcriticsListComponent (DONE)', () => { 1 ); - const btnDes1 = getAndExpectDebugElementByCss( + const btnDes = getAndExpectDebugElementByCss( headerDes1[0], 'div.accordion-button > button.btn', - 2, - 2 + 1, + 1 ); - const btnEl1: HTMLButtonElement = btnDes1[0].nativeElement; + const btnEl: HTMLButtonElement = btnDes[0].nativeElement; // Click header buttons to open body - click(btnEl1 as HTMLElement); + click(btnEl as HTMLElement); detectChangesOnPush(fixture); const editionTkaDescriptionDes = getAndExpectDebugElementByDirective( @@ -997,16 +1140,16 @@ describe('TextcriticsListComponent (DONE)', () => { 1 ); - const btnDes1 = getAndExpectDebugElementByCss( + const btnDes = getAndExpectDebugElementByCss( headerDes1[0], 'div.accordion-button > button.btn', - 2, - 2 + 1, + 1 ); - const btnEl1: HTMLButtonElement = btnDes1[0].nativeElement; + const btnEl: HTMLButtonElement = btnDes[0].nativeElement; // Click header buttons to open body - click(btnEl1 as HTMLElement); + click(btnEl as HTMLElement); detectChangesOnPush(fixture); const editionTkaTableDes = getAndExpectDebugElementByDirective( diff --git a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.ts b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.ts index 0a04cdac7b..9527a7e400 100644 --- a/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.ts +++ b/src/app/views/edition-view/edition-outlets/edition-complex/edition-detail/edition-report/textcritics-list/textcritics-list.component.ts @@ -67,6 +67,21 @@ export class TextcriticsListComponent { this.ref = this; } + /** + * Public method: isWorkEditionId. + * + * It checks if the given id is a work edition id. + * + * @param {string} id The given id. + * @returns {boolean} The result of the check. + */ + isWorkEditionId(id: string): boolean { + if (!id) { + return false; + } + return id.includes('_WE'); + } + /** * Public method: navigateToReportFragment. *