Skip to content

Commit

Permalink
test(search-filter-summary): add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tkohr committed Nov 26, 2024
1 parent 33d7a28 commit 5ff9f51
Show file tree
Hide file tree
Showing 5 changed files with 250 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'
import { SearchFiltersComponent } from './search-filters.component'
import { MockBuilder } from 'ng-mocks'
import { TranslateModule } from '@ngx-translate/core'
import { By } from '@angular/platform-browser'
import { SearchFiltersSummaryComponent } from '@geonetwork-ui/feature/search'

describe('SearchFiltersComponent', () => {
let component: SearchFiltersComponent
let fixture: ComponentFixture<SearchFiltersComponent>

beforeEach(() => {
return MockBuilder(SearchFiltersComponent)
return MockBuilder(SearchFiltersComponent).mock(
SearchFiltersSummaryComponent
)
})

beforeEach(async () => {
Expand Down Expand Up @@ -40,5 +44,15 @@ describe('SearchFiltersComponent', () => {
fixture.detectChanges()
expect(component.searchConfig).toEqual([])
})

it('should pass searchFields to SearchFiltersSummaryComponent', () => {
const searchFields = ['user', 'publisherOrg', 'format', 'isSpatial']
component.searchFields = searchFields
fixture.detectChanges()
const summaryComponent = fixture.debugElement.query(
By.directive(SearchFiltersSummaryComponent)
).componentInstance
expect(summaryComponent.searchFields).toEqual(searchFields)
})
})
})
Original file line number Diff line number Diff line change
@@ -1,21 +1,155 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'

import { SearchFiltersSummaryItemComponent } from './search-filters-summary-item.component'
import { BehaviorSubject, firstValueFrom, of } from 'rxjs'
import { MockBuilder, MockComponent, MockProvider } from 'ng-mocks'
import { SearchFacade } from '../state/search.facade'
import { SearchService } from '../utils/service/search.service'
import { FieldFilters } from '@geonetwork-ui/common/domain/model/search'
import { BadgeComponent } from '@geonetwork-ui/ui/inputs'
import { CommonModule, DatePipe } from '@angular/common'
import { TranslateModule, TranslateService } from '@ngx-translate/core'
import { FieldsService } from '../utils/service/fields.service'
import { FieldType } from '../utils/service/fields'

const FIELD_VALUES_FROM_FILTERS_MOCK = {
organization: [],
format: [],
resourceType: [],
representationType: [],
publicationYear: [],
topic: [],
inspireKeyword: [],
keyword: [],
documentStandard: [],
isSpatial: [],
q: [],
license: [],
owner: [],
producerOrg: [],
publisherOrg: [],
user: ['admin|admin|admin|Administrator', 'barbie|Roberts|Barbara|UserAdmin'],
changeDate: {
start: new Date('2024-11-01T00:00:00.000Z'),
end: new Date('2024-11-29T00:00:00.000Z'),
},
}
/* searchFilters$ is only used to trigger change detection.
** its value is replaced by FIELD_VALUES_FROM_FILTERS_MOCK in stream
*/
class SearchFacadeMock {
searchFilters$ = new BehaviorSubject<FieldFilters>({})
}
class SearchServiceMock {
setFilters = jest.fn()
}

class TranslateServiceMock {
get = jest.fn(() => of(''))
}

describe('SearchFiltersSummaryComponent', () => {
let component: SearchFiltersSummaryItemComponent
let fixture: ComponentFixture<SearchFiltersSummaryItemComponent>
let searchFacade: SearchFacade
let translateService: TranslateService
let fieldsService: FieldsService

beforeEach(() => {
TestBed.configureTestingModule({
imports: [SearchFiltersSummaryItemComponent],
})
return MockBuilder(SearchFiltersSummaryItemComponent)
})

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [CommonModule, TranslateModule.forRoot()],
declarations: [
SearchFiltersSummaryItemComponent,
MockComponent(BadgeComponent),
],
providers: [
MockProvider(SearchFacade, SearchFacadeMock, 'useClass'),
MockProvider(SearchService, SearchServiceMock, 'useClass'),
MockProvider(FieldsService),
MockProvider(DatePipe),
MockProvider(TranslateService, TranslateServiceMock, 'useClass'),
],
}).compileComponents()
fixture = TestBed.createComponent(SearchFiltersSummaryItemComponent)
component = fixture.componentInstance
fixture.detectChanges()
searchFacade = TestBed.inject(SearchFacade)
fieldsService = TestBed.inject(FieldsService)
translateService = TestBed.inject(TranslateService)
})

it('should create', () => {
expect(component).toBeTruthy()
})

it('should set fieldValues$ observable for empty filters', async () => {
const fieldValues = await firstValueFrom(component.fieldValues$)
expect(fieldValues).toEqual([])
})

describe('fieldValues$', () => {
beforeEach(() => {
fieldsService.getFieldType = jest.fn(
(field: 'changeDate' | 'user') =>
(field === 'changeDate' ? 'dateRange' : 'values') as FieldType
)
fieldsService.readFieldValuesFromFilters = jest.fn(() =>
of(FIELD_VALUES_FROM_FILTERS_MOCK)
)
;(searchFacade.searchFilters$ as BehaviorSubject<FieldFilters>).next({})
})
it('should set fieldValues$ observable for user values filters', async () => {
component.fieldName = 'user'
const fieldValues = await firstValueFrom(component.fieldValues$)
expect(fieldValues).toEqual([
{
value: 'admin|admin|admin|Administrator',
label: 'admin admin',
},
{
value: 'barbie|Roberts|Barbara|UserAdmin',
label: 'Barbara Roberts',
},
])
})
it('should set fieldValues$ observable for changeDate dateRange filters', async () => {
component.fieldName = 'changeDate'
fixture.detectChanges()
const fieldValues = await firstValueFrom(component.fieldValues$)
expect(fieldValues).toEqual([
{
value: {
start: new Date('2024-11-01T00:00:00.000Z'),
end: new Date('2024-11-29T00:00:00.000Z'),
},
label: '01.11.2024 - 29.11.2024',
},
])
})
})

