diff --git a/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.spec.ts b/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.spec.ts index 4342280982f1..b1b6153a3642 100644 --- a/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.spec.ts +++ b/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.spec.ts @@ -11,6 +11,7 @@ import { By } from '@angular/platform-browser'; import { BlockEditorModule, DotBlockEditorComponent } from '@dotcms/block-editor'; import { + DotHttpErrorManagerService, DotLicenseService, DotMessageDisplayService, DotMessageService @@ -169,7 +170,7 @@ describe.each([...FIELDS_MOCK])('DotEditContentFieldComponent all fields', (fiel useValue: createFormGroupDirectiveMock() } ], - providers: [FormGroupDirective] + providers: [FormGroupDirective, mockProvider(DotHttpErrorManagerService)] }); beforeEach(async () => { diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-category-field-sidebar/dot-category-field-sidebar.component.spec.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-category-field-sidebar/dot-category-field-sidebar.component.spec.ts index 529a39f7315c..f97a94c1ab8a 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-category-field-sidebar/dot-category-field-sidebar.component.spec.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/components/dot-category-field-sidebar/dot-category-field-sidebar.component.spec.ts @@ -4,7 +4,7 @@ import { of } from 'rxjs'; import { Sidebar } from 'primeng/sidebar'; -import { DotMessageService } from '@dotcms/data-access'; +import { DotHttpErrorManagerService, DotMessageService } from '@dotcms/data-access'; import { DotCategoryFieldSidebarComponent } from './dot-category-field-sidebar.component'; @@ -26,7 +26,8 @@ describe('DotEditContentCategoryFieldSidebarComponent', () => { providers: [ mockProvider(CategoriesService, { getChildren: jest.fn().mockReturnValue(of(CATEGORY_LIST_MOCK)) - }) + }), + mockProvider(DotHttpErrorManagerService) ] }); diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.spec.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.spec.ts index ba7729a2d760..6fdea2865192 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.spec.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/dot-edit-content-category-field.component.spec.ts @@ -1,11 +1,12 @@ import { byTestId, createComponentFactory, mockProvider, Spectator } from '@ngneat/spectator/jest'; import { MockComponent } from 'ng-mocks'; +import { of } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { fakeAsync } from '@angular/core/testing'; import { ControlContainer, FormControl, FormGroup } from '@angular/forms'; -import { DotMessageService } from '@dotcms/data-access'; +import { DotHttpErrorManagerService, DotMessageService } from '@dotcms/data-access'; import { DotCategoryFieldSidebarComponent } from './components/dot-category-field-sidebar/dot-category-field-sidebar.component'; import { DotEditContentCategoryFieldComponent } from './dot-edit-content-category-field.component'; @@ -13,7 +14,9 @@ import { CLOSE_SIDEBAR_CSS_DELAY_MS } from './dot-edit-content-category-field.co import { CATEGORY_FIELD_CONTENTLET_MOCK, CATEGORY_FIELD_MOCK, - CATEGORY_FIELD_VARIABLE_NAME + CATEGORY_FIELD_VARIABLE_NAME, + CATEGORY_HIERARCHY_MOCK, + SELECTED_LIST_MOCK } from './mocks/category-field.mocks'; import { CategoriesService } from './services/categories.service'; import { CategoryFieldStore } from './store/content-category-field.store'; @@ -32,68 +35,95 @@ describe('DotEditContentCategoryFieldComponent', () => { component: DotEditContentCategoryFieldComponent, imports: [MockComponent(DotCategoryFieldSidebarComponent)], componentViewProviders: [ - CategoryFieldStore, { provide: ControlContainer, useValue: createFormGroupDirectiveMock(FAKE_FORM_GROUP) - } + }, + mockProvider(CategoriesService) ], providers: [ mockProvider(DotMessageService), - mockProvider(CategoriesService), - mockProvider(HttpClient) + mockProvider(HttpClient), + mockProvider(DotHttpErrorManagerService) ] }); - beforeEach(() => { - spectator = createComponent({ - props: { - contentlet: CATEGORY_FIELD_CONTENTLET_MOCK, - field: CATEGORY_FIELD_MOCK - } - }); - store = spectator.inject(CategoryFieldStore, true); - - spectator.detectChanges(); - }); - afterEach(() => { jest.resetAllMocks(); }); describe('Elements', () => { - it('should render a button for selecting categories', () => { - expect(spectator.query(byTestId('show-sidebar-btn'))).not.toBeNull(); - }); + describe('With selected', () => { + beforeEach(() => { + spectator = createComponent({ + props: { + contentlet: CATEGORY_FIELD_CONTENTLET_MOCK, + field: CATEGORY_FIELD_MOCK + }, + providers: [ + mockProvider(CategoriesService, { + getSelectedHierarchy: jest + .fn() + .mockReturnValue(of(CATEGORY_HIERARCHY_MOCK)) + }) + ] + }); + }); - it('should not display the category list with chips when there are no categories', () => { - spectator = createComponent({ - props: { - contentlet: [], - field: CATEGORY_FIELD_MOCK - } + it('should render a button for selecting categories', () => { + expect(spectator.query(byTestId('show-sidebar-btn'))).not.toBeNull(); }); - spectator.detectChanges(); + it('should display the category list with chips when there are categories', () => { + expect(spectator.query(byTestId('category-chip-list'))).not.toBeNull(); + }); - expect(spectator.query(byTestId('category-chip-list'))).toBeNull(); - }); + it('should categoryFieldControl has the values loaded on the store', () => { + const categoryValue = spectator.component.categoryFieldControl.value; - it('should display the category list with chips when there are categories', () => { - expect(spectator.query(byTestId('category-chip-list'))).not.toBeNull(); + expect(categoryValue).toEqual(SELECTED_LIST_MOCK); + }); }); - it('should categoryFieldControl has the values loaded on the store', () => { - const categoryValue = spectator.component.categoryFieldControl.value; - - expect(categoryValue).toEqual([ - '1f208488057007cedda0e0b5d52ee3b3', - 'cb83dc32c0a198fd0ca427b3b587f4ce' - ]); + describe('No selected', () => { + it('should not display the category list with chips when there are no categories', () => { + spectator = createComponent({ + props: { + contentlet: [], + field: CATEGORY_FIELD_MOCK + }, + providers: [ + mockProvider(CategoriesService, { + getSelectedHierarchy: jest.fn().mockReturnValue(of([])) + }) + ] + }); + + spectator.detectChanges(); + + expect(spectator.query(byTestId('category-chip-list'))).toBeNull(); + }); }); }); describe('Interactions', () => { + beforeEach(() => { + spectator = createComponent({ + props: { + contentlet: CATEGORY_FIELD_CONTENTLET_MOCK, + field: CATEGORY_FIELD_MOCK + }, + providers: [ + mockProvider(CategoriesService, { + getSelectedHierarchy: jest.fn().mockReturnValue(of(CATEGORY_HIERARCHY_MOCK)) + }) + ] + }); + + store = spectator.inject(CategoryFieldStore, true); + + spectator.detectChanges(); + }); it('should invoke `showCategoriesSidebar` method when the select button is clicked', () => { const selectBtn = spectator.query(byTestId('show-sidebar-btn')); const showCategoriesSidebarSpy = jest.spyOn( @@ -153,10 +183,7 @@ describe('DotEditContentCategoryFieldComponent', () => { // Check if the form has the correct value const categoryValue = spectator.component.categoryFieldControl.value; - expect(categoryValue).toEqual([ - '1f208488057007cedda0e0b5d52ee3b3', - 'cb83dc32c0a198fd0ca427b3b587f4ce' - ]); + expect(categoryValue).toEqual(SELECTED_LIST_MOCK); })); it('should set categoryFieldControl value when adding a new category', () => { @@ -169,21 +196,17 @@ describe('DotEditContentCategoryFieldComponent', () => { const categoryValue = spectator.component.categoryFieldControl.value; - expect(categoryValue).toEqual([ - '1f208488057007cedda0e0b5d52ee3b3', - 'cb83dc32c0a198fd0ca427b3b587f4ce', - '1234' - ]); + expect(categoryValue).toEqual([...SELECTED_LIST_MOCK, '1234']); }); it('should set categoryFieldControl value when removing a category', () => { - store.removeSelected('1f208488057007cedda0e0b5d52ee3b3'); + store.removeSelected(SELECTED_LIST_MOCK[0]); spectator.flushEffects(); const categoryValue = spectator.component.categoryFieldControl.value; - expect(categoryValue).toEqual(['cb83dc32c0a198fd0ca427b3b587f4ce']); + expect(categoryValue).toEqual([SELECTED_LIST_MOCK[1]]); }); }); }); diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/mocks/category-field.mocks.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/mocks/category-field.mocks.ts index c260c778826c..14359c9208fd 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/mocks/category-field.mocks.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/mocks/category-field.mocks.ts @@ -1,7 +1,7 @@ import { DotCategory, DotCMSContentlet, DotCMSContentTypeField } from '@dotcms/dotcms-models'; import { MockDotMessageService } from '@dotcms/utils-testing'; -import { DotCategoryFieldKeyValueObj } from '../models/dot-category-field.models'; +import { DotCategoryFieldKeyValueObj, HierarchyParent } from '../models/dot-category-field.models'; import { transformCategories } from '../utils/category-field.utils'; export const CATEGORY_FIELD_VARIABLE_NAME = 'categorias'; @@ -263,3 +263,42 @@ const MESSAGES_MOCK = { }; export const CATEGORY_MESSAGE_MOCK = new MockDotMessageService(MESSAGES_MOCK); + +export const CATEGORY_HIERARCHY_MOCK: HierarchyParent[] = [ + { + inode: CATEGORY_LEVEL_1[0].inode, + key: CATEGORY_LEVEL_1[0].key, + name: CATEGORY_LEVEL_1[0].categoryName, + + parentList: [ + { + inode: CATEGORY_FIELD_MOCK.categories.inode, + key: CATEGORY_FIELD_MOCK.categories.key, + name: CATEGORY_FIELD_MOCK.categories.categoryName + }, + { + inode: CATEGORY_LEVEL_1[0].inode, + key: CATEGORY_LEVEL_1[0].key, + name: CATEGORY_LEVEL_1[0].categoryName + } + ] + }, + { + inode: CATEGORY_LEVEL_1[1].inode, + key: CATEGORY_LEVEL_1[1].key, + name: CATEGORY_LEVEL_1[1].categoryName, + + parentList: [ + { + inode: CATEGORY_FIELD_MOCK.categories.inode, + key: CATEGORY_FIELD_MOCK.categories.key, + name: CATEGORY_FIELD_MOCK.categories.categoryName + }, + { + inode: CATEGORY_LEVEL_1[0].inode, + key: CATEGORY_LEVEL_1[0].key, + name: CATEGORY_LEVEL_1[0].categoryName + } + ] + } +]; diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/models/dot-category-field.models.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/models/dot-category-field.models.ts index 72341c8d4f59..5f10187146db 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/models/dot-category-field.models.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/models/dot-category-field.models.ts @@ -23,7 +23,7 @@ export interface DotCategoryFieldKeyValueObj { * It is defined as a subset of the DotCategory type, which includes the categoryName, * inode, and parentList properties. */ -export type HierarchyParent = Pick & { +export type HierarchyParent = Pick & { name: string; }; diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/services/categories.service.spec.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/services/categories.service.spec.ts index 018660ad4d7e..0fcc7589b82c 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/services/categories.service.spec.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/services/categories.service.spec.ts @@ -28,4 +28,14 @@ describe('CategoriesService', () => { HttpMethod.GET ); }); + + it('can getSelectedHierarchy of selected categories', () => { + const keys = ['key1', 'key2', 'key3']; + spectator.service.getSelectedHierarchy(keys).subscribe(); + spectator.expectOne( + `${API_URL}/hierarchy`, + + HttpMethod.POST + ); + }); }); diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/store/content-category-field.store.spec.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/store/content-category-field.store.spec.ts index 5af2a19e3845..eae1d10d3c16 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/store/content-category-field.store.spec.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/store/content-category-field.store.spec.ts @@ -6,6 +6,7 @@ import { } from '@ngneat/spectator/jest'; import { of } from 'rxjs'; +import { DotHttpErrorManagerService } from '@dotcms/data-access'; import { ComponentStatus } from '@dotcms/dotcms-models'; import { CategoryFieldStore } from './content-category-field.store'; @@ -13,6 +14,7 @@ import { CategoryFieldStore } from './content-category-field.store'; import { CATEGORY_FIELD_CONTENTLET_MOCK, CATEGORY_FIELD_MOCK, + CATEGORY_HIERARCHY_MOCK, CATEGORY_LEVEL_1, CATEGORY_LEVEL_2, SELECTED_LIST_MOCK @@ -29,17 +31,16 @@ describe('CategoryFieldStore', () => { let categoriesService: SpyObject; const createService = createServiceFactory({ service: CategoryFieldStore, - providers: [ - mockProvider(CategoriesService, { - getChildren: jest.fn().mockReturnValue(of([])) - }) - ] + providers: [mockProvider(CategoriesService), mockProvider(DotHttpErrorManagerService)] }); beforeEach(() => { spectator = createService(); store = spectator.service; categoriesService = spectator.inject(CategoriesService); + + categoriesService.getChildren.mockReturnValue(of(CATEGORY_LEVEL_1)); + categoriesService.getSelectedHierarchy.mockReturnValue(of(CATEGORY_HIERARCHY_MOCK)); }); afterEach(() => { @@ -48,12 +49,10 @@ describe('CategoryFieldStore', () => { it('should initialize with default state', () => { expect(store.categories()).toEqual(EMPTY_ARRAY); - expect(store.selectedCategoriesValues()).toEqual(EMPTY_ARRAY); expect(store.keyParentPath()).toEqual(EMPTY_ARRAY); expect(store.state()).toEqual(ComponentStatus.IDLE); - // computed expect(store.selected()).toEqual(EMPTY_ARRAY); - expect(store.categoryList()).toEqual(EMPTY_ARRAY); + expect(store.mode()).toEqual('list'); }); describe('withMethods', () => { @@ -61,23 +60,30 @@ describe('CategoryFieldStore', () => { const expectedCategoryValues: DotCategoryFieldKeyValueObj[] = [ { key: '1f208488057007cedda0e0b5d52ee3b3', - value: 'Electrical' + value: 'Cleaning Supplies', + inode: '111111', + path: 'Cleaning Supplies' }, { key: 'cb83dc32c0a198fd0ca427b3b587f4ce', - value: 'Doors & Windows' + value: 'Doors & Windows', + inode: '22222', + path: 'Cleaning Supplies' } ]; - store.load(CATEGORY_FIELD_MOCK, CATEGORY_FIELD_CONTENTLET_MOCK); + store.load({ field: CATEGORY_FIELD_MOCK, contentlet: CATEGORY_FIELD_CONTENTLET_MOCK }); - expect(store.rootCategoryInode()).toEqual(CATEGORY_FIELD_MOCK.values); expect(store.selected()).toEqual(expectedCategoryValues); + expect(store.rootCategoryInode()).toEqual(CATEGORY_FIELD_MOCK.values); }); describe('getCategories', () => { beforeEach(() => { - store.load(CATEGORY_FIELD_MOCK, CATEGORY_FIELD_CONTENTLET_MOCK); + store.load({ + field: CATEGORY_FIELD_MOCK, + contentlet: CATEGORY_FIELD_CONTENTLET_MOCK + }); }); it('should fetch the categories with the rootCategoryInode', () => { @@ -122,7 +128,7 @@ describe('CategoryFieldStore', () => { describe('withComputed', () => { it('should show item after load the values', () => { const expectedSelectedValues = SELECTED_LIST_MOCK; - store.load(CATEGORY_FIELD_MOCK, CATEGORY_FIELD_CONTENTLET_MOCK); + store.load({ field: CATEGORY_FIELD_MOCK, contentlet: CATEGORY_FIELD_CONTENTLET_MOCK }); expect(store.selectedCategoriesValues().sort()).toEqual(expectedSelectedValues.sort()); expect(store.categoryList()).toEqual(EMPTY_ARRAY); diff --git a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/utils/category-field.utils.spec.ts b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/utils/category-field.utils.spec.ts index c216b8ed0d49..3dd133dccb67 100644 --- a/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/utils/category-field.utils.spec.ts +++ b/core-web/libs/edit-content/src/lib/fields/dot-edit-content-category-field/utils/category-field.utils.spec.ts @@ -408,10 +408,10 @@ describe('CategoryFieldUtils', () => { sortOrder: 0, type: '', parentList: [ - { key: 'root', categoryName: 'Root Parent', inode: 'rootInode' }, + { key: 'root', name: 'Root Parent', inode: 'rootInode' }, { key: 'parent1', - categoryName: 'Parent 1', + name: 'Parent 1', inode: 'parentInode1' } ] @@ -447,10 +447,10 @@ describe('CategoryFieldUtils', () => { sortOrder: 0, type: '', parentList: [ - { key: 'root', categoryName: 'Root Parent', inode: 'rootInode' }, + { key: 'root', name: 'Root Parent', inode: 'rootInode' }, { key: 'parent1', - categoryName: 'Parent 1', + name: 'Parent 1', inode: 'parentInode1' } ] @@ -471,10 +471,10 @@ describe('CategoryFieldUtils', () => { sortOrder: 0, type: '', parentList: [ - { key: 'root', categoryName: 'Root Parent', inode: 'rootInode' }, + { key: 'root', name: 'Root Parent', inode: 'rootInode' }, { key: 'parent1', - categoryName: 'Parent 1', + name: 'Parent 1', inode: 'parentInode1' } ]