mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-06-30 17:24:22 +00:00
Enhancement: new Tasks UI (#12614)
This commit is contained in:
@@ -9,12 +9,7 @@ import { FormsModule } from '@angular/forms'
|
||||
import { By } from '@angular/platform-browser'
|
||||
import { Router } from '@angular/router'
|
||||
import { RouterTestingModule } from '@angular/router/testing'
|
||||
import {
|
||||
NgbModal,
|
||||
NgbModalRef,
|
||||
NgbModule,
|
||||
NgbNavItem,
|
||||
} from '@ng-bootstrap/ng-bootstrap'
|
||||
import { NgbModal, NgbModalRef, NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { allIcons, NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
|
||||
import { throwError } from 'rxjs'
|
||||
import { routes } from 'src/app/app-routing.module'
|
||||
@@ -33,7 +28,7 @@ import { ToastService } from 'src/app/services/toast.service'
|
||||
import { environment } from 'src/environments/environment'
|
||||
import { ConfirmDialogComponent } from '../../common/confirm-dialog/confirm-dialog.component'
|
||||
import { PageHeaderComponent } from '../../common/page-header/page-header.component'
|
||||
import { TasksComponent, TaskTab } from './tasks.component'
|
||||
import { TasksComponent, TaskSection } from './tasks.component'
|
||||
|
||||
const tasks: PaperlessTask[] = [
|
||||
{
|
||||
@@ -48,8 +43,10 @@ const tasks: PaperlessTask[] = [
|
||||
trigger_source_display: 'Folder Consume',
|
||||
status: PaperlessTaskStatus.Failure,
|
||||
status_display: 'Failure',
|
||||
result_message:
|
||||
'test.pd: Not consuming test.pdf: It is a duplicate of test (#100)',
|
||||
result_data: {
|
||||
error_message:
|
||||
'test.pd: Not consuming test.pdf: It is a duplicate of test (#100)',
|
||||
},
|
||||
acknowledged: false,
|
||||
related_document_ids: [],
|
||||
},
|
||||
@@ -65,8 +62,7 @@ const tasks: PaperlessTask[] = [
|
||||
trigger_source_display: 'Folder Consume',
|
||||
status: PaperlessTaskStatus.Failure,
|
||||
status_display: 'Failure',
|
||||
result_message:
|
||||
'191092.pd: Not consuming 191092.pdf: It is a duplicate of 191092 (#311)',
|
||||
result_data: { duplicate_of: 311 },
|
||||
acknowledged: false,
|
||||
related_document_ids: [],
|
||||
},
|
||||
@@ -82,7 +78,7 @@ const tasks: PaperlessTask[] = [
|
||||
trigger_source_display: 'Folder Consume',
|
||||
status: PaperlessTaskStatus.Pending,
|
||||
status_display: 'Pending',
|
||||
result_message: null,
|
||||
result_data: null,
|
||||
acknowledged: false,
|
||||
related_document_ids: [],
|
||||
},
|
||||
@@ -98,7 +94,7 @@ const tasks: PaperlessTask[] = [
|
||||
trigger_source_display: 'Email Consume',
|
||||
status: PaperlessTaskStatus.Success,
|
||||
status_display: 'Success',
|
||||
result_message: 'Success. New document id 422 created',
|
||||
result_data: { document_id: 422, duplicate_of: 99 },
|
||||
acknowledged: false,
|
||||
related_document_ids: [422],
|
||||
},
|
||||
@@ -114,7 +110,7 @@ const tasks: PaperlessTask[] = [
|
||||
trigger_source_display: 'Folder Consume',
|
||||
status: PaperlessTaskStatus.Success,
|
||||
status_display: 'Success',
|
||||
result_message: 'Success. New document id 421 created',
|
||||
result_data: { document_id: 421 },
|
||||
acknowledged: false,
|
||||
related_document_ids: [421],
|
||||
},
|
||||
@@ -130,7 +126,23 @@ const tasks: PaperlessTask[] = [
|
||||
trigger_source_display: 'Email Consume',
|
||||
status: PaperlessTaskStatus.Started,
|
||||
status_display: 'Started',
|
||||
result_message: null,
|
||||
result_data: null,
|
||||
acknowledged: false,
|
||||
related_document_ids: [],
|
||||
},
|
||||
{
|
||||
id: 461,
|
||||
task_id: 'bb79efb3-1e78-4f31-b4be-0966620b0ce1',
|
||||
input_data: { dry_run: false, scope: 'global' },
|
||||
date_created: new Date('2023-06-07T03:54:35.694916Z'),
|
||||
date_done: null,
|
||||
task_type: PaperlessTaskType.SanityCheck,
|
||||
task_type_display: 'Sanity Check',
|
||||
trigger_source: PaperlessTaskTriggerSource.System,
|
||||
trigger_source_display: 'System',
|
||||
status: PaperlessTaskStatus.Started,
|
||||
status_display: 'Started',
|
||||
result_data: { issues_found: 0 },
|
||||
acknowledged: false,
|
||||
related_document_ids: [],
|
||||
},
|
||||
@@ -185,59 +197,142 @@ describe('TasksComponent', () => {
|
||||
jest.useFakeTimers()
|
||||
fixture.detectChanges()
|
||||
httpTestingController
|
||||
.expectOne(
|
||||
`${environment.apiBaseUrl}tasks/?task_type=consume_file&acknowledged=false`
|
||||
)
|
||||
.expectOne(`${environment.apiBaseUrl}tasks/?acknowledged=false`)
|
||||
.flush(tasks)
|
||||
})
|
||||
|
||||
it('should display file tasks in 4 tabs by status', () => {
|
||||
const tabButtons = fixture.debugElement.queryAll(By.directive(NgbNavItem))
|
||||
it('should display task sections with counts', () => {
|
||||
expect(component.selectedSection).toBe(TaskSection.All)
|
||||
expect(component.selectedTaskType).toBeNull()
|
||||
expect(component.selectedTriggerSource).toBeNull()
|
||||
|
||||
let currentTasksLength = tasks.filter(
|
||||
(t) => t.status === PaperlessTaskStatus.Failure
|
||||
).length
|
||||
component.activeTab = TaskTab.Failed
|
||||
fixture.detectChanges()
|
||||
expect(tabButtons[0].nativeElement.textContent).toEqual(
|
||||
`Failed${currentTasksLength}`
|
||||
)
|
||||
expect(
|
||||
fixture.debugElement.queryAll(By.css('table input[type="checkbox"]'))
|
||||
).toHaveLength(currentTasksLength + 1)
|
||||
|
||||
currentTasksLength = tasks.filter(
|
||||
(t) => t.status === PaperlessTaskStatus.Success
|
||||
).length
|
||||
component.activeTab = TaskTab.Completed
|
||||
fixture.detectChanges()
|
||||
expect(tabButtons[1].nativeElement.textContent).toEqual(
|
||||
`Complete${currentTasksLength}`
|
||||
)
|
||||
const viewScope = fixture.debugElement.query(By.css('.task-view-scope'))
|
||||
const text = viewScope.nativeElement.textContent
|
||||
|
||||
currentTasksLength = tasks.filter(
|
||||
(t) => t.status === PaperlessTaskStatus.Started
|
||||
).length
|
||||
component.activeTab = TaskTab.Started
|
||||
fixture.detectChanges()
|
||||
expect(tabButtons[2].nativeElement.textContent).toEqual(
|
||||
`Started${currentTasksLength}`
|
||||
)
|
||||
expect(text).toContain('All')
|
||||
expect(text).toContain('Needs attention')
|
||||
expect(text).toContain('2')
|
||||
expect(text).toContain('In progress')
|
||||
expect(text).toContain('3')
|
||||
expect(text).toContain('Recently completed')
|
||||
})
|
||||
|
||||
currentTasksLength = tasks.filter(
|
||||
(t) => t.status === PaperlessTaskStatus.Pending
|
||||
).length
|
||||
component.activeTab = TaskTab.Queued
|
||||
it('should filter visible sections by selected status', () => {
|
||||
component.setSection(TaskSection.InProgress)
|
||||
fixture.detectChanges()
|
||||
expect(tabButtons[3].nativeElement.textContent).toEqual(
|
||||
`Queued${currentTasksLength}`
|
||||
|
||||
expect(component.visibleSections).toEqual([TaskSection.InProgress])
|
||||
expect(fixture.nativeElement.textContent).toContain('In progress')
|
||||
expect(fixture.nativeElement.textContent).not.toContain('Recent completed')
|
||||
})
|
||||
|
||||
it('should filter tasks by task type', () => {
|
||||
component.setSection(TaskSection.InProgress)
|
||||
component.setTaskType(PaperlessTaskType.SanityCheck)
|
||||
|
||||
expect(component.tasksForSection(TaskSection.InProgress)).toHaveLength(1)
|
||||
expect(component.tasksForSection(TaskSection.InProgress)[0].task_type).toBe(
|
||||
PaperlessTaskType.SanityCheck
|
||||
)
|
||||
})
|
||||
|
||||
it('should to go page 1 between tab switch', () => {
|
||||
component.page = 10
|
||||
component.duringTabChange()
|
||||
expect(component.page).toEqual(1)
|
||||
it('should filter tasks by trigger source', () => {
|
||||
component.setSection(TaskSection.InProgress)
|
||||
component.setTriggerSource(PaperlessTaskTriggerSource.EmailConsume)
|
||||
|
||||
expect(component.tasksForSection(TaskSection.InProgress)).toHaveLength(1)
|
||||
expect(
|
||||
component.tasksForSection(TaskSection.InProgress)[0].trigger_source
|
||||
).toBe(PaperlessTaskTriggerSource.EmailConsume)
|
||||
})
|
||||
|
||||
it('should reset all active filters together', () => {
|
||||
component.setSection(TaskSection.InProgress)
|
||||
component.setTaskType(PaperlessTaskType.SanityCheck)
|
||||
component.setTriggerSource(PaperlessTaskTriggerSource.System)
|
||||
component.filterText = 'system'
|
||||
jest.advanceTimersByTime(150)
|
||||
|
||||
expect(component.isFiltered).toBe(true)
|
||||
|
||||
component.resetFilters()
|
||||
|
||||
expect(component.selectedSection).toBe(TaskSection.InProgress)
|
||||
expect(component.selectedTaskType).toBeNull()
|
||||
expect(component.selectedTriggerSource).toBeNull()
|
||||
expect(component.filterText).toBe('')
|
||||
expect(component.isFiltered).toBe(false)
|
||||
})
|
||||
|
||||
it('should keep header controls focused on actions and auto refresh', () => {
|
||||
fixture.detectChanges()
|
||||
|
||||
const header = fixture.debugElement.query(By.css('pngx-page-header'))
|
||||
const headerText = header.nativeElement.textContent
|
||||
|
||||
expect(headerText).toContain('Dismiss visible')
|
||||
expect(headerText).toContain('Auto refresh')
|
||||
expect(headerText).not.toContain('All types')
|
||||
expect(headerText).not.toContain('All sources')
|
||||
expect(headerText).not.toContain('Reset filters')
|
||||
})
|
||||
|
||||
it('should render the view scope row above the filter bar', () => {
|
||||
fixture.detectChanges()
|
||||
|
||||
const controls = fixture.debugElement.query(By.css('.task-controls'))
|
||||
const viewScope = controls.query(By.css('.task-view-scope'))
|
||||
const search = controls.query(By.css('.task-search'))
|
||||
|
||||
expect(viewScope).not.toBeNull()
|
||||
expect(search).not.toBeNull()
|
||||
expect(
|
||||
viewScope.nativeElement.compareDocumentPosition(search.nativeElement) &
|
||||
Node.DOCUMENT_POSITION_FOLLOWING
|
||||
).toBeTruthy()
|
||||
})
|
||||
|
||||
it('should expose stable task type options and disable empty ones', () => {
|
||||
expect(component.taskTypeOptions.map((option) => option.value)).toContain(
|
||||
PaperlessTaskType.TrainClassifier
|
||||
)
|
||||
expect(
|
||||
component.isTaskTypeOptionDisabled(PaperlessTaskType.TrainClassifier)
|
||||
).toBe(true)
|
||||
expect(
|
||||
component.isTaskTypeOptionDisabled(PaperlessTaskType.ConsumeFile)
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
it('should fall back to the raw selected task type label when no option matches', () => {
|
||||
component.selectedTaskType = 'unknown_task_type' as PaperlessTaskType
|
||||
|
||||
expect(component.selectedTaskTypeLabel).toBe('unknown_task_type')
|
||||
})
|
||||
|
||||
it('should expose stable trigger source options and disable empty ones', () => {
|
||||
expect(
|
||||
component.triggerSourceOptions.map((option) => option.value)
|
||||
).toContain(PaperlessTaskTriggerSource.ApiUpload)
|
||||
expect(
|
||||
component.isTriggerSourceOptionDisabled(
|
||||
PaperlessTaskTriggerSource.ApiUpload
|
||||
)
|
||||
).toBe(true)
|
||||
expect(
|
||||
component.isTriggerSourceOptionDisabled(
|
||||
PaperlessTaskTriggerSource.EmailConsume
|
||||
)
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
it('should fall back to the raw selected trigger source label when no option matches', () => {
|
||||
component.selectedTriggerSource =
|
||||
'unknown_trigger_source' as PaperlessTaskTriggerSource
|
||||
|
||||
expect(component.selectedTriggerSourceLabel).toBe('unknown_trigger_source')
|
||||
})
|
||||
|
||||
it('should support expanding / collapsing one task at a time', () => {
|
||||
@@ -249,6 +344,31 @@ describe('TasksComponent', () => {
|
||||
expect(component.expandedTask).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should show structured task details when expanded', () => {
|
||||
component.setSection(TaskSection.InProgress)
|
||||
component.expandTask(tasks[6])
|
||||
fixture.detectChanges()
|
||||
|
||||
const detailText = fixture.nativeElement.textContent
|
||||
|
||||
expect(detailText).toContain('Input data')
|
||||
expect(detailText).toContain('Result data')
|
||||
expect(detailText).toContain('"scope": "global"')
|
||||
expect(detailText).toContain('"issues_found": 0')
|
||||
})
|
||||
|
||||
it('should show duplicate warnings and duplicate details when present', () => {
|
||||
component.setSection(TaskSection.Completed)
|
||||
component.expandTask(tasks[3])
|
||||
fixture.detectChanges()
|
||||
|
||||
const content = fixture.nativeElement.textContent
|
||||
|
||||
expect(content).toContain('Duplicate of document #99')
|
||||
expect(content).toContain('Duplicate')
|
||||
expect(content).toContain('Open')
|
||||
})
|
||||
|
||||
it('should support dismiss single task', () => {
|
||||
const dismissSpy = jest.spyOn(tasksService, 'dismissTasks')
|
||||
component.dismissTask(tasks[0])
|
||||
@@ -259,7 +379,7 @@ describe('TasksComponent', () => {
|
||||
component.toggleSelected(tasks[0])
|
||||
component.toggleSelected(tasks[1])
|
||||
component.toggleSelected(tasks[3])
|
||||
component.toggleSelected(tasks[3]) // uncheck, for coverage
|
||||
component.toggleSelected(tasks[3])
|
||||
const selected = new Set([tasks[0].id, tasks[1].id])
|
||||
expect(component.selectedTasks).toEqual(selected)
|
||||
let modal: NgbModalRef
|
||||
@@ -308,31 +428,50 @@ describe('TasksComponent', () => {
|
||||
expect(component.selectedTasks.size).toBe(0)
|
||||
})
|
||||
|
||||
it('should support dismiss all tasks', () => {
|
||||
it('should support dismiss visible tasks', () => {
|
||||
component.setSection(TaskSection.NeedsAttention)
|
||||
let modal: NgbModalRef
|
||||
modalService.activeInstances.subscribe((m) => (modal = m[m.length - 1]))
|
||||
const dismissSpy = jest.spyOn(tasksService, 'dismissTasks')
|
||||
component.dismissTasks()
|
||||
expect(modal).not.toBeUndefined()
|
||||
modal.componentInstance.confirmClicked.emit()
|
||||
expect(dismissSpy).toHaveBeenCalledWith(new Set(tasks.map((t) => t.id)))
|
||||
expect(dismissSpy).toHaveBeenCalledWith(new Set([467, 466]))
|
||||
})
|
||||
|
||||
it('should support toggle all tasks', () => {
|
||||
it('should dismiss the currently visible scoped and filtered tasks', () => {
|
||||
component.setSection(TaskSection.InProgress)
|
||||
component.setTaskType(PaperlessTaskType.SanityCheck)
|
||||
component.setTriggerSource(PaperlessTaskTriggerSource.System)
|
||||
|
||||
const dismissSpy = jest.spyOn(tasksService, 'dismissTasks')
|
||||
|
||||
component.dismissTasks()
|
||||
|
||||
expect(dismissSpy).toHaveBeenCalledWith(new Set([461]))
|
||||
})
|
||||
|
||||
it('should support toggling a full section', () => {
|
||||
component.setSection(TaskSection.NeedsAttention)
|
||||
fixture.detectChanges()
|
||||
|
||||
const toggleCheck = fixture.debugElement.query(
|
||||
By.css('table input[type=checkbox]')
|
||||
)
|
||||
toggleCheck.nativeElement.dispatchEvent(new MouseEvent('click'))
|
||||
fixture.detectChanges()
|
||||
expect(component.selectedTasks).toEqual(
|
||||
new Set(
|
||||
tasks
|
||||
.filter((t) => t.status === PaperlessTaskStatus.Failure)
|
||||
.map((t) => t.id)
|
||||
)
|
||||
By.css('#all-tasks-needs_attention')
|
||||
)
|
||||
expect(toggleCheck).not.toBeNull()
|
||||
toggleCheck.nativeElement.dispatchEvent(new MouseEvent('click'))
|
||||
fixture.detectChanges()
|
||||
expect(component.selectedTasks).toEqual(new Set([467, 466]))
|
||||
})
|
||||
|
||||
it('should remove a full section from selection when toggled off', () => {
|
||||
component.setSection(TaskSection.NeedsAttention)
|
||||
component.selectedTasks = new Set([467, 466])
|
||||
|
||||
component.toggleSection(TaskSection.NeedsAttention, {
|
||||
target: { checked: false },
|
||||
} as PointerEvent)
|
||||
|
||||
expect(component.selectedTasks).toEqual(new Set())
|
||||
})
|
||||
|
||||
@@ -355,57 +494,127 @@ describe('TasksComponent', () => {
|
||||
})
|
||||
|
||||
it('should filter tasks by file name', () => {
|
||||
fixture.detectChanges()
|
||||
const input = fixture.debugElement.query(
|
||||
By.css('pngx-page-header input[type=text]')
|
||||
By.css('.task-search input[type=text]')
|
||||
)
|
||||
expect(input).not.toBeNull()
|
||||
input.nativeElement.value = '191092'
|
||||
input.nativeElement.dispatchEvent(new Event('input'))
|
||||
jest.advanceTimersByTime(150) // debounce time
|
||||
jest.advanceTimersByTime(150)
|
||||
fixture.detectChanges()
|
||||
expect(component.filterText).toEqual('191092')
|
||||
expect(
|
||||
fixture.debugElement.queryAll(By.css('table tbody tr')).length
|
||||
).toEqual(2) // 1 task x 2 lines
|
||||
expect(component.tasksForSection(TaskSection.NeedsAttention)).toHaveLength(
|
||||
1
|
||||
)
|
||||
})
|
||||
|
||||
it('should match task type and source in name filtering', () => {
|
||||
component.setSection(TaskSection.InProgress)
|
||||
component.filterText = 'system'
|
||||
jest.advanceTimersByTime(150)
|
||||
|
||||
expect(component.tasksForSection(TaskSection.InProgress)).toHaveLength(1)
|
||||
expect(component.tasksForSection(TaskSection.InProgress)[0].task_type).toBe(
|
||||
PaperlessTaskType.SanityCheck
|
||||
)
|
||||
})
|
||||
|
||||
it('should fall back to task type when filename is unavailable', () => {
|
||||
component.setSection(TaskSection.InProgress)
|
||||
fixture.detectChanges()
|
||||
|
||||
const nameColumn = fixture.debugElement.queryAll(
|
||||
By.css('tbody td.name-col')
|
||||
)
|
||||
const sanityTaskRow = nameColumn.find((cell) =>
|
||||
cell.nativeElement.textContent.includes('Sanity Check')
|
||||
)
|
||||
|
||||
expect(sanityTaskRow.nativeElement.textContent).toContain('Sanity Check')
|
||||
expect(sanityTaskRow.nativeElement.textContent).toContain('System')
|
||||
})
|
||||
|
||||
it('should filter tasks by result', () => {
|
||||
component.activeTab = TaskTab.Failed
|
||||
fixture.detectChanges()
|
||||
component.setSection(TaskSection.NeedsAttention)
|
||||
component.filterTargetID = 1
|
||||
fixture.detectChanges()
|
||||
const input = fixture.debugElement.query(
|
||||
By.css('pngx-page-header input[type=text]')
|
||||
By.css('.task-search input[type=text]')
|
||||
)
|
||||
expect(input).not.toBeNull()
|
||||
input.nativeElement.value = 'duplicate'
|
||||
input.nativeElement.dispatchEvent(new Event('input'))
|
||||
jest.advanceTimersByTime(150) // debounce time
|
||||
jest.advanceTimersByTime(150)
|
||||
fixture.detectChanges()
|
||||
expect(component.filterText).toEqual('duplicate')
|
||||
expect(component.tasksForSection(TaskSection.NeedsAttention)).toHaveLength(
|
||||
2
|
||||
)
|
||||
})
|
||||
|
||||
it('should prefer explicit reason in the result message', () => {
|
||||
expect(
|
||||
fixture.debugElement.queryAll(By.css('table tbody tr')).length
|
||||
).toEqual(4) // 2 tasks x 2 lines
|
||||
component.taskResultMessage({
|
||||
...tasks[0],
|
||||
result_data: { reason: 'Manual review required', duplicate_of: 311 },
|
||||
})
|
||||
).toBe('Manual review required')
|
||||
})
|
||||
|
||||
it('should return null preview and popover text when there is no result message', () => {
|
||||
expect(component.taskResultPreview(tasks[2])).toBeNull()
|
||||
expect(component.taskResultPopoverMessage(tasks[2])).toBe('')
|
||||
expect(component.taskResultMessageOverflowsPopover(tasks[2])).toBe(false)
|
||||
})
|
||||
|
||||
it('should navigate to a duplicate document details page', () => {
|
||||
const routerSpy = jest.spyOn(router, 'navigate')
|
||||
|
||||
component.openDuplicateDocument(99)
|
||||
|
||||
expect(routerSpy).toHaveBeenCalledWith(['documents', 99, 'details'])
|
||||
})
|
||||
|
||||
it('should report when a result message overflows the popover limit', () => {
|
||||
const longMessage = 'x'.repeat(350)
|
||||
const task = {
|
||||
...tasks[0],
|
||||
result_data: { error_message: longMessage },
|
||||
}
|
||||
|
||||
expect(component.taskResultPopoverMessage(task)).toBe(
|
||||
longMessage.slice(0, 300)
|
||||
)
|
||||
expect(component.taskResultMessageOverflowsPopover(task)).toBe(true)
|
||||
})
|
||||
|
||||
it('should support keyboard events for filtering', () => {
|
||||
fixture.detectChanges()
|
||||
const input = fixture.debugElement.query(
|
||||
By.css('pngx-page-header input[type=text]')
|
||||
By.css('.task-search input[type=text]')
|
||||
)
|
||||
expect(input).not.toBeNull()
|
||||
input.nativeElement.value = '191092'
|
||||
input.nativeElement.dispatchEvent(
|
||||
new KeyboardEvent('keyup', { key: 'Enter' })
|
||||
)
|
||||
expect(component.filterText).toEqual('191092') // no debounce needed
|
||||
expect(component.filterText).toEqual('191092')
|
||||
input.nativeElement.dispatchEvent(
|
||||
new KeyboardEvent('keyup', { key: 'Escape' })
|
||||
)
|
||||
expect(component.filterText).toEqual('')
|
||||
})
|
||||
|
||||
it('should reset filter and target on tab switch', () => {
|
||||
component.filterText = '191092'
|
||||
component.filterTargetID = 1
|
||||
component.activeTab = TaskTab.Completed
|
||||
component.beforeTabChange()
|
||||
expect(component.filterText).toEqual('')
|
||||
expect(component.filterTargetID).toEqual(0)
|
||||
it('should keep clearing selection independent from resetting filters', () => {
|
||||
component.setTaskType(PaperlessTaskType.ConsumeFile)
|
||||
component.toggleSelected(tasks[0])
|
||||
expect(component.selectedTasks.size).toBe(1)
|
||||
|
||||
component.clearSelection()
|
||||
|
||||
expect(component.selectedTasks.size).toBe(0)
|
||||
expect(component.selectedTaskType).toBe(PaperlessTaskType.ConsumeFile)
|
||||
expect(component.isFiltered).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user