Skip to content

Commit c466daf

Browse files
authored
fix(registration): fixed registration link for file with view only link (#1024)
- Ticket: https://openscience.atlassian.net/browse/ENG-11532 - Feature flag: n/a ## Summary of Changes 1. Fixed issue with AVOL.
1 parent bbe5d88 commit c466daf

3 files changed

Lines changed: 87 additions & 18 deletions

File tree

src/app/shared/components/registration-blocks-data/registration-blocks-data.component.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,12 @@ <h4 class="mb-2">
2525
@if (isDraft()) {
2626
<p>{{ file.file_name }}</p>
2727
} @else {
28-
<a class="font-bold cursor-pointer" target="_blank" rel="noopener" [href]="file?.file_urls?.html">
28+
<a
29+
class="font-bold cursor-pointer"
30+
target="_blank"
31+
rel="noopener"
32+
[href]="getFileUrl(file?.file_urls?.html)"
33+
>
2934
{{ file.file_name }}
3035
</a>
3136
}
Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
import { TestBed } from '@angular/core/testing';
1+
import { MockProvider } from 'ng-mocks';
2+
3+
import { ComponentFixture, TestBed } from '@angular/core/testing';
24

35
import { FieldType } from '@osf/shared/enums/field-type.enum';
46
import { Question } from '@osf/shared/models/registration/page-schema.model';
7+
import { ViewOnlyLinkHelperService } from '@osf/shared/services/view-only-link-helper.service';
58

69
import { MOCK_REVIEW } from '@testing/mocks/review.mock';
710
import { provideOSFCore } from '@testing/osf.testing.provider';
11+
import { provideRouterMock, RouterMockBuilder, RouterMockType } from '@testing/providers/router-provider.mock';
12+
import { ViewOnlyLinkHelperMock, ViewOnlyLinkHelperMockType } from '@testing/providers/view-only-link-helper.mock';
813

914
import { RegistrationBlocksDataComponent } from './registration-blocks-data.component';
1015

@@ -13,39 +18,61 @@ const MOCK_QUESTIONS: Question[] = [
1318
{ id: '2', displayText: 'Q2', required: false, responseKey: 'question2', fieldType: FieldType.Checkbox },
1419
];
1520

21+
interface SetupOverrides {
22+
routerUrl?: string;
23+
viewOnlyParam?: string | null;
24+
}
25+
1626
describe('RegistrationBlocksDataComponent', () => {
17-
beforeEach(() => {
27+
let component: RegistrationBlocksDataComponent;
28+
let fixture: ComponentFixture<RegistrationBlocksDataComponent>;
29+
let routerMock: RouterMockType;
30+
let viewOnlyHelper: ViewOnlyLinkHelperMockType;
31+
32+
function setup(overrides: SetupOverrides = {}) {
33+
routerMock = RouterMockBuilder.create()
34+
.withUrl(overrides.routerUrl ?? '/')
35+
.build();
36+
viewOnlyHelper = ViewOnlyLinkHelperMock.simple();
37+
viewOnlyHelper.getViewOnlyParamFromUrl.mockReturnValue(
38+
overrides.viewOnlyParam !== undefined ? overrides.viewOnlyParam : null
39+
);
40+
1841
TestBed.configureTestingModule({
1942
imports: [RegistrationBlocksDataComponent],
20-
providers: [provideOSFCore()],
43+
providers: [
44+
provideOSFCore(),
45+
provideRouterMock(routerMock),
46+
MockProvider(ViewOnlyLinkHelperService, viewOnlyHelper),
47+
],
2148
});
22-
});
2349

24-
it('should create', () => {
25-
const fixture = TestBed.createComponent(RegistrationBlocksDataComponent);
50+
fixture = TestBed.createComponent(RegistrationBlocksDataComponent);
51+
component = fixture.componentInstance;
2652
fixture.detectChanges();
53+
}
54+
55+
beforeEach(() => setup());
2756

28-
expect(fixture.componentInstance).toBeTruthy();
57+
it('should create', () => {
58+
expect(component).toBeTruthy();
2959
});
3060

3161
it('should compute updatedKeysMap from updatedFields', () => {
32-
const fixture = TestBed.createComponent(RegistrationBlocksDataComponent);
3362
fixture.componentRef.setInput('updatedFields', ['question1', 'question3']);
3463
fixture.detectChanges();
3564

36-
expect(fixture.componentInstance.updatedKeysMap()).toEqual({ question1: true, question3: true });
65+
expect(component.updatedKeysMap()).toEqual({ question1: true, question3: true });
3766
});
3867

3968
it('should return empty updatedKeysMap when updatedFields is empty', () => {
40-
const fixture = TestBed.createComponent(RegistrationBlocksDataComponent);
4169
fixture.componentRef.setInput('updatedFields', []);
4270
fixture.detectChanges();
4371

44-
expect(fixture.componentInstance.updatedKeysMap()).toEqual({});
72+
expect(component.updatedKeysMap()).toEqual({});
4573
});
4674

4775
it('should render questions with review data', () => {
48-
const fixture = TestBed.createComponent(RegistrationBlocksDataComponent);
4976
fixture.componentRef.setInput('questions', MOCK_QUESTIONS);
5077
fixture.componentRef.setInput('reviewData', MOCK_REVIEW);
5178
fixture.detectChanges();
@@ -56,7 +83,6 @@ describe('RegistrationBlocksDataComponent', () => {
5683
});
5784

5885
it('should show required error when question is required and no data on non-overview page', () => {
59-
const fixture = TestBed.createComponent(RegistrationBlocksDataComponent);
6086
fixture.componentRef.setInput('questions', MOCK_QUESTIONS);
6187
fixture.componentRef.setInput('reviewData', {});
6288
fixture.componentRef.setInput('isOverviewPage', false);
@@ -67,7 +93,6 @@ describe('RegistrationBlocksDataComponent', () => {
6793
});
6894

6995
it('should not show required error on overview page', () => {
70-
const fixture = TestBed.createComponent(RegistrationBlocksDataComponent);
7196
fixture.componentRef.setInput('questions', MOCK_QUESTIONS);
7297
fixture.componentRef.setInput('reviewData', {});
7398
fixture.componentRef.setInput('isOverviewPage', true);
@@ -78,7 +103,6 @@ describe('RegistrationBlocksDataComponent', () => {
78103
});
79104

80105
it('should show updated tag when field is updated and not original revision', () => {
81-
const fixture = TestBed.createComponent(RegistrationBlocksDataComponent);
82106
fixture.componentRef.setInput('questions', MOCK_QUESTIONS);
83107
fixture.componentRef.setInput('reviewData', MOCK_REVIEW);
84108
fixture.componentRef.setInput('updatedFields', ['question1']);
@@ -90,7 +114,6 @@ describe('RegistrationBlocksDataComponent', () => {
90114
});
91115

92116
it('should not show updated tag on original revision', () => {
93-
const fixture = TestBed.createComponent(RegistrationBlocksDataComponent);
94117
fixture.componentRef.setInput('questions', MOCK_QUESTIONS);
95118
fixture.componentRef.setInput('reviewData', MOCK_REVIEW);
96119
fixture.componentRef.setInput('updatedFields', ['question1']);
@@ -100,4 +123,24 @@ describe('RegistrationBlocksDataComponent', () => {
100123
const tags = fixture.nativeElement.querySelectorAll('p-tag');
101124
expect(tags.length).toBe(0);
102125
});
126+
127+
it('should return empty string when file url is missing', () => {
128+
expect(component.getFileUrl()).toBe('');
129+
});
130+
131+
it('should return original file url when view_only param is absent', () => {
132+
const htmlUrl = 'https://osf.io/abc12/';
133+
134+
expect(component.getFileUrl(htmlUrl)).toBe(htmlUrl);
135+
});
136+
137+
it('should append view_only query param to file url', () => {
138+
viewOnlyHelper.getViewOnlyParamFromUrl.mockReturnValue('token');
139+
140+
const htmlUrl = 'https://osf.io/abc12/';
141+
const result = component.getFileUrl(htmlUrl);
142+
143+
expect(viewOnlyHelper.getViewOnlyParamFromUrl).toHaveBeenCalledWith('/');
144+
expect(result).toBe('https://osf.io/abc12/?view_only=token');
145+
});
103146
});

src/app/shared/components/registration-blocks-data/registration-blocks-data.component.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ import { TranslatePipe } from '@ngx-translate/core';
33
import { Message } from 'primeng/message';
44
import { Tag } from 'primeng/tag';
55

6-
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
6+
import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';
7+
import { Router } from '@angular/router';
78

89
import { INPUT_VALIDATION_MESSAGES } from '@osf/shared/constants/input-validation-messages.const';
910
import { FieldType } from '@osf/shared/enums/field-type.enum';
1011
import { Question } from '@osf/shared/models/registration/page-schema.model';
1112
import { FixSpecialCharPipe } from '@osf/shared/pipes/fix-special-char.pipe';
13+
import { ViewOnlyLinkHelperService } from '@osf/shared/services/view-only-link-helper.service';
1214

1315
@Component({
1416
selector: 'osf-registration-blocks-data',
@@ -18,6 +20,9 @@ import { FixSpecialCharPipe } from '@osf/shared/pipes/fix-special-char.pipe';
1820
changeDetection: ChangeDetectionStrategy.OnPush,
1921
})
2022
export class RegistrationBlocksDataComponent {
23+
private readonly router = inject(Router);
24+
private readonly viewOnlyService = inject(ViewOnlyLinkHelperService);
25+
2126
questions = input<Question[]>();
2227
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2328
reviewData = input<Record<string, any>>({});
@@ -34,4 +39,20 @@ export class RegistrationBlocksDataComponent {
3439

3540
readonly FieldType = FieldType;
3641
readonly INPUT_VALIDATION_MESSAGES = INPUT_VALIDATION_MESSAGES;
42+
43+
getFileUrl(htmlUrl?: string): string {
44+
if (!htmlUrl) {
45+
return '';
46+
}
47+
48+
const viewOnly = this.viewOnlyService.getViewOnlyParamFromUrl(this.router.url);
49+
50+
if (!viewOnly) {
51+
return htmlUrl;
52+
}
53+
54+
const url = new URL(htmlUrl);
55+
url.searchParams.set('view_only', viewOnly);
56+
return url.toString();
57+
}
3758
}

0 commit comments

Comments
 (0)