describe('translateLabel', () => {
const fieldName = 'user'
const labelKey = `search.filters.summaryLabel.${fieldName}`
const fallbackKey = `search.filters.${fieldName}`
beforeEach(() => {
component.fieldName = fieldName
fixture.detectChanges()
translateService.get = jest.fn((key) => {
if (key === labelKey) {
return of(labelKey) // Simulate missing translation
} else if (key === fallbackKey) {
return of('Fallback Label')
}
return of('')
})
})
it('should translate label with fallback if necessary', () => {
component.translateLabel()
expect(component.translatedLabel).toBe('Fallback Label')
})
})
})
Original file line number Diff line number Diff line change
@@ -1,21 +1,92 @@
import { ComponentFixture, TestBed } from '@angular/core/testing'
import { SearchFiltersSummaryComponent } from './search-filters-summary.component'
import { MockComponent, MockProvider } from 'ng-mocks'
import { SearchService } from '../utils/service/search.service'
import { SearchFacade } from '../state/search.facade'
import { BehaviorSubject, firstValueFrom, of } from 'rxjs'
import { TranslateModule } from '@ngx-translate/core'
import { SearchFiltersSummaryItemComponent } from '../search-filters-summary-item/search-filters-summary-item.component'
import { FieldFilters } from '@geonetwork-ui/common/domain/model/search'

class SearchFacadeMock {
searchFilters$ = new BehaviorSubject<FieldFilters>({
format: {},
isSpatial: {},
license: {},
'userInfo.keyword': {},
})
}
class SearchServiceMock {
setFilters = jest.fn()
}
describe('SearchFiltersSummaryComponent', () => {
let component: SearchFiltersSummaryComponent
let fixture: ComponentFixture<SearchFiltersSummaryComponent>
let searchFacade: SearchFacade
let searchService: SearchService

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SearchFiltersSummaryComponent],
imports: [TranslateModule.forRoot()],
declarations: [
SearchFiltersSummaryComponent,
MockComponent(SearchFiltersSummaryItemComponent),
],
providers: [
MockProvider(SearchFacade, SearchFacadeMock, 'useClass'),
MockProvider(SearchService, SearchServiceMock, 'useClass'),
],
}).compileComponents()

fixture = TestBed.createComponent(SearchFiltersSummaryComponent)
searchFacade = TestBed.inject(SearchFacade)
searchService = TestBed.inject(SearchService)
component = fixture.componentInstance
fixture.detectChanges()
})

it('should create', () => {
expect(component).toBeTruthy()
})

it('should set searchFilterActive$ observable to false for empty filters', async () => {
const isActive = await firstValueFrom(component.searchFilterActive$)
expect(isActive).toBeFalsy()
})

it('should set searchFilterActive$ observable to true for NON empty value filters', async () => {
const filters = {
format: {},
isSpatial: {},
license: {},
'userInfo.keyword': { 'admin|admin|admin|Administrator': true },
}
;(searchFacade.searchFilters$ as BehaviorSubject<FieldFilters>).next(
filters
)
const isActive = await firstValueFrom(component.searchFilterActive$)
expect(isActive).toBeTruthy()
})

it('should set searchFilterActive$ observable to true for NON empty dateRange filters', async () => {
const filters = {
format: {},
isSpatial: {},
license: {},
changeDate: {
start: new Date('2021-01-01'),
end: new Date('2021-01-02'),
},
}
;(searchFacade.searchFilters$ as BehaviorSubject<FieldFilters>).next(
filters
)
const isActive = await firstValueFrom(component.searchFilterActive$)
expect(isActive).toBeTruthy()
})

it('should clear filters', () => {
component.clearFilters()
expect(searchService.setFilters).toHaveBeenCalledWith({})
})
})
23 changes: 23 additions & 0 deletions libs/util/shared/src/lib/utils/format-fields.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { formatUserInfo } from './format-fields'

describe('formatUserInfo', () => {
it('should format user info correctly', () => {
expect(formatUserInfo('barbie|Roberts|Barbara|UserAdmin (5)')).toEqual(
'Barbara Roberts'
)
})

it('should format user info correctly with count', () => {
expect(
formatUserInfo('barbie|Roberts|Barbara|UserAdmin (5)', true)
).toEqual('Barbara Roberts (5)')
})

it('should return undefined if user info is empty', () => {
expect(formatUserInfo('')).toBeUndefined()
})

it('should return undefined if user info is not a string', () => {
expect(formatUserInfo(undefined)).toBeUndefined()
})
})
4 changes: 2 additions & 2 deletions libs/util/shared/src/lib/utils/format-fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ export function formatUserInfo(
displayCount = false
): string {
const infos = (typeof userInfo === 'string' ? userInfo : '').split('|')
const count = displayCount ? infos[3].split(' ')[1] : ''
const count = displayCount ? ` ${infos[3].split(' ')[1]}` : ''
if (infos && infos.length === 4) {
return `${infos[2]} ${infos[1]} ${count}`
return `${infos[2]} ${infos[1]}${count}`
}
return undefined
}

0 comments on commit 5ff9f51

Please sign in to comment.