@@ -2,9 +2,11 @@ import { MockComponents, MockProvider } from 'ng-mocks';
22
33import { DialogService } from 'primeng/dynamicdialog' ;
44
5+ import { signal , WritableSignal } from '@angular/core' ;
56import { ComponentFixture , TestBed } from '@angular/core/testing' ;
67
78import { OperationNames } from '@shared/enums/operation-names.enum' ;
9+ import { OperationInvocation } from '@shared/models/addons/operation-invocation.model' ;
810import { AddonsSelectors } from '@shared/stores/addons' ;
911
1012import { GoogleFilePickerComponent } from '../../google-file-picker/google-file-picker.component' ;
@@ -20,9 +22,11 @@ describe('StorageItemSelectorComponent', () => {
2022 let component : StorageItemSelectorComponent ;
2123 let fixture : ComponentFixture < StorageItemSelectorComponent > ;
2224 let mockDialogService : ReturnType < DialogServiceMockBuilder [ 'build' ] > ;
25+ let mockOperationInvocation : WritableSignal < OperationInvocation | null > ;
2326
2427 beforeEach ( async ( ) => {
2528 mockDialogService = DialogServiceMockBuilder . create ( ) . withOpenMock ( ) . build ( ) ;
29+ mockOperationInvocation = signal < OperationInvocation | null > ( null ) ;
2630
2731 await TestBed . configureTestingModule ( {
2832 imports : [
@@ -45,6 +49,10 @@ describe('StorageItemSelectorComponent', () => {
4549 selector : AddonsSelectors . getCreatedOrUpdatedConfiguredAddonSubmitting ,
4650 value : false ,
4751 } ,
52+ {
53+ selector : AddonsSelectors . getOperationInvocation ,
54+ value : mockOperationInvocation ,
55+ } ,
4856 ] ,
4957 } ) ,
5058 MockProvider ( DialogService , mockDialogService ) ,
@@ -53,6 +61,10 @@ describe('StorageItemSelectorComponent', () => {
5361
5462 fixture = TestBed . createComponent ( StorageItemSelectorComponent ) ;
5563 component = fixture . componentInstance ;
64+ fixture . componentRef . setInput ( 'isGoogleFilePicker' , false ) ;
65+ fixture . componentRef . setInput ( 'accountName' , 'test-account' ) ;
66+ fixture . componentRef . setInput ( 'accountId' , 'test-id' ) ;
67+ fixture . componentRef . setInput ( 'operationInvocationResult' , [ ] ) ;
5668 } ) ;
5769
5870 it ( 'should create' , ( ) => {
@@ -115,4 +127,97 @@ describe('StorageItemSelectorComponent', () => {
115127 expect ( breadcrumbs [ 0 ] . id ) . toBe ( itemId ) ;
116128 expect ( breadcrumbs [ 0 ] . label ) . toBe ( itemName ) ;
117129 } ) ;
130+
131+ describe ( 'showLoadMoreButton' , ( ) => {
132+ it ( 'should return false when operationInvocation is null' , ( ) => {
133+ mockOperationInvocation . set ( null ) ;
134+ fixture . detectChanges ( ) ;
135+
136+ expect ( component . showLoadMoreButton ( ) ) . toBe ( false ) ;
137+ } ) ;
138+
139+ it ( 'should return false when nextSampleCursor is not present' , ( ) => {
140+ mockOperationInvocation . set ( {
141+ id : 'test-id' ,
142+ type : 'operation-invocation' ,
143+ invocationStatus : 'success' ,
144+ operationName : 'list_root_items' ,
145+ operationKwargs : { } ,
146+ operationResult : [ ] ,
147+ itemCount : 10 ,
148+ thisSampleCursor : 'cursor-1' ,
149+ } ) ;
150+ fixture . detectChanges ( ) ;
151+
152+ expect ( component . showLoadMoreButton ( ) ) . toBe ( false ) ;
153+ } ) ;
154+
155+ it ( 'should return true when nextSampleCursor differs from thisSampleCursor' , ( ) => {
156+ mockOperationInvocation . set ( {
157+ id : 'test-id' ,
158+ type : 'operation-invocation' ,
159+ invocationStatus : 'success' ,
160+ operationName : 'list_root_items' ,
161+ operationKwargs : { } ,
162+ operationResult : [ ] ,
163+ itemCount : 20 ,
164+ thisSampleCursor : 'cursor-1' ,
165+ nextSampleCursor : 'cursor-2' ,
166+ } ) ;
167+ fixture . detectChanges ( ) ;
168+
169+ expect ( component . showLoadMoreButton ( ) ) . toBe ( true ) ;
170+ } ) ;
171+
172+ it ( 'should return true for opaque/base64 cursors like GitLab uses' , ( ) => {
173+ // GitLab uses base64-encoded cursors where lexicographic comparison doesn't work
174+ mockOperationInvocation . set ( {
175+ id : 'test-id' ,
176+ type : 'operation-invocation' ,
177+ invocationStatus : 'success' ,
178+ operationName : 'list_root_items' ,
179+ operationKwargs : { } ,
180+ operationResult : [ ] ,
181+ itemCount : 20 ,
182+ thisSampleCursor : 'eyJpZCI6MTIzfQ==' ,
183+ nextSampleCursor : 'eyJpZCI6MTQ1fQ==' ,
184+ } ) ;
185+ fixture . detectChanges ( ) ;
186+
187+ expect ( component . showLoadMoreButton ( ) ) . toBe ( true ) ;
188+ } ) ;
189+
190+ it ( 'should return false when nextSampleCursor equals thisSampleCursor' , ( ) => {
191+ mockOperationInvocation . set ( {
192+ id : 'test-id' ,
193+ type : 'operation-invocation' ,
194+ invocationStatus : 'success' ,
195+ operationName : 'list_root_items' ,
196+ operationKwargs : { } ,
197+ operationResult : [ ] ,
198+ itemCount : 10 ,
199+ thisSampleCursor : 'cursor-1' ,
200+ nextSampleCursor : 'cursor-1' ,
201+ } ) ;
202+ fixture . detectChanges ( ) ;
203+
204+ expect ( component . showLoadMoreButton ( ) ) . toBe ( false ) ;
205+ } ) ;
206+
207+ it ( 'should return true when nextSampleCursor exists but thisSampleCursor is undefined' , ( ) => {
208+ mockOperationInvocation . set ( {
209+ id : 'test-id' ,
210+ type : 'operation-invocation' ,
211+ invocationStatus : 'success' ,
212+ operationName : 'list_root_items' ,
213+ operationKwargs : { } ,
214+ operationResult : [ ] ,
215+ itemCount : 20 ,
216+ nextSampleCursor : 'cursor-2' ,
217+ } ) ;
218+ fixture . detectChanges ( ) ;
219+
220+ expect ( component . showLoadMoreButton ( ) ) . toBe ( true ) ;
221+ } ) ;
222+ } ) ;
118223} ) ;
0 commit comments