[ACS-7311] add no-angular-material-selectors eslint rule (#3732)

* [ACS-7311] add no-angular-material-selectors rule, fix errors

* [ACS-7311] fix faulty unit tests
This commit is contained in:
Grzegorz Jaśkowski
2024-04-04 16:45:06 +02:00
committed by GitHub
parent 2f9cc8075f
commit 4408eb4489
8 changed files with 219 additions and 194 deletions

View File

@@ -44,11 +44,16 @@ import { FolderRuleSetsService } from '../services/folder-rule-sets.service';
import { ruleMock, ruleSettingsMock } from '../mock/rules.mock';
import { Store } from '@ngrx/store';
import { AppService } from '@alfresco/aca-shared';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatProgressBarHarness } from '@angular/material/progress-bar/testing';
import { MatSlideToggleHarness } from '@angular/material/slide-toggle/testing';
describe('ManageRulesSmartComponent', () => {
let fixture: ComponentFixture<ManageRulesSmartComponent>;
let component: ManageRulesSmartComponent;
let debugElement: DebugElement;
let loader: HarnessLoader;
let folderRuleSetsService: FolderRuleSetsService;
let folderRulesService: FolderRulesService;
@@ -74,6 +79,7 @@ describe('ManageRulesSmartComponent', () => {
fixture = TestBed.createComponent(ManageRulesSmartComponent);
component = fixture.componentInstance;
debugElement = fixture.debugElement;
loader = TestbedHarnessEnvironment.loader(fixture);
folderRuleSetsService = TestBed.inject(FolderRuleSetsService);
folderRulesService = TestBed.inject(FolderRulesService);
@@ -193,7 +199,7 @@ describe('ManageRulesSmartComponent', () => {
expect(component).toBeTruthy();
const matProgressBar = debugElement.query(By.css('mat-progress-bar'));
const matProgressBar = loader.getHarness(MatProgressBarHarness);
const rules = debugElement.query(By.css('.aca-rule-list-item'));
const ruleDetails = debugElement.query(By.css('aca-rule-details'));
@@ -307,16 +313,18 @@ describe('ManageRulesSmartComponent', () => {
actionsService.loading$ = of(false);
});
it('should show inherit rules toggle button, and disable it when isInheritanceToggleDisabled = true', () => {
it('should show inherit rules toggle button, and disable it when isInheritanceToggleDisabled = true', async () => {
fixture.detectChanges();
const createButton = debugElement.query(By.css(`[data-automation-id="manage-rules-inheritance-toggle-button"]`));
const createButton = await loader.getHarness(
MatSlideToggleHarness.with({ selector: `[data-automation-id="manage-rules-inheritance-toggle-button"]` })
);
expect(createButton).toBeTruthy();
component.isInheritanceToggleDisabled = true;
fixture.detectChanges();
expect(createButton.nativeNode.classList).toContain('mat-disabled');
expect(await createButton.isDisabled()).toBeTrue();
});
it('should call onInheritanceToggleChange() on change', () => {

View File

@@ -29,20 +29,19 @@ import { actionLinkToCategoryTransformedMock, actionsTransformedListMock } from
import { By } from '@angular/platform-browser';
import { dummyCategoriesConstraints, dummyConstraints, dummyTagsConstraints } from '../../mock/action-parameter-constraints.mock';
import { CategoryService, TagService } from '@alfresco/adf-content-services';
import { MatSelect } from '@angular/material/select';
import { MatDialog } from '@angular/material/dialog';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSelectHarness } from '@angular/material/select/testing';
describe('RuleActionUiComponent', () => {
let fixture: ComponentFixture<RuleActionUiComponent>;
let component: RuleActionUiComponent;
let loader: HarnessLoader;
const getSelectElement = (): HTMLElement => fixture.debugElement.query(By.directive(MatSelect)).nativeElement;
const changeMatSelectValue = (value: string) => {
getSelectElement().click();
fixture.detectChanges();
const matOption = fixture.debugElement.query(By.css(`.mat-option[ng-reflect-value="${value}"]`)).nativeElement;
matOption.click();
const changeMatSelectValue = async (value: string) => {
const matSelect = await loader.getHarness(MatSelectHarness);
await matSelect.clickOptions({ selector: `[ng-reflect-value="${value}"]` });
fixture.detectChanges();
};
@@ -62,6 +61,7 @@ describe('RuleActionUiComponent', () => {
fixture = TestBed.createComponent(RuleActionUiComponent);
component = fixture.componentInstance;
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should clear empty parameters', async () => {
@@ -69,7 +69,7 @@ describe('RuleActionUiComponent', () => {
component.parameterConstraints = dummyConstraints;
fixture.detectChanges();
changeMatSelectValue('mock-action-1-definition');
await changeMatSelectValue('mock-action-1-definition');
setInputValue('test');
await fixture.whenStable();
@@ -82,25 +82,24 @@ describe('RuleActionUiComponent', () => {
expect(component.parameters).toEqual({ 'mock-action-parameter-boolean': false });
});
it('should populate the dropdown selector with the action definitions', () => {
it('should populate the dropdown selector with the action definitions', async () => {
component.actionDefinitions = actionsTransformedListMock;
fixture.detectChanges();
getSelectElement().click();
fixture.detectChanges();
const matOptions = fixture.debugElement.queryAll(By.css(`mat-option`));
expect(matOptions.length).toBe(2);
expect(matOptions[0].nativeElement.innerText).toBe('Action 1 title');
expect(matOptions[1].nativeElement.innerText).toBe('mock-action-2-definition');
const select = await loader.getHarness(MatSelectHarness);
await select.open();
const options = await select.getOptions();
expect(options.length).toBe(2);
expect(await options[0].getText()).toBe('Action 1 title');
expect(await options[1].getText()).toBe('mock-action-2-definition');
});
it('should populate the card view with parameters when an action is selected', () => {
it('should populate the card view with parameters when an action is selected', async () => {
component.actionDefinitions = actionsTransformedListMock;
component.parameterConstraints = dummyConstraints;
fixture.detectChanges();
changeMatSelectValue('mock-action-1-definition');
await changeMatSelectValue('mock-action-1-definition');
const cardView = getPropertiesCardView();
@@ -111,16 +110,16 @@ describe('RuleActionUiComponent', () => {
expect(cardView.properties[3]).toBeInstanceOf(CardViewTextItemModel);
expect(cardView.properties[4]).toBeInstanceOf(CardViewSelectItemModel);
changeMatSelectValue('mock-action-2-definition');
await changeMatSelectValue('mock-action-2-definition');
expect(fixture.debugElement.query(By.directive(CardViewComponent))).toBeNull();
});
it('should create category-value action parameter as a text box rather than node picker', () => {
it('should create category-value action parameter as a text box rather than node picker', async () => {
component.actionDefinitions = [actionLinkToCategoryTransformedMock];
component.parameterConstraints = dummyConstraints;
fixture.detectChanges();
changeMatSelectValue('mock-action-3-definition');
await changeMatSelectValue('mock-action-3-definition');
const cardView = getPropertiesCardView();
@@ -130,14 +129,14 @@ describe('RuleActionUiComponent', () => {
expect(cardView.properties[0]).toBeInstanceOf(CardViewTextItemModel);
});
it('should open category selector dialog on category-value action parameter clicked', () => {
it('should open category selector dialog on category-value action parameter clicked', async () => {
const dialog = fixture.debugElement.injector.get(MatDialog);
component.actionDefinitions = [actionLinkToCategoryTransformedMock];
component.parameterConstraints = dummyConstraints;
spyOn(dialog, 'open');
fixture.detectChanges();
changeMatSelectValue('mock-action-3-definition');
await changeMatSelectValue('mock-action-3-definition');
fixture.debugElement.query(By.css('.adf-textitem-action')).nativeElement.click();
expect(dialog.open).toHaveBeenCalledTimes(1);
@@ -149,13 +148,13 @@ describe('RuleActionUiComponent', () => {
component.actionDefinitions = actionsTransformedListMock;
});
it('should not filter out tags related options if tagService.areTagsEnabled returns true', (done) => {
it('should not filter out tags related options if tagService.areTagsEnabled returns true', async () => {
component.parameterConstraints = dummyTagsConstraints;
const tagService = TestBed.inject(TagService);
spyOn(tagService, 'areTagsEnabled').and.returnValue(true);
fixture.detectChanges();
changeMatSelectValue('mock-action-1-definition');
await changeMatSelectValue('mock-action-1-definition');
expect(tagService.areTagsEnabled).toHaveBeenCalled();
(getPropertiesCardView().properties[2] as CardViewSelectItemModel<string>).options$.subscribe((options) => {
expect(options).toEqual(
@@ -164,17 +163,16 @@ describe('RuleActionUiComponent', () => {
label: `${constraint.label} [${constraint.value}]`
}))
);
done();
});
});
it('should filter out tags related options if tagService.areTagsEnabled returns false', (done) => {
it('should filter out tags related options if tagService.areTagsEnabled returns false', async () => {
component.parameterConstraints = dummyTagsConstraints;
const tagService = TestBed.inject(TagService);
spyOn(tagService, 'areTagsEnabled').and.returnValue(false);
fixture.detectChanges();
changeMatSelectValue('mock-action-1-definition');
await changeMatSelectValue('mock-action-1-definition');
expect(tagService.areTagsEnabled).toHaveBeenCalled();
(getPropertiesCardView().properties[2] as CardViewSelectItemModel<string>).options$.subscribe((options) => {
expect(options).toEqual([
@@ -183,17 +181,16 @@ describe('RuleActionUiComponent', () => {
label: 'Label 3 [cm:notTagRelated]'
}
]);
done();
});
});
it('should not filter out categories related options if categoryService.areCategoriesEnabled returns true', (done) => {
it('should not filter out categories related options if categoryService.areCategoriesEnabled returns true', async () => {
component.parameterConstraints = dummyCategoriesConstraints;
const categoriesService = TestBed.inject(CategoryService);
spyOn(categoriesService, 'areCategoriesEnabled').and.returnValue(true);
fixture.detectChanges();
changeMatSelectValue('mock-action-1-definition');
await changeMatSelectValue('mock-action-1-definition');
expect(categoriesService.areCategoriesEnabled).toHaveBeenCalled();
(getPropertiesCardView().properties[2] as CardViewSelectItemModel<string>).options$.subscribe((options) => {
expect(options).toEqual(
@@ -202,17 +199,16 @@ describe('RuleActionUiComponent', () => {
label: `${constraint.label} [${constraint.value}]`
}))
);
done();
});
});
it('should filter out categories related options if categoryService.areCategoriesEnabled returns false', (done) => {
it('should filter out categories related options if categoryService.areCategoriesEnabled returns false', async () => {
component.parameterConstraints = dummyCategoriesConstraints;
const categoryService = TestBed.inject(CategoryService);
spyOn(categoryService, 'areCategoriesEnabled').and.returnValue(false);
fixture.detectChanges();
changeMatSelectValue('mock-action-1-definition');
await changeMatSelectValue('mock-action-1-definition');
expect(categoryService.areCategoriesEnabled).toHaveBeenCalled();
(getPropertiesCardView().properties[2] as CardViewSelectItemModel<string>).options$.subscribe((options) => {
expect(options).toEqual([
@@ -221,7 +217,6 @@ describe('RuleActionUiComponent', () => {
label: 'Label 2 [cm:notCategoryRelated]'
}
]);
done();
});
});
});

View File

@@ -33,24 +33,32 @@ import { CategoryService, TagService } from '@alfresco/adf-content-services';
import { of } from 'rxjs';
import { RuleSimpleCondition } from '../../model/rule-simple-condition.model';
import { delay } from 'rxjs/operators';
import { MatOption } from '@angular/material/core';
import { RuleConditionField, ruleConditionFields } from './rule-condition-fields';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSelectHarness } from '@angular/material/select/testing';
import { MatAutocompleteHarness } from '@angular/material/autocomplete/testing';
describe('RuleSimpleConditionUiComponent', () => {
let fixture: ComponentFixture<RuleSimpleConditionUiComponent>;
let categoryService: CategoryService;
let loader: HarnessLoader;
const fieldSelectAutomationId = 'field-select';
const folderRulesBaseLabel = 'ACA_FOLDER_RULES.RULE_DETAILS.COMPARATORS';
const getByDataAutomationId = (dataAutomationId: string): DebugElement =>
fixture.debugElement.query(By.css(`[data-automation-id="${dataAutomationId}"]`));
const changeMatSelectValue = (dataAutomationId: string, value: string) => {
const matSelect = getByDataAutomationId(dataAutomationId).nativeElement;
matSelect.click();
const changeMatSelectValue = async (dataAutomationId: string, value: string) => {
const matSelect = await loader.getHarness(MatSelectHarness.with({ selector: `[data-automation-id="${dataAutomationId}"]` }));
await matSelect.clickOptions({ selector: `[ng-reflect-value="${value}"]` });
fixture.detectChanges();
const matOption = fixture.debugElement.query(By.css(`.mat-option[ng-reflect-value="${value}"]`)).nativeElement;
matOption.click();
};
const changeMatAutocompleteValue = async (value: string) => {
const matAutocomplete = await loader.getHarness(MatAutocompleteHarness);
await matAutocomplete.selectOption({ selector: `[ng-reflect-value="${value}"]` });
fixture.detectChanges();
};
@@ -61,16 +69,16 @@ describe('RuleSimpleConditionUiComponent', () => {
fixture.detectChanges();
};
const expectConditionFieldsDisplayedAsOptions = (conditionFields: RuleConditionField[]): void => {
fixture.detectChanges();
getByDataAutomationId(fieldSelectAutomationId).nativeElement.click();
fixture.detectChanges();
const options = fixture.debugElement.queryAll(By.directive(MatOption));
conditionFields.forEach((field, i) => {
const option = options[i];
expect(field.name).toBe(option.componentInstance.value);
expect(field.label).toBe(option.nativeElement.textContent.trim());
});
const expectConditionFieldsDisplayedAsOptions = async (conditionFields: RuleConditionField[]): Promise<void> => {
loader = TestbedHarnessEnvironment.loader(fixture);
const select = await loader.getHarness(MatSelectHarness);
await select.open();
const options = await select.getOptions();
await Promise.all(
conditionFields.map(async (field, i) => {
expect(field.label).toEqual(await options[i].getText());
})
);
};
beforeEach(() => {
@@ -80,6 +88,7 @@ describe('RuleSimpleConditionUiComponent', () => {
fixture = TestBed.createComponent(RuleSimpleConditionUiComponent);
categoryService = TestBed.inject(CategoryService);
loader = TestbedHarnessEnvironment.loader(fixture);
});
it('should default the field to the name, the comparator to equals and the value empty', () => {
@@ -90,60 +99,30 @@ describe('RuleSimpleConditionUiComponent', () => {
expect(getByDataAutomationId('value-input').nativeElement.value).toBe('');
});
it('should hide the comparator select box if the type of the field is special', () => {
it('should hide the comparator select box if the type of the field is mimeType', async () => {
fixture.componentInstance.mimeTypes = [{ value: '', label: '' } as MimeType];
fixture.detectChanges();
const comparatorFormField = getByDataAutomationId('comparator-form-field').nativeElement;
expect(fixture.componentInstance.isComparatorHidden).toBeFalsy();
expect(getComputedStyle(comparatorFormField).display).not.toBe('none');
changeMatSelectValue(fieldSelectAutomationId, 'category');
await changeMatSelectValue(fieldSelectAutomationId, 'mimetype');
expect(fixture.componentInstance.isComparatorHidden).toBeTruthy();
expect(getComputedStyle(comparatorFormField).display).toBe('none');
});
it('should hide the comparator select box if the type of the field is mimeType', () => {
fixture.detectChanges();
const comparatorFormField = getByDataAutomationId('comparator-form-field').nativeElement;
it('should set the comparator to equals if the field is set to a type with different comparators', async () => {
spyOn(fixture.componentInstance, 'onChangeField').and.callThrough();
const comparatorSelect = await loader.getHarness(MatSelectHarness.with({ selector: '[data-automation-id="comparator-select"]' }));
expect(fixture.componentInstance.isComparatorHidden).toBeFalsy();
expect(getComputedStyle(comparatorFormField).display).not.toBe('none');
await changeMatSelectValue('comparator-select', 'contains');
expect(await comparatorSelect.getValueText()).toBe(folderRulesBaseLabel + '.CONTAINS');
changeMatSelectValue(fieldSelectAutomationId, 'mimetype');
expect(fixture.componentInstance.isComparatorHidden).toBeTruthy();
expect(getComputedStyle(comparatorFormField).display).toBe('none');
});
it('should hide the comparator select box if the type of the field is autoComplete', () => {
const autoCompleteField = 'category';
fixture.detectChanges();
const comparatorFormField = getByDataAutomationId('comparator-form-field').nativeElement;
expect(fixture.componentInstance.isComparatorHidden).toBeFalsy();
expect(getComputedStyle(comparatorFormField).display).not.toBe('none');
changeMatSelectValue(fieldSelectAutomationId, autoCompleteField);
expect(fixture.componentInstance.isComparatorHidden).toBeTruthy();
expect(getComputedStyle(comparatorFormField).display).toBe('none');
});
it('should set the comparator to equals if the field is set to a type with different comparators', () => {
const onChangeFieldSpy = spyOn(fixture.componentInstance, 'onChangeField').and.callThrough();
fixture.detectChanges();
changeMatSelectValue('comparator-select', 'contains');
expect(getByDataAutomationId('comparator-select').componentInstance.value).toBe('contains');
changeMatSelectValue(fieldSelectAutomationId, 'mimetype');
expect(onChangeFieldSpy).toHaveBeenCalledTimes(1);
expect(getByDataAutomationId('comparator-select').componentInstance.value).toBe('equals');
changeMatSelectValue(fieldSelectAutomationId, 'size');
expect(onChangeFieldSpy).toHaveBeenCalledTimes(2);
expect(getByDataAutomationId('comparator-select').componentInstance.value).toBe('equals');
await changeMatSelectValue(fieldSelectAutomationId, 'size');
expect(await comparatorSelect.getValueText()).toBe(folderRulesBaseLabel + '.EQUALS');
expect(fixture.componentInstance.onChangeField).toHaveBeenCalled();
});
it('should display an additional option for a currently selected unknown field', () => {
@@ -160,10 +139,10 @@ describe('RuleSimpleConditionUiComponent', () => {
expect((unknownOptionMatOption.nativeElement as HTMLElement).innerText.trim()).toBe(simpleConditionUnknownFieldMock.field);
});
it('should remove the option for the unknown field as soon as another option is selected', () => {
it('should remove the option for the unknown field as soon as another option is selected', async () => {
fixture.componentInstance.writeValue(simpleConditionUnknownFieldMock);
fixture.detectChanges();
changeMatSelectValue(fieldSelectAutomationId, 'cm:name');
await changeMatSelectValue(fieldSelectAutomationId, 'cm:name');
const matSelect = getByDataAutomationId(fieldSelectAutomationId).nativeElement;
matSelect.click();
fixture.detectChanges();
@@ -214,38 +193,106 @@ describe('RuleSimpleConditionUiComponent', () => {
expect(getByDataAutomationId('value-input').nativeElement.value).toBe('');
});
it('should provide auto-complete option when category is selected', () => {
it('should show loading spinner while auto-complete options are fetched, and then remove it once it is received', fakeAsync(async () => {
spyOn(categoryService, 'searchCategories').and.returnValue(of(categoriesListMock).pipe(delay(1000)));
fixture.detectChanges();
changeMatSelectValue(fieldSelectAutomationId, 'category');
await changeMatSelectValue(fieldSelectAutomationId, 'category');
tick(500);
getByDataAutomationId('auto-complete-input-field')?.nativeElement?.click();
let loadingSpinner = getByDataAutomationId('auto-complete-loading-spinner');
expect(loadingSpinner).not.toBeNull();
tick(1000);
fixture.detectChanges();
loadingSpinner = getByDataAutomationId('auto-complete-loading-spinner');
expect(loadingSpinner).toBeNull();
discardPeriodicTasks();
}));
expect(getByDataAutomationId('auto-complete-input-field')).toBeTruthy();
expect(fixture.componentInstance.form.get('parameter').value).toEqual('');
describe('With categories option selected', () => {
beforeEach(() => {
spyOn(categoryService, 'searchCategories').and.returnValue(of(categoriesListMock));
});
it('should hide the comparator select box if the type of the field is autoComplete', async () => {
const autoCompleteField = 'category';
fixture.detectChanges();
const comparatorFormField = getByDataAutomationId('comparator-form-field').nativeElement;
expect(fixture.componentInstance.isComparatorHidden).toBeFalsy();
expect(getComputedStyle(comparatorFormField).display).not.toBe('none');
await changeMatSelectValue(fieldSelectAutomationId, autoCompleteField);
expect(fixture.componentInstance.isComparatorHidden).toBeTruthy();
expect(getComputedStyle(comparatorFormField).display).toBe('none');
});
it('should hide the comparator select box if the type of the field is special', async () => {
fixture.detectChanges();
const comparatorFormField = getByDataAutomationId('comparator-form-field').nativeElement;
expect(fixture.componentInstance.isComparatorHidden).toBeFalsy();
expect(getComputedStyle(comparatorFormField).display).not.toBe('none');
await changeMatSelectValue(fieldSelectAutomationId, 'category');
expect(fixture.componentInstance.isComparatorHidden).toBeTruthy();
expect(getComputedStyle(comparatorFormField).display).toBe('none');
});
it('should provide auto-complete option when category is selected', async () => {
fixture.detectChanges();
await changeMatSelectValue(fieldSelectAutomationId, 'category');
expect(getByDataAutomationId('auto-complete-input-field')).toBeTruthy();
expect(fixture.componentInstance.form.get('parameter').value).toEqual('');
});
it('should fetch category list when category option is selected', fakeAsync(async () => {
fixture.detectChanges();
await changeMatSelectValue(fieldSelectAutomationId, 'category');
tick(500);
expect(categoryService.searchCategories).toHaveBeenCalledWith('');
}));
it('should fetch new category list with user input when user types into parameter field after category option is select', fakeAsync(async () => {
const categoryValue = 'a new category';
fixture.detectChanges();
await changeMatSelectValue(fieldSelectAutomationId, 'category');
tick(500);
expect(categoryService.searchCategories).toHaveBeenCalledWith('');
setValueInInputField('auto-complete-input-field', categoryValue);
tick(500);
expect(categoryService.searchCategories).toHaveBeenCalledWith(categoryValue);
}));
it('should display correct label for category when user selects a category from auto-complete dropdown', fakeAsync(async () => {
fixture.detectChanges();
await changeMatSelectValue(fieldSelectAutomationId, 'category');
tick(500);
getByDataAutomationId('auto-complete-input-field')?.nativeElement?.click();
await changeMatAutocompleteValue(categoriesListMock.list.entries[0].entry.id);
const displayValue = getByDataAutomationId('auto-complete-input-field')?.nativeElement?.value;
expect(displayValue).toBe('category/path/1/FakeCategory1');
discardPeriodicTasks();
}));
it('should automatically select first category when user focuses out of parameter form field with category option selected', fakeAsync(async () => {
fixture.detectChanges();
await changeMatSelectValue(fieldSelectAutomationId, 'category');
tick(500);
const autoCompleteInputField = getByDataAutomationId('auto-complete-input-field')?.nativeElement;
autoCompleteInputField.value = 'FakeCat';
autoCompleteInputField.dispatchEvent(new Event('focusout'));
const parameterValue = fixture.componentInstance.form.get('parameter').value;
expect(parameterValue).toEqual(categoriesListMock.list.entries[0].entry.id);
discardPeriodicTasks();
}));
});
it('should fetch category list when category option is selected', fakeAsync(() => {
spyOn(categoryService, 'searchCategories').and.returnValue(of(categoriesListMock));
fixture.detectChanges();
changeMatSelectValue(fieldSelectAutomationId, 'category');
tick(500);
expect(categoryService.searchCategories).toHaveBeenCalledWith('');
}));
it('should fetch new category list with user input when user types into parameter field after category option is select', fakeAsync(() => {
const categoryValue = 'a new category';
spyOn(categoryService, 'searchCategories').and.returnValue(of(categoriesListMock));
fixture.detectChanges();
changeMatSelectValue(fieldSelectAutomationId, 'category');
tick(500);
expect(categoryService.searchCategories).toHaveBeenCalledWith('');
setValueInInputField('auto-complete-input-field', categoryValue);
tick(500);
expect(categoryService.searchCategories).toHaveBeenCalledWith(categoryValue);
}));
it('should fetch category details when a saved rule with category condition is edited', () => {
const savedCategoryMock: RuleSimpleCondition = {
field: 'category',
@@ -269,77 +316,37 @@ describe('RuleSimpleConditionUiComponent', () => {
expect(categoryService.getCategory).toHaveBeenCalledWith(savedCategoryMock.parameter, { include: ['path'] });
});
it('should show loading spinner while auto-complete options are fetched, and then remove it once it is received', fakeAsync(() => {
spyOn(categoryService, 'searchCategories').and.returnValue(of(categoriesListMock).pipe(delay(1000)));
fixture.detectChanges();
changeMatSelectValue(fieldSelectAutomationId, 'category');
tick(500);
getByDataAutomationId('auto-complete-input-field')?.nativeElement?.click();
let loadingSpinner = getByDataAutomationId('auto-complete-loading-spinner');
expect(loadingSpinner).not.toBeNull();
tick(1000);
fixture.detectChanges();
loadingSpinner = getByDataAutomationId('auto-complete-loading-spinner');
expect(loadingSpinner).toBeNull();
discardPeriodicTasks();
}));
it('should display correct label for category when user selects a category from auto-complete dropdown', fakeAsync(() => {
spyOn(categoryService, 'searchCategories').and.returnValue(of(categoriesListMock));
fixture.detectChanges();
changeMatSelectValue(fieldSelectAutomationId, 'category');
tick(500);
getByDataAutomationId('auto-complete-input-field')?.nativeElement?.click();
changeMatSelectValue('folder-rule-auto-complete', categoriesListMock.list.entries[0].entry.id);
const displayValue = getByDataAutomationId('auto-complete-input-field')?.nativeElement?.value;
expect(displayValue).toBe('category/path/1/FakeCategory1');
discardPeriodicTasks();
}));
it('should automatically select first category when user focuses out of parameter form field with category option selected', fakeAsync(() => {
spyOn(categoryService, 'searchCategories').and.returnValue(of(categoriesListMock));
fixture.detectChanges();
changeMatSelectValue(fieldSelectAutomationId, 'category');
tick(500);
const autoCompleteInputField = getByDataAutomationId('auto-complete-input-field')?.nativeElement;
autoCompleteInputField.value = 'FakeCat';
autoCompleteInputField.dispatchEvent(new Event('focusout'));
const parameterValue = fixture.componentInstance.form.get('parameter').value;
expect(parameterValue).toEqual(categoriesListMock.list.entries[0].entry.id);
discardPeriodicTasks();
}));
it('should display correct condition field options when tagService.areTagsEnabled returns true', () => {
it('should display correct condition field options when tagService.areTagsEnabled returns true', async () => {
const tagService = TestBed.inject(TagService);
spyOn(tagService, 'areTagsEnabled').and.returnValue(true);
fixture = TestBed.createComponent(RuleSimpleConditionUiComponent);
expect(tagService.areTagsEnabled).toHaveBeenCalled();
expectConditionFieldsDisplayedAsOptions(ruleConditionFields);
await expectConditionFieldsDisplayedAsOptions(ruleConditionFields);
});
it('should display correct condition field options when tagService.areTagsEnabled returns false', () => {
it('should display correct condition field options when tagService.areTagsEnabled returns false', async () => {
const tagService = TestBed.inject(TagService);
spyOn(tagService, 'areTagsEnabled').and.returnValue(false);
fixture = TestBed.createComponent(RuleSimpleConditionUiComponent);
expect(tagService.areTagsEnabled).toHaveBeenCalled();
expectConditionFieldsDisplayedAsOptions(ruleConditionFields.filter((field) => field.name !== 'tag'));
await expectConditionFieldsDisplayedAsOptions(ruleConditionFields.filter((field) => field.name !== 'tag'));
});
it('should display correct condition field options when categoryService.areCategoriesEnabled returns true', () => {
it('should display correct condition field options when categoryService.areCategoriesEnabled returns true', async () => {
spyOn(categoryService, 'areCategoriesEnabled').and.returnValue(true);
fixture = TestBed.createComponent(RuleSimpleConditionUiComponent);
expect(categoryService.areCategoriesEnabled).toHaveBeenCalled();
expectConditionFieldsDisplayedAsOptions(ruleConditionFields);
await expectConditionFieldsDisplayedAsOptions(ruleConditionFields);
});
it('should display correct condition field options when categoryService.areCategoriesEnabled returns false', () => {
it('should display correct condition field options when categoryService.areCategoriesEnabled returns false', async () => {
spyOn(categoryService, 'areCategoriesEnabled').and.returnValue(false);
fixture = TestBed.createComponent(RuleSimpleConditionUiComponent);
expect(categoryService.areCategoriesEnabled).toHaveBeenCalled();
expectConditionFieldsDisplayedAsOptions(ruleConditionFields.filter((field) => field.name !== 'category'));
await expectConditionFieldsDisplayedAsOptions(ruleConditionFields.filter((field) => field.name !== 'category'));
});
});

View File

@@ -30,10 +30,14 @@ import { CoreTestingModule } from '@alfresco/adf-core';
import { By } from '@angular/platform-browser';
import { errorScriptConstraintMock } from '../../mock/actions.mock';
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSelectHarness } from '@angular/material/select/testing';
describe('RuleOptionsUiComponent', () => {
let fixture: ComponentFixture<RuleOptionsUiComponent>;
let component: RuleOptionsUiComponent;
let loader: HarnessLoader;
const getByDataAutomationId = (dataAutomationId: string): DebugElement =>
fixture.debugElement.query(By.css(`[data-automation-id="${dataAutomationId}"]`));
@@ -63,6 +67,7 @@ describe('RuleOptionsUiComponent', () => {
fixture = TestBed.createComponent(RuleOptionsUiComponent);
component = fixture.componentInstance;
loader = TestbedHarnessEnvironment.loader(fixture);
component.writeValue({
isEnabled: true,
@@ -126,7 +131,7 @@ describe('RuleOptionsUiComponent', () => {
expect(getByDataAutomationId('rule-option-select-errorScript')).toBeTruthy();
});
it('should populate the error script dropdown with scripts', () => {
it('should populate the error script dropdown with scripts', async () => {
component.writeValue({
isEnabled: true,
isInheritable: false,
@@ -140,11 +145,12 @@ describe('RuleOptionsUiComponent', () => {
(getByDataAutomationId('rule-option-select-errorScript').nativeElement as HTMLElement).click();
fixture.detectChanges();
const matOptions = fixture.debugElement.queryAll(By.css(`.mat-option`));
const selection = await loader.getHarness(MatSelectHarness);
const matOptions = await selection.getOptions();
expect(matOptions.length).toBe(3);
expect((matOptions[0].nativeElement as HTMLElement).innerText.trim()).toBe('ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.NO_SCRIPT');
expect((matOptions[1].nativeElement as HTMLElement).innerText.trim()).toBe('Script 1');
expect((matOptions[2].nativeElement as HTMLElement).innerText.trim()).toBe('Script 2');
expect((await matOptions[0].getText()).trim()).toBe('ACA_FOLDER_RULES.RULE_DETAILS.OPTIONS.NO_SCRIPT');
expect((await matOptions[1].getText()).trim()).toBe('Script 1');
expect((await matOptions[2].getText()).trim()).toBe('Script 2');
});
it('should always show a label for the error script dropdown even when MAT_FORM_FIELD_DEFAULT_OPTIONS sets floatLabel to never', () => {
@@ -157,7 +163,7 @@ describe('RuleOptionsUiComponent', () => {
component.errorScriptConstraint = errorScriptConstraintMock;
fixture.detectChanges();
const matFormField = fixture.debugElement.query(By.css(`[data-automation-id="rule-option-form-field-errorScript"] .mat-form-field-label`));
const matFormField = fixture.debugElement.query(By.css('[data-automation-id="rule-option-form-field-errorScript"'));
fixture.detectChanges();
expect(matFormField).not.toBeNull();
expect(matFormField.componentInstance['floatLabel']).toBe('always');

View File

@@ -56,7 +56,8 @@ describe('FolderRuleSetsService', () => {
.withArgs(`/nodes/${owningFolderIdMock}/rule-sets/-default-?include=isLinkedTo,owningFolder,linkedToBy`, 'GET')
.and.returnValue(of(getDefaultRuleSetResponseMock))
.withArgs(`/nodes/${owningFolderIdMock}/rule-sets?include=isLinkedTo,owningFolder,linkedToBy&skipCount=0&maxItems=100`, 'GET')
.and.returnValue(of(getRuleSetsResponseMock));
.and.returnValue(of(getRuleSetsResponseMock))
.and.stub();
getRulesSpy = spyOn<any>(folderRulesService, 'getRules')
.withArgs(jasmine.anything(), 'rule-set-no-links')
.and.returnValue(of({ rules: ownedRulesMock, hasMoreRules: false }))
@@ -138,15 +139,15 @@ describe('FolderRuleSetsService', () => {
expect(selectRuleSpy).toHaveBeenCalledWith(ruleMock('inherited-rule-1'));
});
it('should send a POST request to create a new link between two folders', () => {
folderRuleSetsService.createRuleSetLink('folder-1-id', 'folder-2-id');
it('should send a POST request to create a new link between two folders', async () => {
await folderRuleSetsService.createRuleSetLink('folder-1-id', 'folder-2-id');
expect(callApiSpy).toHaveBeenCalledWith('/nodes/folder-1-id/rule-set-links', 'POST', {
id: 'folder-2-id'
});
});
it('should send a DELETE request to delete a link between two folders', () => {
folderRuleSetsService.deleteRuleSetLink('folder-1-id', 'rule-set-1-id');
it('should send a DELETE request to delete a link between two folders', async () => {
await folderRuleSetsService.deleteRuleSetLink('folder-1-id', 'rule-set-1-id');
expect(callApiSpy).toHaveBeenCalledWith('/nodes/folder-1-id/rule-set-links/rule-set-1-id', 'DELETE');
});
});