import { provideHttpClient, withInterceptorsFromDi } from '@angular/common/http' import { HttpTestingController, provideHttpClientTesting, } from '@angular/common/http/testing' import { TestBed } from '@angular/core/testing' import { of, Subscription } from 'rxjs' import { CustomFieldDataType } from 'src/app/data/custom-field' import { DOCUMENT_SORT_FIELDS, DOCUMENT_SORT_FIELDS_FULLTEXT, } from 'src/app/data/document' import { FILTER_TITLE } from 'src/app/data/filter-rule-type' import { SETTINGS_KEYS } from 'src/app/data/ui-settings' import { environment } from 'src/environments/environment' import { PermissionsService } from '../permissions.service' import { SettingsService } from '../settings.service' import { CustomFieldsService } from './custom-fields.service' import { DocumentService } from './document.service' let httpTestingController: HttpTestingController let service: DocumentService let subscription: Subscription let settingsService: SettingsService let permissionsService: PermissionsService let customFieldsService: CustomFieldsService const endpoint = 'documents' const documents = [ { id: 1, title: 'Doc 1', content: 'some content', tags: [1, 2, 3], correspondent: 11, document_type: 3, storage_path: 8, }, { id: 2, title: 'Doc 2', content: 'some content', }, { id: 3, title: 'Doc 3', content: 'some content', }, ] beforeEach(() => { TestBed.configureTestingModule({ imports: [], providers: [ DocumentService, provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting(), ], }) httpTestingController = TestBed.inject(HttpTestingController) settingsService = TestBed.inject(SettingsService) customFieldsService = TestBed.inject(CustomFieldsService) permissionsService = TestBed.inject(PermissionsService) jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true) jest.spyOn(customFieldsService, 'listAll').mockReturnValue( of({ all: [1, 2, 3], count: 3, results: [ { id: 1, name: 'Custom Field 1', data_type: CustomFieldDataType.String, }, { id: 2, name: 'Custom Field 2', data_type: CustomFieldDataType.Integer, }, ], }) ) service = TestBed.inject(DocumentService) }) describe(`DocumentService`, () => { // common tests e.g. commonAbstractPaperlessServiceTests differ slightly it('should call appropriate api endpoint for list all', () => { subscription = service.listAll().subscribe() const req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/?page=1&page_size=100000` ) expect(req.request.method).toEqual('GET') }) it('should call appropriate api endpoint for get a single document', () => { subscription = service.get(documents[0].id).subscribe() const req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/?full_perms=true` ) expect(req.request.method).toEqual('GET') }) it('should call appropriate api endpoint for create a single document', () => { subscription = service.create(documents[0]).subscribe() const req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/` ) expect(req.request.method).toEqual('POST') }) it('should call appropriate api endpoint for delete a single document', () => { subscription = service.delete(documents[0]).subscribe() const req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/` ) expect(req.request.method).toEqual('DELETE') }) it('should call appropriate api endpoint for update a single document', () => { subscription = service.update(documents[0]).subscribe() const req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/` ) expect(req.request.method).toEqual('PUT') }) it('should call appropriate api endpoint for patch a single document', () => { subscription = service.patch(documents[0]).subscribe() const req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/` ) expect(req.request.method).toEqual('PATCH') }) it('should call appropriate api endpoint for listing all documents ids in a filter set', () => { subscription = service .listAllFilteredIds([ { rule_type: FILTER_TITLE, value: 'apple', }, ]) .subscribe() const req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/?page=1&page_size=100000&fields=id&title__icontains=apple` ) expect(req.request.method).toEqual('GET') }) it('should call appropriate api endpoint for uploading a document', () => { subscription = service.uploadDocument(documents[0]).subscribe() const req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/post_document/` ) expect(req.request.method).toEqual('POST') }) it('should call appropriate api endpoint for getting metadata', () => { subscription = service.getMetadata(documents[0].id).subscribe() const req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/metadata/` ) expect(req.request.method).toEqual('GET') }) it('should call appropriate api endpoint for getting selection data', () => { const ids = [documents[0].id] subscription = service.getSelectionData(ids).subscribe() const req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/selection_data/` ) expect(req.request.method).toEqual('POST') expect(req.request.body).toEqual({ documents: ids, }) }) it('should call appropriate api endpoint for getting suggestions', () => { subscription = service.getSuggestions(documents[0].id).subscribe() const req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/suggestions/` ) expect(req.request.method).toEqual('GET') }) it('should call appropriate api endpoint for bulk download', () => { const ids = [1, 2, 3] const content = 'both' const useFilenameFormatting = false subscription = service .bulkDownload(ids, content, useFilenameFormatting) .subscribe() const req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/bulk_download/` ) expect(req.request.method).toEqual('POST') expect(req.request.body).toEqual({ documents: ids, content, follow_formatting: useFilenameFormatting, }) }) it('should call appropriate api endpoint for bulk edit', () => { const ids = [1, 2, 3] const method = 'modify_tags' const parameters = { add_tags: [15], remove_tags: [6], } subscription = service.bulkEdit(ids, method, parameters).subscribe() const req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/bulk_edit/` ) expect(req.request.method).toEqual('POST') expect(req.request.body).toEqual({ documents: ids, method, parameters, }) }) it('should return the correct preview URL for a single document', () => { let url = service.getPreviewUrl(documents[0].id) expect(url).toEqual( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/preview/` ) url = service.getPreviewUrl(documents[0].id, true) expect(url).toEqual( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/preview/?original=true` ) }) it('should return the correct thumb URL for a single document', () => { let url = service.getThumbUrl(documents[0].id) expect(url).toEqual( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/thumb/` ) }) it('should return the correct download URL for a single document', () => { let url = service.getDownloadUrl(documents[0].id) expect(url).toEqual( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/download/` ) url = service.getDownloadUrl(documents[0].id, true) expect(url).toEqual( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/download/?original=true` ) }) it('should set search query', () => { const searchQuery = 'hello' service.searchQuery = searchQuery let url = service.getPreviewUrl(documents[0].id) expect(url).toEqual( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/preview/#search=%22${searchQuery}%22` ) }) it('should support get next asn', () => { subscription = service.getNextAsn().subscribe((asn) => asn) const req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/next_asn/` ) expect(req.request.method).toEqual('GET') }) it('should pass remove_inbox_tags setting to patch', () => { subscription = service.patch(documents[0]).subscribe() let req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/` ) expect(req.request.body.remove_inbox_tags).toEqual(false) settingsService.set(SETTINGS_KEYS.DOCUMENT_EDITING_REMOVE_INBOX_TAGS, true) subscription = service.patch(documents[0]).subscribe() req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/` ) expect(req.request.body.remove_inbox_tags).toEqual(true) }) it('should call appropriate api endpoint for getting audit log', () => { subscription = service.getHistory(documents[0].id).subscribe() const req = httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/history/` ) }) }) it('should construct sort fields respecting permissions', () => { expect( service.sortFields.find((f) => f.field === 'correspondent__name') ).not.toBeUndefined() expect( service.sortFields.find((f) => f.field === 'document_type__name') ).not.toBeUndefined() expect( service.sortFields.find((f) => f.field === 'owner') ).not.toBeUndefined() jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(false) service['setupSortFields']() const fields = DOCUMENT_SORT_FIELDS.filter( (f) => ['correspondent__name', 'document_type__name', 'owner'].indexOf( f.field ) === -1 ) expect(service.sortFields).toEqual(fields) expect(service.sortFieldsFullText).toEqual([ ...fields, ...DOCUMENT_SORT_FIELDS_FULLTEXT, ]) settingsService.set(SETTINGS_KEYS.NOTES_ENABLED, false) service['setupSortFields']() expect( service.sortFields.find((f) => f.field === 'num_notes') ).toBeUndefined() }) it('should include custom fields in sort fields if user has permission', () => { const permissionsService: PermissionsService = TestBed.inject(PermissionsService) jest.spyOn(permissionsService, 'currentUserCan').mockReturnValue(true) service['customFields'] = [ { id: 1, name: 'Custom Field 1', data_type: CustomFieldDataType.String, }, { id: 2, name: 'Custom Field 2', data_type: CustomFieldDataType.Integer, }, ] service['setupSortFields']() expect(service.sortFields).toEqual([ ...DOCUMENT_SORT_FIELDS, { field: 'custom_field_1', name: 'Custom Field 1', }, { field: 'custom_field_2', name: 'Custom Field 2', }, ]) }) it('should call appropriate api endpoint for email document', () => { subscription = service .emailDocument( documents[0].id, 'hello@paperless-ngx.com', 'hello', 'world', true ) .subscribe() httpTestingController.expectOne( `${environment.apiBaseUrl}${endpoint}/${documents[0].id}/email/` ) }) afterEach(() => { subscription?.unsubscribe() httpTestingController.verify() })