|
| 1 | +import { Store } from '@ngxs/store'; |
| 2 | + |
1 | 3 | import { MockComponent } from 'ng-mocks'; |
2 | 4 |
|
| 5 | +import { Mock } from 'vitest'; |
| 6 | + |
3 | 7 | import { ComponentFixture, TestBed } from '@angular/core/testing'; |
4 | 8 |
|
| 9 | +import { SelectComponent } from '@osf/shared/components/select/select.component'; |
| 10 | +import { SupportedFeature } from '@osf/shared/enums/addon-supported-features.enum'; |
| 11 | +import { ResourceType } from '@osf/shared/enums/resource-type.enum'; |
| 12 | +import { UserPermissions } from '@osf/shared/enums/user-permissions.enum'; |
| 13 | +import { FileFolderModel } from '@osf/shared/models/files/file-folder.model'; |
| 14 | +import { NodeShortInfoModel } from '@osf/shared/models/nodes/node-with-children.model'; |
| 15 | + |
| 16 | +import { MOCK_CONFIGURED_ADDON } from '@testing/mocks/configured-addon.mock'; |
| 17 | +import { OSF_FILE_MOCK } from '@testing/mocks/osf-file.mock'; |
5 | 18 | import { provideOSFCore } from '@testing/osf.testing.provider'; |
| 19 | +import { |
| 20 | + BaseSetupOverrides, |
| 21 | + mergeSignalOverrides, |
| 22 | + provideMockStore, |
| 23 | + SignalOverride, |
| 24 | +} from '@testing/providers/store-provider.mock'; |
6 | 25 |
|
7 | | -import { SelectComponent } from '../../../../shared/components/select/select.component'; |
| 26 | +import { FileProvider } from '../../constants/file-provider.constants'; |
| 27 | +import { |
| 28 | + FilesSelectors, |
| 29 | + GetMoveDialogConfiguredStorageAddons, |
| 30 | + GetMoveDialogRootFolders, |
| 31 | + GetStorageSupportedFeatures, |
| 32 | +} from '../../store'; |
8 | 33 |
|
9 | 34 | import { FileSelectDestinationComponent } from './file-select-destination.component'; |
10 | 35 |
|
11 | | -describe.skip('FileSelectDestinationComponent', () => { |
| 36 | +interface SetupOverrides extends BaseSetupOverrides { |
| 37 | + projectId?: string; |
| 38 | + storageProvider?: string; |
| 39 | + components?: NodeShortInfoModel[]; |
| 40 | + areComponentsLoading?: boolean; |
| 41 | +} |
| 42 | + |
| 43 | +describe('FileSelectDestinationComponent', () => { |
12 | 44 | let component: FileSelectDestinationComponent; |
13 | 45 | let fixture: ComponentFixture<FileSelectDestinationComponent>; |
| 46 | + let store: Store; |
| 47 | + |
| 48 | + const rootFolder: FileFolderModel = { |
| 49 | + ...OSF_FILE_MOCK, |
| 50 | + id: 'root-1', |
| 51 | + name: 'OSF Storage', |
| 52 | + provider: FileProvider.OsfStorage, |
| 53 | + }; |
| 54 | + |
| 55 | + const components: NodeShortInfoModel[] = [ |
| 56 | + { id: 'project-1', title: 'Project 1', isPublic: true, permissions: [UserPermissions.Write] }, |
| 57 | + { |
| 58 | + id: 'component-1', |
| 59 | + title: 'Component 1', |
| 60 | + isPublic: true, |
| 61 | + permissions: [UserPermissions.Write], |
| 62 | + parentId: 'project-1', |
| 63 | + }, |
| 64 | + { id: 'readonly-1', title: 'Readonly', isPublic: true, permissions: [UserPermissions.Read], parentId: 'project-1' }, |
| 65 | + ]; |
| 66 | + |
| 67 | + function setup(overrides: SetupOverrides = {}) { |
| 68 | + const defaultSignals: SignalOverride[] = [ |
| 69 | + { selector: FilesSelectors.getMoveDialogRootFolders, value: [rootFolder] }, |
| 70 | + { selector: FilesSelectors.isMoveDialogRootFoldersLoading, value: false }, |
| 71 | + { |
| 72 | + selector: FilesSelectors.getMoveDialogConfiguredStorageAddons, |
| 73 | + value: [{ ...MOCK_CONFIGURED_ADDON, id: 'addon-1', externalServiceName: FileProvider.OsfStorage }], |
| 74 | + }, |
| 75 | + { selector: FilesSelectors.isMoveDialogConfiguredStorageAddonsLoading, value: false }, |
| 76 | + { selector: FilesSelectors.isMoveDialogFilesLoading, value: false }, |
| 77 | + { |
| 78 | + selector: FilesSelectors.getStorageSupportedFeatures, |
| 79 | + value: { [FileProvider.OsfStorage]: [SupportedFeature.AddUpdateFiles] }, |
| 80 | + }, |
| 81 | + ]; |
14 | 82 |
|
15 | | - beforeEach(() => { |
16 | 83 | TestBed.configureTestingModule({ |
17 | 84 | imports: [FileSelectDestinationComponent, MockComponent(SelectComponent)], |
18 | | - providers: [provideOSFCore()], |
| 85 | + providers: [ |
| 86 | + provideOSFCore(), |
| 87 | + provideMockStore({ signals: mergeSignalOverrides(defaultSignals, overrides.selectorOverrides) }), |
| 88 | + ], |
19 | 89 | }); |
20 | 90 |
|
| 91 | + store = TestBed.inject(Store); |
21 | 92 | fixture = TestBed.createComponent(FileSelectDestinationComponent); |
22 | 93 | component = fixture.componentInstance; |
| 94 | + fixture.componentRef.setInput('projectId', overrides.projectId ?? 'project-1'); |
| 95 | + fixture.componentRef.setInput('storageProvider', overrides.storageProvider ?? FileProvider.OsfStorage); |
| 96 | + fixture.componentRef.setInput('components', overrides.components ?? components); |
| 97 | + fixture.componentRef.setInput('areComponentsLoading', overrides.areComponentsLoading ?? false); |
23 | 98 | fixture.detectChanges(); |
24 | | - }); |
| 99 | + } |
25 | 100 |
|
26 | 101 | it('should create', () => { |
| 102 | + setup(); |
27 | 103 | expect(component).toBeTruthy(); |
28 | 104 | }); |
| 105 | + |
| 106 | + it('should load storage addons on init and request supported features', () => { |
| 107 | + setup(); |
| 108 | + const calls = (store.dispatch as Mock).mock.calls.map((c) => c[0]); |
| 109 | + |
| 110 | + expect(calls).toContainEqual(new GetMoveDialogRootFolders('project-1', ResourceType.Project)); |
| 111 | + expect(calls).toContainEqual(new GetMoveDialogConfiguredStorageAddons('project-1')); |
| 112 | + expect(calls).toContainEqual(new GetStorageSupportedFeatures('addon-1', FileProvider.OsfStorage)); |
| 113 | + }); |
| 114 | + |
| 115 | + it('should emit project selection and reload storage addons on project change', () => { |
| 116 | + setup(); |
| 117 | + const emitSpy = vi.spyOn(component.selectProject, 'emit'); |
| 118 | + (store.dispatch as Mock).mockClear(); |
| 119 | + |
| 120 | + component.onChangeProject('project-2'); |
| 121 | + |
| 122 | + expect(emitSpy).toHaveBeenCalledWith('project-2'); |
| 123 | + expect(store.dispatch).toHaveBeenCalledWith(new GetMoveDialogRootFolders('project-2', ResourceType.Project)); |
| 124 | + expect(store.dispatch).toHaveBeenCalledWith(new GetMoveDialogConfiguredStorageAddons('project-2')); |
| 125 | + }); |
| 126 | + |
| 127 | + it('should update current root folder and emit storage selection on storage change', () => { |
| 128 | + setup(); |
| 129 | + const emitSpy = vi.spyOn(component.selectStorage, 'emit'); |
| 130 | + |
| 131 | + component.onStorageChange('root-1'); |
| 132 | + |
| 133 | + expect(component.currentRootFolder()?.folder.id).toBe('root-1'); |
| 134 | + expect(emitSpy).toHaveBeenCalled(); |
| 135 | + }); |
| 136 | + |
| 137 | + it('should include only write-access nodes in options', () => { |
| 138 | + setup(); |
| 139 | + const values = component.options().map((o) => o.value); |
| 140 | + |
| 141 | + expect(values).toContain('project-1'); |
| 142 | + expect(values).toContain('component-1'); |
| 143 | + expect(values).not.toContain('readonly-1'); |
| 144 | + }); |
| 145 | + |
| 146 | + it('should detect add update feature by provider', () => { |
| 147 | + setup(); |
| 148 | + |
| 149 | + expect(component.hasAddUpdateFeature(FileProvider.OsfStorage)).toBe(true); |
| 150 | + expect(component.hasAddUpdateFeature('dropbox')).toBe(false); |
| 151 | + }); |
| 152 | + |
| 153 | + it('should expose loading state when component loading is true', () => { |
| 154 | + setup({ areComponentsLoading: true }); |
| 155 | + |
| 156 | + expect(component.isLoading()).toBe(true); |
| 157 | + }); |
29 | 158 | }); |
0 commit comments