Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,14 @@ module.exports = {
'<rootDir>/src/app/features/project/addons/components/connect-configured-addon/',
'<rootDir>/src/app/features/project/addons/components/disconnect-addon-modal/',
'<rootDir>/src/app/features/project/addons/components/confirm-account-connection-modal/',
'<rootDir>/src/app/features/files/components',
'<rootDir>/src/app/features/files/components/create-folder-dialog',
'<rootDir>/src/app/features/files/components/edit-file-metadata-dialog',
'<rootDir>/src/app/features/files/components/file-keywords',
'<rootDir>/src/app/features/files/components/file-metadata',
'<rootDir>/src/app/features/files/components/file-resource-metadata',
'<rootDir>/src/app/features/files/components/move-file-dialog',
'<rootDir>/src/app/features/files/components/rename-file-dialog',
'<rootDir>/src/app/features/files/pages/community-metadata',
'<rootDir>/src/app/features/files/pages/file-detail',
'<rootDir>/src/app/features/my-projects/',
'<rootDir>/src/app/features/project/analytics/',
'<rootDir>/src/app/features/project/contributors/',
Expand Down Expand Up @@ -99,7 +104,6 @@ module.exports = {
'<rootDir>/src/app/features/settings/tokens/mappers/',
'<rootDir>/src/app/features/settings/tokens/store/',
'<rootDir>/src/app/shared/components/file-menu/',
'<rootDir>/src/app/shared/components/files-tree/',
'<rootDir>/src/app/shared/components/line-chart/',
'<rootDir>/src/app/shared/components/make-decision-dialog/',
'<rootDir>/src/app/shared/components/pie-chart/',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,45 @@
import { Store } from '@ngxs/store';

import { MockProvider } from 'ng-mocks';

import { ComponentFixture, TestBed } from '@angular/core/testing';

import { FilesSelectors } from '@osf/features/files/store';
import { MOCK_STORE } from '@shared/mocks';
import { DataciteService } from '@shared/services/datacite/datacite.service';

import { FileRevisionsComponent } from './file-revisions.component';

import { OSFTestingStoreModule } from '@testing/osf.testing.module';
import { DataciteMockFactory } from '@testing/mocks/datacite.service.mock';
import { OSFTestingModule } from '@testing/osf.testing.module';

describe('FileRevisionsComponent', () => {
let component: FileRevisionsComponent;
let fixture: ComponentFixture<FileRevisionsComponent>;
let dataciteMock: jest.Mocked<DataciteService>;

beforeEach(async () => {
dataciteMock = DataciteMockFactory();
(MOCK_STORE.selectSignal as jest.Mock).mockImplementation((selector) => {
switch (selector) {
case FilesSelectors.isFileRevisionsLoading:
return () => false;
default:
return () => [];
}
});
await TestBed.configureTestingModule({
imports: [FileRevisionsComponent, OSFTestingStoreModule],
providers: [MockProvider(Store, MOCK_STORE), MockProvider(DataciteService, dataciteMock)],
imports: [FileRevisionsComponent, OSFTestingModule],
}).compileComponents();

fixture = TestBed.createComponent(FileRevisionsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
it('should log download', () => {
component.downloadRevision('123');
expect(dataciteMock.logIdentifiableDownload).toHaveBeenCalledWith(component.resourceMetadata);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import { map, of } from 'rxjs';

import { DatePipe } from '@angular/common';
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { toObservable, toSignal } from '@angular/core/rxjs-interop';
import { ActivatedRoute } from '@angular/router';

import { CopyButtonComponent } from '@osf/shared/components';
import { InfoIconComponent } from '@osf/shared/components/info-icon/info-icon.component';
import { DataciteService } from '@shared/services/datacite/datacite.service';

import { FilesSelectors } from '../../store';

Expand All @@ -39,13 +40,16 @@ import { environment } from 'src/environments/environment';
],
})
export class FileRevisionsComponent {
private readonly dataciteService = inject(DataciteService);
private readonly route = inject(ActivatedRoute);

readonly fileRevisions = select(FilesSelectors.getFileRevisions);
readonly isLoading = select(FilesSelectors.isFileRevisionsLoading);
readonly resourceMetadata = toObservable(select(FilesSelectors.getResourceMetadata));
readonly fileGuid = toSignal(this.route.params.pipe(map((params) => params['fileGuid'])) ?? of(undefined));

downloadRevision(version: string): void {
this.dataciteService.logIdentifiableDownload(this.resourceMetadata).subscribe();
if (this.fileGuid()) {
window.open(`${environment.downloadUrl}/${this.fileGuid()}/?revision=${version}`)?.focus();
}
Expand Down
4 changes: 3 additions & 1 deletion src/app/features/files/mappers/resource-metadata.mapper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ResourceMetadata } from '@shared/models';
import { ResourceMetadata } from '@osf/shared/models';
import { IdentifiersMapper } from '@shared/mappers/identifiers.mapper';

import { GetResourceCustomMetadataResponse } from '../models/get-resource-custom-metadata-response.model';
import { GetResourceShortInfoResponse } from '../models/get-resource-short-info-response.model';
Expand All @@ -20,6 +21,7 @@ export function MapResourceMetadata(
awardUri: funder.award_uri,
awardTitle: funder.award_title,
})),
identifiers: IdentifiersMapper.fromJsonApi(shortInfo.data.embeds.identifiers),
language: customMetadata.data.embeds.custom_metadata.data.attributes.language,
resourceTypeGeneral: customMetadata.data.embeds.custom_metadata.data.attributes.resource_type_general,
};
Expand Down
1 change: 1 addition & 0 deletions src/app/features/files/models/file-target.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ export interface OsfFileTarget {
public: boolean;
type: string;
isAnonymous?: boolean;
link: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ export interface FileTargetResponse {
},
null,
null,
null
{
html: string;
self: string;
iri: string;
}
>,
null
>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ApiData, JsonApiResponse } from '@osf/shared/models';
import { IdentifiersJsonApiResponse } from '@shared/models/identifiers/identifier-json-api.model';

export type GetResourceShortInfoResponse = JsonApiResponse<
ApiData<
Expand All @@ -8,7 +9,7 @@ export type GetResourceShortInfoResponse = JsonApiResponse<
date_created: string;
date_modified: string;
},
null,
{ identifiers: IdentifiersJsonApiResponse },
null,
null
>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ApiData, JsonApiResponse } from '@shared/models';
import { IdentifiersJsonApiResponse } from '@shared/models/identifiers/identifier-json-api.model';

export type GetShortInfoResponse = JsonApiResponse<
ApiData<
Expand All @@ -8,7 +9,7 @@ export type GetShortInfoResponse = JsonApiResponse<
date_created: string;
date_modified: string;
},
null,
{ identifiers: IdentifiersJsonApiResponse },
null,
null
>,
Expand Down
107 changes: 96 additions & 11 deletions src/app/features/files/pages/file-detail/file-detail.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,114 @@
import { MockComponent } from 'ng-mocks';
// Dependencies
import { Store } from '@ngxs/store';

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
import { MockProvider } from 'ng-mocks';

import { ButtonGroupModule } from 'primeng/buttongroup';
import { DialogService } from 'primeng/dynamicdialog';
import { Message } from 'primeng/message';
import { TagModule } from 'primeng/tag';

import { SubHeaderComponent } from '@shared/components';
import { of } from 'rxjs';

import { DestroyRef } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';

import { FileDetailComponent } from './file-detail.component';
import { FileDetailComponent } from '@osf/features/files/pages/file-detail/file-detail.component';
import {
LinkedResourcesComponent,
OverviewComponentsComponent,
OverviewToolbarComponent,
OverviewWikiComponent,
RecentActivityComponent,
} from '@osf/features/project/overview/components';
import {
LoadingSpinnerComponent,
ResourceMetadataComponent,
SubHeaderComponent,
ViewOnlyLinkMessageComponent,
} from '@shared/components';
import { MOCK_STORE } from '@shared/mocks';
import { CustomConfirmationService } from '@shared/services/custom-confirmation.service';
import { DataciteService } from '@shared/services/datacite/datacite.service';
import { ToastService } from '@shared/services/toast.service';

import { OSFTestingStoreModule } from '@testing/osf.testing.module';
import { OSFTestingModule } from '@testing/osf.testing.module';

describe('FileDetailComponent', () => {
let component: FileDetailComponent;
let fixture: ComponentFixture<FileDetailComponent>;
let component: FileDetailComponent;
let dataciteService: jest.Mocked<DataciteService>;

beforeEach(async () => {
window.open = jest.fn();
dataciteService = {
logIdentifiableView: jest.fn().mockReturnValue(of(void 0)),
logIdentifiableDownload: jest.fn().mockReturnValue(of(void 0)),
} as unknown as jest.Mocked<DataciteService>;

const mockRoute: Partial<ActivatedRoute> = {
params: of({ providerId: 'osf', preprintId: 'p1' }),
queryParams: of({ providerId: 'osf', preprintId: 'p1' }),
};
(MOCK_STORE.selectSignal as jest.Mock).mockImplementation((selector) => {
switch (selector) {
default:
return () => [];
}
});

await TestBed.configureTestingModule({
imports: [FileDetailComponent, MockComponent(SubHeaderComponent), OSFTestingStoreModule],
providers: [],
imports: [
FileDetailComponent,
OSFTestingModule,
ButtonGroupModule,
TagModule,
SubHeaderComponent,
FormsModule,
LoadingSpinnerComponent,
OverviewWikiComponent,
OverviewComponentsComponent,
LinkedResourcesComponent,
RecentActivityComponent,
OverviewToolbarComponent,
ResourceMetadataComponent,
TranslatePipe,
Message,
RouterLink,
ViewOnlyLinkMessageComponent,
],
providers: [
TranslatePipe,
{ provide: ActivatedRoute, useValue: mockRoute },
{ provide: Store, useValue: MOCK_STORE },
{ provide: DataciteService, useValue: dataciteService },
Router,
DestroyRef,
MockProvider(ToastService),
MockProvider(CustomConfirmationService),
DialogService,
TranslateService,
],
}).compileComponents();

fixture = TestBed.createComponent(FileDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
afterEach(() => {
jest.clearAllMocks();
});

it('should call dataciteService.logIdentifiableDownload when downloadFile is triggered', () => {
const link = '123';
component.downloadFile(link);
expect(dataciteService.logIdentifiableDownload).toHaveBeenCalledWith(component.fileMetadata$);
});

it('should call dataciteService.logIdentifiableView on start ', () => {
expect(dataciteService.logIdentifiableView).toHaveBeenCalledWith(component.fileMetadata$);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
inject,
signal,
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';

Expand All @@ -41,6 +41,7 @@ import { MetadataResourceEnum, ResourceType } from '@osf/shared/enums';
import { pathJoin } from '@osf/shared/helpers';
import { MetadataTabsModel, OsfFile } from '@osf/shared/models';
import { CustomConfirmationService, MetaTagsService, ToastService } from '@osf/shared/services';
import { DataciteService } from '@shared/services/datacite/datacite.service';

import {
FileKeywordsComponent,
Expand Down Expand Up @@ -99,6 +100,7 @@ export class FileDetailComponent {
private readonly metaTags = inject(MetaTagsService);
private readonly datePipe = inject(DatePipe);
private readonly translateService = inject(TranslateService);
readonly dataciteService = inject(DataciteService);

private readonly actions = createDispatchMap({
getFile: GetFile,
Expand All @@ -115,6 +117,7 @@ export class FileDetailComponent {
});

file = select(FilesSelectors.getOpenedFile);
fileMetadata$ = toObservable(select(FilesSelectors.getResourceMetadata));
isFileLoading = select(FilesSelectors.isOpenedFileLoading);
cedarRecords = select(MetadataSelectors.getCedarRecords);
cedarTemplates = select(MetadataSelectors.getCedarTemplates);
Expand Down Expand Up @@ -186,8 +189,7 @@ export class FileDetailComponent {
return {
title: this.fileCustomMetadata()?.title || file.name,
description:
this.fileCustomMetadata()?.description ??
this.translateService.instant('files.metaTagDescriptionPlaceholder'),
this.fileCustomMetadata()?.description ?? this.translateService.instant('files.metaTagDescriptionPlaceholder'),
url: pathJoin(environment.webUrl, this.fileGuid),
publishedDate: this.datePipe.transform(file.dateCreated, 'yyyy-MM-dd'),
modifiedDate: this.datePipe.transform(file.dateModified, 'yyyy-MM-dd'),
Expand Down Expand Up @@ -247,9 +249,11 @@ export class FileDetailComponent {
this.route.params.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => {
this.actions.getFileMetadata(params['fileGuid']);
});
this.dataciteService.logIdentifiableView(this.fileMetadata$).subscribe();
}

downloadFile(link: string): void {
this.dataciteService.logIdentifiableDownload(this.fileMetadata$).subscribe();
window.open(link)?.focus();
}

Expand Down
Loading