diff --git a/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping-form.e2e.component.ts b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping-form.e2e.component.ts index 2545b8b6b63d5c3f5b8a47ebcddbc8e03af46a6e..e140ef04867eeb97212c840b44e44535696422e4 100644 --- a/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping-form.e2e.component.ts +++ b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping-form.e2e.component.ts @@ -1,5 +1,6 @@ export class AggregationMappingFormE2EComponent { - private readonly rootElement: string = 'aggregation-mapping-form'; + private readonly root: string = 'aggregation-mapping-form'; + private readonly nameInput: string = 'aggregation-mapping-name-text-input'; private readonly formEngineInput: string = 'form-engine-name-text-input'; private readonly formIdInput: string = 'form-id-text-input'; @@ -11,8 +12,8 @@ export class AggregationMappingFormE2EComponent { private readonly saveButton: string = 'save-button'; private readonly cancelButton: string = 'cancel-button'; - public getRootElement(): Cypress.Chainable<Element> { - return cy.getTestElement(this.rootElement); + public getRoot(): Cypress.Chainable<Element> { + return cy.getTestElement(this.root); } public getNameInput(): Cypress.Chainable<Element> { diff --git a/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping.e2e.component.ts b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping.e2e.component.ts index 10e67b06e5b45984cdb19be1ab4ee33595cbbf21..69df7bcedef6c8927a65f0e24873afc3d6c54bbb 100644 --- a/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping.e2e.component.ts +++ b/alfa-client/apps/admin-e2e/src/components/aggregation-mapping/aggregation-mapping.e2e.component.ts @@ -1,27 +1,47 @@ +import { getTestElement } from '../../support/cypress-helper'; +import { convertToDataTestId } from '../../support/tech-util'; + export class AggregationMappingE2EComponent { private readonly headerText: string = 'aggregation-mapping-header-text'; - private readonly listItemName: string = 'list-item-name'; - private readonly listItemFormEngineName: string = 'list-item-form-engine-name'; - private readonly listItemFormId: string = 'list-item-form-id'; private readonly weitereFelderAuswertenButton = 'weitere-felder-auswerten-button'; public getHeaderText(): Cypress.Chainable<Element> { return cy.getTestElement(this.headerText); } - public getListItemName(): Cypress.Chainable<Element> { - return cy.getTestElementWithClass(this.listItemName); + public getWeitereFelderAuswertenButton(): Cypress.Chainable<Element> { + return cy.getTestElement(this.weitereFelderAuswertenButton); + } + + public getListItem(name: string): AggregationMappingListItemE2EComponent { + return new AggregationMappingListItemE2EComponent(name); + } +} + +export class AggregationMappingListItemE2EComponent { + private root: string; + + private readonly listItemName: string = 'list-item-name'; + private readonly listItemFormEngineName: string = 'list-item-form-engine-name'; + private readonly listItemFormId: string = 'list-item-form-id'; + + constructor(root: string) { + this.root = convertToDataTestId(root); } - public getListItemFormEngineName(): Cypress.Chainable<Element> { - return cy.getTestElementWithClass(this.listItemFormEngineName); + public getRoot(): Cypress.Chainable<Element> { + return getTestElement(this.root); } - public getListItemFormId(): Cypress.Chainable<Element> { - return cy.getTestElementWithClass(this.listItemFormId); + public getName(): Cypress.Chainable<Element> { + return this.getRoot().findTestElementWithClass(this.listItemName); } - public getWeitereFelderAuswertenButton(): Cypress.Chainable<Element> { - return cy.getTestElement(this.weitereFelderAuswertenButton); + public getFormEngineName(): Cypress.Chainable<Element> { + return this.getRoot().findTestElementWithClass(this.listItemFormEngineName); + } + + public getFormId(): Cypress.Chainable<Element> { + return this.getRoot().findTestElementWithClass(this.listItemFormId); } } diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts index e1a594ff31d79d36cbe0e4ebdf240d90177f0f10..ffabc87021d990125ddb5402cac4244d4dc2fa6b 100644 --- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts +++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/aggregation-mapping/aggregation-mapping.cy.ts @@ -1,4 +1,5 @@ import { AggregationMapping, FieldMapping } from '@admin-client/reporting-shared'; +import { E2EAggregationMappingVerifier } from 'apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.verifier'; import { AggregationMappingFormE2EComponent } from '../../../components/aggregation-mapping/aggregation-mapping-form.e2e.component'; import { AggregationMappingE2EComponent } from '../../../components/aggregation-mapping/aggregation-mapping.e2e.component'; import { E2EAggregationMappingHelper } from '../../../helper/aggregation-mapping/aggregation-mapping.helper'; @@ -7,10 +8,11 @@ import { exist, notExist } from '../../../support/cypress.util'; import { loginAsDaria } from '../../../support/user-util'; describe('Aggregation Mapping hinzufügen', () => { - const component: AggregationMappingE2EComponent = new AggregationMappingE2EComponent(); - const formComponent: AggregationMappingFormE2EComponent = new AggregationMappingFormE2EComponent(); + const page: AggregationMappingE2EComponent = new AggregationMappingE2EComponent(); + const form: AggregationMappingFormE2EComponent = new AggregationMappingFormE2EComponent(); const helper: E2EAggregationMappingHelper = new E2EAggregationMappingHelper(); + const verifier: E2EAggregationMappingVerifier = new E2EAggregationMappingVerifier(); const fieldMapping0: FieldMapping = { sourcePath: '/path/to/source/a', @@ -40,43 +42,45 @@ describe('Aggregation Mapping hinzufügen', () => { }); it('should show "Weitere Felder auswerten" button', () => { - exist(component.getWeitereFelderAuswertenButton()); + helper.openStatistik(); + + exist(page.getWeitereFelderAuswertenButton()); }); it('should show form after button click', () => { - component.getWeitereFelderAuswertenButton().click(); + page.getWeitereFelderAuswertenButton().click(); - exist(formComponent.getRootElement()); + exist(form.getRoot()); }); it('should navigate to aggregation mapping on cancel', () => { - formComponent.getCancelButton().click(); + form.getCancelButton().click(); - exist(component.getWeitereFelderAuswertenButton()); + exist(page.getWeitereFelderAuswertenButton()); }); it('should add data field in form', () => { - component.getWeitereFelderAuswertenButton().click(); - formComponent.getAddFieldButton().click(); + page.getWeitereFelderAuswertenButton().click(); + form.getAddFieldButton().click(); - exist(formComponent.getDataFieldInput(1)); + exist(form.getDataFieldInput(1)); }); it('should fill out form with two data fields', () => { - helper.enterForm(aggregationMapping); + helper.fillFormular(aggregationMapping); - helper.verifyForm(aggregationMapping); + verifier.verifyForm(aggregationMapping); }); it('should delete data fields', () => { - formComponent.getDataFieldDeleteButton(0).click(); + form.getDataFieldDeleteButton(0).click(); - notExist(formComponent.getDataFieldInput(1)); + notExist(form.getDataFieldInput(1)); }); it('should show aggregation mapping in list after save', () => { - formComponent.getSaveButton().click(); + form.getSaveButton().click(); - helper.verifyAggregationMappingInList(aggregationMapping); + verifier.verifyAggregationMappingInList(aggregationMapping); }); }); diff --git a/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.executor.ts b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.executor.ts new file mode 100644 index 0000000000000000000000000000000000000000..7e9b392696e1839765a8d8c6668722db0bffd262 --- /dev/null +++ b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.executor.ts @@ -0,0 +1,22 @@ +import { AggregationMapping, FieldMapping } from '@admin-client/reporting-shared'; +import { AggregationMappingFormE2EComponent } from '../../components/aggregation-mapping/aggregation-mapping-form.e2e.component'; +import { enterWith } from '../../support/cypress.util'; + +export class E2EAggregationMappingExecutor { + private formComponent: AggregationMappingFormE2EComponent = new AggregationMappingFormE2EComponent(); + + public fillFormular(aggregationMapping: AggregationMapping): void { + enterWith(this.formComponent.getNameInput(), aggregationMapping.name); + enterWith(this.formComponent.getFormEngineInput(), aggregationMapping.formIdentifier.formEngineName); + enterWith(this.formComponent.getFormIdInput(), aggregationMapping.formIdentifier.formId); + + aggregationMapping.mappings.forEach((fieldMapping, index) => { + this.enterFieldMapping(fieldMapping, index); + }); + } + + private enterFieldMapping(fieldMapping: FieldMapping, index: number): void { + enterWith(this.formComponent.getSourceMappingFieldInput(index), fieldMapping.sourcePath); + enterWith(this.formComponent.getTargetMappingFieldInput(index), fieldMapping.targetPath); + } +} diff --git a/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.helper.ts b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.helper.ts index b36249dc2f9ef1a5e4ecf0d36a2bc17f7f61f7f5..b39a391240e6a139c1f9df4e673e4e3ccda6e3e8 100644 --- a/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.helper.ts +++ b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.helper.ts @@ -1,65 +1,16 @@ -import { AggregationMapping, FieldMapping } from '@admin-client/reporting-shared'; -import { AggregationMappingFormE2EComponent } from '../../components/aggregation-mapping/aggregation-mapping-form.e2e.component'; -import { AggregationMappingE2EComponent } from '../../components/aggregation-mapping/aggregation-mapping.e2e.component'; -import { enterWith, haveText, haveValue } from '../../support/cypress.util'; +import { AggregationMapping } from '@admin-client/reporting-shared'; +import { E2EAggregationMappingExecutor } from './aggregation-mapping.executor'; +import { E2EAggregationMapperNavigator } from './aggregation-mapping.navigator'; export class E2EAggregationMappingHelper { - private component: AggregationMappingE2EComponent = new AggregationMappingE2EComponent(); - private formComponent: AggregationMappingFormE2EComponent = new AggregationMappingFormE2EComponent(); + private readonly navigator: E2EAggregationMapperNavigator = new E2EAggregationMapperNavigator(); + private readonly executor: E2EAggregationMappingExecutor = new E2EAggregationMappingExecutor(); - public enterName(text: string): void { - enterWith(this.formComponent.getNameInput(), text); + public openStatistik(): void { + this.navigator.openStatistik(); } - public enterFormEngine(text: string): void { - enterWith(this.formComponent.getFormEngineInput(), text); - } - - public enterFormId(text: string): void { - enterWith(this.formComponent.getFormIdInput(), text); - } - - public enterSourcePath(text: string, index: number): void { - enterWith(this.formComponent.getSourceMappingFieldInput(index), text); - } - - public enterTargetPath(text: string, index: number): void { - enterWith(this.formComponent.getTargetMappingFieldInput(index), text); - } - - public enterFieldMapping(fieldMapping: FieldMapping, index: number): void { - this.enterSourcePath(fieldMapping.sourcePath, index); - this.enterTargetPath(fieldMapping.targetPath, index); - } - - public enterForm(aggregationMapping: AggregationMapping): void { - this.enterName(aggregationMapping.name); - this.enterFormEngine(aggregationMapping.formIdentifier.formEngineName); - this.enterFormId(aggregationMapping.formIdentifier.formId); - - aggregationMapping.mappings.forEach((fieldMapping, index) => { - this.enterFieldMapping(fieldMapping, index); - }); - } - - public verifyFieldMapping(fieldMapping: FieldMapping, index: number): void { - haveValue(this.formComponent.getSourceMappingFieldInput(index), fieldMapping.sourcePath); - haveValue(this.formComponent.getTargetMappingFieldInput(index), fieldMapping.targetPath); - } - - public verifyForm(aggregationMapping: AggregationMapping): void { - haveValue(this.formComponent.getNameInput(), aggregationMapping.name); - haveValue(this.formComponent.getFormEngineInput(), aggregationMapping.formIdentifier.formEngineName); - haveValue(this.formComponent.getFormIdInput(), aggregationMapping.formIdentifier.formId); - - aggregationMapping.mappings.forEach((fieldMapping, index) => { - this.verifyFieldMapping(fieldMapping, index); - }); - } - - public verifyAggregationMappingInList(aggregationMapping: AggregationMapping): void { - haveText(this.component.getListItemName(), aggregationMapping.name); - haveText(this.component.getListItemFormEngineName(), aggregationMapping.formIdentifier.formEngineName); - haveText(this.component.getListItemFormId(), aggregationMapping.formIdentifier.formId); + public fillFormular(aggregationMapping: AggregationMapping): void { + this.executor.fillFormular(aggregationMapping); } } diff --git a/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.navigator.ts b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.navigator.ts new file mode 100644 index 0000000000000000000000000000000000000000..f82cc547926244caca1d78afeb30be3a843b665e --- /dev/null +++ b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.navigator.ts @@ -0,0 +1,18 @@ +import { AggregationMappingE2EComponent } from '../../components/aggregation-mapping/aggregation-mapping.e2e.component'; +import { MainPage } from '../../page-objects/main.po'; +import { exist } from '../../support/cypress.util'; +import { E2EAppHelper } from '../app.helper'; + +export class E2EAggregationMapperNavigator { + private readonly appHelper: E2EAppHelper = new E2EAppHelper(); + + private readonly mainPage: MainPage = new MainPage(); + + private readonly aggregationMappingPage: AggregationMappingE2EComponent = new AggregationMappingE2EComponent(); + + public openStatistik(): void { + this.appHelper.navigateToDomain(); + this.mainPage.getStatistikNavigationItem().click(); + exist(this.aggregationMappingPage.getHeaderText()); + } +} diff --git a/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.verifier.ts b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.verifier.ts new file mode 100644 index 0000000000000000000000000000000000000000..df93defea446b90102747c7af9ddd41edb254e59 --- /dev/null +++ b/alfa-client/apps/admin-e2e/src/helper/aggregation-mapping/aggregation-mapping.verifier.ts @@ -0,0 +1,34 @@ +import { AggregationMapping, FieldMapping } from '@admin-client/reporting-shared'; +import { AggregationMappingFormE2EComponent } from '../../components/aggregation-mapping/aggregation-mapping-form.e2e.component'; +import { + AggregationMappingE2EComponent, + AggregationMappingListItemE2EComponent, +} from '../../components/aggregation-mapping/aggregation-mapping.e2e.component'; +import { haveText, haveValue } from '../../support/cypress.util'; + +export class E2EAggregationMappingVerifier { + private component: AggregationMappingE2EComponent = new AggregationMappingE2EComponent(); + private formComponent: AggregationMappingFormE2EComponent = new AggregationMappingFormE2EComponent(); + + public verifyFieldMapping(fieldMapping: FieldMapping, index: number): void { + haveValue(this.formComponent.getSourceMappingFieldInput(index), fieldMapping.sourcePath); + haveValue(this.formComponent.getTargetMappingFieldInput(index), fieldMapping.targetPath); + } + + public verifyForm(aggregationMapping: AggregationMapping): void { + haveValue(this.formComponent.getNameInput(), aggregationMapping.name); + haveValue(this.formComponent.getFormEngineInput(), aggregationMapping.formIdentifier.formEngineName); + haveValue(this.formComponent.getFormIdInput(), aggregationMapping.formIdentifier.formId); + + aggregationMapping.mappings.forEach((fieldMapping, index) => { + this.verifyFieldMapping(fieldMapping, index); + }); + } + + public verifyAggregationMappingInList(aggregationMapping: AggregationMapping): void { + const listItem: AggregationMappingListItemE2EComponent = this.component.getListItem(aggregationMapping.name); + haveText(listItem.getName(), aggregationMapping.name); + haveText(listItem.getFormEngineName(), aggregationMapping.formIdentifier.formEngineName); + haveText(listItem.getFormId(), aggregationMapping.formIdentifier.formId); + } +} diff --git a/alfa-client/apps/admin-e2e/src/helper/app.helper.ts b/alfa-client/apps/admin-e2e/src/helper/app.helper.ts new file mode 100644 index 0000000000000000000000000000000000000000..ee3170e548ffc5b7cad695a0f28d0b1e7e993a11 --- /dev/null +++ b/alfa-client/apps/admin-e2e/src/helper/app.helper.ts @@ -0,0 +1,9 @@ +import { MainPage } from '../page-objects/main.po'; + +export class E2EAppHelper { + private readonly mainPage: MainPage = new MainPage(); + + public navigateToDomain(): void { + this.mainPage.getHeader().getLogo().click(); + } +} diff --git a/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts b/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts index 75ecbdaefa5d692ca637af325afb58ec05f80abe..c982465ac95dbb58ecfc31e412b40c55b2c441fa 100644 --- a/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts +++ b/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts @@ -31,7 +31,7 @@ export class MainPage { private readonly benutzerNavigationItem: string = 'link-path-benutzer'; private readonly organisationEinheitNavigationItem: string = 'link-path-organisationseinheiten'; private readonly postfachNavigationItem: string = 'link-path-postfach'; - private readonly statistikNavigationItem: string = 'link-path-statistik'; + private readonly statistikNavigationItem: string = 'link-path-aggregation-mapping'; public getBuildInfo(): BuildInfoE2EComponent { return this.buildInfo; diff --git a/alfa-client/apps/admin-e2e/src/support/cypress-helper.ts b/alfa-client/apps/admin-e2e/src/support/cypress-helper.ts index 83e7bb11f0e77a4773924fb84431047ddd271a17..5d457ea558240cbd2d5e415ffc8136f8be4452ad 100644 --- a/alfa-client/apps/admin-e2e/src/support/cypress-helper.ts +++ b/alfa-client/apps/admin-e2e/src/support/cypress-helper.ts @@ -21,6 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ +import { HttpMethod } from '@alfa-client/tech-shared'; import { Interception, RouteHandler, RouteMatcher } from 'cypress/types/net-stubbing'; import { OrganisationsEinheitE2E } from './organisationseinheit'; @@ -31,7 +32,7 @@ enum CypressTasks { enum MongoCollections { ORGANISATIONS_EINHEIT = 'organisationsEinheit', - SETTINGS = 'settings', + AGGREGATION_MAPPING = 'aggregationMapping', } const DOWNLOAD_FOLDER: string = 'cypress/downloads'; @@ -48,7 +49,7 @@ export function intercept(method: string, url: string): Cypress.Chainable<null> return cy.intercept(method, url); } -export function interceptWithResponse(method, url: RouteMatcher, response: RouteHandler): Cypress.Chainable<null> { +export function interceptWithResponse(method: HttpMethod, url: RouteMatcher, response: RouteHandler): Cypress.Chainable<null> { return cy.intercept(method, url, response); } @@ -110,6 +111,5 @@ export function initOrganisationsEinheitenData(data: OrganisationsEinheitE2E[]): } export function dropCollections() { - cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.ORGANISATIONS_EINHEIT]); - cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.SETTINGS]); + cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.ORGANISATIONS_EINHEIT, MongoCollections.AGGREGATION_MAPPING]); } diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-forwarding-dialog.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-forwarding-dialog.e2e.component.ts index 27fbc0aa695b4e30a7e311679e3331dfd621b8ea..7f5d897628057b0c929c61fd9596ad7de3dad49a 100644 --- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-forwarding-dialog.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-forwarding-dialog.e2e.component.ts @@ -2,7 +2,7 @@ export class ForwardingDialogE2EComponent { private readonly root: string = 'forwarding-dialog'; private readonly cancelButton: string = 'cancel-dialog-button'; private readonly cancelIconButton: string = 'cancel-dialog-icon-button'; - private readonly forwardingButton: string = 'forwarding-button'; + private readonly forwardingButton: string = 'forwarding-dialog-forwarding-button'; private readonly searchText: string = 'instant_search-text-input'; private readonly searchEntry: string = 'item-button'; private readonly forwardingItem: string = 'forwarding-item'; diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/forwarding/forwarding.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/forwarding/forwarding.cy.ts new file mode 100644 index 0000000000000000000000000000000000000000..38dc17bb68d5b4e430c6ae5c3c3cd5bbc4cb8f4c --- /dev/null +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/forwarding/forwarding.cy.ts @@ -0,0 +1,40 @@ +import { registerLocaleData } from '@angular/common'; +import localeDe from '@angular/common/locales/de'; +import localeDeExtra from '@angular/common/locales/extra/de'; +import { E2EAppHelper } from 'apps/alfa-e2e/src/helper/app.helper'; +import { E2EForwardingHelper } from 'apps/alfa-e2e/src/helper/forwarding/forwarding.helper'; +import { E2EOrganisationsEinheit } from 'apps/alfa-e2e/src/model/organisationseinheit'; +import { E2EVorgangVerifier } from '../../../helper/vorgang/vorgang.verifier'; +import { VorgangE2E } from '../../../model/vorgang'; +import { dropCollections } from '../../../support/cypress-helper'; +import { createVorgang, initVorgang } from '../../../support/vorgang-util'; + +registerLocaleData(localeDe, 'de', localeDeExtra); + +describe('Vorgang weiterleiten', () => { + const appHelper: E2EAppHelper = new E2EAppHelper(); + + const vorgangVerifier: E2EVorgangVerifier = new E2EVorgangVerifier(); + + const forwardingHelper: E2EForwardingHelper = new E2EForwardingHelper(); + + const vorgang: VorgangE2E = { ...createVorgang(), name: 'Weiterleitung' }; + + before(() => { + initVorgang(vorgang); + + appHelper.loginAsSabine(); + }); + + after(() => { + dropCollections(); + }); + + it('should disable all functions after successfully forwarding', () => { + forwardingHelper.openForwarding(vorgang.name); + + forwardingHelper.forwardTo(E2EOrganisationsEinheit.HAMBURG_STADTENTWAESSERUNG); + + vorgangVerifier.verifyVorgangIsLocked(); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/helper/app.helper.ts b/alfa-client/apps/alfa-e2e/src/helper/app.helper.ts new file mode 100644 index 0000000000000000000000000000000000000000..e264eb98df16537f69c250fa09252c35346c43b8 --- /dev/null +++ b/alfa-client/apps/alfa-e2e/src/helper/app.helper.ts @@ -0,0 +1,23 @@ +import { VorgangListE2EComponent } from '../components/vorgang/vorgang-list.e2e.component'; +import { MainPage, waitForSpinnerToDisappear } from '../page-objects/main.po'; +import { exist } from '../support/cypress.util'; +import { loginAsSabine } from '../support/user-util'; + +export class E2EAppHelper { + private readonly mainPage: MainPage = new MainPage(); + private readonly vorgangList: VorgangListE2EComponent = new VorgangListE2EComponent(); + + public loginAsSabine(): void { + loginAsSabine(); + this.waitAfterLogin(); + } + + private waitAfterLogin(): void { + waitForSpinnerToDisappear(); + exist(this.vorgangList.getRoot()); + } + + public navigateToDomain(): void { + this.mainPage.getHeader().getLogo().click(); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/helper/forwarding/forwarding.executor.ts b/alfa-client/apps/alfa-e2e/src/helper/forwarding/forwarding.executor.ts new file mode 100644 index 0000000000000000000000000000000000000000..22295bb180d00c9d23b787fde72a001bea29cab2 --- /dev/null +++ b/alfa-client/apps/alfa-e2e/src/helper/forwarding/forwarding.executor.ts @@ -0,0 +1,16 @@ +import { ForwardingDialogE2EComponent } from '../../components/vorgang/vorgang-forwarding-dialog.e2e.component'; +import { waitForSpinnerToDisappear } from '../../page-objects/main.po'; +import { exist } from '../../support/cypress.util'; + +export class E2EForwardingExecutor { + private readonly forwardingDialog = new ForwardingDialogE2EComponent(); + + public fillForwardingDialog(organisationsEinheit: string): void { + this.forwardingDialog.getSearchText().type(organisationsEinheit); + waitForSpinnerToDisappear(); + this.forwardingDialog.clickSearchEntry(0); + exist(this.forwardingDialog.getForwardingItem()); + this.forwardingDialog.getForwardingButton().click(); + waitForSpinnerToDisappear(); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/helper/forwarding/forwarding.helper.ts b/alfa-client/apps/alfa-e2e/src/helper/forwarding/forwarding.helper.ts new file mode 100644 index 0000000000000000000000000000000000000000..408faf920fba169b3a69908575d7d422e2cf743d --- /dev/null +++ b/alfa-client/apps/alfa-e2e/src/helper/forwarding/forwarding.helper.ts @@ -0,0 +1,15 @@ +import { E2EForwardingExecutor } from './forwarding.executor'; +import { E2EForwardingNavigator } from './forwarding.navigator'; + +export class E2EForwardingHelper { + private readonly executor: E2EForwardingExecutor = new E2EForwardingExecutor(); + private readonly navigator: E2EForwardingNavigator = new E2EForwardingNavigator(); + + public openForwarding(vorgangName: string): void { + this.navigator.openForwardDialog(vorgangName); + } + + public forwardTo(organisationsEinheit: string): void { + this.executor.fillForwardingDialog(organisationsEinheit); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/helper/forwarding/forwarding.navigator.ts b/alfa-client/apps/alfa-e2e/src/helper/forwarding/forwarding.navigator.ts new file mode 100644 index 0000000000000000000000000000000000000000..3400d79516d98512531d28f43b8575f583a5d0f4 --- /dev/null +++ b/alfa-client/apps/alfa-e2e/src/helper/forwarding/forwarding.navigator.ts @@ -0,0 +1,17 @@ +import { VorgangFormularButtonsE2EComponent } from '../../components/vorgang/vorgang-formular-buttons.e2e.components'; +import { ForwardingDialogE2EComponent } from '../../components/vorgang/vorgang-forwarding-dialog.e2e.component'; +import { exist } from '../../support/cypress.util'; +import { E2EVorgangNavigator } from '../vorgang/vorgang.navigator'; + +export class E2EForwardingNavigator { + private readonly vorgangNavigator: E2EVorgangNavigator = new E2EVorgangNavigator(); + + private readonly formularButtons: VorgangFormularButtonsE2EComponent = new VorgangFormularButtonsE2EComponent(); + private readonly forwardingDialog: ForwardingDialogE2EComponent = new ForwardingDialogE2EComponent(); + + public openForwardDialog(vorgangName: string): void { + this.vorgangNavigator.openVorgangDetailByName(vorgangName); + this.formularButtons.getForwardButton().click(); + exist(this.forwardingDialog.getRoot()); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/helper/vorgang/vorgang.navigator.ts b/alfa-client/apps/alfa-e2e/src/helper/vorgang/vorgang.navigator.ts index 7b4fc54b196ff4dc2c83ffbf029a8b063c6b1054..3225f82b8ac3c2dd7158bbc00e1499f30c0f4c14 100644 --- a/alfa-client/apps/alfa-e2e/src/helper/vorgang/vorgang.navigator.ts +++ b/alfa-client/apps/alfa-e2e/src/helper/vorgang/vorgang.navigator.ts @@ -1,8 +1,12 @@ import { VorgangListE2EComponent } from '../../components/vorgang/vorgang-list.e2e.component'; import { waitForSpinnerToDisappear } from '../../page-objects/main.po'; +import { exist } from '../../support/cypress.util'; +import { E2EAppHelper } from '../app.helper'; import { E2EVorgangVerifier } from './vorgang.verifier'; export class E2EVorgangNavigator { + private readonly appHelper: E2EAppHelper = new E2EAppHelper(); + private readonly verifier: E2EVorgangVerifier = new E2EVorgangVerifier(); private readonly vorgangListPage = new VorgangListE2EComponent(); @@ -12,4 +16,11 @@ export class E2EVorgangNavigator { waitForSpinnerToDisappear(); this.verifier.verifyVorgangDetailOpen(vorgangName); } + + public openVorgang(vorgangName: string): void { + this.appHelper.navigateToDomain(); + waitForSpinnerToDisappear(); + exist(this.vorgangListPage.getRoot()); + this.openVorgangDetailByName(vorgangName); + } } diff --git a/alfa-client/apps/alfa-e2e/src/helper/vorgang/vorgang.verifier.ts b/alfa-client/apps/alfa-e2e/src/helper/vorgang/vorgang.verifier.ts index c42945065f7c18f03c4f74fbcbf2809c9b2a8021..d8e8e39394686a7a4414a6d38564e69c5969f6f0 100644 --- a/alfa-client/apps/alfa-e2e/src/helper/vorgang/vorgang.verifier.ts +++ b/alfa-client/apps/alfa-e2e/src/helper/vorgang/vorgang.verifier.ts @@ -1,8 +1,10 @@ +import { VorgangFormularButtonsE2EComponent } from '../../components/vorgang/vorgang-formular-buttons.e2e.components'; import { VorgangPage } from '../../page-objects/vorgang.po'; import { contains, exist, notExist } from '../../support/cypress.util'; export class E2EVorgangVerifier { private readonly vorgangPage: VorgangPage = new VorgangPage(); + private readonly formularButtons: VorgangFormularButtonsE2EComponent = new VorgangFormularButtonsE2EComponent(); public verifyVorgangDetailOpen(vorgangName: string): void { exist(this.vorgangPage.getVorgangDetailHeader().getRoot()); @@ -16,4 +18,25 @@ export class E2EVorgangVerifier { public verifyNoForwardingButtonExists(): void { notExist(this.vorgangPage.getFormularButtons().getForwardButton()); } + + public verifyVorgangIsLocked(): void { + this.verifyFormularButtonsNotVisible(); + notExist(this.vorgangPage.getWiedervorlagenContainer().getCreateWiedervorlageButton()); + notExist(this.vorgangPage.getKommentarContainer().getHinzufuegenButton()); + notExist(this.vorgangPage.getPostfachMailcontainer().getCreateButtonWithText()); + notExist(this.vorgangPage.getPostfachMailcontainer().getCreateButtonWithoutText()); + } + + private verifyFormularButtonsNotVisible(): void { + notExist(this.formularButtons.getAbschliessenButton()); + notExist(this.formularButtons.getBearbeitenButton()); + notExist(this.formularButtons.getBescheidenButton()); + notExist(this.formularButtons.getEndgueltigLoeschenButton()); + notExist(this.formularButtons.getForwardButton()); + notExist(this.formularButtons.getLoeschAnforderungZuruecknehmenButton()); + notExist(this.formularButtons.getVerwerfenButton()); + notExist(this.formularButtons.getWiedereroeffnenButton()); + notExist(this.formularButtons.getZurueckholenButton()); + notExist(this.formularButtons.getZurueckstellenButton()); + } } diff --git a/alfa-client/apps/alfa-e2e/src/model/organisationseinheit.ts b/alfa-client/apps/alfa-e2e/src/model/organisationseinheit.ts new file mode 100644 index 0000000000000000000000000000000000000000..302f3c401870a6951537a8fceeea96760e239abf --- /dev/null +++ b/alfa-client/apps/alfa-e2e/src/model/organisationseinheit.ts @@ -0,0 +1,3 @@ +export enum E2EOrganisationsEinheit { + HAMBURG_STADTENTWAESSERUNG = 'Wasserwerk - Hamburg Wasser - Hamburger Stadtentwässerung', +} diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts index d22faf648e3d30b95e5d957b99673a29579e619b..ae974499af8180747f7915423b75c4e91a4a48a5 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts @@ -21,10 +21,31 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { BinaryFileListLinkRel, BinaryFileListResource, BinaryFileResource, BinaryFileService, } from '@alfa-client/binary-file-shared'; -import { CommandOrder, CommandResource, CommandResourceService, CommandService, CreateCommandProps, getEffectedResourceUrl, } from '@alfa-client/command-shared'; +import { + BinaryFileListLinkRel, + BinaryFileListResource, + BinaryFileResource, + BinaryFileService, +} from '@alfa-client/binary-file-shared'; +import { + CommandOrder, + CommandResource, + CommandResourceService, + CommandService, + CreateCommandProps, + getEffectedResourceUrl, +} from '@alfa-client/command-shared'; import { PostfachService } from '@alfa-client/postfach-shared'; -import { createEmptyStateResource, createErrorStateResource, createStateResource, EMPTY_STRING, getEmbeddedResources, ResourceListService, ResourceRepository, StateResource, } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createErrorStateResource, + createStateResource, + EMPTY_STRING, + getEmbeddedResources, + ResourceListService, + ResourceRepository, + StateResource, +} from '@alfa-client/tech-shared'; import { Mock, mock } from '@alfa-client/test-utils'; import { VorgangCommandService, VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { TestBed } from '@angular/core/testing'; @@ -35,19 +56,43 @@ import { createProblemDetail } from 'libs/tech-shared/test/error'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; import { EMPTY, Observable, of } from 'rxjs'; import { createBinaryFileListResource, createBinaryFileResource } from '../../../binary-file-shared/test/binary-file'; -import { createCommandErrorStateResource, createCommandResource, createCommandStateResource, createCreateCommandProps, createSuccessfullyDoneCommandStateResource, } from '../../../command-shared/test/command'; +import { + createCommandErrorStateResource, + createCommandResource, + createCommandStateResource, + createCreateCommandProps, + createSuccessfullyDoneCommandStateResource, +} from '../../../command-shared/test/command'; import { createFile } from '../../../tech-shared/test/file'; import { singleCold, singleColdCompleted } from '../../../tech-shared/test/marbles'; import { createBescheid, createBescheidDocument, createBescheidListResource, createBescheidResource } from '../test/bescheid'; import { createDocumentResource } from '../test/document'; import { BescheidFacade } from './+state/bescheid.facade'; import { BescheidLinkRel } from './bescheid.linkrel'; -import { Bescheid, BESCHEID_UPLOADED_ATTACHMENTS, BescheidDocument, BescheidListResource, BescheidResource, BescheidStatus, BescheidWizardStep, createEmptyBescheidDocument, createEmptyUploadInProgress, createInitialWizard, } from './bescheid.model'; +import { + Bescheid, + BESCHEID_UPLOADED_ATTACHMENTS, + BescheidDocument, + BescheidListResource, + BescheidResource, + BescheidStatus, + BescheidWizardStep, + createEmptyBescheidDocument, + createEmptyUploadInProgress, + createInitialWizard, +} from './bescheid.model'; import { BescheidService } from './bescheid.service'; import { DocumentLinkRel } from './document.linkrel'; import { DocumentResource } from './document.model'; -import { BescheidListResourceService, BescheidResourceService, buildCreateBescheidDocumentFromFileProps, buildUpdateBescheidCommandProps, createBescheidListResourceService, createBescheidResourceService, } from '@alfa-client/bescheid-shared'; +import { + BescheidListResourceService, + BescheidResourceService, + buildCreateBescheidDocumentFromFileProps, + buildUpdateBescheidCommandProps, + createBescheidListResourceService, + createBescheidResourceService, +} from '@alfa-client/bescheid-shared'; import { expect } from '@jest/globals'; import { cold } from 'jest-marbles'; import * as DateUtil from '../../../tech-shared/src/lib/date.util'; @@ -147,7 +192,7 @@ describe('BescheidService', () => { it('should reload postfach list', () => { service.exit(); - expect(postfachService.setPostfachMailOnReload).toHaveBeenCalled(); + expect(postfachService._setPostfachMailOnReload).toHaveBeenCalled(); }); it('should clear uploaded files', () => { diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts index f7b1e2f64bac1adb6a924aa1e6719cdbc1028ec5..22107e92d9b6ff28981edc35f13ab3da9b8880b8 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts @@ -44,10 +44,34 @@ import { DocumentResource, Wizard, } from '@alfa-client/bescheid-shared'; -import { BinaryFileListLinkRel, BinaryFileListResource, BinaryFileResource, BinaryFileService, } from '@alfa-client/binary-file-shared'; -import { CommandOrder, CommandResource, CommandService, getEffectedResourceUrl, notHasCommandError, tapOnCommandSuccessfullyDone, } from '@alfa-client/command-shared'; +import { + BinaryFileListLinkRel, + BinaryFileListResource, + BinaryFileResource, + BinaryFileService, +} from '@alfa-client/binary-file-shared'; +import { + CommandOrder, + CommandResource, + CommandService, + getEffectedResourceUrl, + notHasCommandError, + tapOnCommandSuccessfullyDone, +} from '@alfa-client/command-shared'; import { PostfachService } from '@alfa-client/postfach-shared'; -import { createEmptyStateResource, createStateResource, filterIsLoadedOrHasError, getEmbeddedResources, hasStateResourceError, isLoaded, isNotEmpty, isNotNil, ResourceRepository, sortByGermanDateStr, StateResource, } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createStateResource, + filterIsLoadedOrHasError, + getEmbeddedResources, + hasStateResourceError, + isLoaded, + isNotEmpty, + isNotNil, + ResourceRepository, + sortByGermanDateStr, + StateResource, +} from '@alfa-client/tech-shared'; import { VorgangCommandService, VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { inject, Injectable } from '@angular/core'; import { getUrl, hasLink, LinkRel, Resource, ResourceUri } from '@ngxp/rest'; @@ -65,7 +89,7 @@ export class BescheidService { private readonly resourceRepository = inject(ResourceRepository); private readonly postfachService = inject(PostfachService); private readonly vorgangService = inject(VorgangService); - // The injection of this service and the one below is problematic. + // The injection of this services is problematic. // It must be analysed how to inject BescheidService via providers in BescheidSharedModule. private readonly bescheidResourceService = createBescheidResourceService( this.resourceRepository, @@ -73,7 +97,7 @@ export class BescheidService { this.vorgangService, ); private readonly bescheidListResourceService = createBescheidListResourceService(this.resourceRepository, this.vorgangService); - + // readonly _bescheidDocument$: BehaviorSubject<BescheidDocument> = new BehaviorSubject(createEmptyBescheidDocument()); readonly _wizard$: BehaviorSubject<Wizard> = new BehaviorSubject(createInitialWizard()); @@ -84,7 +108,7 @@ export class BescheidService { public exit(): void { this.bescheidListResourceService.refresh(); - this.postfachService.setPostfachMailOnReload(); + this.postfachService._setPostfachMailOnReload(); this._clearUploadedFiles(); } diff --git a/alfa-client/libs/forwarding/src/lib/forwarding-dialog-container/forwarding-dialog/forwarding-button/forwarding-button.component.html b/alfa-client/libs/forwarding/src/lib/forwarding-dialog-container/forwarding-dialog/forwarding-button/forwarding-button.component.html index 1b36245dd262eb85c56fa35d29ba8f4bf1ba53d4..5bf44a14c8978d8fea1e07d51b0ccc1279935ca4 100644 --- a/alfa-client/libs/forwarding/src/lib/forwarding-dialog-container/forwarding-dialog/forwarding-button/forwarding-button.component.html +++ b/alfa-client/libs/forwarding/src/lib/forwarding-dialog-container/forwarding-dialog/forwarding-button/forwarding-button.component.html @@ -4,7 +4,7 @@ (clickEmitter)="clickEmitter.emit()" text="Weiterleiten" variant="outline" - dataTestId="forwarding-button" + dataTestId="forwarding-dialog-forwarding-button" data-test-id="forwarding-button-container" > <ods-forward-vorgang-icon icon class="fill-primary" /> diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts index 522ed1f6ce6a4ae086d1226253f1d1236eb3eb9d..5860d364284ddcb2e8a62b90e568bd84ad336ad9 100644 --- a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts +++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts @@ -35,7 +35,7 @@ import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; import { createCommandResource } from 'libs/command-shared/test/command'; import { createKommentar, createKommentarListResource, createKommentarResource } from 'libs/kommentar-shared/test/kommentar'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; -import { of } from 'rxjs'; +import { of, Subscription } from 'rxjs'; import { singleCold } from '../../../tech-shared/test/marbles'; import { KommentarLinkRel, KommentarListLinkRel } from './kommentar.linkrel'; import { Kommentar, KOMMENTAR_UPLOADED_ATTACHMENTS, KommentarListResource, KommentarResource } from './kommentar.model'; @@ -51,9 +51,12 @@ describe('KommentarService', () => { let binaryFileService: Mock<BinaryFileService>; const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource> = createStateResource(vorgang); + const kommentarList: KommentarListResource = createKommentarListResource(); const kommentar: Kommentar = createKommentar(); const kommentarResource: KommentarResource = createKommentarResource(); + const command: CommandResource = createCommandResource(); const commandStateResource: StateResource<CommandResource> = createStateResource(command); @@ -61,7 +64,10 @@ describe('KommentarService', () => { repository = mock(KommentarRepository); commandService = mock(CommandService); navigationService = mock(NavigationService); - vorgangService = mock(VorgangService); + vorgangService = { + ...mock(VorgangService), + getVorgangWithEingang: jest.fn().mockReturnValue(of(vorgangWithEingangStateResource)), + }; binaryFileService = mock(BinaryFileService); navigationService.urlChanged.mockReturnValue(of({})); @@ -79,14 +85,21 @@ describe('KommentarService', () => { beforeEach(() => { repository.findKommentare.mockReturnValue(of(kommentarList)); - service.setListLoadingTrue = jest.fn(); - service.setKommentarList = jest.fn(); + service._setListLoadingTrue = jest.fn(); + service._setKommentarList = jest.fn(); + service._refreshVorgangSubscription = jest.fn(); + }); + + it('should call refresh vorgang subscription', () => { + service.getKommentareByVorgang(vorgang); + + expect(service._refreshVorgangSubscription).toHaveBeenCalled(); }); it('should set loading to true', () => { service.getKommentareByVorgang(vorgang); - expect(service.setListLoadingTrue).toHaveBeenCalled(); + expect(service._setListLoadingTrue).toHaveBeenCalled(); }); it('should call repository', () => { @@ -98,7 +111,25 @@ describe('KommentarService', () => { it('should set loaded resource', () => { service.getKommentareByVorgang(vorgang); - expect(service.setKommentarList).toHaveBeenCalledWith(kommentarList); + expect(service._setKommentarList).toHaveBeenCalledWith(kommentarList); + }); + }); + + describe('refresh vorgang subscription', () => { + beforeEach(() => { + service.vorgangSubscription = <any>mock(Subscription); + service._listenToVorgangChange = jest.fn(); + }); + + it('should unsubscribe existing subscription', () => { + service._refreshVorgangSubscription(); + + expect(service.vorgangSubscription.unsubscribe).toHaveBeenCalled(); + }); + it('should call listen to vorgang change', () => { + service._refreshVorgangSubscription(); + + expect(service._listenToVorgangChange).toHaveBeenCalled(); }); }); @@ -126,28 +157,28 @@ describe('KommentarService', () => { expect(commandService.createCommand).toHaveBeenCalledWith( service.kommentarList$.value.resource, KommentarListLinkRel.CREATE_KOMMENTAR, - service.createCreateKommentarCommand(kommentar), + service._createCreateKommentarCommand(kommentar), ); }); it('should call getEffectedResource', () => { - service.afterCreateOrEditKommentar = jest.fn(); + service._afterCreateOrEditKommentar = jest.fn(); service.createKommentar(kommentar).subscribe(); - expect(service.afterCreateOrEditKommentar).toHaveBeenCalledWith(commandStateResource); + expect(service._afterCreateOrEditKommentar).toHaveBeenCalledWith(commandStateResource); }); it('should call createCreateKommentarCommand', () => { - service.createCreateKommentarCommand = jest.fn(); + service._createCreateKommentarCommand = jest.fn(); service.createKommentar(kommentar); - expect(service.createCreateKommentarCommand).toHaveBeenCalledWith(kommentar); + expect(service._createCreateKommentarCommand).toHaveBeenCalledWith(kommentar); }); it('should create CreateKommentarCommand', () => { - var command: CreateCommand = service.createCreateKommentarCommand(kommentar); + var command: CreateCommand = service._createCreateKommentarCommand(kommentar); expect(command).toEqual({ order: CommandOrder.CREATE_KOMMENTAR, body: kommentar }); }); @@ -178,28 +209,28 @@ describe('KommentarService', () => { expect(commandService.createCommand).toHaveBeenCalledWith( kommentarResource, KommentarLinkRel.EDIT, - service.createEditKommentarCommand(kommentar), + service._createEditKommentarCommand(kommentar), ); }); it('should call getEffectedResource', () => { - service.afterCreateOrEditKommentar = jest.fn(); + service._afterCreateOrEditKommentar = jest.fn(); service.editKommentar(kommentarResource, kommentar).subscribe(); - expect(service.afterCreateOrEditKommentar).toHaveBeenCalledWith(commandStateResource); + expect(service._afterCreateOrEditKommentar).toHaveBeenCalledWith(commandStateResource); }); it('should call createEditKommentarCommand', () => { - service.createEditKommentarCommand = jest.fn(); + service._createEditKommentarCommand = jest.fn(); service.editKommentar(kommentarResource, kommentar); - expect(service.createEditKommentarCommand).toHaveBeenCalledWith(kommentar); + expect(service._createEditKommentarCommand).toHaveBeenCalledWith(kommentar); }); it('should create CreateKommentarCommand', () => { - var command: CreateCommand = service.createEditKommentarCommand(kommentar); + var command: CreateCommand = service._createEditKommentarCommand(kommentar); expect(command).toEqual({ order: CommandOrder.EDIT_KOMMENTAR, body: kommentar }); }); @@ -217,7 +248,7 @@ describe('KommentarService', () => { it('should hide formular', () => { service.hideFormular = jest.fn(); - service.afterCreateOrEditKommentar({ + service._afterCreateOrEditKommentar({ ...commandStateResource, resource: createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]), }); @@ -226,7 +257,7 @@ describe('KommentarService', () => { }); it('should reload vorgang', () => { - service.afterCreateOrEditKommentar({ + service._afterCreateOrEditKommentar({ ...commandStateResource, resource: createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]), }); @@ -235,20 +266,20 @@ describe('KommentarService', () => { }); it('should set kommentar list on reload', () => { - service.setKommentarListReload = jest.fn(); + service._setKommentarListReload = jest.fn(); - service.afterCreateOrEditKommentar({ + service._afterCreateOrEditKommentar({ ...commandStateResource, resource: createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]), }); - expect(service.setKommentarListReload).toHaveBeenCalled(); + expect(service._setKommentarListReload).toHaveBeenCalled(); }); }); describe('on command is pending', () => { it('should do nothing', () => { - service.afterCreateOrEditKommentar({ + service._afterCreateOrEditKommentar({ ...commandStateResource, resource: createCommandResource([CommandLinkRel.UPDATE]), }); @@ -265,13 +296,13 @@ describe('KommentarService', () => { }); it('should clear uploaded files', () => { - service.onNavigation({}); + service._onNavigation({}); expect(service.clearUploadedFiles).toHaveBeenCalled(); }); it('should hide forumlar', () => { - service.onNavigation({}); + service._onNavigation({}); expect(service.hideFormular).toHaveBeenCalled(); }); @@ -280,7 +311,7 @@ describe('KommentarService', () => { it('should set reload flag of kommentar list', () => { service.kommentarList$.next(createEmptyStateResource()); - service.onNavigation({}); + service._onNavigation({}); expect(service.kommentarList$.value.reload).toEqual(true); }); @@ -290,7 +321,7 @@ describe('KommentarService', () => { it('should set kommentar list to reload', () => { service.kommentarList$.next(createEmptyStateResource()); - service.onNavigation({ vorgangWithEingangUrl: 'X' }); + service._onNavigation({ vorgangWithEingangUrl: 'X' }); expect(service.kommentarList$.value.reload).toEqual(true); }); @@ -300,13 +331,13 @@ describe('KommentarService', () => { describe('attachments', () => { it('should be loaded if link avaible', () => { const kommentarResource = createKommentarResource([KommentarLinkRel.ATTACHMENTS]); - service.getAttachments(kommentarResource); + service._getAttachments(kommentarResource); expect(binaryFileService.getFiles).toHaveBeenCalledWith(kommentarResource, KommentarLinkRel.ATTACHMENTS); }); it('should not be loaded if no link available', () => { - service.getAttachments(kommentarResource); + service._getAttachments(kommentarResource); expect(binaryFileService.getFiles).not.toHaveBeenCalled(); }); @@ -421,4 +452,63 @@ describe('KommentarService', () => { expect(service._currentlyEdited$).toBeObservable(singleCold(resourceUri)); }); }); + + describe('listen to vorgang change', () => { + beforeEach(() => { + service._handleVorgangChange = jest.fn(); + }); + + it('should call vorgang service to get vorgang with eingang', () => { + service._listenToVorgangChange(); + + expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); + }); + + it('should call handle vorgang change', () => { + service._listenToVorgangChange(); + + expect(service._handleVorgangChange).toHaveBeenCalledWith(vorgangWithEingangStateResource); + }); + }); + + describe('handle vorgang change', () => { + it('should set reload flag if list is loaded and state resource is loading', () => { + service.shouldReload = false; + service.kommentarList$.next(createStateResource(createKommentarListResource())); + + service._handleVorgangChange({ ...vorgangWithEingangStateResource, loading: true }); + + expect(service.shouldReload).toBeTruthy(); + }); + + it('should set reload flag if list is loaded and state resource is reloading', () => { + service.kommentarList$.next(createStateResource(createKommentarListResource())); + service.shouldReload = false; + + service._handleVorgangChange({ ...vorgangWithEingangStateResource, reload: true }); + + expect(service.shouldReload).toBeTruthy(); + }); + + describe('on setted reload flag', () => { + beforeEach(() => { + service._setKommentarListReload = jest.fn(); + service.shouldReload = true; + }); + + describe('and loaded vorgang resource', () => { + it('should call set kommentar list reload', () => { + service._handleVorgangChange(vorgangWithEingangStateResource); + + expect(service._setKommentarListReload).toHaveBeenCalled(); + }); + + it('and loaded vorgang resource should call set kommentar list reload', () => { + service._handleVorgangChange(vorgangWithEingangStateResource); + + expect(service.shouldReload).toBeFalsy(); + }); + }); + }); + }); }); diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts index 0055824e34836c3ad1195ce85d01ff4f2b772a35..395872897b9e894a0c4336f50f16a10f7598e878 100644 --- a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts +++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts @@ -24,8 +24,17 @@ import { BinaryFileListResource, BinaryFileService } from '@alfa-client/binary-file-shared'; import { CommandOrder, CommandResource, CommandService, CreateCommand, isDone } from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { createEmptyStateResource, createStateResource, doIfLoadingRequired, EMPTY_STRING, isNotEmpty, StateResource, } from '@alfa-client/tech-shared'; -import { VorgangResource, VorgangService } from '@alfa-client/vorgang-shared'; +import { + createEmptyStateResource, + createStateResource, + doIfLoadingRequired, + EMPTY_STRING, + isLoaded, + isNotEmpty, + isNotNull, + StateResource, +} from '@alfa-client/tech-shared'; +import { VorgangResource, VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { Injectable } from '@angular/core'; import { Params } from '@angular/router'; import { hasLink, Resource, ResourceUri } from '@ngxp/rest'; @@ -46,6 +55,10 @@ export class KommentarService { private navigationSub: Subscription; + vorgangSubscription: Subscription; + + shouldReload: boolean = false; + constructor( private repository: KommentarRepository, private commandService: CommandService, @@ -54,18 +67,19 @@ export class KommentarService { private binaryFileService: BinaryFileService, ) { this.listenToNavigation(); + this._listenToVorgangChange(); } private listenToNavigation(): void { this.unsubscribe(); - this.navigationSub = this.navigationService.urlChanged().subscribe((params: Params) => this.onNavigation(params)); + this.navigationSub = this.navigationService.urlChanged().subscribe((params: Params) => this._onNavigation(params)); } private unsubscribe(): void { if (!isNil(this.navigationSub)) this.navigationSub.unsubscribe(); } - onNavigation(params: Params): void { + _onNavigation(params: Params): void { this.clearUploadedFiles(); this.hideFormular(); if (NavigationService.isVorgangListPage(params)) { @@ -81,28 +95,59 @@ export class KommentarService { } public getKommentareByVorgang(vorgang: VorgangResource): Observable<StateResource<KommentarListResource>> { + this._refreshVorgangSubscription(); doIfLoadingRequired(this.kommentarList$.value, () => this.loadKommentare(vorgang)); return this.kommentarList$.asObservable(); } + _refreshVorgangSubscription(): void { + this.vorgangSubscription.unsubscribe(); + this._listenToVorgangChange(); + } + + _listenToVorgangChange(): void { + this.vorgangSubscription = this.vorgangService + .getVorgangWithEingang() + .subscribe((vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource>) => + this._handleVorgangChange(vorgangWithEingangStateResource), + ); + } + + _handleVorgangChange(vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource>): void { + if (this.shouldReloadList(vorgangWithEingangStateResource)) { + this.shouldReload = true; + } + if (isLoaded(vorgangWithEingangStateResource) && this.shouldReload) { + this._setKommentarListReload(); + this.shouldReload = false; + } + } + + private shouldReloadList(vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource>): boolean { + return ( + (vorgangWithEingangStateResource.loading || vorgangWithEingangStateResource.reload) && + isNotNull(this.kommentarList$.value.resource) + ); + } + private loadKommentare(vorgang: VorgangResource): void { - this.setListLoadingTrue(); + this._setListLoadingTrue(); const sub: Subscription = this.repository.findKommentare(vorgang).subscribe((kommentarList: KommentarListResource) => { - this.setKommentarList(kommentarList); + this._setKommentarList(kommentarList); sub.unsubscribe(); }); } - setListLoadingTrue(): void { + _setListLoadingTrue(): void { this.kommentarList$.next({ ...this.kommentarList$.value, loading: true }); } - setKommentarListReload() { + _setKommentarListReload() { this.kommentarList$.next({ ...this.kommentarList$.value, reload: true }); } - setKommentarList(kommentarList: KommentarListResource): void { + _setKommentarList(kommentarList: KommentarListResource): void { this.kommentarList$.next(createStateResource(kommentarList)); } @@ -128,45 +173,45 @@ export class KommentarService { } public createKommentar(kommentar: Kommentar): Observable<StateResource<CommandResource>> { - return this.createKommentarCommand( + return this._createKommentarCommand( this.kommentarList$.value.resource, KommentarListLinkRel.CREATE_KOMMENTAR, - this.createCreateKommentarCommand(kommentar), + this._createCreateKommentarCommand(kommentar), ); } - createCreateKommentarCommand(kommentar: Kommentar): CreateCommand { + _createCreateKommentarCommand(kommentar: Kommentar): CreateCommand { return { order: CommandOrder.CREATE_KOMMENTAR, body: kommentar }; } public editKommentar(kommentar: KommentarResource, toPatch: Kommentar): Observable<StateResource<CommandResource>> { - return this.createKommentarCommand(kommentar, KommentarLinkRel.EDIT, this.createEditKommentarCommand(toPatch)); + return this._createKommentarCommand(kommentar, KommentarLinkRel.EDIT, this._createEditKommentarCommand(toPatch)); } - createEditKommentarCommand(kommentar: Kommentar): CreateCommand { + _createEditKommentarCommand(kommentar: Kommentar): CreateCommand { return { order: CommandOrder.EDIT_KOMMENTAR, body: kommentar }; } - createKommentarCommand( + _createKommentarCommand( resource: Resource, linkRel: string, command: CreateCommand, ): Observable<StateResource<CommandResource>> { return this.commandService.createCommand(resource, linkRel, command).pipe( - tap((createdCommand: StateResource<CommandResource>) => this.afterCreateOrEditKommentar(createdCommand)), + tap((createdCommand: StateResource<CommandResource>) => this._afterCreateOrEditKommentar(createdCommand)), startWith(createEmptyStateResource<CommandResource>(true)), ); } - afterCreateOrEditKommentar(command: StateResource<CommandResource>): void { + _afterCreateOrEditKommentar(command: StateResource<CommandResource>): void { if (isDone(command.resource)) { this.hideFormular(); - this.setKommentarListReload(); + this._setKommentarListReload(); this.vorgangService.reloadCurrentVorgang(); } } - getAttachments(kommentar: KommentarResource): Observable<StateResource<BinaryFileListResource>> { + _getAttachments(kommentar: KommentarResource): Observable<StateResource<BinaryFileListResource>> { if (hasLink(kommentar, KommentarLinkRel.ATTACHMENTS)) { return this.binaryFileService.getFiles(kommentar, KommentarLinkRel.ATTACHMENTS); } diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.spec.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.spec.ts index 9753cc7fa2dafde144f13618d84c55a24b1bc1a3..4470d7d9b7d85481c65e909ef9e12fef63b59194 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.spec.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.spec.ts @@ -102,7 +102,7 @@ describe('KommentarFormComponent', () => { const patchSpy = jest.spyOn(KommentarFormService.prototype, 'patch').mockImplementation(); const kommentarResource = createKommentarResource([KommentarLinkRel.ATTACHMENTS]); component.kommentar = kommentarResource; - kommentarService.getAttachments.mockReturnValue(of(createStateResource(createBinaryFileListResource()))); + kommentarService._getAttachments.mockReturnValue(of(createStateResource(createBinaryFileListResource()))); component.ngOnChanges(); @@ -111,7 +111,7 @@ describe('KommentarFormComponent', () => { it('should load attachments', (done) => { component.kommentar = createKommentarResource([KommentarLinkRel.ATTACHMENTS]); - kommentarService.getAttachments.mockReturnValue(of(createStateResource(createBinaryFileListResource()))); + kommentarService._getAttachments.mockReturnValue(of(createStateResource(createBinaryFileListResource()))); component.ngOnChanges(); @@ -124,11 +124,11 @@ describe('KommentarFormComponent', () => { it('should call kommentarService', () => { const kommentarResource = createKommentarResource([KommentarLinkRel.ATTACHMENTS]); component.kommentar = kommentarResource; - kommentarService.getAttachments.mockReturnValue(of(createStateResource(createBinaryFileListResource()))); + kommentarService._getAttachments.mockReturnValue(of(createStateResource(createBinaryFileListResource()))); component.ngOnChanges(); - expect(kommentarService.getAttachments).toHaveBeenCalledWith(kommentarResource); + expect(kommentarService._getAttachments).toHaveBeenCalledWith(kommentarResource); }); describe('submit', () => { diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.ts index 0566d0f19efcc3e09aff3d5a726465eae21371d9..851cf4590f31bd8877ee22a935ca569c804c6aa1 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.ts @@ -23,7 +23,14 @@ */ import { BinaryFileListLinkRel, BinaryFileResource } from '@alfa-client/binary-file-shared'; import { CommandResource, tapOnCommandSuccessfullyDone } from '@alfa-client/command-shared'; -import { KOMMENTAR_UPLOADED_ATTACHMENTS, KommentarLinkRel, KommentarListLinkRel, KommentarListResource, KommentarResource, KommentarService, } from '@alfa-client/kommentar-shared'; +import { + KOMMENTAR_UPLOADED_ATTACHMENTS, + KommentarLinkRel, + KommentarListLinkRel, + KommentarListResource, + KommentarResource, + KommentarService, +} from '@alfa-client/kommentar-shared'; import { createEmptyStateResource, getEmbeddedResources, StateResource } from '@alfa-client/tech-shared'; import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core'; import { isNil } from 'lodash-es'; @@ -66,7 +73,7 @@ export class KommentarFormComponent implements OnChanges { private updateAttachments() { this.attachments$ = this.kommentarService - .getAttachments(this.kommentar) + ._getAttachments(this.kommentar) .pipe(map((stateResource) => getEmbeddedResources<BinaryFileResource>(stateResource, BinaryFileListLinkRel.FILE_LIST))); } diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts index 1fa11168673776f20130a7be5616abb0ac84380a..e27318f11b1c3ab1c1263586b23781a0f42b5606 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts @@ -127,7 +127,7 @@ describe('KommentarListInVorgangContainerComponent', () => { describe('reloadKommentarListOnVorgangReload', () => { beforeEach(() => { - kommentarService.setKommentarListReload.mockClear(); + kommentarService._setKommentarListReload.mockClear(); }); it('should call kommentarService', () => { @@ -138,7 +138,7 @@ describe('KommentarListInVorgangContainerComponent', () => { component.reloadKommentarListOnVorgangReload(); - expect(kommentarService.setKommentarListReload).toHaveBeenCalled(); + expect(kommentarService._setKommentarListReload).toHaveBeenCalled(); }); it('should not call kommentarService', () => { @@ -149,7 +149,7 @@ describe('KommentarListInVorgangContainerComponent', () => { component.reloadKommentarListOnVorgangReload(); - expect(kommentarService.setKommentarListReload).not.toHaveBeenCalled(); + expect(kommentarService._setKommentarListReload).not.toHaveBeenCalled(); }); }); diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.ts index 21d3159a29496a6927f7076de4734ff03c663f44..78bdbb63fd8a82dc06d7ea412d9967577796b64e 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.ts @@ -55,7 +55,7 @@ export class KommentarListInVorgangContainerComponent implements OnChanges, OnIn reloadKommentarListOnVorgangReload(): void { if (this.vorgangStateResource.reload) { - this.kommentarService.setKommentarListReload(); + this.kommentarService._setKommentarListReload(); } } diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach.service.spec.ts b/alfa-client/libs/postfach-shared/src/lib/postfach.service.spec.ts index 678219f735fd5882a763a535687688c630bd5045..9149471c8d22327948bb18ae382aeeeb45cafe32 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach.service.spec.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach.service.spec.ts @@ -35,7 +35,13 @@ import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; import { createCommandErrorResource, createCommandResource } from 'libs/command-shared/test/command'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; import { BehaviorSubject, of } from 'rxjs'; -import { createPostfachFeatures, createPostfachMail, createPostfachMailListResource, createPostfachMailResource, createPostfachSettings, } from '../../test/postfach'; +import { + createPostfachFeatures, + createPostfachMail, + createPostfachMailListResource, + createPostfachMailResource, + createPostfachSettings, +} from '../../test/postfach'; import { PostfachFacade } from './+state/postfach.facade'; import { PostfachMailLinkRel, PostfachMailListLinkRel } from './postfach.linkrel'; import { PostfachMessages } from './postfach.message'; @@ -50,7 +56,7 @@ describe('PostfachService', () => { let repository: Mock<PostfachRepository>; const commandService: Mock<CommandService> = mock(CommandService); const navigationService: Mock<NavigationService> = mock(NavigationService); - const vorgangService: Mock<VorgangService> = mock(VorgangService); + let vorgangService: Mock<VorgangService>; const snackbarService: Mock<SnackBarService> = mock(SnackBarService); const dialog: Mock<MatDialog> = <Mock<MatDialog>>{ closeAll: jest.fn() }; const postfachFacade: Mock<PostfachFacade> = mock(PostfachFacade); @@ -58,7 +64,14 @@ describe('PostfachService', () => { const urlChangedParams = {}; + const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource> = createStateResource(vorgang); + beforeEach(() => { + vorgangService = { + ...mock(VorgangService), + getVorgangWithEingang: jest.fn().mockReturnValue(of(vorgangWithEingangStateResource)), + }; navigationService.urlChanged = jest.fn(); navigationService.urlChanged.mockReturnValue(of(urlChangedParams)); @@ -114,7 +127,7 @@ describe('PostfachService', () => { describe('reload postfach list', () => { beforeEach(() => { - service.refreshPostfachMailList = jest.fn(); + service._refreshPostfachMailList = jest.fn(); }); it('should execute on command is done', () => { @@ -125,7 +138,7 @@ describe('PostfachService', () => { service.sendMail(postfachMail); - expect(service.refreshPostfachMailList).toHaveBeenCalledWith(commandStateResource); + expect(service._refreshPostfachMailList).toHaveBeenCalledWith(commandStateResource); }); it('should not execute on pending command', () => { @@ -133,7 +146,7 @@ describe('PostfachService', () => { service.sendMail(postfachMail); - expect(service.refreshPostfachMailList).not.toHaveBeenCalled(); + expect(service._refreshPostfachMailList).not.toHaveBeenCalled(); }); }); }); @@ -145,13 +158,13 @@ describe('PostfachService', () => { const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); it('should call doSendNachricht', () => { - service.doSendNachricht = jest.fn(); + service._doSendNachricht = jest.fn(); commandService.createCommand.mockReturnValue(of(commandStateResource)); vorgangService.getPendingSendPostfachMailCommand.mockReturnValue(of(commandStateResource)); service.sendExistingMail(postfachNachricht, nachricht); - expect(service.doSendNachricht).toHaveBeenCalledWith( + expect(service._doSendNachricht).toHaveBeenCalledWith( postfachNachricht, PostfachMailLinkRel.SEND, createSendPostfachMailCommand(nachricht), @@ -163,7 +176,7 @@ describe('PostfachService', () => { const postfachMailResource: PostfachMailResource = createPostfachMailResource(); beforeEach(() => { - service.handleSendPostfachMailIsDone = jest.fn(); + service._handleSendPostfachMailIsDone = jest.fn(); commandService.createCommand.mockReturnValue(of(createStateResource(createCommandResource()))); vorgangService.getPendingSendPostfachMailCommand.mockReturnValue(of(createStateResource(createCommandResource()))); @@ -191,7 +204,7 @@ describe('PostfachService', () => { commandService.createCommand.mockReturnValue(of(createStateResource(createCommandResource([CommandLinkRel.UPDATE])))); service.resendMail(postfachMailResource); - expect(service.handleSendPostfachMailIsDone).not.toHaveBeenCalled(); + expect(service._handleSendPostfachMailIsDone).not.toHaveBeenCalled(); }); it('should call handleSendPostfachMailIsDone if command is done', () => { @@ -202,7 +215,7 @@ describe('PostfachService', () => { service.resendMail(postfachMailResource); - expect(service.handleSendPostfachMailIsDone).toHaveBeenCalledWith(commandResponse); + expect(service._handleSendPostfachMailIsDone).toHaveBeenCalledWith(commandResponse); }); }); @@ -210,25 +223,25 @@ describe('PostfachService', () => { const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); beforeEach(() => { - service.commandIsDone = jest.fn(); + service._commandIsDone = jest.fn(); }); it('should call vorgang service', () => { - service.handleSendNachrichtCommand(commandStateResource); + service._handleSendNachrichtCommand(commandStateResource); expect(vorgangService.setPendingSendPostfachMailCommand).toHaveBeenCalledWith(commandStateResource); }); it('should call commandIsDone', () => { - service.handleSendNachrichtCommand(commandStateResource); + service._handleSendNachrichtCommand(commandStateResource); - expect(service.commandIsDone).toHaveBeenCalledWith(commandStateResource); + expect(service._commandIsDone).toHaveBeenCalledWith(commandStateResource); }); }); describe('commandIsDone', () => { beforeEach(() => { - service.handleSendPostfachMailIsDone = jest.fn(); + service._handleSendPostfachMailIsDone = jest.fn(); }); it('should call handleSendPostfachMailIsDone', () => { @@ -236,9 +249,9 @@ describe('PostfachService', () => { createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]), ); - service.commandIsDone(commandStateResource); + service._commandIsDone(commandStateResource); - expect(service.handleSendPostfachMailIsDone).toHaveBeenCalledWith(commandStateResource); + expect(service._handleSendPostfachMailIsDone).toHaveBeenCalledWith(commandStateResource); }); describe('on command is done', () => { @@ -248,7 +261,7 @@ describe('PostfachService', () => { errorMessage: null, }); - service.commandIsDone(commandStateResource); + service._commandIsDone(commandStateResource); expect(snackbarService.show).toHaveBeenCalledWith(commandStateResource.resource, PostfachMessages.SEND_SUCCESSFUL); }); @@ -260,7 +273,7 @@ describe('PostfachService', () => { createCommandErrorResource([CommandLinkRel.EFFECTED_RESOURCE]), ); - service.commandIsDone(commandStateResource); + service._commandIsDone(commandStateResource); expect(snackbarService.showError).toHaveBeenCalledWith(PostfachMessages.SEND_FAILED); }); @@ -269,58 +282,58 @@ describe('PostfachService', () => { describe('listenToNavigation', () => { it('should call usnsubcribeToNavigation', () => { - service.listenToNavigation(); + service._listenToNavigation(); expect(navigationService.urlChanged).toHaveBeenCalled(); }); it('should call navigation service', () => { - service.unsubscribeToNavigation = jest.fn(); + service._unsubscribeToNavigation = jest.fn(); - service.listenToNavigation(); + service._listenToNavigation(); - expect(service.unsubscribeToNavigation).toHaveBeenCalled(); + expect(service._unsubscribeToNavigation).toHaveBeenCalled(); }); it('should call onNavigation', () => { - service.onNavigation = jest.fn(); + service._onNavigation = jest.fn(); - service.listenToNavigation(); + service._listenToNavigation(); - expect(service.onNavigation).toHaveBeenCalledWith(urlChangedParams); + expect(service._onNavigation).toHaveBeenCalledWith(urlChangedParams); }); }); describe('onNavigation', () => { describe('to vorgang list', () => { beforeEach(() => { - service.setPollingFalse = jest.fn(); - service.clearPostfachMailList = jest.fn(); - service.unsubscribe = jest.fn(); + service._setPollingFalse = jest.fn(); + service._clearPostfachMailList = jest.fn(); + service._unsubscribe = jest.fn(); }); it('should set polling false', () => { - service.onNavigation({}); + service._onNavigation({}); - expect(service.setPollingFalse).toHaveBeenCalled(); + expect(service._setPollingFalse).toHaveBeenCalled(); }); it('should call clearPostfachMailList', () => { - service.onNavigation({}); + service._onNavigation({}); - expect(service.clearPostfachMailList).toHaveBeenCalled(); + expect(service._clearPostfachMailList).toHaveBeenCalled(); }); it('should call closeOpenDialogs', () => { - service.onNavigation({}); + service._onNavigation({}); expect(dialog.closeAll).toHaveBeenCalled(); }); it('should call unsubscribe', () => { - service.onNavigation({}); + service._onNavigation({}); - expect(service.unsubscribe).toHaveBeenCalled(); + expect(service._unsubscribe).toHaveBeenCalled(); }); }); @@ -328,7 +341,7 @@ describe('PostfachService', () => { it('should set postfach nachrichten list to reload', () => { service.postfachMailList$.next(createEmptyStateResource()); - service.onNavigation({ vorgangWithEingangUrl: 'X' }); + service._onNavigation({ vorgangWithEingangUrl: 'X' }); expect(service.postfachMailList$.value.reload).toEqual(true); }); @@ -336,12 +349,12 @@ describe('PostfachService', () => { describe('to postfach page', () => { beforeEach(() => { - service.resetHasNewPostfachNachrichten = jest.fn(); + service._resetHasNewPostfachNachrichten = jest.fn(); navigationService.isPostfachPage.mockReturnValue(true); }); it('should call navigationService', () => { - service.onNavigation({}); + service._onNavigation({}); expect(navigationService.isPostfachPage).toHaveBeenCalled(); }); @@ -349,17 +362,17 @@ describe('PostfachService', () => { it('should reset hasNewPostfachNachrichten', () => { navigationService.isPostfachPage.mockReturnValue(true); - service.onNavigation({}); + service._onNavigation({}); - expect(service.resetHasNewPostfachNachrichten).toHaveBeenCalled(); + expect(service._resetHasNewPostfachNachrichten).toHaveBeenCalled(); }); }); }); describe('getPendingSendPostfachMailCommand', () => { beforeEach(() => { - service.unsubscribe = jest.fn(); - service.pollSendPostfachMailCommand = jest.fn(); + service._unsubscribe = jest.fn(); + service._pollSendPostfachMailCommand = jest.fn(); commandService.pollCommand.mockReturnValue(of(createStateResource(createCommandResource()))); vorgangService.getPendingSendPostfachMailCommand.mockReturnValue(of(createStateResource(createCommandResource()))); @@ -377,12 +390,12 @@ describe('PostfachService', () => { it('should call doResetHasNewPostfachNachrichten', () => { service.getPostfachMailListByVorgang = jest.fn(); - service.doResetHasNewPostfachNachrichten = jest.fn(); + service._doResetHasNewPostfachNachrichten = jest.fn(); (<any>service.getPostfachMailListByVorgang).mockReturnValue(of(postfachListNachrichtenResource)); - service.resetHasNewPostfachNachrichten(); + service._resetHasNewPostfachNachrichten(); - expect(service.doResetHasNewPostfachNachrichten).toHaveBeenCalled(); + expect(service._doResetHasNewPostfachNachrichten).toHaveBeenCalled(); }); }); @@ -398,7 +411,7 @@ describe('PostfachService', () => { }); it('should call repository if link exists', () => { - service.doResetHasNewPostfachNachrichten(); + service._doResetHasNewPostfachNachrichten(); expect(repository.resetHasNewPostfachNachrichten).toHaveBeenCalledWith(postfachNachrichtenListResource); }); @@ -408,7 +421,7 @@ describe('PostfachService', () => { const postfachNachrichtenListResource: PostfachMailListResource = createPostfachMailListResource(); service.postfachMailList$.next(createStateResource(postfachNachrichtenListResource)); - service.doResetHasNewPostfachNachrichten(); + service._doResetHasNewPostfachNachrichten(); expect(repository.resetHasNewPostfachNachrichten).not.toHaveBeenCalled(); }); @@ -419,16 +432,23 @@ describe('PostfachService', () => { beforeEach(() => { repository.loadPostfachMailList.mockReturnValue(of(postfachMailList)); - service.setPostfachMailListLoading = jest.fn(); - service.setPostfachMailList = jest.fn(); + service._setPostfachMailListLoading = jest.fn(); + service._setPostfachMailList = jest.fn(); vorgangService.getVorgangWithEingang.mockReturnValue(of(createStateResource(createVorgangWithEingangResource()))); service.postfachMailList$.next(createEmptyStateResource()); + service._refreshVorgangSubscription = jest.fn(); + }); + + it('should call refresh vorgang subscription', () => { + service.getPostfachMailListByVorgang(); + + expect(service._refreshVorgangSubscription).toHaveBeenCalled(); }); it('should set loading to true', () => { service.getPostfachMailListByVorgang(); - expect(service.setPostfachMailListLoading).toHaveBeenCalled(); + expect(service._setPostfachMailListLoading).toHaveBeenCalled(); }); it('should call vorgang service', () => { @@ -446,7 +466,7 @@ describe('PostfachService', () => { it('should set loading to false', () => { service.getPostfachMailListByVorgang(); - expect(service.setPostfachMailList).toHaveBeenCalled(); + expect(service._setPostfachMailList).toHaveBeenCalled(); }); }); @@ -454,28 +474,28 @@ describe('PostfachService', () => { const stateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); beforeEach(() => { - service.setPollingFalse = jest.fn(); - service.setPostfachMailList = jest.fn(); + service._setPollingFalse = jest.fn(); + service._setPostfachMailList = jest.fn(); commandService.getEffectedResource.mockReturnValue(of(createCommandResource())); }); it('should call command service to get effected resource', () => { - service.handleSendPostfachMailIsDone(stateResource); + service._handleSendPostfachMailIsDone(stateResource); expect(commandService.getEffectedResource).toHaveBeenCalledWith(stateResource.resource); }); it('should set postfachMailList', () => { - service.handleSendPostfachMailIsDone(stateResource); + service._handleSendPostfachMailIsDone(stateResource); - expect(service.setPostfachMailList).toHaveBeenCalled(); + expect(service._setPostfachMailList).toHaveBeenCalled(); }); it('should set polling to false', () => { - service.handleSendPostfachMailIsDone(stateResource); + service._handleSendPostfachMailIsDone(stateResource); - expect(service.setPollingFalse).toHaveBeenCalled(); + expect(service._setPollingFalse).toHaveBeenCalled(); }); }); @@ -548,9 +568,68 @@ describe('PostfachService', () => { }); it('should clear uploaded files', () => { - service.closeOpenDialogs(); + service._closeOpenDialogs(); expect(service.clearUploadedFiles).toHaveBeenCalled(); }); }); + + describe('listen to vorgang change', () => { + beforeEach(() => { + service._handleVorgangChange = jest.fn(); + }); + + it('should call vorgang service to get vorgang with eingang', () => { + service._listenToVorgangChange(); + + expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); + }); + + it('should call handle vorgang change', () => { + service._listenToVorgangChange(); + + expect(service._handleVorgangChange).toHaveBeenCalledWith(vorgangWithEingangStateResource); + }); + }); + + describe('handle vorgang change', () => { + it('should set reload flag if list is loaded and state resource is loading', () => { + service.shouldReload = false; + service.postfachMailList$.next(createStateResource(createPostfachMailListResource())); + + service._handleVorgangChange({ ...vorgangWithEingangStateResource, loading: true }); + + expect(service.shouldReload).toBeTruthy(); + }); + + it('should set reload flag if list is loaded and state resource is reloading', () => { + service.postfachMailList$.next(createStateResource(createPostfachMailListResource())); + service.shouldReload = false; + + service._handleVorgangChange({ ...vorgangWithEingangStateResource, reload: true }); + + expect(service.shouldReload).toBeTruthy(); + }); + + describe('on setted reload flag', () => { + beforeEach(() => { + service._setPostfachMailOnReload = jest.fn(); + service.shouldReload = true; + }); + + describe('and loaded vorgang resource', () => { + it('should call set kommentar list reload', () => { + service._handleVorgangChange(vorgangWithEingangStateResource); + + expect(service._setPostfachMailOnReload).toHaveBeenCalled(); + }); + + it('and loaded vorgang resource should call set kommentar list reload', () => { + service._handleVorgangChange(vorgangWithEingangStateResource); + + expect(service.shouldReload).toBeFalsy(); + }); + }); + }); + }); }); diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach.service.ts b/alfa-client/libs/postfach-shared/src/lib/postfach.service.ts index e39019766d5f873a246643dec3c951cc4e2efd39..f650edd3f4c598a309482fe95658930794deaae8 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach.service.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach.service.ts @@ -23,11 +23,26 @@ */ import { POSTFACH_NACHRICHT_UPLOADED_ATTACHMENTS } from '@admin-client/postfach-shared'; import { BinaryFileService } from '@alfa-client/binary-file-shared'; -import { CommandResource, CommandService, doIfCommandIsDone, hasCommandError, isDone, isPending, } from '@alfa-client/command-shared'; +import { + CommandResource, + CommandService, + doIfCommandIsDone, + hasCommandError, + isDone, + isPending, +} from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { createEmptyStateResource, createStateResource, doIfLoadingRequired, isNotNull, isNotUndefined, StateResource, } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createStateResource, + doIfLoadingRequired, + isLoaded, + isNotNull, + isNotUndefined, + StateResource, +} from '@alfa-client/tech-shared'; import { SnackBarService } from '@alfa-client/ui'; -import { VorgangResource, VorgangService } from '@alfa-client/vorgang-shared'; +import { VorgangResource, VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { inject, Injectable } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { Params } from '@angular/router'; @@ -38,7 +53,14 @@ import { first, map, take, tap } from 'rxjs/operators'; import { PostfachFacade } from './+state/postfach.facade'; import { PostfachMailLinkRel, PostfachMailListLinkRel } from './postfach.linkrel'; import { PostfachMessages } from './postfach.message'; -import { CreatePostfachMailCommand, PostfachFeatures, PostfachMail, PostfachMailListResource, PostfachMailResource, PostfachSettings, } from './postfach.model'; +import { + CreatePostfachMailCommand, + PostfachFeatures, + PostfachMail, + PostfachMailListResource, + PostfachMailResource, + PostfachSettings, +} from './postfach.model'; import { PostfachRepository } from './postfach.repository'; import { createResendPostfachMailCommand, createSendPostfachMailCommand } from './postfach.util'; @@ -65,12 +87,17 @@ export class PostfachService { private vorgangSubscription: Subscription; private postfachNachrichtenListSubscription: Subscription; + private vorgangChangeSubscription: Subscription; + + shouldReload: boolean = false; + constructor() { - this.listenToNavigation(); + this._listenToNavigation(); + this._listenToVorgangChange(); } public sendMail(postfachMail: PostfachMail): Observable<StateResource<CommandResource>> { - return this.doSendNachricht( + return this._doSendNachricht( this.postfachMailList$.value.resource, PostfachMailListLinkRel.SEND_POSTFACH_MAIL, createSendPostfachMailCommand(postfachMail), @@ -81,18 +108,18 @@ export class PostfachService { postfachMailResource: PostfachMailResource, postfachMail: PostfachMail, ): Observable<StateResource<CommandResource>> { - return this.doSendNachricht(postfachMailResource, PostfachMailLinkRel.SEND, createSendPostfachMailCommand(postfachMail)); + return this._doSendNachricht(postfachMailResource, PostfachMailLinkRel.SEND, createSendPostfachMailCommand(postfachMail)); } public resendMail(postfachMailResource: PostfachMailResource): Observable<StateResource<CommandResource>> { - return this.doSendNachricht( + return this._doSendNachricht( postfachMailResource, PostfachMailLinkRel.RESEND_POSTFACH_MAIL, createResendPostfachMailCommand(), ); } - doSendNachricht( + _doSendNachricht( resource: Resource, linkRel: string, command: CreatePostfachMailCommand, @@ -102,20 +129,20 @@ export class PostfachService { this.commandService .createCommand(resource, linkRel, command) .pipe(first()) - .subscribe((createdCommand) => this.handleSendNachrichtCommand(createdCommand)); + .subscribe((createdCommand) => this._handleSendNachrichtCommand(createdCommand)); return this.getPendingSendPostfachMailCommand(); } - handleSendNachrichtCommand(commandStateResource: StateResource<CommandResource>): void { + _handleSendNachrichtCommand(commandStateResource: StateResource<CommandResource>): void { this.vorgangService.setPendingSendPostfachMailCommand(commandStateResource); - this.commandIsDone(commandStateResource); + this._commandIsDone(commandStateResource); } - commandIsDone(commandStateResource: StateResource<CommandResource>): void { + _commandIsDone(commandStateResource: StateResource<CommandResource>): void { doIfCommandIsDone(commandStateResource.resource, () => { this.showSnackbar(commandStateResource.resource); - this.handleSendPostfachMailIsDone(commandStateResource); + this._handleSendPostfachMailIsDone(commandStateResource); }); } @@ -130,79 +157,79 @@ export class PostfachService { public getPendingSendPostfachMailCommand(): Observable<StateResource<CommandResource>> { return this.vorgangService .getPendingSendPostfachMailCommand() - .pipe(map((pendingCommand) => this.pollSendPostfachMailCommand(pendingCommand))); + .pipe(map((pendingCommand) => this._pollSendPostfachMailCommand(pendingCommand))); } - listenToNavigation(): void { - this.unsubscribeToNavigation(); - this.navigationSubscription = this.navigationService.urlChanged().subscribe((params) => this.onNavigation(params)); + _listenToNavigation(): void { + this._unsubscribeToNavigation(); + this.navigationSubscription = this.navigationService.urlChanged().subscribe((params) => this._onNavigation(params)); } - unsubscribeToNavigation(): void { + _unsubscribeToNavigation(): void { if (!isNil(this.navigationSubscription)) this.navigationSubscription.unsubscribe(); } - onNavigation(params: Params): void { + _onNavigation(params: Params): void { if (NavigationService.isVorgangListPage(params)) { - this.setPollingFalse(); - this.clearPostfachMailList(); - this.closeOpenDialogs(); - this.unsubscribe(); + this._setPollingFalse(); + this._clearPostfachMailList(); + this._closeOpenDialogs(); + this._unsubscribe(); } if (NavigationService.isVorgangDetailPage(params, VorgangService.VORGANG_WITH_EINGANG_URL)) { - this.setPostfachMailOnReload(); + this._setPostfachMailOnReload(); } if (this.navigationService.isPostfachPage()) { - this.resetHasNewPostfachNachrichten(); + this._resetHasNewPostfachNachrichten(); } } - setPollingFalse(): void { + _setPollingFalse(): void { this.isPollSendPostachMail.next(false); } - clearPostfachMailList(): void { + _clearPostfachMailList(): void { this.postfachMailList$.next(createEmptyStateResource<PostfachMailListResource>()); } - closeOpenDialogs(): void { + _closeOpenDialogs(): void { this.dialog.closeAll(); this.clearUploadedFiles(); } - unsubscribe(): void { + _unsubscribe(): void { if (isNotUndefined(this.sendPostfachMailSubscription)) this.sendPostfachMailSubscription.unsubscribe(); if (isNotUndefined(this.loadPostfachMailSubscription)) this.loadPostfachMailSubscription.unsubscribe(); if (isNotUndefined(this.vorgangSubscription)) this.vorgangSubscription.unsubscribe(); } - setPostfachMailOnReload(): void { + _setPostfachMailOnReload(): void { this.postfachMailList$.next({ ...this.postfachMailList$.value, reload: true }); } - resetHasNewPostfachNachrichten(): void { + _resetHasNewPostfachNachrichten(): void { this.postfachNachrichtenListSubscription = this.getPostfachMailListByVorgang().subscribe((postfachNachrichtenList) => { if (isNotNull(postfachNachrichtenList.resource)) { setTimeout(() => this.postfachNachrichtenListSubscription.unsubscribe(), 0); - this.doResetHasNewPostfachNachrichten(); + this._doResetHasNewPostfachNachrichten(); } }); } - doResetHasNewPostfachNachrichten(): void { + _doResetHasNewPostfachNachrichten(): void { if (hasLink(this.postfachMailList$.value.resource, PostfachMailListLinkRel.RESET_HAS_NEW_POSTFACH_NACHRICHT)) { this.repository.resetHasNewPostfachNachrichten(this.postfachMailList$.value.resource).pipe(take(1)).subscribe(); } } - pollSendPostfachMailCommand(command: StateResource<CommandResource>): StateResource<CommandResource> { + _pollSendPostfachMailCommand(command: StateResource<CommandResource>): StateResource<CommandResource> { if (this.shouldPoll(command)) { - this.setPollingTrue(); + this._setPollingTrue(); this.sendPostfachMailSubscription = this.commandService.pollCommand(command.resource).subscribe((updatedStateResource) => { this.vorgangService.setPendingSendPostfachMailCommand(updatedStateResource); if (isDone(updatedStateResource.resource)) { - this.handleSendPostfachMailIsDone(updatedStateResource); + this._handleSendPostfachMailIsDone(updatedStateResource); setTimeout(() => this.sendPostfachMailSubscription.unsubscribe(), 0); } }); @@ -214,39 +241,40 @@ export class PostfachService { return command.loaded && isPending(command.resource) && !this.isPollSendPostachMail.value; } - setPollingTrue(): void { + _setPollingTrue(): void { this.isPollSendPostachMail.next(true); } - handleSendPostfachMailIsDone(updatedStateResource: StateResource<CommandResource>): void { - this.refreshPostfachMailList(updatedStateResource); - this.setPollingFalse(); + _handleSendPostfachMailIsDone(updatedStateResource: StateResource<CommandResource>): void { + this._refreshPostfachMailList(updatedStateResource); + this._setPollingFalse(); } - refreshPostfachMailList(updatedStateResource: StateResource<CommandResource>): void { - this.setPostfachMailListLoading(); - this.getEffectedResource(updatedStateResource) + _refreshPostfachMailList(updatedStateResource: StateResource<CommandResource>): void { + this._setPostfachMailListLoading(); + this._getEffectedResource(updatedStateResource) .pipe(first()) .subscribe((effectedResource) => { - this.setPostfachMailList(effectedResource); + this._setPostfachMailList(effectedResource); }); } - getEffectedResource(updatedStateResource: StateResource<CommandResource>): Observable<PostfachMailListResource> { + _getEffectedResource(updatedStateResource: StateResource<CommandResource>): Observable<PostfachMailListResource> { return this.commandService.getEffectedResource<PostfachMailListResource>(updatedStateResource.resource); } public getPostfachMailListByGivenVorgang(vorgang: VorgangResource): Observable<StateResource<PostfachMailListResource>> { doIfLoadingRequired(this.postfachMailList$.value, () => { - this.setPostfachMailListLoading(); + this._setPostfachMailListLoading(); this.loadPostfachMailsByVorgang(vorgang); }); return this.postfachMailList$.asObservable(); } public getPostfachMailListByVorgang(): Observable<StateResource<PostfachMailListResource>> { + this._refreshVorgangSubscription(); doIfLoadingRequired(this.postfachMailList$.value, () => { - this.setPostfachMailListLoading(); + this._setPostfachMailListLoading(); this.vorgangSubscription = this.vorgangService.getVorgangWithEingang().subscribe((vorgangWithEingangStateResource) => { if (vorgangWithEingangStateResource.resource) { this.loadPostfachMailsByVorgang(vorgangWithEingangStateResource.resource); @@ -257,20 +285,50 @@ export class PostfachService { return this.postfachMailList$.asObservable(); } - setPostfachMailListLoading(): void { + _refreshVorgangSubscription(): void { + this.vorgangChangeSubscription.unsubscribe(); + this._listenToVorgangChange(); + } + + _listenToVorgangChange(): void { + this.vorgangChangeSubscription = this.vorgangService + .getVorgangWithEingang() + .subscribe((vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource>) => + this._handleVorgangChange(vorgangWithEingangStateResource), + ); + } + + _handleVorgangChange(vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource>): void { + if (this.shouldReloadList(vorgangWithEingangStateResource)) { + this.shouldReload = true; + } + if (isLoaded(vorgangWithEingangStateResource) && this.shouldReload) { + this._setPostfachMailOnReload(); + this.shouldReload = false; + } + } + + private shouldReloadList(vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource>): boolean { + return ( + (vorgangWithEingangStateResource.loading || vorgangWithEingangStateResource.reload) && + isNotNull(this.postfachMailList$.value.resource) + ); + } + + _setPostfachMailListLoading(): void { this.postfachMailList$.next({ ...this.postfachMailList$.value, loading: true }); } public loadPostfachMailsByVorgang(vorgang: VorgangResource): void { this.loadPostfachMailSubscription = this.repository.loadPostfachMailList(vorgang).subscribe((postfachMaiList) => { if (!isNull(postfachMaiList)) { - this.setPostfachMailList(postfachMaiList); + this._setPostfachMailList(postfachMaiList); setTimeout(() => this.loadPostfachMailSubscription.unsubscribe(), 0); } }); } - setPostfachMailList(postfachMailList: PostfachMailListResource): void { + _setPostfachMailList(postfachMailList: PostfachMailListResource): void { this.postfachMailList$.next(createStateResource(postfachMailList)); } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.spec.ts index f2b47f34a70349440a1b12df07830044472fc724..62804bcc27411f45fac774d32995f4267b2162f7 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.spec.ts @@ -82,7 +82,7 @@ describe('PostfachMailListContainerComponent', () => { describe('reloadPostfachMailListOnVorgangReload', () => { beforeEach(() => { - postfachService.setPostfachMailOnReload.mockClear(); + postfachService._setPostfachMailOnReload.mockClear(); }); it('should call postfachService', () => { @@ -93,7 +93,7 @@ describe('PostfachMailListContainerComponent', () => { component.reloadPostfachMailListOnVorgangReload(); - expect(postfachService.setPostfachMailOnReload).toHaveBeenCalled(); + expect(postfachService._setPostfachMailOnReload).toHaveBeenCalled(); }); it('should not call postfachService', () => { @@ -104,7 +104,7 @@ describe('PostfachMailListContainerComponent', () => { component.reloadPostfachMailListOnVorgangReload(); - expect(postfachService.setPostfachMailOnReload).not.toHaveBeenCalled(); + expect(postfachService._setPostfachMailOnReload).not.toHaveBeenCalled(); }); }); }); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.ts index 70ae1c3856ad88ebe07b61aaf03b800b79d5fd7a..14c858585f1b747ec7175b1d717c13f23e44d547 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.ts @@ -21,10 +21,10 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { Component, Input, OnChanges } from '@angular/core'; import { ON_PAGE, PostfachMailListResource, PostfachService } from '@alfa-client/postfach-shared'; import { isNotNull, StateResource } from '@alfa-client/tech-shared'; import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { Component, Input, OnChanges } from '@angular/core'; import { Observable } from 'rxjs'; @Component({ @@ -51,7 +51,7 @@ export class PostfachMailListContainerComponent implements OnChanges { reloadPostfachMailListOnVorgangReload(): void { if (this.vorgangStateResource.reload) { - this.postfachService.setPostfachMailOnReload(); + this.postfachService._setPostfachMailOnReload(); } } } diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.spec.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.spec.ts index 4d6c0e5ba0bca3a14b4e33d989d737fa379552ff..13e5fcd714c9800fd2dbd9b8fdacc3135037bd58 100644 --- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.spec.ts +++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.spec.ts @@ -24,7 +24,6 @@ import { BinaryFileService } from '@alfa-client/binary-file-shared'; import { CommandOrder, CommandResource, CommandService } from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import * as TechShared from '@alfa-client/tech-shared'; import { createEmptyStateResource, createStateResource, decodeUrlFromEmbedding, StateResource } from '@alfa-client/tech-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; import { SnackBarService } from '@alfa-client/ui'; @@ -35,14 +34,25 @@ import { cold, hot } from 'jest-marbles'; import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; import { createCommandResource } from 'libs/command-shared/test/command'; import { createVorgangResource, createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; -import { createWiedervorlage, createWiedervorlageListResource, createWiedervorlageResource, } from 'libs/wiedervorlage-shared/test/wiedervorlage'; -import { of } from 'rxjs'; +import { + createWiedervorlage, + createWiedervorlageListResource, + createWiedervorlageResource, +} from 'libs/wiedervorlage-shared/test/wiedervorlage'; +import { of, Subscription } from 'rxjs'; import { WiedervorlageLinkRel, WiedervorlageListLinkRel } from './wiedervorlage.linkrel'; import { WiedervorlageMessages } from './wiedervorlage.message'; -import { Wiedervorlage, WIEDERVORLAGE_UPLOADED_ATTACHMENTS, WiedervorlageListResource, WiedervorlageResource, } from './wiedervorlage.model'; +import { + Wiedervorlage, + WIEDERVORLAGE_UPLOADED_ATTACHMENTS, + WiedervorlageListResource, + WiedervorlageResource, +} from './wiedervorlage.model'; import { WiedervorlageRepository } from './wiedervorlage.repository'; import { WiedervorlageService } from './wiedervorlage.service'; +import * as TechShared from '@alfa-client/tech-shared'; + jest.mock('@alfa-client/tech-shared', () => mockAsEsModule('@alfa-client/tech-shared')); function mockAsEsModule(module: string) { @@ -59,11 +69,14 @@ describe('WiedervorlageService', () => { let commandService: Mock<CommandService>; let snackbarService: Mock<SnackBarService>; let binaryFileService: Mock<BinaryFileService>; - let vorgangService: Mock<VorgangService> = mock(VorgangService); + let vorgangService: Mock<VorgangService>; const vorgangResource: VorgangWithEingangResource = createVorgangWithEingangResource(); + const vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource> = createStateResource(vorgangResource); + const wiedervorlageResource: WiedervorlageResource = createWiedervorlageResource(); const wiedervorlage: Wiedervorlage = createWiedervorlage(); + const commandResource: CommandResource = createCommandResource(); const commandResourceWithEffectedResourceLink: CommandResource = createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]); @@ -73,7 +86,10 @@ describe('WiedervorlageService', () => { commandService = mock(CommandService); snackbarService = mock(SnackBarService); binaryFileService = mock(BinaryFileService); - vorgangService = mock(VorgangService); + vorgangService = { + ...mock(VorgangService), + getVorgangWithEingang: jest.fn().mockReturnValue(of(vorgangWithEingangStateResource)), + }; navigationService.urlChanged.mockReturnValue(of({})); @@ -93,10 +109,6 @@ describe('WiedervorlageService', () => { const vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource> = createStateResource(vorgangResource); - beforeEach(() => { - vorgangService.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); - }); - it('should call vorgangFacade getVorgangWithEingang', () => { service.getWiedervorlageList(); @@ -113,11 +125,11 @@ describe('WiedervorlageService', () => { }); it.skip('should call loadWiedervorlagenByVorgang if required', (done) => { - service.loadWiedervorlagenByVorgang = jest.fn(); + service._loadWiedervorlagenByVorgang = jest.fn(); // service.wiedervorlageList$.next({ ...wiedervorlageListStateResource, reload: true }); service.getWiedervorlageList().subscribe((list) => { - expect(service.loadWiedervorlagenByVorgang).toHaveBeenCalled(); + expect(service._loadWiedervorlagenByVorgang).toHaveBeenCalled(); done(); }); // expect(service.loadWiedervorlagenByVorgang).toHaveBeenCalled(); @@ -127,12 +139,12 @@ describe('WiedervorlageService', () => { }); it('should NOT call loadWiedervorlagenByVorgang if already loaded', () => { - service.loadWiedervorlagenByVorgang = jest.fn(); + service._loadWiedervorlagenByVorgang = jest.fn(); service.wiedervorlageList$.asObservable = jest.fn().mockReturnValue(of(wiedervorlageListStateResource)); service.getWiedervorlageList(); - expect(service.loadWiedervorlagenByVorgang).not.toHaveBeenCalled(); + expect(service._loadWiedervorlagenByVorgang).not.toHaveBeenCalled(); }); }); @@ -142,6 +154,16 @@ describe('WiedervorlageService', () => { const wiedervorlageListStateResource: StateResource<WiedervorlageListResource> = createStateResource(wiedervorlageListResource); + beforeEach(() => { + service._refreshVorgangSubscription = jest.fn(); + }); + + it('should call refresh vorgang subscription', () => { + service.getWiedervorlageListByGivenVorgang(vorgang); + + expect(service._refreshVorgangSubscription).toHaveBeenCalled(); + }); + it('should return initial value', () => { service.wiedervorlageList$.asObservable = jest.fn().mockReturnValue(hot('-a', { a: wiedervorlageListResource })); @@ -151,21 +173,39 @@ describe('WiedervorlageService', () => { }); it('should load wiedervorlagen by vorgang if required', () => { - service.loadWiedervorlagenByVorgang = jest.fn(); + service._loadWiedervorlagenByVorgang = jest.fn(); service.wiedervorlageList$.next(createEmptyStateResource()); service.getWiedervorlageListByGivenVorgang(vorgang).subscribe(); - expect(service.loadWiedervorlagenByVorgang).toHaveBeenCalledWith(vorgang); + expect(service._loadWiedervorlagenByVorgang).toHaveBeenCalledWith(vorgang); }); it('should NOT load wiedervorlagen by vorgang if already loaded', () => { - service.loadWiedervorlagenByVorgang = jest.fn(); + service._loadWiedervorlagenByVorgang = jest.fn(); service.wiedervorlageList$.next(wiedervorlageListStateResource); service.getWiedervorlageListByGivenVorgang(vorgang).subscribe(); - expect(service.loadWiedervorlagenByVorgang).not.toHaveBeenCalled(); + expect(service._loadWiedervorlagenByVorgang).not.toHaveBeenCalled(); + }); + }); + + describe('refresh vorgang subscription', () => { + beforeEach(() => { + service.vorgangSubscription = <any>mock(Subscription); + service._listenToVorgangChange = jest.fn(); + }); + + it('should unsubscribe existing subscription', () => { + service._refreshVorgangSubscription(); + + expect(service.vorgangSubscription.unsubscribe).toHaveBeenCalled(); + }); + it('should call listen to vorgang change', () => { + service._refreshVorgangSubscription(); + + expect(service._listenToVorgangChange).toHaveBeenCalled(); }); }); @@ -187,11 +227,11 @@ describe('WiedervorlageService', () => { }); it('should set loading to true', () => { - service.setWiedervorlageLoading = jest.fn(); + service._setWiedervorlageLoading = jest.fn(); service.getWiedervorlage().subscribe(); - expect(service.setWiedervorlageLoading).toHaveBeenCalled(); + expect(service._setWiedervorlageLoading).toHaveBeenCalled(); }); it('should call navigationService', () => { @@ -251,12 +291,12 @@ describe('WiedervorlageService', () => { }); it('should call proceedAfterRecieveCommand', () => { - service.proceedAfterReceiveCommand = jest.fn(); + service._proceedAfterReceiveCommand = jest.fn(); service.saveWiedervorlage(wiedervorlageResource, wiedervorlage).subscribe(); const expectedMessage = WiedervorlageMessages.SAVED.replace('{betreff}', wiedervorlage.betreff); - expect(service.proceedAfterReceiveCommand).toHaveBeenCalledWith( + expect(service._proceedAfterReceiveCommand).toHaveBeenCalledWith( createStateResource(commandResourceWithEffectedResourceLink), expectedMessage, ); @@ -296,12 +336,12 @@ describe('WiedervorlageService', () => { }); it('should call proceedAfterReceiveCommand', () => { - service.proceedAfterReceiveCommand = jest.fn(); + service._proceedAfterReceiveCommand = jest.fn(); service.createWiedervorlage(wiedervorlage).subscribe(); const expectedMessage = WiedervorlageMessages.CREATED.replace('{betreff}', wiedervorlage.betreff); - expect(service.proceedAfterReceiveCommand).toHaveBeenCalledWith(createStateResource(commandResource), expectedMessage); + expect(service._proceedAfterReceiveCommand).toHaveBeenCalledWith(createStateResource(commandResource), expectedMessage); }); }); @@ -311,13 +351,13 @@ describe('WiedervorlageService', () => { }); it('should set reload on wiedervorlageList', () => { - service.proceedAfterReceiveCommand(createStateResource(commandResourceWithEffectedResourceLink), null); + service._proceedAfterReceiveCommand(createStateResource(commandResourceWithEffectedResourceLink), null); expect(service.wiedervorlageList$.value.reload).toBe(true); }); it('should do nothing on apiError', () => { - service.proceedAfterReceiveCommand(createEmptyStateResource(), null); + service._proceedAfterReceiveCommand(createEmptyStateResource(), null); expect(service.wiedervorlageList$.value.reload).toBe(false); }); @@ -326,13 +366,13 @@ describe('WiedervorlageService', () => { snackbarService.show = jest.fn(); const snackbarMessage: string = 'XX wurde XX'; - service.proceedAfterReceiveCommand(createStateResource(commandResourceWithEffectedResourceLink), snackbarMessage); + service._proceedAfterReceiveCommand(createStateResource(commandResourceWithEffectedResourceLink), snackbarMessage); expect(snackbarService.show).toHaveBeenCalledWith(commandResourceWithEffectedResourceLink, snackbarMessage); }); it('should clear uploaded files', () => { - service.proceedAfterReceiveCommand(createStateResource(commandResourceWithEffectedResourceLink), null); + service._proceedAfterReceiveCommand(createStateResource(commandResourceWithEffectedResourceLink), null); expect(service.clearUploadedFiles).toHaveBeenCalled(); }); @@ -421,7 +461,7 @@ describe('WiedervorlageService', () => { it('should call service if command is done', () => { const commandResource: CommandResource = createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]); - service.showSnackBar(commandResource, message); + service._showSnackBar(commandResource, message); expect(snackbarService.show).toHaveBeenCalledWith(commandResource, message); }); @@ -429,7 +469,7 @@ describe('WiedervorlageService', () => { it('should NOT call service if command is pending', () => { const commandResource: CommandResource = createCommandResource(); - service.showSnackBar(commandResource, message); + service._showSnackBar(commandResource, message); expect(snackbarService.show).not.toHaveBeenCalled(); }); @@ -439,14 +479,14 @@ describe('WiedervorlageService', () => { beforeEach(() => { (<any>service).navigateToVorgangDetailPage = jest.fn(); - service.setWiedervorlageListReload = jest.fn(); + service._setWiedervorlageListReload = jest.fn(); (<any>service).forceWiedervorlageReload = jest.fn(); - service.clearWiedervorlagenList = jest.fn(); + service._clearWiedervorlagenList = jest.fn(); service.clearUploadedFiles = jest.fn(); }); it('should clear uploaded files', () => { - service.onNavigation({}); + service._onNavigation({}); expect(service.clearUploadedFiles).toHaveBeenCalled(); }); @@ -457,13 +497,13 @@ describe('WiedervorlageService', () => { }); it('should set wiedervorlage list on reload', () => { - service.onNavigation({}); + service._onNavigation({}); - expect(service.setWiedervorlageListReload).toHaveBeenCalled(); + expect(service._setWiedervorlageListReload).toHaveBeenCalled(); }); it('should set wiedervorlage on reload', () => { - service.onNavigation({}); + service._onNavigation({}); expect((<any>service).forceWiedervorlageReload).toHaveBeenCalled(); }); @@ -471,9 +511,9 @@ describe('WiedervorlageService', () => { describe('to vorgang list', () => { it('should clear list', () => { - service.onNavigation({}); + service._onNavigation({}); - expect(service.clearWiedervorlagenList).toHaveBeenCalled(); + expect(service._clearWiedervorlagenList).toHaveBeenCalled(); }); }); }); @@ -534,4 +574,63 @@ describe('WiedervorlageService', () => { expect(binaryFileService.clearUploadedFiles).toHaveBeenCalledWith(WIEDERVORLAGE_UPLOADED_ATTACHMENTS); }); }); + + describe('listen to vorgang change', () => { + beforeEach(() => { + service._handleVorgangChange = jest.fn(); + }); + + it('should call vorgang service to get vorgang with eingang', () => { + service._listenToVorgangChange(); + + expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); + }); + + it('should call handle vorgang change', () => { + service._listenToVorgangChange(); + + expect(service._handleVorgangChange).toHaveBeenCalledWith(vorgangWithEingangStateResource); + }); + }); + + describe('handle vorgang change', () => { + it('should set reload flag if list is loaded and state resource is loading', () => { + service.shouldReload = false; + service.wiedervorlageList$.next(createStateResource(createWiedervorlageListResource())); + + service._handleVorgangChange({ ...vorgangWithEingangStateResource, loading: true }); + + expect(service.shouldReload).toBeTruthy(); + }); + + it('should set reload flag if list is loaded and state resource is reloading', () => { + service.wiedervorlageList$.next(createStateResource(createWiedervorlageListResource())); + service.shouldReload = false; + + service._handleVorgangChange({ ...vorgangWithEingangStateResource, reload: true }); + + expect(service.shouldReload).toBeTruthy(); + }); + + describe('on setted reload flag', () => { + beforeEach(() => { + service._setWiedervorlageListReload = jest.fn(); + service.shouldReload = true; + }); + + describe('and loaded vorgang resource', () => { + it('should call set wiedervorlage list reload', () => { + service._handleVorgangChange(vorgangWithEingangStateResource); + + expect(service._setWiedervorlageListReload).toHaveBeenCalled(); + }); + + it('and loaded vorgang resource should call set wiedervorlage list reload', () => { + service._handleVorgangChange(vorgangWithEingangStateResource); + + expect(service.shouldReload).toBeFalsy(); + }); + }); + }); + }); }); diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.ts index 208bf667e34a682bf13a4022276667409c9f4831..6590ff67384d09ef8d8f46a867bfdfb9536648a3 100644 --- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.ts +++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.ts @@ -24,9 +24,20 @@ import { BinaryFileService } from '@alfa-client/binary-file-shared'; import { CommandOrder, CommandResource, CommandService, CreateCommand, isDone } from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { createEmptyStateResource, createStateResource, decodeUrlFromEmbedding, doIfLoadingRequired, hasStateResourceError, isNotNull, isNotUndefined, replacePlaceholder, StateResource, } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createStateResource, + decodeUrlFromEmbedding, + doIfLoadingRequired, + hasStateResourceError, + isLoaded, + isNotNull, + isNotUndefined, + replacePlaceholder, + StateResource, +} from '@alfa-client/tech-shared'; import { SnackBarService } from '@alfa-client/ui'; -import { VorgangHeaderLinkRel, VorgangResource, VorgangService } from '@alfa-client/vorgang-shared'; +import { VorgangHeaderLinkRel, VorgangResource, VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { Injectable, OnDestroy } from '@angular/core'; import { Params } from '@angular/router'; import { hasLink, ResourceUri } from '@ngxp/rest'; @@ -35,7 +46,12 @@ import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs'; import { filter, map, startWith, tap } from 'rxjs/operators'; import { WiedervorlageLinkRel, WiedervorlageListLinkRel } from './wiedervorlage.linkrel'; import { WiedervorlageMessages } from './wiedervorlage.message'; -import { Wiedervorlage, WIEDERVORLAGE_UPLOADED_ATTACHMENTS, WiedervorlageListResource, WiedervorlageResource, } from './wiedervorlage.model'; +import { + Wiedervorlage, + WIEDERVORLAGE_UPLOADED_ATTACHMENTS, + WiedervorlageListResource, + WiedervorlageResource, +} from './wiedervorlage.model'; import { WiedervorlageRepository } from './wiedervorlage.repository'; import { WiedervorlageRoutes } from './wiedervorlage.route'; import { createErledigenCommand, createWiedereroeffnenCommand } from './wiedervorlage.util'; @@ -62,7 +78,10 @@ export class WiedervorlageService implements OnDestroy { StateResource<CommandResource> >(createEmptyStateResource<CommandResource>()); + shouldReload: boolean = false; + private subscription: Subscription; + vorgangSubscription: Subscription; constructor( private repository: WiedervorlageRepository, @@ -73,13 +92,14 @@ export class WiedervorlageService implements OnDestroy { private vorgangService: VorgangService, ) { this.listenToNavigation(); + this._listenToVorgangChange(); } public getWiedervorlageList(): Observable<StateResource<WiedervorlageListResource>> { return combineLatest([this.wiedervorlageList$.asObservable(), this.vorgangService.getVorgangWithEingang()]).pipe( tap(([wiedervorlageList, vorgangResource]) => { if (isNotNull(vorgangResource.resource)) { - doIfLoadingRequired(wiedervorlageList, () => this.loadWiedervorlagenByVorgang(vorgangResource.resource)); + doIfLoadingRequired(wiedervorlageList, () => this._loadWiedervorlagenByVorgang(vorgangResource.resource)); } }), map(([wiedervorlageList]) => wiedervorlageList), @@ -90,20 +110,51 @@ export class WiedervorlageService implements OnDestroy { public getWiedervorlageListByGivenVorgang( vorgangResource: VorgangResource, ): Observable<StateResource<WiedervorlageListResource>> { - doIfLoadingRequired(this.wiedervorlageList$.value, () => this.loadWiedervorlagenByVorgang(vorgangResource)); + this._refreshVorgangSubscription(); + doIfLoadingRequired(this.wiedervorlageList$.value, () => this._loadWiedervorlagenByVorgang(vorgangResource)); return this.wiedervorlageList$.asObservable(); } - loadWiedervorlagenByVorgang(vorgangResource: VorgangResource): void { + _refreshVorgangSubscription(): void { + this.vorgangSubscription.unsubscribe(); + this._listenToVorgangChange(); + } + + _listenToVorgangChange(): void { + this.vorgangSubscription = this.vorgangService + .getVorgangWithEingang() + .subscribe((vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource>) => + this._handleVorgangChange(vorgangWithEingangStateResource), + ); + } + + _handleVorgangChange(vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource>): void { + if (this.shouldReloadList(vorgangWithEingangStateResource)) { + this.shouldReload = true; + } + if (isLoaded(vorgangWithEingangStateResource) && this.shouldReload) { + this._setWiedervorlageListReload(); + this.shouldReload = false; + } + } + + private shouldReloadList(vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource>): boolean { + return ( + (vorgangWithEingangStateResource.loading || vorgangWithEingangStateResource.reload) && + isNotNull(this.wiedervorlageList$.value.resource) + ); + } + + _loadWiedervorlagenByVorgang(vorgangResource: VorgangResource): void { if (hasLink(vorgangResource, VorgangHeaderLinkRel.WIEDERVORLAGEN)) { const subscription: Subscription = this.repository.getWiedervorlageList(vorgangResource).subscribe((wiedervorlagenList) => { if (!isNull(wiedervorlagenList)) { - this.setWiedervorlagenList(wiedervorlagenList); + this._setWiedervorlagenList(wiedervorlagenList); subscription.unsubscribe(); } }); } else { - this.clearWiedervorlagenList(); + this._clearWiedervorlagenList(); } } @@ -116,7 +167,7 @@ export class WiedervorlageService implements OnDestroy { ); } - setWiedervorlagenList(wiedervorlagenList: WiedervorlageListResource): void { + _setWiedervorlagenList(wiedervorlagenList: WiedervorlageListResource): void { this.wiedervorlageList$.next(createStateResource(wiedervorlagenList)); } @@ -128,13 +179,13 @@ export class WiedervorlageService implements OnDestroy { } private updateWiedervorlage(): void { - this.setWiedervorlageLoading(); + this._setWiedervorlageLoading(); this.loadAndSetWiedervorlageByUrl(this.getWiedervorlageUri()); } private loadAndSetWiedervorlageByUrl(url: ResourceUri): void { - this.setWiedervorlageLoading(); + this._setWiedervorlageLoading(); const subscription: Subscription = this.repository.getWiedervorlage(url).subscribe((wiedervorlage) => { this.wiedervorlage$.next(createStateResource(wiedervorlage)); @@ -148,23 +199,23 @@ export class WiedervorlageService implements OnDestroy { private listenToNavigation(): void { this.unsubscribe(); - this.subscription = this.navigationService.urlChanged().subscribe((params) => this.onNavigation(params)); + this.subscription = this.navigationService.urlChanged().subscribe((params) => this._onNavigation(params)); } - onNavigation(params: Params): void { + _onNavigation(params: Params): void { this.clearUploadedFiles(); if (this.navigateToVorgangDetailPage(params)) { - this.setWiedervorlageListReload(); + this._setWiedervorlageListReload(); this.forceWiedervorlageReload(); this.submitInProgress$.next(createEmptyStateResource<CommandResource>()); } if (NavigationService.isVorgangListPage(params)) { - this.clearWiedervorlagenList(); + this._clearWiedervorlagenList(); this.submitInProgress$.next(createEmptyStateResource<CommandResource>()); } } - clearWiedervorlagenList(): void { + _clearWiedervorlagenList(): void { this.wiedervorlageList$.next(createEmptyStateResource<WiedervorlageListResource>()); } @@ -183,23 +234,23 @@ export class WiedervorlageService implements OnDestroy { return this.navigationService.getDecodedParam(WiedervorlageService.encodedWiedervorlageUriParam); } - setWiedervorlageLoading(): void { + _setWiedervorlageLoading(): void { this.wiedervorlage$.next({ ...this.wiedervorlage$.value, loading: true }); } public createWiedervorlage(wiedervorlage: Wiedervorlage): Observable<StateResource<CommandResource>> { this.setSubmitInProgressLoading(); - return this.createCreateWiedervorlageCommand(this.wiedervorlageList$.value.resource, wiedervorlage).pipe( + return this._createCreateWiedervorlageCommand(this.wiedervorlageList$.value.resource, wiedervorlage).pipe( filter((commandStateResource) => !commandStateResource.loading), tap((commandStateResource) => - this.proceedAfterReceiveCommand(commandStateResource, this.buildMessage(WiedervorlageMessages.CREATED, wiedervorlage)), + this._proceedAfterReceiveCommand(commandStateResource, this.buildMessage(WiedervorlageMessages.CREATED, wiedervorlage)), ), startWith(createEmptyStateResource<CommandResource>(true)), ); } - createCreateWiedervorlageCommand( + _createCreateWiedervorlageCommand( wiedervorlageListResource: WiedervorlageListResource, wiedervorlage: Wiedervorlage, ): Observable<StateResource<CommandResource>> { @@ -220,10 +271,10 @@ export class WiedervorlageService implements OnDestroy { ): Observable<StateResource<CommandResource>> { this.setSubmitInProgressLoading(); - return this.createSaveWiedervorlageCommand(wiedervorlageResource, wiedervorlage).pipe( + return this._createSaveWiedervorlageCommand(wiedervorlageResource, wiedervorlage).pipe( filter((commandStateResource) => !commandStateResource.loading), tap((commandStateResource) => - this.proceedAfterReceiveCommand(commandStateResource, this.buildMessage(WiedervorlageMessages.SAVED, wiedervorlage)), + this._proceedAfterReceiveCommand(commandStateResource, this.buildMessage(WiedervorlageMessages.SAVED, wiedervorlage)), ), startWith(createEmptyStateResource<CommandResource>(true)), ); @@ -233,7 +284,7 @@ export class WiedervorlageService implements OnDestroy { this.submitInProgress$.next({ ...this.submitInProgress$.value, loading: true }); } - createSaveWiedervorlageCommand( + _createSaveWiedervorlageCommand( wiedervorlageResource: WiedervorlageResource, wiedervorlage: Wiedervorlage, ): Observable<StateResource<CommandResource>> { @@ -248,7 +299,7 @@ export class WiedervorlageService implements OnDestroy { return { order: CommandOrder.EDIT_WIEDERVORLAGE, body: wiedervorlage }; } - proceedAfterReceiveCommand(commandStateResource: StateResource<CommandResource>, message: string): void { + _proceedAfterReceiveCommand(commandStateResource: StateResource<CommandResource>, message: string): void { this.submitInProgress$.next({ ...this.submitInProgress$.value, resource: commandStateResource.resource, @@ -256,14 +307,14 @@ export class WiedervorlageService implements OnDestroy { if (isDone(commandStateResource.resource)) { this.submitInProgress$.next(createStateResource(commandStateResource.resource)); this.snackbarService.show(commandStateResource.resource, message); - this.setWiedervorlageListReload(); + this._setWiedervorlageListReload(); this.clearUploadedFiles(); } else if (hasStateResourceError(commandStateResource)) { this.submitInProgress$.next(createStateResource(commandStateResource.resource)); } } - setWiedervorlageListReload(): void { + _setWiedervorlageListReload(): void { this.wiedervorlageList$.next({ ...this.wiedervorlageList$.value, reload: true }); } @@ -298,7 +349,7 @@ export class WiedervorlageService implements OnDestroy { .subscribe((commandStateResource) => { if (isDone(commandStateResource.resource)) { this.handleSource(commandStateResource.resource); - this.showSnackBar( + this._showSnackBar( commandStateResource.resource, this.buildMessage(snackBarMessage, this.wiedervorlage$.value.resource), ); @@ -321,7 +372,7 @@ export class WiedervorlageService implements OnDestroy { return replacePlaceholder(message, 'betreff', wiedervorlage.betreff); } - showSnackBar(commandResource: CommandResource, message: string) { + _showSnackBar(commandResource: CommandResource, message: string) { if (isDone(commandResource)) { this.snackbarService.show(commandResource, message); } diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.spec.ts index 305ae85a3562debef815c485cc0820e6971e9139..533f48ef565166aac55ae5fcf355ed99f86a81ce 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.spec.ts @@ -86,7 +86,7 @@ describe('WiedervorlageListInVorgangContainerComponent', () => { describe('reloadWiedervorlageListOnVorgangReload', () => { beforeEach(() => { - wiedervorlageService.setWiedervorlageListReload.mockClear(); + wiedervorlageService._setWiedervorlageListReload.mockClear(); }); it('should call wiedervorlageService', () => { @@ -97,7 +97,7 @@ describe('WiedervorlageListInVorgangContainerComponent', () => { component.reloadWiedervorlageListOnVorgangReload(); - expect(wiedervorlageService.setWiedervorlageListReload).toHaveBeenCalled(); + expect(wiedervorlageService._setWiedervorlageListReload).toHaveBeenCalled(); }); it('should not call wiedervorlageService', () => { @@ -108,7 +108,7 @@ describe('WiedervorlageListInVorgangContainerComponent', () => { component.reloadWiedervorlageListOnVorgangReload(); - expect(wiedervorlageService.setWiedervorlageListReload).not.toHaveBeenCalled(); + expect(wiedervorlageService._setWiedervorlageListReload).not.toHaveBeenCalled(); }); }); }); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.ts index 6a99467e90164b63414677a0e80f4f9ea2470759..4313ee4c1f9ee06cd1515686c8985ec0806fa068 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.ts @@ -21,11 +21,11 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { Component, Input, OnChanges } from '@angular/core'; -import { StateResource } from '@alfa-client/tech-shared'; +import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared'; import { VorgangHeaderLinkRel, VorgangResource } from '@alfa-client/vorgang-shared'; import { WiedervorlageListResource, WiedervorlageService } from '@alfa-client/wiedervorlage-shared'; -import { Observable } from 'rxjs'; +import { Component, Input, OnChanges } from '@angular/core'; +import { Observable, of } from 'rxjs'; @Component({ selector: 'alfa-wiedervorlage-list-in-vorgang-container', @@ -35,7 +35,8 @@ import { Observable } from 'rxjs'; export class WiedervorlageListInVorgangContainerComponent implements OnChanges { @Input() vorgangStateResource: StateResource<VorgangResource>; - wiedervorlagenStateResource$: Observable<StateResource<WiedervorlageListResource>>; + wiedervorlagenStateResource$: Observable<StateResource<WiedervorlageListResource>> = + of(createEmptyStateResource<WiedervorlageListResource>()); readonly vorgangLinkRel = VorgangHeaderLinkRel; @@ -43,15 +44,14 @@ export class WiedervorlageListInVorgangContainerComponent implements OnChanges { ngOnChanges(): void { this.reloadWiedervorlageListOnVorgangReload(); - this.wiedervorlagenStateResource$ = - this.wiedervorlageService.getWiedervorlageListByGivenVorgang( - this.vorgangStateResource.resource, - ); + this.wiedervorlagenStateResource$ = this.wiedervorlageService.getWiedervorlageListByGivenVorgang( + this.vorgangStateResource.resource, + ); } reloadWiedervorlageListOnVorgangReload(): void { if (this.vorgangStateResource.reload) { - this.wiedervorlageService.setWiedervorlageListReload(); + this.wiedervorlageService._setWiedervorlageListReload(); } } }