Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ describe('SavedSearchesService', () => {
});
service = TestBed.inject(SavedSearchesService);
authService = TestBed.inject(AuthenticationService);
spyOn(service.nodesApi, 'getNode').and.callFake(() => Promise.resolve({ entry: { id: testNodeId } } as NodeEntry));
spyOn(service.nodesApi, 'getNodeContent').and.callFake(() => createBlob());
spyOn(service.nodesApi, 'deleteNode').and.callFake(() => Promise.resolve());
spyOn(service.preferencesApi, 'getPreference').and.callFake(() =>
Expand All @@ -72,106 +71,140 @@ describe('SavedSearchesService', () => {
localStorage.removeItem(LOCAL_STORAGE_KEY);
});

it('should retrieve saved searches from the preferences API', (done) => {
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
spyOn(localStorage, 'getItem').and.callFake(() => 'true');
service.init();

service.getSavedSearches().subscribe((searches) => {
expect(localStorage.getItem).toHaveBeenCalledWith(LOCAL_STORAGE_KEY);
expect(service.preferencesApi.getPreference).toHaveBeenCalledWith('-me-', 'saved-searches');
expect(searches.length).toBe(2);
expect(searches[0].name).toBe('Search 1');
expect(searches[1].name).toBe('Search 2');
done();
describe('Saved searches retrieval and migration', () => {
beforeEach(() => {
spyOn(service.nodesApi, 'getNode').and.callFake(() => Promise.resolve({ entry: { id: testNodeId } } as NodeEntry));
});
it('should retrieve saved searches from the preferences API', (done) => {
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
spyOn(localStorage, 'getItem').and.callFake(() => 'true');
service.init();

service.getSavedSearches().subscribe((searches) => {
expect(localStorage.getItem).toHaveBeenCalledWith(LOCAL_STORAGE_KEY);
expect(service.preferencesApi.getPreference).toHaveBeenCalledWith('-me-', 'saved-searches');
expect(searches.length).toBe(2);
expect(searches[0].name).toBe('Search 1');
expect(searches[1].name).toBe('Search 2');
done();
});
});
});

it('should automatically migrate saved searches if config.json file exists', (done) => {
spyOn(localStorage, 'setItem');
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
it('should automatically migrate saved searches if config.json file exists', (done) => {
spyOn(localStorage, 'setItem');
spyOn(authService, 'getUsername').and.callFake(() => testUserName);

service.getSavedSearches().subscribe((searches) => {
expect(service.nodesApi.getNode).toHaveBeenCalledWith('-my-', { relativePath: 'config.json' });
expect(service.nodesApi.getNodeContent).toHaveBeenCalledWith(testNodeId);
expect(localStorage.setItem).toHaveBeenCalledWith(LOCAL_STORAGE_KEY, 'true');
expect(service.preferencesApi.updatePreference).toHaveBeenCalledWith('-me-', 'saved-searches', SAVED_SEARCHES_CONTENT);
expect(service.nodesApi.deleteNode).toHaveBeenCalledWith(testNodeId, { permanent: true });
expect(searches.length).toBe(2);
done();
service.getSavedSearches().subscribe((searches) => {
expect(service.nodesApi.getNode).toHaveBeenCalledWith('-my-', { relativePath: 'config.json' });
expect(service.nodesApi.getNodeContent).toHaveBeenCalledWith(testNodeId);
expect(localStorage.setItem).toHaveBeenCalledWith(LOCAL_STORAGE_KEY, 'true');
expect(service.preferencesApi.updatePreference).toHaveBeenCalledWith('-me-', 'saved-searches', SAVED_SEARCHES_CONTENT);
expect(service.nodesApi.deleteNode).toHaveBeenCalledWith(testNodeId, { permanent: true });
expect(searches.length).toBe(2);
done();
});
});
});

it('should save a new search', (done) => {
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
spyOn(localStorage, 'getItem').and.callFake(() => 'true');
const newSearch = { name: 'Search 3', description: 'Description 3', encodedUrl: 'url3' };
service.init();
it('should save a new search', (done) => {
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
spyOn(localStorage, 'getItem').and.callFake(() => 'true');
const newSearch = { name: 'Search 3', description: 'Description 3', encodedUrl: 'url3' };
service.init();

service.saveSearch(newSearch).subscribe(() => {
expect(service.preferencesApi.updatePreference).toHaveBeenCalledWith('-me-', 'saved-searches', jasmine.any(String));
expect(service.savedSearches$).toBeDefined();
done();
service.saveSearch(newSearch).subscribe(() => {
expect(service.preferencesApi.updatePreference).toHaveBeenCalledWith('-me-', 'saved-searches', jasmine.any(String));
expect(service.savedSearches$).toBeDefined();
done();
});
});
});

it('should emit initial saved searches on subscription', (done) => {
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
spyOn(localStorage, 'getItem').and.returnValue('true');
service.init();
it('should emit initial saved searches on subscription', (done) => {
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
spyOn(localStorage, 'getItem').and.returnValue('true');
service.init();

service.savedSearches$.pipe().subscribe((searches) => {
expect(searches.length).toBe(2);
expect(searches[0].name).toBe('Search 1');
expect(service.preferencesApi.getPreference).toHaveBeenCalledWith('-me-', 'saved-searches');
done();
service.savedSearches$.pipe().subscribe((searches) => {
expect(searches.length).toBe(2);
expect(searches[0].name).toBe('Search 1');
expect(service.preferencesApi.getPreference).toHaveBeenCalledWith('-me-', 'saved-searches');
done();
});

service.getSavedSearches().subscribe();
});

service.getSavedSearches().subscribe();
});
it('should emit updated saved searches after saving a new search', (done) => {
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
spyOn(localStorage, 'getItem').and.callFake(() => 'true');
const newSearch = { name: 'Search 3', description: 'Description 3', encodedUrl: 'url3' };
service.init();

service.saveSearch(newSearch).subscribe(() => {
service.savedSearches$.subscribe((searches) => {
expect(searches.length).toBe(3);
expect(searches[2].name).toBe('Search 2');
expect(service.preferencesApi.updatePreference).toHaveBeenCalledWith('-me-', 'saved-searches', jasmine.any(String));
done();
});
});
});

it('should emit updated saved searches after saving a new search', (done) => {
spyOn(authService, 'getUsername').and.callFake(() => testUserName);
spyOn(localStorage, 'getItem').and.callFake(() => 'true');
const newSearch = { name: 'Search 3', description: 'Description 3', encodedUrl: 'url3' };
service.init();
it('should edit a search', (done) => {
const updatedSearch = { name: 'Search 3', description: 'Description 3', encodedUrl: 'url3', order: 0 };
prepareDefaultMock();

service.editSavedSearch(updatedSearch).subscribe(() => {
service.savedSearches$.subscribe((searches) => {
expect(searches.length).toBe(2);
expect(searches[0].name).toBe('Search 3');
expect(searches[0].order).toBe(0);
expect(searches[1].name).toBe('Search 2');
expect(searches[1].order).toBe(1);
done();
});
});
});

service.saveSearch(newSearch).subscribe(() => {
service.savedSearches$.subscribe((searches) => {
expect(searches.length).toBe(3);
expect(searches[2].name).toBe('Search 2');
expect(service.preferencesApi.updatePreference).toHaveBeenCalledWith('-me-', 'saved-searches', jasmine.any(String));
done();
it('should delete a search', (done) => {
const searchToDelete = { name: 'Search 1', description: 'Description 1', encodedUrl: 'url1', order: 0 };
prepareDefaultMock();

service.deleteSavedSearch(searchToDelete).subscribe(() => {
service.savedSearches$.subscribe((searches) => {
expect(searches.length).toBe(1);
expect(searches[0].name).toBe('Search 2');
expect(searches[0].order).toBe(0);
done();
});
});
});
});

it('should edit a search', (done) => {
const updatedSearch = { name: 'Search 3', description: 'Description 3', encodedUrl: 'url3', order: 0 };
prepareDefaultMock();
describe('Saved searches error handling', () => {
it('should fallback to preferences API if getting saved searches node ID fails', (done) => {
spyOn(authService, 'getUsername').and.returnValue(testUserName);
spyOn(localStorage, 'getItem').and.returnValue('');
const error = new Error(JSON.stringify({ error: { statusCode: 500 } }));
spyOn(service.nodesApi, 'getNode').and.returnValue(Promise.reject(error));

service.editSavedSearch(updatedSearch).subscribe(() => {
service.savedSearches$.subscribe((searches) => {
service.getSavedSearches().subscribe((searches) => {
expect(service.preferencesApi.getPreference).toHaveBeenCalledWith('-me-', 'saved-searches');
expect(searches.length).toBe(2);
expect(searches[0].name).toBe('Search 3');
expect(searches[0].order).toBe(0);

expect(searches[1].name).toBe('Search 2');
expect(searches[1].order).toBe(1);
done();
});
});
});

it('should delete a search', (done) => {
const searchToDelete = { name: 'Search 1', description: 'Description 1', encodedUrl: 'url1', order: 0 };
prepareDefaultMock();
it('should handle 404 from getNode() by setting migration flag and falling back to preferences API', (done) => {
spyOn(authService, 'getUsername').and.returnValue(testUserName);
spyOn(localStorage, 'getItem').and.returnValue('');
spyOn(localStorage, 'setItem');
const notFoundError = new Error(JSON.stringify({ error: { statusCode: 404 } }));
spyOn(service.nodesApi, 'getNode').and.returnValue(Promise.reject(notFoundError));

service.deleteSavedSearch(searchToDelete).subscribe(() => {
service.savedSearches$.subscribe((searches) => {
expect(searches.length).toBe(1);
expect(searches[0].name).toBe('Search 2');
expect(searches[0].order).toBe(0);
service.getSavedSearches().subscribe((searches) => {
expect(localStorage.setItem).toHaveBeenCalledWith(LOCAL_STORAGE_KEY, 'true');
expect(service.preferencesApi.getPreference).toHaveBeenCalledWith('-me-', 'saved-searches');
expect(searches.length).toBe(2);
done();
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ export class SavedSearchesService {

readonly savedSearches$ = new ReplaySubject<SavedSearch[]>(1);

constructor(private readonly apiService: AlfrescoApiService, private readonly authService: AuthenticationService) {}
constructor(
private readonly apiService: AlfrescoApiService,
private readonly authService: AuthenticationService
) {}

init(): void {
this.fetchSavedSearches();
Expand All @@ -70,23 +73,18 @@ export class SavedSearchesService {
getSavedSearches(): Observable<SavedSearch[]> {
const savedSearchesMigrated = localStorage.getItem(this.getLocalStorageKey()) ?? '';
if (savedSearchesMigrated === 'true') {
return from(this.preferencesApi.getPreference('-me-', 'saved-searches')).pipe(
map((preference) => JSON.parse(preference.entry.value)),
catchError(() => of([]))
);
return this.getSavedSearchesFromPreferenceApi();
} else {
return this.getSavedSearchesNodeId().pipe(
take(1),
concatMap(() => {
if (this.savedSearchFileNodeId !== '') {
return this.migrateSavedSearches();
} else {
return from(this.preferencesApi.getPreference('-me-', 'saved-searches')).pipe(
map((preference) => JSON.parse(preference.entry.value)),
catchError(() => of([]))
);
return this.getSavedSearchesFromPreferenceApi();
}
})
}),
catchError(() => this.getSavedSearchesFromPreferenceApi())
);
}
}
Expand Down Expand Up @@ -237,10 +235,8 @@ export class SavedSearchesService {
const errorStatusCode = JSON.parse(error.message).error.statusCode;
if (errorStatusCode === 404) {
localStorage.setItem(this.getLocalStorageKey(), 'true');
return '';
} else {
return throwError(() => error);
}
return throwError(() => error);
})
);
}
Expand Down Expand Up @@ -271,4 +267,11 @@ export class SavedSearchesService {
})
);
}

private getSavedSearchesFromPreferenceApi(): Observable<SavedSearch[]> {
return from(this.preferencesApi.getPreference('-me-', 'saved-searches')).pipe(
map((preference) => JSON.parse(preference.entry.value)),
catchError(() => of([]))
);
}
}
Loading