Skip to content

Commit 2372b48

Browse files
authored
fix(ENG-10424): Fix view files in files section using VOL (#904)
- Ticket: [ENG-10414] - Feature flag: n/a ## Purpose Fix view files in files section using VOL ## Summary of Changes Added { queryParamsHandling: 'preserve' } to two router.navigate() calls in files.component.ts — one in handleRootFolderChange() (provider switching) and one in the invalid-provider fallback effect
1 parent 1325bc9 commit 2372b48

2 files changed

Lines changed: 143 additions & 3 deletions

File tree

src/app/features/files/pages/files/files.component.spec.ts

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { DialogService } from 'primeng/dynamicdialog';
44

55
import { signal } from '@angular/core';
66
import { ComponentFixture, TestBed } from '@angular/core/testing';
7-
import { ActivatedRoute } from '@angular/router';
7+
import { ActivatedRoute, Router } from '@angular/router';
88

99
import { SENTRY_TOKEN } from '@core/provider/sentry.provider';
1010
import { FileUploadDialogComponent } from '@osf/shared/components/file-upload-dialog/file-upload-dialog.component';
@@ -18,8 +18,10 @@ import { CustomConfirmationService } from '@osf/shared/services/custom-confirmat
1818
import { FilesService } from '@osf/shared/services/files.service';
1919
import { CurrentResourceSelectors } from '@osf/shared/stores/current-resource';
2020
import { GoogleFilePickerComponent } from '@shared/components/google-file-picker/google-file-picker.component';
21+
import { FileLabelModel } from '@shared/models/files/file-label.model';
2122

2223
import { FilesSelectionActionsComponent } from '../../components';
24+
import { FileProvider } from '../../constants';
2325
import { FilesSelectors } from '../../store';
2426

2527
import { FilesComponent } from './files.component';
@@ -29,6 +31,8 @@ import { getNodeFilesMappedData } from '@testing/data/files/node.data';
2931
import { testNode } from '@testing/mocks/base-node.mock';
3032
import { OSFTestingModule } from '@testing/osf.testing.module';
3133
import { MockComponentWithSignal } from '@testing/providers/component-provider.mock';
34+
import { ActivatedRouteMock } from '@testing/providers/route-provider.mock';
35+
import { provideRouterMock, RouterMockType } from '@testing/providers/router-provider.mock';
3236
import { provideMockStore } from '@testing/providers/store-provider.mock';
3337

3438
describe('Component: Files', () => {
@@ -188,4 +192,138 @@ describe('Component: Files', () => {
188192
expect(() => component.updateFilesList()).not.toThrow();
189193
});
190194
});
195+
196+
describe('handleRootFolderChange', () => {
197+
it('should preserve view_only query param when switching storage providers', () => {
198+
const router = TestBed.inject(Router);
199+
const navigateSpy = jest.spyOn(router, 'navigate').mockResolvedValue(true);
200+
201+
const selectedFolder: FileLabelModel = {
202+
label: 'Dropbox',
203+
folder: { provider: FileProvider.Dropbox } as any,
204+
};
205+
206+
component.handleRootFolderChange(selectedFolder);
207+
208+
expect(navigateSpy).toHaveBeenCalledWith([`/${component.resourceId()}/files`, FileProvider.Dropbox], {
209+
queryParamsHandling: 'preserve',
210+
});
211+
});
212+
});
213+
214+
describe('invalid provider fallback effect', () => {
215+
let innerComponent: FilesComponent;
216+
let innerFixture: ComponentFixture<FilesComponent>;
217+
let routerMock: RouterMockType;
218+
219+
beforeEach(async () => {
220+
jest.clearAllMocks();
221+
routerMock = {
222+
...TestBed.inject(Router),
223+
navigate: jest.fn().mockResolvedValue(true),
224+
url: '/abc123/files/unknownprovider?view_only=testtoken',
225+
} as RouterMockType;
226+
227+
await TestBed.configureTestingModule({
228+
imports: [
229+
FilesComponent,
230+
OSFTestingModule,
231+
...MockComponents(
232+
FileUploadDialogComponent,
233+
FormSelectComponent,
234+
GoogleFilePickerComponent,
235+
LoadingSpinnerComponent,
236+
SearchInputComponent,
237+
SubHeaderComponent,
238+
ViewOnlyLinkMessageComponent,
239+
GoogleFilePickerComponent,
240+
FilesSelectionActionsComponent
241+
),
242+
],
243+
providers: [
244+
FilesService,
245+
MockProvider(CustomConfirmationService),
246+
DialogService,
247+
{
248+
provide: SENTRY_TOKEN,
249+
useValue: {
250+
captureException: jest.fn(),
251+
captureMessage: jest.fn(),
252+
setUser: jest.fn(),
253+
},
254+
},
255+
{
256+
provide: ActivatedRoute,
257+
useValue: ActivatedRouteMock.withParams({ fileProvider: 'unknownprovider' }).build(),
258+
},
259+
provideRouterMock(routerMock),
260+
provideMockStore({
261+
signals: [
262+
{
263+
selector: CurrentResourceSelectors.getResourceDetails,
264+
value: testNode,
265+
},
266+
{
267+
selector: FilesSelectors.getRootFolders,
268+
value: getNodeFilesMappedData(),
269+
},
270+
{
271+
selector: FilesSelectors.getCurrentFolder,
272+
value: getNodeFilesMappedData(0),
273+
},
274+
{
275+
selector: FilesSelectors.getConfiguredStorageAddons,
276+
value: getConfiguredAddonsMappedData(),
277+
},
278+
{
279+
selector: FilesSelectors.getProvider,
280+
value: 'osfstorage',
281+
},
282+
{
283+
selector: FilesSelectors.getStorageSupportedFeatures,
284+
value: {
285+
osfstorage: ['AddUpdateFiles', 'DownloadAsZip', 'DeleteFiles', 'CopyInto'],
286+
},
287+
},
288+
],
289+
}),
290+
],
291+
})
292+
.overrideComponent(FilesComponent, {
293+
remove: {
294+
imports: [FilesTreeComponent],
295+
},
296+
add: {
297+
imports: [
298+
MockComponentWithSignal('osf-files-tree', [
299+
'files',
300+
'currentFolder',
301+
'isLoading',
302+
'viewOnly',
303+
'resourceId',
304+
'provider',
305+
'storage',
306+
'totalCount',
307+
'allowedMenuActions',
308+
'supportUpload',
309+
'selectedFiles',
310+
'scrollHeight',
311+
]),
312+
],
313+
},
314+
})
315+
.compileComponents();
316+
317+
innerFixture = TestBed.createComponent(FilesComponent);
318+
innerComponent = innerFixture.componentInstance;
319+
innerFixture.detectChanges();
320+
});
321+
322+
it('should preserve view_only query param when redirecting to osfstorage for invalid provider', () => {
323+
expect(routerMock.navigate).toHaveBeenCalledWith(
324+
[`/${innerComponent.resourceId()}/files`, FileProvider.OsfStorage],
325+
{ queryParamsHandling: 'preserve' }
326+
);
327+
});
328+
});
191329
});

src/app/features/files/pages/files/files.component.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,9 @@ export class FilesComponent {
292292
const rootFoldersOption = rootFoldersOptions.find((option) => option.folder.provider === providerName);
293293

294294
if (!rootFoldersOption) {
295-
this.router.navigate([`/${this.resourceId()}/files`, FileProvider.OsfStorage]);
295+
this.router.navigate([`/${this.resourceId()}/files`, FileProvider.OsfStorage], {
296+
queryParamsHandling: 'preserve',
297+
});
296298
} else {
297299
this.currentRootFolder.set({
298300
label: rootFoldersOption.label,
@@ -688,6 +690,6 @@ export class FilesComponent {
688690
handleRootFolderChange(selectedFolder: FileLabelModel) {
689691
const provider = selectedFolder.folder?.provider;
690692
const resourceId = this.resourceId();
691-
this.router.navigate([`/${resourceId}/files`, provider]);
693+
this.router.navigate([`/${resourceId}/files`, provider], { queryParamsHandling: 'preserve' });
692694
}
693695
}

0 commit comments

Comments
 (0)