Skip to content

Commit 83b7340

Browse files
committed
Merge remote-tracking branch 'upstream/feature/pbs-26-2' into pbs-26-2
2 parents 71f3a65 + ee5d1bb commit 83b7340

4 files changed

Lines changed: 122 additions & 0 deletions

File tree

src/app/app.routes.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,13 @@ export const routes: Routes = [
107107
'@osf/features/preprints/pages/preprint-pending-moderation/preprint-pending-moderation.component'
108108
).then((mod) => mod.PreprintPendingModerationComponent),
109109
},
110+
{
111+
path: 'preprints/:providerId/:id/download',
112+
loadComponent: () =>
113+
import('@osf/features/preprints/pages/preprint-download-redirect/preprint-download-redirect.component').then(
114+
(c) => c.PreprintDownloadRedirectComponent
115+
),
116+
},
110117
{
111118
path: 'preprints/:providerId/:id',
112119
loadComponent: () =>
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { MockProvider } from 'ng-mocks';
2+
3+
import { PLATFORM_ID } from '@angular/core';
4+
import { TestBed } from '@angular/core/testing';
5+
import { ActivatedRoute } from '@angular/router';
6+
7+
import { SocialShareService } from '@osf/shared/services/social-share.service';
8+
9+
import { PreprintDownloadRedirectComponent } from './preprint-download-redirect.component';
10+
11+
import { provideOSFCore } from '@testing/osf.testing.provider';
12+
import { ActivatedRouteMockBuilder } from '@testing/providers/route-provider.mock';
13+
14+
const MOCK_ID = 'test-preprint-id';
15+
const MOCK_DOWNLOAD_URL = 'https://osf.io/download/test-preprint-id';
16+
17+
describe('PreprintDownloadRedirectComponent', () => {
18+
let locationReplaceMock: jest.Mock;
19+
20+
beforeEach(() => {
21+
locationReplaceMock = jest.fn();
22+
Object.defineProperty(window, 'location', {
23+
value: { replace: locationReplaceMock },
24+
writable: true,
25+
configurable: true,
26+
});
27+
});
28+
29+
function setup(overrides: { id?: string | null; isBrowser?: boolean } = {}) {
30+
const { id = MOCK_ID, isBrowser = true } = overrides;
31+
32+
const mockRoute = ActivatedRouteMockBuilder.create()
33+
.withParams(id ? { id } : {})
34+
.build();
35+
36+
const mockSocialShareService = {
37+
createDownloadUrl: jest.fn().mockReturnValue(MOCK_DOWNLOAD_URL),
38+
};
39+
40+
TestBed.configureTestingModule({
41+
imports: [PreprintDownloadRedirectComponent],
42+
providers: [
43+
provideOSFCore(),
44+
MockProvider(ActivatedRoute, mockRoute),
45+
MockProvider(SocialShareService, mockSocialShareService),
46+
MockProvider(PLATFORM_ID, isBrowser ? 'browser' : 'server'),
47+
],
48+
});
49+
50+
const fixture = TestBed.createComponent(PreprintDownloadRedirectComponent);
51+
return { fixture, component: fixture.componentInstance, mockSocialShareService };
52+
}
53+
54+
it('should create', () => {
55+
const { component } = setup();
56+
expect(component).toBeTruthy();
57+
});
58+
59+
it('should render download message', () => {
60+
const { fixture } = setup();
61+
fixture.detectChanges();
62+
expect(fixture.nativeElement.querySelector('p').textContent).toContain('preprints.downloadRedirect.message');
63+
});
64+
65+
it('should redirect to download URL when id is present in browser', () => {
66+
const { mockSocialShareService } = setup({ id: MOCK_ID });
67+
expect(mockSocialShareService.createDownloadUrl).toHaveBeenCalledWith(MOCK_ID);
68+
expect(locationReplaceMock).toHaveBeenCalledWith(MOCK_DOWNLOAD_URL);
69+
});
70+
71+
it('should not redirect when id is missing', () => {
72+
const { mockSocialShareService } = setup({ id: null });
73+
expect(mockSocialShareService.createDownloadUrl).not.toHaveBeenCalled();
74+
expect(locationReplaceMock).not.toHaveBeenCalled();
75+
});
76+
77+
it('should not redirect when not in browser', () => {
78+
const { mockSocialShareService } = setup({ isBrowser: false });
79+
expect(mockSocialShareService.createDownloadUrl).not.toHaveBeenCalled();
80+
expect(locationReplaceMock).not.toHaveBeenCalled();
81+
});
82+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { TranslatePipe } from '@ngx-translate/core';
2+
3+
import { isPlatformBrowser } from '@angular/common';
4+
import { ChangeDetectionStrategy, Component, inject, PLATFORM_ID } from '@angular/core';
5+
import { ActivatedRoute } from '@angular/router';
6+
7+
import { SocialShareService } from '@osf/shared/services/social-share.service';
8+
9+
@Component({
10+
selector: 'osf-preprint-download-redirect',
11+
template: `<p>{{ 'preprints.downloadRedirect.message' | translate }}</p>`,
12+
changeDetection: ChangeDetectionStrategy.OnPush,
13+
imports: [TranslatePipe],
14+
})
15+
export class PreprintDownloadRedirectComponent {
16+
private readonly route = inject(ActivatedRoute);
17+
private readonly socialShareService = inject(SocialShareService);
18+
private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
19+
20+
constructor() {
21+
const id = this.route.snapshot.paramMap.get('id') ?? '';
22+
23+
if (!id || !this.isBrowser) {
24+
return;
25+
}
26+
27+
const url = this.socialShareService.createDownloadUrl(id);
28+
window.location.replace(url);
29+
}
30+
}

src/assets/i18n/en.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2345,6 +2345,9 @@
23452345
"singularCapitalized": "Thesis"
23462346
}
23472347
},
2348+
"downloadRedirect": {
2349+
"message": "Your download will begin shortly."
2350+
},
23482351
"details": {
23492352
"reasonForWithdrawal": "Reason for withdrawal",
23502353
"originalPublicationDate": "Original Publication Date",

0 commit comments

Comments
 (0)