diff --git a/Dangerfile b/Dangerfile index 40f01ff9a68..ad4ec258e80 100644 --- a/Dangerfile +++ b/Dangerfile @@ -1,5 +1,5 @@ # Fail if jasmine specs contain fdescribe or fit -fail("jasmine fdescribe/fit left in tests") if `grep --include '*.spec.ts' -rP 'fdescribe\(|fit\(' frontend/src/`.length > 1 +fail("jasmine fdescribe/fit left in tests") if `grep --include '*.spec.ts' -rP 'fdescribe\\(|fit\\(' frontend/src/`.length > 1 # Search for modified components not being made OnPush git.modified_files diff --git a/frontend/src/app/modules/common/dynamic-forms/components/dynamic-form/dynamic-form.component.spec.ts b/frontend/src/app/modules/common/dynamic-forms/components/dynamic-form/dynamic-form.component.spec.ts index 9f6fb6e01b7..0882660b507 100644 --- a/frontend/src/app/modules/common/dynamic-forms/components/dynamic-form/dynamic-form.component.spec.ts +++ b/frontend/src/app/modules/common/dynamic-forms/components/dynamic-form/dynamic-form.component.spec.ts @@ -456,5 +456,42 @@ describe('DynamicFormComponent', () => { dynamicFormService.submit$.and.returnValue(defer(() => Promise.resolve('ok'))); })); + + // Moving the DynamicForm.form assignment out of the _setupDynamicForm breaks the + // expressionProperties execution + it('should run expressionProperties', fakeAsync(() => { + const [firstField, ...restOfFields] = dynamicFormSettings.fields; + const expressionPropertiesSpy = jasmine.createSpy('expressionPropertiesSpy'); + const firstFieldCopy = { + ...firstField, + expressionProperties: { + 'templateOptions.test': expressionPropertiesSpy, + } + }; + const dynamicFormSettingsForSubmit = { + ...dynamicFormSettings, + fields: [ + firstFieldCopy, + ...restOfFields, + ] + } + // @ts-ignore + dynamicFormService.getSettingsFromBackend$.and.returnValue(defer(() => Promise.resolve(dynamicFormSettingsForSubmit))); + dynamicFormService.submit$.and.returnValue(defer(() => Promise.resolve('ok'))); + + // Should not show notifications when showNotifications === false + component.showNotifications = false; + + component.resourcePath = '/api/v3/projects/1234/form'; + component.ngOnChanges({}); + flush(); + fixture.detectChanges(); + const submitButton = fixture.debugElement.query(By.css('button[type=submit]')); + submitButton.nativeElement.click(); + + flush(); + + expect(expressionPropertiesSpy).toHaveBeenCalled(); + })); }); diff --git a/frontend/src/app/modules/common/dynamic-forms/components/dynamic-form/dynamic-form.component.ts b/frontend/src/app/modules/common/dynamic-forms/components/dynamic-form/dynamic-form.component.ts index 1b6f72d74a9..df522f3b5bc 100644 --- a/frontend/src/app/modules/common/dynamic-forms/components/dynamic-form/dynamic-form.component.ts +++ b/frontend/src/app/modules/common/dynamic-forms/components/dynamic-form/dynamic-form.component.ts @@ -93,7 +93,7 @@ export class DynamicFormComponent extends UntilDestroyedMixin implements OnChang @Input() showValidationErrorsOn:'change'|'blur'|'submit'|'never' = 'submit'; @Input() handleSubmit = true; @Input() helpTextAttributeScope:string|undefined; - @Input('dynamicFormGroup') form:FormGroup = new FormGroup({}); + @Input() dynamicFormGroup:FormGroup; @Input() set model(payload:IOPFormModel) { if (!this.innerModel && !payload) { @@ -125,6 +125,7 @@ export class DynamicFormComponent extends UntilDestroyedMixin implements OnChang noPathToSubmitToError = `DynamicForm needs a resourcePath input in order to be submitted and validated. Please provide one.`; innerModel:IOPFormModel; + form:FormGroup; get model() { return this.form.value; @@ -271,7 +272,7 @@ export class DynamicFormComponent extends UntilDestroyedMixin implements OnChang this._setupDynamicForm(dynamicFormSettings); } - private _setupDynamicForm({ fields, model }:IOPDynamicFormSettings) { + private _setupDynamicForm({ fields, model, form }:IOPDynamicFormSettings) { const scopedFields = fields.map(field => ({ ...field, templateOptions: { @@ -281,6 +282,7 @@ export class DynamicFormComponent extends UntilDestroyedMixin implements OnChang })); this.fields = this.fieldsSettingsPipe ? this.fieldsSettingsPipe(scopedFields) : scopedFields; this.innerModel = model; + this.form = this.dynamicFormGroup || form; this._changeDetectorRef.detectChanges(); } diff --git a/frontend/src/app/modules/common/dynamic-forms/services/dynamic-form/dynamic-form.service.ts b/frontend/src/app/modules/common/dynamic-forms/services/dynamic-form/dynamic-form.service.ts index 6b192baae36..ba04b92b876 100644 --- a/frontend/src/app/modules/common/dynamic-forms/services/dynamic-form/dynamic-form.service.ts +++ b/frontend/src/app/modules/common/dynamic-forms/services/dynamic-form/dynamic-form.service.ts @@ -48,6 +48,7 @@ export class DynamicFormService { const formSchema = formConfig._embedded?.schema; const formPayload = formConfig._embedded?.payload; const dynamicForm = { + form: new FormGroup({}), fields: this._dynamicFieldsService.getConfig(formSchema, formPayload), model: this._dynamicFieldsService.getModel(formPayload), }; diff --git a/frontend/src/app/modules/common/dynamic-forms/typings.d.ts b/frontend/src/app/modules/common/dynamic-forms/typings.d.ts index 1fe3c23b6be..ab2caf1faba 100644 --- a/frontend/src/app/modules/common/dynamic-forms/typings.d.ts +++ b/frontend/src/app/modules/common/dynamic-forms/typings.d.ts @@ -4,6 +4,7 @@ import { FormGroup } from "@angular/forms"; export interface IOPDynamicFormSettings { fields:IOPFormlyFieldSettings[]; model:IOPFormModel; + form:FormGroup; } export interface IOPFormlyFieldSettings extends FormlyFieldConfig {