paperless-ngx/src-ui/src/app/components/manage/management-list/management-list.component.spec.ts
shamoon 181673c9a3 frontend unit tests
toasts component testing

conditional import of angular setup-jest for vscode-jest support

Update jest.config.js

Create open-documents.service.spec.ts

Add unit tests for all REST services

settings service test

Remove component from settings service test

Create permissions.service.spec.ts

upload documents service tests

Update package.json

Create toast.service.spec.ts

Tasks service test

Statistics widget component tests

Update permissions.service.ts

Create app.component.spec.ts

settings component testing

tasks component unit testing

Management list component generic tests

Some management component tests

document notes component unit tests

Create document-list.component.spec.ts

Create save-view-config-dialog.component.spec.ts

Create filter-editor.component.spec.ts

small and large document cards unit testing

Create bulk-editor.component.spec.ts

document detail unit tests

saving work on documentdetail component spec

Create document-asn.component.spec.ts

dashboard & widgets unit testing

Fix ResizeObserver mock

common component unit tests

fix some merge errors

Update app-frame.component.spec.ts

Create page-header.component.spec.ts

input component unit tests

FilterableDropdownComponent unit testing

and found minor errors

update taskservice unit tests

Edit dialogs unit tests

Create date-dropdown.component.spec.ts

Remove selectors from guard tests

confirm dialog component tests

app frame component test

Miscellaneous component tests

Update document-list-view.service.spec.ts

directives unit tests

Remove unused resizeobserver mock

guard unit tests

Update query-params.spec.ts

try to fix flaky playwright

filter rules utils & testing

Interceptor unit tests

Pipes unit testing

Utils unit tests

Update upload-documents.service.spec.ts

consumer status service tests

Update setup-jest.ts

Create document-list-view.service.spec.ts

Update app-routing.module.ts
2023-06-15 23:53:04 -07:00

233 lines
8.1 KiB
TypeScript

