diff --git a/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts index ca39996188..ce8e846900 100644 --- a/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts +++ b/src/app/admin/admin-notifications/admin-notifications-publication-claim-page/admin-notifications-publication-claim-page.component.spec.ts @@ -1,35 +1,40 @@ import { CommonModule } from '@angular/common'; import { NO_ERRORS_SCHEMA } from '@angular/core'; import { - async, ComponentFixture, TestBed, + waitForAsync, } from '@angular/core/testing'; import { TranslateModule } from '@ngx-translate/core'; -import { NotificationsSuggestionTargetsPageComponent } from '../../../quality-assurance-notifications-pages/notifications-suggestion-targets-page/notifications-suggestion-targets-page.component'; +import { PublicationClaimComponent } from '../../../notifications/suggestion-targets/publication-claim/publication-claim.component'; +import { AdminNotificationsPublicationClaimPageComponent } from './admin-notifications-publication-claim-page.component'; -describe('NotificationsSuggestionTargetsPageComponent', () => { - let component: NotificationsSuggestionTargetsPageComponent; - let fixture: ComponentFixture; +describe('AdminNotificationsPublicationClaimPageComponent', () => { + let component: AdminNotificationsPublicationClaimPageComponent; + let fixture: ComponentFixture; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ CommonModule, TranslateModule.forRoot(), - NotificationsSuggestionTargetsPageComponent, + AdminNotificationsPublicationClaimPageComponent, ], providers: [ - NotificationsSuggestionTargetsPageComponent, + AdminNotificationsPublicationClaimPageComponent, ], schemas: [NO_ERRORS_SCHEMA], + }).overrideComponent(AdminNotificationsPublicationClaimPageComponent, { + remove: { + imports: [PublicationClaimComponent], + }, }) .compileComponents(); })); beforeEach(() => { - fixture = TestBed.createComponent(NotificationsSuggestionTargetsPageComponent); + fixture = TestBed.createComponent(AdminNotificationsPublicationClaimPageComponent); component = fixture.componentInstance; fixture.detectChanges(); }); diff --git a/src/app/admin/admin-notify-dashboard/admin-notify-dashboard.component.spec.ts b/src/app/admin/admin-notify-dashboard/admin-notify-dashboard.component.spec.ts index 7d2e3204ed..a8bc2eea8e 100644 --- a/src/app/admin/admin-notify-dashboard/admin-notify-dashboard.component.spec.ts +++ b/src/app/admin/admin-notify-dashboard/admin-notify-dashboard.component.spec.ts @@ -1,3 +1,4 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; import { ComponentFixture, TestBed, @@ -11,6 +12,7 @@ import { SearchService } from '../../core/shared/search/search.service'; import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils'; import { ActivatedRouteStub } from '../../shared/testing/active-router.stub'; import { AdminNotifyDashboardComponent } from './admin-notify-dashboard.component'; +import { AdminNotifyMetricsComponent } from './admin-notify-metrics/admin-notify-metrics.component'; import { AdminNotifyMessage } from './models/admin-notify-message.model'; import { AdminNotifySearchResult } from './models/admin-notify-message-search-result.model'; @@ -46,6 +48,11 @@ describe('AdminNotifyDashboardComponent', () => { { provide: SearchService, useValue: { search: () => createSuccessfulRemoteDataObject$(results) } }, { provide: ActivatedRoute, useValue: new ActivatedRouteStub() }, ], + schemas: [NO_ERRORS_SCHEMA], + }).overrideComponent(AdminNotifyDashboardComponent, { + remove: { + imports: [AdminNotifyMetricsComponent], + }, }) .compileComponents(); diff --git a/src/app/admin/admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.html b/src/app/admin/admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.html index e51e207bbe..6c8342d2e6 100644 --- a/src/app/admin/admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.html +++ b/src/app/admin/admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.html @@ -3,7 +3,7 @@ [linkType]="linkType" [listID]="listID">
- + {{"admin.search.collection.edit" | translate}}
diff --git a/src/app/admin/admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.spec.ts b/src/app/admin/admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.spec.ts index cb2f1af9b7..7a4e2da68d 100644 --- a/src/app/admin/admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.spec.ts +++ b/src/app/admin/admin-search-page/admin-search-results/admin-search-result-list-element/collection-search-result/collection-admin-search-result-list-element.component.spec.ts @@ -19,6 +19,7 @@ import { mockTruncatableService } from '../../../../../shared/mocks/mock-trucata import { getMockThemeService } from '../../../../../shared/mocks/theme-service.mock'; import { CollectionElementLinkType } from '../../../../../shared/object-collection/collection-element-link.type'; import { CollectionSearchResult } from '../../../../../shared/object-collection/shared/collection-search-result.model'; +import { CollectionSearchResultListElementComponent } from '../../../../../shared/object-list/search-result-list-element/collection-search-result/collection-search-result-list-element.component'; import { ThemeService } from '../../../../../shared/theme-support/theme.service'; import { TruncatableService } from '../../../../../shared/truncatable/truncatable.service'; import { CollectionAdminSearchResultListElementComponent } from './collection-admin-search-result-list-element.component'; @@ -51,8 +52,13 @@ describe('CollectionAdminSearchResultListElementComponent', () => { { provide: ThemeService, useValue: getMockThemeService() }, ], schemas: [NO_ERRORS_SCHEMA], - }) - .compileComponents(); + }).overrideComponent(CollectionAdminSearchResultListElementComponent, { + remove: { + imports: [ + CollectionSearchResultListElementComponent, + ], + }, + }).compileComponents(); })); beforeEach(() => { @@ -62,7 +68,7 @@ describe('CollectionAdminSearchResultListElementComponent', () => { component.linkTypes = CollectionElementLinkType; component.index = 0; component.viewModes = ViewMode; - + fixture.detectChanges(); }); it('should create', () => { @@ -70,10 +76,7 @@ describe('CollectionAdminSearchResultListElementComponent', () => { }); it('should render an edit button with the correct link', () => { - component.ngOnInit(); - fixture.detectChanges(); - - const a = fixture.debugElement.query(By.css('a')); + const a = fixture.debugElement.query(By.css('a[data-test="coll-link"]')); const link = a.nativeElement.href; expect(link).toContain(getCollectionEditRoute(id)); }); diff --git a/src/app/app-routes.ts b/src/app/app-routes.ts index b3d5291cf2..ba322eef45 100644 --- a/src/app/app-routes.ts +++ b/src/app/app-routes.ts @@ -157,13 +157,6 @@ export const APP_ROUTES: Route[] = [ .then((m) => m.ROUTES), canActivate: [EndUserAgreementCurrentUserGuard], }, - { - path: NOTIFICATIONS_MODULE_PATH, - loadChildren: () => import('./admin/admin-notifications/admin-notifications-routes') - .then((m) => m.ROUTES), - providers: [provideSuggestionNotificationsState()], - canActivate: [AuthenticatedGuard, EndUserAgreementCurrentUserGuard], - }, { path: NOTIFICATIONS_MODULE_PATH, loadChildren: () => import('./quality-assurance-notifications-pages/notifications-pages-routes') diff --git a/src/app/browse-by/browse-by-page/browse-by-page.component.spec.ts b/src/app/browse-by/browse-by-page/browse-by-page.component.spec.ts index 1b6390c541..db39793cae 100644 --- a/src/app/browse-by/browse-by-page/browse-by-page.component.spec.ts +++ b/src/app/browse-by/browse-by-page/browse-by-page.component.spec.ts @@ -8,6 +8,7 @@ import { By } from '@angular/platform-browser'; import { ActivatedRoute } from '@angular/router'; import { BrowseDefinition } from '../../core/shared/browse-definition.model'; +import { GenericConstructor } from '../../core/shared/generic-constructor'; import { DynamicComponentLoaderDirective } from '../../shared/abstract-component-loader/dynamic-component-loader.directive'; import { getMockThemeService } from '../../shared/mocks/theme-service.mock'; import { ActivatedRouteStub } from '../../shared/testing/active-router.stub'; @@ -24,6 +25,19 @@ import { BrowseByPageComponent } from './browse-by-page.component'; class BrowseByTestComponent { } +@Component({ + // eslint-disable-next-line @angular-eslint/component-selector + selector: 'ds-browse-by-switcher', + template: ``, + standalone: true, + imports: [DynamicComponentLoaderDirective], +}) +class TestBrowseBySwitcherComponent extends BrowseBySwitcherComponent { + getComponent(): GenericConstructor { + return BrowseByTestComponent; + } +} + class TestBrowseByPageBrowseDefinition extends BrowseDefinition { getRenderType(): BrowseByDataType { return 'BrowseByPageComponent' as BrowseByDataType; @@ -42,7 +56,7 @@ describe('BrowseByPageComponent', () => { themeService = getMockThemeService(); await TestBed.configureTestingModule({ - imports: [BrowseBySwitcherComponent, BrowseByPageComponent, DynamicComponentLoaderDirective], + imports: [TestBrowseBySwitcherComponent, BrowseByPageComponent, DynamicComponentLoaderDirective], providers: [ BrowseByTestComponent, { provide: ActivatedRoute, useValue: activatedRoute }, @@ -53,6 +67,9 @@ describe('BrowseByPageComponent', () => { remove: { imports: [BrowseBySwitcherComponent], }, + add: { + imports: [TestBrowseBySwitcherComponent], + }, }) .compileComponents(); diff --git a/src/app/core/cache/builders/link.service.spec.ts b/src/app/core/cache/builders/link.service.spec.ts index a6e5b24e50..96650f1a55 100644 --- a/src/app/core/cache/builders/link.service.spec.ts +++ b/src/app/core/cache/builders/link.service.spec.ts @@ -1,15 +1,13 @@ /* eslint-disable max-classes-per-file */ -import { Injectable } from '@angular/core'; import { TestBed } from '@angular/core/testing'; -import { isEmpty } from 'rxjs/operators'; +import { + isEmpty, + take, +} from 'rxjs/operators'; import { APP_DATA_SERVICES_MAP } from '../../../../config/app-config.interface'; -import { - followLink, - FollowLinkConfig, -} from '../../../shared/utils/follow-link-config.model'; -import { DATA_SERVICE_FACTORY } from '../../data/base/data-service.decorator'; -import { FindListOptions } from '../../data/find-list-options.model'; +import { TestDataService } from '../../../shared/testing/test-data-service.mock'; +import { followLink } from '../../../shared/utils/follow-link-config.model'; import { HALLink } from '../../shared/hal-link.model'; import { HALResource } from '../../shared/hal-resource.model'; import { ResourceType } from '../../shared/resource-type'; @@ -39,16 +37,9 @@ class TestModel implements HALResource { successor?: TestModel; } -@Injectable() -class TestDataService { - findListByHref(href: string, findListOptions: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]) { - return 'findListByHref'; - } - - findByHref(href: string, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig[]) { - return 'findByHref'; - } -} +const mockDataServiceMap: any = { + [TEST_MODEL.value]: () => import('../../../shared/testing/test-data-service.mock').then(m => m.TestDataService), +}; let testDataService: TestDataService; @@ -76,35 +67,39 @@ describe('LinkService', () => { spyOn(testDataService, 'findListByHref').and.callThrough(); spyOn(testDataService, 'findByHref').and.callThrough(); TestBed.configureTestingModule({ - providers: [LinkService, { - provide: TestDataService, - useValue: testDataService, - }, { - provide: DATA_SERVICE_FACTORY, - useValue: jasmine.createSpy('getDataServiceFor').and.returnValue(TestDataService), - }, { - provide: LINK_DEFINITION_FACTORY, - useValue: jasmine.createSpy('getLinkDefinition').and.returnValue({ - resourceType: TEST_MODEL, - linkName: 'predecessor', - propertyName: 'predecessor', - }), - }, { - provide: LINK_DEFINITION_MAP_FACTORY, - useValue: jasmine.createSpy('getLinkDefinitions').and.returnValue([ - { + providers: [ + LinkService, + { + provide: TestDataService, + useValue: testDataService, + }, + { + provide: APP_DATA_SERVICES_MAP, + useValue: mockDataServiceMap, + }, + { + provide: LINK_DEFINITION_FACTORY, + useValue: jasmine.createSpy('getLinkDefinition').and.returnValue({ resourceType: TEST_MODEL, linkName: 'predecessor', propertyName: 'predecessor', - }, - { - resourceType: TEST_MODEL, - linkName: 'successor', - propertyName: 'successor', - }, - ]), - }, - { provide: APP_DATA_SERVICES_MAP, useValue: {} }, + }), + }, + { + provide: LINK_DEFINITION_MAP_FACTORY, + useValue: jasmine.createSpy('getLinkDefinitions').and.returnValue([ + { + resourceType: TEST_MODEL, + linkName: 'predecessor', + propertyName: 'predecessor', + }, + { + resourceType: TEST_MODEL, + linkName: 'successor', + propertyName: 'successor', + }, + ]), + }, ], }); service = TestBed.inject(LinkService); @@ -113,10 +108,13 @@ describe('LinkService', () => { describe('resolveLink', () => { describe(`when the linkdefinition concerns a single object`, () => { beforeEach(() => { - service.resolveLink(testModel, followLink('predecessor', {}, followLink('successor'))); + result = service.resolveLink(testModel, followLink('predecessor', {}, followLink('successor'))); }); - it('should call dataservice.findByHref with the correct href and nested links', () => { - expect(testDataService.findByHref).toHaveBeenCalledWith(testModel._links.predecessor.href, true, true, followLink('successor')); + it('should call dataservice.findByHref with the correct href and nested links', (done) => { + result.predecessor.pipe(take(1)).subscribe(() => { + expect(testDataService.findByHref).toHaveBeenCalledWith(testModel._links.predecessor.href, true, true, followLink('successor')); + done(); + }); }); }); describe(`when the linkdefinition concerns a list`, () => { @@ -127,10 +125,13 @@ describe('LinkService', () => { propertyName: 'predecessor', isList: true, }); - service.resolveLink(testModel, followLink('predecessor', { findListOptions: { some: 'options ' } as any }, followLink('successor'))); + result = service.resolveLink(testModel, followLink('predecessor', { findListOptions: { some: 'options ' } as any }, followLink('successor'))); }); - it('should call dataservice.findListByHref with the correct href, findListOptions, and nested links', () => { - expect(testDataService.findListByHref).toHaveBeenCalledWith(testModel._links.predecessor.href, { some: 'options ' } as any, true, true, followLink('successor')); + it('should call dataservice.findListByHref with the correct href, findListOptions, and nested links', (done) => { + result.predecessor.pipe(take(1)).subscribe((res) => { + expect(testDataService.findListByHref).toHaveBeenCalledWith(testModel._links.predecessor.href, { some: 'options ' } as any, true, true, followLink('successor')); + done(); + }); }); }); describe('either way', () => { @@ -142,15 +143,14 @@ describe('LinkService', () => { expect((service as any).getLinkDefinition).toHaveBeenCalledWith(testModel.constructor as any, 'predecessor'); }); - it('should call getDataServiceFor with the correct resource type', () => { - expect((service as any).getDataServiceFor).toHaveBeenCalledWith(TEST_MODEL); - }); - - it('should return the model with the resolved link', () => { + it('should return the model with the resolved link', (done) => { expect(result.type).toBe(TEST_MODEL); expect(result.value).toBe('a test value'); expect(result._links.self.href).toBe('http://self.link'); - expect(result.predecessor).toBe('findByHref'); + result.predecessor.subscribe((res) => { + expect(res).toBe('findByHref'); + done(); + }); }); }); @@ -167,12 +167,16 @@ describe('LinkService', () => { describe(`when there is no dataservice for the resourcetype in the link`, () => { beforeEach(() => { - ((service as any).getDataServiceFor as jasmine.Spy).and.returnValue(undefined); + (service as any).map = {}; }); - it('should throw an error', () => { - expect(() => { - service.resolveLink(testModel, followLink('predecessor', {}, followLink('successor'))); - }).toThrow(); + it('should throw an error', (done) => { + result = service.resolveLink(testModel, followLink('predecessor', {}, followLink('successor'))); + result.predecessor.subscribe({ + error: (error: unknown) => { + expect(error).toBeDefined(); + done(); + }, + }); }); }); }); @@ -237,8 +241,11 @@ describe('LinkService', () => { result = service.resolveLinks(testModel, followLink('predecessor')); }); - it('should return the model with the resolved link', () => { - expect(result.predecessor).toBe('findByHref'); + it('should return the model with the resolved link', (done) => { + result.predecessor.subscribe((res) => { + expect(res).toBe('findByHref'); + done(); + }); }); }); diff --git a/src/app/core/cache/builders/link.service.ts b/src/app/core/cache/builders/link.service.ts index b72e722976..b1ced76bb8 100644 --- a/src/app/core/cache/builders/link.service.ts +++ b/src/app/core/cache/builders/link.service.ts @@ -7,7 +7,6 @@ import { import { EMPTY, Observable, - of, } from 'rxjs'; import { catchError, @@ -93,7 +92,7 @@ export class LinkService { } } - return of(null); + return EMPTY; }), catchError((err: unknown) => { throw new Error(`The @link() for ${String(linkToFollow.name)} on ${model.constructor.name} models uses the resource type ${matchingLinkDef.resourceType.value.toUpperCase()}, but there is no service with an @dataService(${matchingLinkDef.resourceType.value.toUpperCase()}) annotation in order to retrieve it`); diff --git a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html index c9afc6ca63..b79b185b40 100644 --- a/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html +++ b/src/app/dso-shared/dso-edit-metadata/dso-edit-metadata-value/dso-edit-metadata-value.component.html @@ -36,7 +36,7 @@ [authorityValue]="mdValue.newValue.confidence" [iconMode]="true" > -