import { DatePipe } from '@angular/common'
import { HttpClientTestingModule } from '@angular/common/http/testing'
import {
ComponentFixture,
TestBed,
fakeAsync,
tick,
} from '@angular/core/testing'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { By } from '@angular/platform-browser'
import {
NgbModal,
NgbModalModule,
NgbModalRef,
NgbPaginationModule,
} from '@ng-bootstrap/ng-bootstrap'
import { of, throwError } from 'rxjs'
import { PaperlessTag } from 'src/app/data/paperless-tag'
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
import { SortableDirective } from 'src/app/directives/sortable.directive'
import { SafeHtmlPipe } from 'src/app/pipes/safehtml.pipe'
import { TagService } from 'src/app/services/rest/tag.service'
import { PageHeaderComponent } from '../../common/page-header/page-header.component'
import { TagListComponent } from '../tag-list/tag-list.component'
import { ManagementListComponent } from './management-list.component'
import { PermissionsService } from 'src/app/services/permissions.service'
import { ToastService } from 'src/app/services/toast.service'
import { EditDialogComponent } from '../../common/edit-dialog/edit-dialog.component'
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
import { DocumentListViewService } from 'src/app/services/document-list-view.service'
import { FILTER_HAS_TAGS_ALL } from 'src/app/data/filter-rule-type'
import { RouterTestingModule } from '@angular/router/testing'
import { routes } from 'src/app/app-routing.module'
import { PermissionsGuard } from 'src/app/guards/permissions.guard'
import { MATCH_AUTO } from 'src/app/data/matching-model'
import { MATCH_NONE } from 'src/app/data/matching-model'
import { MATCH_LITERAL } from 'src/app/data/matching-model'
const tags: PaperlessTag[] = [
{
id: 1,
name: 'Tag1 Foo',
matching_algorithm: MATCH_LITERAL,
match: 'foo',
},
{
id: 2,
name: 'Tag2',
matching_algorithm: MATCH_NONE,
},
{
id: 3,
name: 'Tag3',
matching_algorithm: MATCH_AUTO,
},
]
describe('ManagementListComponent', () => {
let component: ManagementListComponent<PaperlessTag>
let fixture: ComponentFixture<ManagementListComponent<PaperlessTag>>
let tagService: TagService
let modalService: NgbModal
let toastService: ToastService
let documentListViewService: DocumentListViewService
beforeEach(async () => {
TestBed.configureTestingModule({
declarations: [
TagListComponent,
SortableDirective,
PageHeaderComponent,
IfPermissionsDirective,
SafeHtmlPipe,
ConfirmDialogComponent,
],
providers: [
{
provide: PermissionsService,
useValue: {
currentUserCan: () => true,
currentUserHasObjectPermissions: () => true,
currentUserOwnsObject: () => true,
},
},
DatePipe,
PermissionsGuard,
],
imports: [
HttpClientTestingModule,
NgbPaginationModule,
FormsModule,
ReactiveFormsModule,
NgbModalModule,
RouterTestingModule.withRoutes(routes),
],
}).compileComponents()
tagService = TestBed.inject(TagService)
jest
.spyOn(tagService, 'listFiltered')
.mockImplementation(
(page, pageSize, sortField, sortReverse, nameFilter, fullPerms) => {
const results = nameFilter
? tags.filter((t) => t.name.toLowerCase().includes(nameFilter))
: tags
return of({
count: results.length,
all: results.map((o) => o.id),
results,
})
}
)
modalService = TestBed.inject(NgbModal)
toastService = TestBed.inject(ToastService)
documentListViewService = TestBed.inject(DocumentListViewService)
fixture = TestBed.createComponent(TagListComponent)
component = fixture.componentInstance
fixture.detectChanges()
})
// These tests are shared among all management list components
it('should support filtering, clear on Esc key', fakeAsync(() => {
const nameFilterInput = fixture.debugElement.query(By.css('input'))
nameFilterInput.nativeElement.value = 'foo'
// nameFilterInput.nativeElement.dispatchEvent(new Event('input'))
component.nameFilter = 'foo' // subject normally triggered by ngModel
tick(400) // debounce
fixture.detectChanges()
expect(component.data).toEqual([tags[0]])
nameFilterInput.nativeElement.dispatchEvent(
new KeyboardEvent('keyup', { code: 'Escape' })
)
tick(400) // debounce
fixture.detectChanges()
expect(component.nameFilter).toBeNull()
expect(component.data).toEqual(tags)
}))
it('should support create, show notification on error / success', () => {
let modal: NgbModalRef
modalService.activeInstances.subscribe((m) => (modal = m[m.length - 1]))
const toastErrorSpy = jest.spyOn(toastService, 'showError')
const toastInfoSpy = jest.spyOn(toastService, 'showInfo')
const reloadSpy = jest.spyOn(component, 'reloadData')
const createButton = fixture.debugElement.queryAll(By.css('button'))[0]
createButton.triggerEventHandler('click')
expect(modal).not.toBeUndefined()
const editDialog =
modal.componentInstance as EditDialogComponent<PaperlessTag>
// fail first
editDialog.failed.emit({ error: 'error creating item' })
expect(toastErrorSpy).toHaveBeenCalled()
expect(reloadSpy).not.toHaveBeenCalled()
// succeed
editDialog.succeeded.emit()
expect(toastInfoSpy).toHaveBeenCalled()
expect(reloadSpy).toHaveBeenCalled()
})
it('should support edit, show notification on error / success', () => {
let modal: NgbModalRef
modalService.activeInstances.subscribe((m) => (modal = m[m.length - 1]))
const toastErrorSpy = jest.spyOn(toastService, 'showError')
const toastInfoSpy = jest.spyOn(toastService, 'showInfo')
const reloadSpy = jest.spyOn(component, 'reloadData')
const editButton = fixture.debugElement.queryAll(By.css('button'))[3]
editButton.triggerEventHandler('click')
expect(modal).not.toBeUndefined()
const editDialog =
modal.componentInstance as EditDialogComponent<PaperlessTag>
expect(editDialog.object).toEqual(tags[0])
// fail first
editDialog.failed.emit({ error: 'error editing item' })
expect(toastErrorSpy).toHaveBeenCalled()
expect(reloadSpy).not.toHaveBeenCalled()
// succeed
editDialog.succeeded.emit()
expect(toastInfoSpy).toHaveBeenCalled()
expect(reloadSpy).toHaveBeenCalled()
})
it('should support delete, show notification on error / success', () => {
let modal: NgbModalRef
modalService.activeInstances.subscribe((m) => (modal = m[m.length - 1]))
const toastErrorSpy = jest.spyOn(toastService, 'showError')
const deleteSpy = jest.spyOn(tagService, 'delete')
const reloadSpy = jest.spyOn(component, 'reloadData')
const deleteButton = fixture.debugElement.queryAll(By.css('button'))[4]
deleteButton.triggerEventHandler('click')
expect(modal).not.toBeUndefined()
const editDialog = modal.componentInstance as ConfirmDialogComponent
// fail first
deleteSpy.mockReturnValueOnce(throwError(() => new Error('error deleting')))
editDialog.confirmClicked.emit()
expect(toastErrorSpy).toHaveBeenCalled()
expect(reloadSpy).not.toHaveBeenCalled()
// succeed
deleteSpy.mockReturnValueOnce(of(true))
editDialog.confirmClicked.emit()
expect(reloadSpy).toHaveBeenCalled()
})
it('should support quick filter for objects', () => {
const qfSpy = jest.spyOn(documentListViewService, 'quickFilter')
const filterButton = fixture.debugElement.queryAll(By.css('button'))[2]
filterButton.triggerEventHandler('click')
expect(qfSpy).toHaveBeenCalledWith([
{ rule_type: FILTER_HAS_TAGS_ALL, value: tags[0].id.toString() },
]) // subclasses set the filter rule type
})
it('should reload on sort', () => {
const reloadSpy = jest.spyOn(component, 'reloadData')
const sortable = fixture.debugElement.query(By.directive(SortableDirective))
sortable.triggerEventHandler('click')
expect(reloadSpy).toHaveBeenCalled()
})
})