Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3089875a4 | ||
|
|
7d8147c21d |
No files matched your search
@@ -256,8 +256,8 @@ isort.force-single-line = true
|
||||
[tool.codespell]
|
||||
ignore-words-list = "criterias,afterall,valeu,ureue,equest,ure,assertIn,Oktober,commitish,NIN,nin,reprot"
|
||||
skip = """\
|
||||
src-ui/src/locale/*,src-ui/pnpm-lock.yaml,src-ui/e2e/*,src/paperless/tests/samples/mail/*,src/documents/tests/samples\
|
||||
/*,src/paperless_testing/sample_files/*,*.po,*.json\
|
||||
src-ui/src/locale/*,src-ui/pnpm-lock.yaml,src-ui/e2e/*,src/paperless_mail/tests/samples/*,src/paperless/tests/samples\
|
||||
/mail/*,src/documents/tests/samples/*,*.po,*.json\
|
||||
"""
|
||||
write-changes = true
|
||||
|
||||
|
||||
@@ -134,9 +134,7 @@ def seed_database() -> None:
|
||||
originals.mkdir(parents=True)
|
||||
thumbnails = Path(os.environ["PAPERLESS_MEDIA_ROOT"]) / "documents" / "thumbnails"
|
||||
thumbnails.mkdir(parents=True)
|
||||
sample_pdf = (
|
||||
SOURCE_ROOT / "paperless_testing" / "sample_files" / "simple-digital.pdf"
|
||||
)
|
||||
sample_pdf = SOURCE_ROOT / "documents" / "tests" / "samples" / "simple.pdf"
|
||||
for document in documents:
|
||||
shutil.copyfile(sample_pdf, originals / document.filename)
|
||||
shutil.copyfile(
|
||||
|
||||
@@ -19,7 +19,6 @@ import {
|
||||
PaperlessTaskTriggerSource,
|
||||
PaperlessTaskType,
|
||||
} from 'src/app/data/paperless-task'
|
||||
import { Results } from 'src/app/data/results'
|
||||
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
|
||||
import { PermissionsGuard } from 'src/app/guards/permissions.guard'
|
||||
import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe'
|
||||
@@ -153,11 +152,6 @@ const tasks: PaperlessTask[] = [
|
||||
},
|
||||
]
|
||||
|
||||
const paginatedTasks: Results<PaperlessTask> = {
|
||||
count: tasks.length,
|
||||
results: tasks,
|
||||
}
|
||||
|
||||
const sectionCountResponse = {
|
||||
all: 7,
|
||||
needs_attention: 2,
|
||||
@@ -204,7 +198,7 @@ describe('TasksComponent', () => {
|
||||
}).compileComponents()
|
||||
|
||||
tasksService = TestBed.inject(TasksService)
|
||||
reloadSpy = jest.spyOn(tasksService, 'reload')
|
||||
reloadSpy = jest.spyOn(tasksService, 'reload').mockImplementation(() => {})
|
||||
httpTestingController = TestBed.inject(HttpTestingController)
|
||||
modalService = TestBed.inject(NgbModal)
|
||||
router = TestBed.inject(Router)
|
||||
@@ -214,15 +208,6 @@ describe('TasksComponent', () => {
|
||||
jest.useFakeTimers()
|
||||
fixture.detectChanges()
|
||||
|
||||
httpTestingController
|
||||
.expectOne(
|
||||
(req) =>
|
||||
req.url === `${environment.apiBaseUrl}tasks/` &&
|
||||
req.params.get('acknowledged') === 'false' &&
|
||||
req.params.get('page_size') === '1000'
|
||||
)
|
||||
.flush(paginatedTasks)
|
||||
|
||||
httpTestingController
|
||||
.expectOne(
|
||||
(req) =>
|
||||
|
||||
@@ -344,11 +344,11 @@
|
||||
ngbPopover="Tasks" i18n-ngbPopover [disablePopover]="!slimSidebarPopoversEnabled" placement="end"
|
||||
container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim">
|
||||
<i-bs class="me-2" name="list-task"></i-bs><span class="nav-link-label"><ng-container i18n>Tasks</ng-container></span>
|
||||
@if (tasksService.needsAttentionTasks.length > 0 && !slimSidebarEnabled) {
|
||||
<span class="badge bg-danger ms-2 d-inline flex-shrink-0">{{tasksService.needsAttentionTasks.length}}</span>
|
||||
@if (tasksService.needsAttentionTasksCount > 0 && !slimSidebarEnabled) {
|
||||
<span class="badge bg-danger ms-2 d-inline flex-shrink-0">{{tasksService.needsAttentionTasksCount}}</span>
|
||||
}
|
||||
@if (tasksService.needsAttentionTasks.length > 0 && slimSidebarEnabled) {
|
||||
<span class="badge bg-danger position-absolute top-0 end-0 d-none d-md-block">{{tasksService.needsAttentionTasks.length}}</span>
|
||||
@if (tasksService.needsAttentionTasksCount > 0 && slimSidebarEnabled) {
|
||||
<span class="badge bg-danger position-absolute top-0 end-0 d-none d-md-block">{{tasksService.needsAttentionTasksCount}}</span>
|
||||
}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -588,8 +588,8 @@ describe('AppFrameComponent', () => {
|
||||
|
||||
it('should show tasks badge for needs-attention tasks', () => {
|
||||
jest
|
||||
.spyOn(tasksService, 'needsAttentionTasks', 'get')
|
||||
.mockReturnValue([{} as any, {} as any])
|
||||
.spyOn(tasksService, 'needsAttentionTasksCount', 'get')
|
||||
.mockReturnValue(2)
|
||||
|
||||
fixture.detectChanges()
|
||||
|
||||
|
||||
@@ -9,11 +9,7 @@ import {
|
||||
} from '@angular/common/http/testing'
|
||||
import { TestBed } from '@angular/core/testing'
|
||||
import { environment } from 'src/environments/environment'
|
||||
import {
|
||||
PaperlessTaskStatus,
|
||||
PaperlessTaskTriggerSource,
|
||||
PaperlessTaskType,
|
||||
} from '../data/paperless-task'
|
||||
import { PaperlessTaskType } from '../data/paperless-task'
|
||||
import { TasksService } from './tasks.service'
|
||||
|
||||
describe('TasksService', () => {
|
||||
@@ -38,23 +34,23 @@ describe('TasksService', () => {
|
||||
httpTestingController.verify()
|
||||
})
|
||||
|
||||
it('calls tasks api endpoint on reload', () => {
|
||||
it('calls tasks status counts api endpoint on reload', () => {
|
||||
tasksService.reload()
|
||||
const req = httpTestingController.expectOne(
|
||||
(req: HttpRequest<unknown>) =>
|
||||
req.url === `${environment.apiBaseUrl}tasks/` &&
|
||||
req.params.get('acknowledged') === 'false' &&
|
||||
req.params.get('page_size') === '1000'
|
||||
req.url === `${environment.apiBaseUrl}tasks/status_counts/` &&
|
||||
req.params.get('acknowledged') === 'false'
|
||||
)
|
||||
expect(req.request.method).toEqual('GET')
|
||||
req.flush({ count: 0, results: [] })
|
||||
req.flush({ all: 5, needs_attention: 3, in_progress: 1, completed: 1 })
|
||||
expect(tasksService.needsAttentionTasksCount).toEqual(3)
|
||||
})
|
||||
|
||||
it('cancels an in-progress reload when reloading again', () => {
|
||||
tasksService.reload()
|
||||
const staleReload = httpTestingController.expectOne(
|
||||
(req: HttpRequest<unknown>) =>
|
||||
req.url === `${environment.apiBaseUrl}tasks/`
|
||||
req.url === `${environment.apiBaseUrl}tasks/status_counts/`
|
||||
)
|
||||
tasksService.reload()
|
||||
|
||||
@@ -62,9 +58,9 @@ describe('TasksService', () => {
|
||||
httpTestingController
|
||||
.expectOne(
|
||||
(req: HttpRequest<unknown>) =>
|
||||
req.url === `${environment.apiBaseUrl}tasks/`
|
||||
req.url === `${environment.apiBaseUrl}tasks/status_counts/`
|
||||
)
|
||||
.flush({ count: 0, results: [] })
|
||||
.flush({ all: 0, needs_attention: 0, in_progress: 0, completed: 0 })
|
||||
})
|
||||
|
||||
it('continues reloading after a reload request fails', () => {
|
||||
@@ -72,7 +68,7 @@ describe('TasksService', () => {
|
||||
httpTestingController
|
||||
.expectOne(
|
||||
(req: HttpRequest<unknown>) =>
|
||||
req.url === `${environment.apiBaseUrl}tasks/`
|
||||
req.url === `${environment.apiBaseUrl}tasks/status_counts/`
|
||||
)
|
||||
.flush('error', { status: 500, statusText: 'error' })
|
||||
|
||||
@@ -82,16 +78,16 @@ describe('TasksService', () => {
|
||||
httpTestingController
|
||||
.expectOne(
|
||||
(req: HttpRequest<unknown>) =>
|
||||
req.url === `${environment.apiBaseUrl}tasks/`
|
||||
req.url === `${environment.apiBaseUrl}tasks/status_counts/`
|
||||
)
|
||||
.flush({ count: 0, results: [] })
|
||||
.flush({ all: 0, needs_attention: 0, in_progress: 0, completed: 0 })
|
||||
})
|
||||
|
||||
it('reloads after dismissing a task while a reload is already in progress', () => {
|
||||
tasksService.reload()
|
||||
const staleReload = httpTestingController.expectOne(
|
||||
(req: HttpRequest<unknown>) =>
|
||||
req.url === `${environment.apiBaseUrl}tasks/` &&
|
||||
req.url === `${environment.apiBaseUrl}tasks/status_counts/` &&
|
||||
req.params.get('acknowledged') === 'false'
|
||||
)
|
||||
|
||||
@@ -104,12 +100,12 @@ describe('TasksService', () => {
|
||||
httpTestingController
|
||||
.expectOne(
|
||||
(req: HttpRequest<unknown>) =>
|
||||
req.url === `${environment.apiBaseUrl}tasks/` &&
|
||||
req.url === `${environment.apiBaseUrl}tasks/status_counts/` &&
|
||||
req.params.get('acknowledged') === 'false'
|
||||
)
|
||||
.flush({ count: 0, results: [] })
|
||||
.flush({ all: 50, needs_attention: 42, in_progress: 3, completed: 5 })
|
||||
|
||||
expect(tasksService.needsAttentionTasks).toHaveLength(0)
|
||||
expect(tasksService.needsAttentionTasksCount).toEqual(42)
|
||||
})
|
||||
|
||||
it('calls acknowledge_tasks api endpoint on dismiss and reloads', () => {
|
||||
@@ -126,11 +122,10 @@ describe('TasksService', () => {
|
||||
httpTestingController
|
||||
.expectOne(
|
||||
(req: HttpRequest<unknown>) =>
|
||||
req.url === `${environment.apiBaseUrl}tasks/` &&
|
||||
req.params.get('acknowledged') === 'false' &&
|
||||
req.params.get('page_size') === '1000'
|
||||
req.url === `${environment.apiBaseUrl}tasks/status_counts/` &&
|
||||
req.params.get('acknowledged') === 'false'
|
||||
)
|
||||
.flush({ count: 0, results: [] })
|
||||
.flush({ all: 0, needs_attention: 0, in_progress: 0, completed: 0 })
|
||||
})
|
||||
|
||||
it('calls acknowledge_tasks api endpoint on dismiss all and reloads', () => {
|
||||
@@ -147,65 +142,10 @@ describe('TasksService', () => {
|
||||
httpTestingController
|
||||
.expectOne(
|
||||
(req: HttpRequest<unknown>) =>
|
||||
req.url === `${environment.apiBaseUrl}tasks/` &&
|
||||
req.params.get('acknowledged') === 'false' &&
|
||||
req.params.get('page_size') === '1000'
|
||||
req.url === `${environment.apiBaseUrl}tasks/status_counts/` &&
|
||||
req.params.get('acknowledged') === 'false'
|
||||
)
|
||||
.flush({ count: 0, results: [] })
|
||||
})
|
||||
|
||||
it('includes revoked tasks in needs attention', () => {
|
||||
const mockTasks = [
|
||||
{
|
||||
task_type: PaperlessTaskType.SanityCheck,
|
||||
trigger_source: PaperlessTaskTriggerSource.System,
|
||||
status: PaperlessTaskStatus.Failure,
|
||||
acknowledged: false,
|
||||
task_id: '1235',
|
||||
input_data: {},
|
||||
date_created: new Date(),
|
||||
related_document_ids: [],
|
||||
},
|
||||
{
|
||||
task_type: PaperlessTaskType.MailFetch,
|
||||
trigger_source: PaperlessTaskTriggerSource.Scheduled,
|
||||
status: PaperlessTaskStatus.Revoked,
|
||||
acknowledged: false,
|
||||
task_id: '1236',
|
||||
input_data: {},
|
||||
date_created: new Date(),
|
||||
related_document_ids: [],
|
||||
},
|
||||
{
|
||||
task_type: PaperlessTaskType.EmptyTrash,
|
||||
trigger_source: PaperlessTaskTriggerSource.Manual,
|
||||
status: PaperlessTaskStatus.Success,
|
||||
acknowledged: false,
|
||||
task_id: '1238',
|
||||
input_data: {},
|
||||
date_created: new Date(),
|
||||
related_document_ids: [],
|
||||
},
|
||||
]
|
||||
|
||||
tasksService.reload()
|
||||
|
||||
const req = httpTestingController.expectOne(
|
||||
(req: HttpRequest<unknown>) =>
|
||||
req.url === `${environment.apiBaseUrl}tasks/` &&
|
||||
req.params.get('acknowledged') === 'false' &&
|
||||
req.params.get('page_size') === '1000'
|
||||
)
|
||||
|
||||
req.flush({ count: mockTasks.length, results: mockTasks })
|
||||
|
||||
expect(tasksService.needsAttentionTasks).toHaveLength(2)
|
||||
expect(tasksService.needsAttentionTasks.map((task) => task.status)).toEqual(
|
||||
expect.arrayContaining([
|
||||
PaperlessTaskStatus.Failure,
|
||||
PaperlessTaskStatus.Revoked,
|
||||
])
|
||||
)
|
||||
.flush({ all: 0, needs_attention: 0, in_progress: 0, completed: 0 })
|
||||
})
|
||||
|
||||
it('supports running tasks', () => {
|
||||
|
||||
@@ -5,14 +5,12 @@ import {
|
||||
catchError,
|
||||
finalize,
|
||||
first,
|
||||
map,
|
||||
switchMap,
|
||||
takeUntil,
|
||||
tap,
|
||||
} from 'rxjs/operators'
|
||||
import {
|
||||
PaperlessTask,
|
||||
PaperlessTaskStatus,
|
||||
PaperlessTaskStatusCounts,
|
||||
PaperlessTaskType,
|
||||
} from 'src/app/data/paperless-task'
|
||||
@@ -27,50 +25,42 @@ export class TasksService {
|
||||
|
||||
private baseUrl: string = environment.apiBaseUrl
|
||||
private endpoint: string = 'tasks'
|
||||
private readonly defaultReloadPageSize = 1000
|
||||
|
||||
public loading: boolean = false
|
||||
|
||||
private readonly tasks = signal<PaperlessTask[]>([])
|
||||
private readonly tasksStatusCounts = signal<PaperlessTaskStatusCounts>({
|
||||
all: 0,
|
||||
needs_attention: 0,
|
||||
in_progress: 0,
|
||||
completed: 0,
|
||||
})
|
||||
private readonly reloadNotifier = new Subject<void>()
|
||||
|
||||
private unsubscribeNotifer: Subject<any> = new Subject()
|
||||
|
||||
constructor() {
|
||||
this.reloadNotifier
|
||||
.pipe(
|
||||
switchMap(() => {
|
||||
this.loading = true
|
||||
return this.http
|
||||
.get<Results<PaperlessTask>>(`${this.baseUrl}${this.endpoint}/`, {
|
||||
params: {
|
||||
acknowledged: 'false',
|
||||
page_size: this.defaultReloadPageSize,
|
||||
},
|
||||
})
|
||||
.pipe(
|
||||
map((response) => response.results),
|
||||
takeUntil(this.unsubscribeNotifer),
|
||||
catchError(() => EMPTY),
|
||||
finalize(() => {
|
||||
this.loading = false
|
||||
})
|
||||
)
|
||||
})
|
||||
)
|
||||
.subscribe((tasks) => {
|
||||
this.tasks.set(tasks)
|
||||
.pipe(switchMap(() => this.fetchUnacknowledgedTasksCounts()))
|
||||
.subscribe((taskStatusCounts) => {
|
||||
this.tasksStatusCounts.set(taskStatusCounts)
|
||||
})
|
||||
}
|
||||
|
||||
public get needsAttentionTasks(): PaperlessTask[] {
|
||||
return this.tasks().filter((t) =>
|
||||
[PaperlessTaskStatus.Failure, PaperlessTaskStatus.Revoked].includes(
|
||||
t.status
|
||||
)
|
||||
private fetchUnacknowledgedTasksCounts(): Observable<PaperlessTaskStatusCounts> {
|
||||
this.loading = true
|
||||
return this.statusCounts({ acknowledged: false }).pipe(
|
||||
takeUntil(this.unsubscribeNotifer),
|
||||
catchError(() => EMPTY),
|
||||
finalize(() => {
|
||||
this.loading = false
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
public get needsAttentionTasksCount(): number {
|
||||
return this.tasksStatusCounts().needs_attention
|
||||
}
|
||||
|
||||
public reload() {
|
||||
this.reloadNotifier.next()
|
||||
}
|
||||
@@ -105,7 +95,7 @@ export class TasksService {
|
||||
|
||||
public dismissTasks(task_ids: Set<number>): Observable<any> {
|
||||
return this.http
|
||||
.post(`${this.baseUrl}tasks/acknowledge/`, {
|
||||
.post(`${this.baseUrl}${this.endpoint}/acknowledge/`, {
|
||||
tasks: [...task_ids],
|
||||
})
|
||||
.pipe(
|
||||
@@ -119,7 +109,7 @@ export class TasksService {
|
||||
|
||||
public dismissAllTasks(): Observable<any> {
|
||||
return this.http
|
||||
.post(`${this.baseUrl}tasks/acknowledge/`, {
|
||||
.post(`${this.baseUrl}${this.endpoint}/acknowledge/`, {
|
||||
all: true,
|
||||
})
|
||||
.pipe(
|
||||
|
||||
@@ -11,8 +11,6 @@ from typing import TYPE_CHECKING
|
||||
|
||||
import pytest
|
||||
|
||||
from paperless_testing import samples
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Generator
|
||||
from pathlib import Path
|
||||
@@ -151,39 +149,3 @@ def fake_progress_manager(
|
||||
|
||||
monkeypatch.setattr("documents.tasks.ProgressManager", FakeProgressManager)
|
||||
return FakeProgressManager
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def shared_samples_dir() -> Path:
|
||||
"""Directory of sample files used by more than one app's tests."""
|
||||
return samples.SHARED_SAMPLES_DIR
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def simple_digital_pdf_file() -> Path:
|
||||
"""One-page PDF with a text layer."""
|
||||
return samples.SIMPLE_DIGITAL_PDF
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def multi_page_digital_pdf_file() -> Path:
|
||||
"""Three-page PDF with a text layer."""
|
||||
return samples.MULTI_PAGE_DIGITAL_PDF
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def with_form_pdf_file() -> Path:
|
||||
"""PDF containing a fillable form."""
|
||||
return samples.WITH_FORM_PDF
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def multi_page_images_pdf_file() -> Path:
|
||||
"""Multi-page PDF of scanned images, no text layer."""
|
||||
return samples.MULTI_PAGE_IMAGES_PDF
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def thumbnail_webp_file() -> Path:
|
||||
"""Small WebP thumbnail."""
|
||||
return samples.THUMBNAIL_WEBP
|
||||
@@ -12,25 +12,29 @@ if TYPE_CHECKING:
|
||||
from paperless_testing.dirs import PaperlessDirs
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def document_samples_dir() -> Path:
|
||||
"""Path to the shared test sample documents."""
|
||||
return Path(__file__).parent / "samples" / "documents"
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def sample_doc(
|
||||
paperless_dirs: "PaperlessDirs",
|
||||
simple_digital_pdf_file: Path,
|
||||
multi_page_images_pdf_file: Path,
|
||||
thumbnail_webp_file: Path,
|
||||
document_samples_dir: Path,
|
||||
) -> "Document":
|
||||
"""Create a document with valid files and matching checksums."""
|
||||
with filelock.FileLock(paperless_dirs.media_lock):
|
||||
shutil.copy(
|
||||
simple_digital_pdf_file,
|
||||
document_samples_dir / "originals" / "0000001.pdf",
|
||||
paperless_dirs.originals_dir / "0000001.pdf",
|
||||
)
|
||||
shutil.copy(
|
||||
multi_page_images_pdf_file,
|
||||
document_samples_dir / "archive" / "0000001.pdf",
|
||||
paperless_dirs.archive_dir / "0000001.pdf",
|
||||
)
|
||||
shutil.copy(
|
||||
thumbnail_webp_file,
|
||||
document_samples_dir / "thumbnails" / "0000001.webp",
|
||||
paperless_dirs.thumbnail_dir / "0000001.webp",
|
||||
)
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1 @@
|
||||
This is a test file.
|
||||
@@ -53,7 +53,7 @@ class TestBulkDownload(DirectoriesMixin, SampleDirMixin, APITestCase):
|
||||
archive_checksum="D",
|
||||
)
|
||||
|
||||
shutil.copy(self.SIMPLE_PDF, self.doc2.source_path)
|
||||
shutil.copy(self.SAMPLE_DIR / "simple.pdf", self.doc2.source_path)
|
||||
shutil.copy(self.SAMPLE_DIR / "simple.png", self.doc2b.source_path)
|
||||
shutil.copy(self.SAMPLE_DIR / "simple.jpg", self.doc3.source_path)
|
||||
shutil.copy(self.SAMPLE_DIR / "test_with_bom.pdf", self.doc3.archive_path)
|
||||
|
||||
@@ -46,6 +46,7 @@ from documents.models import UiSettings
|
||||
from documents.models import Workflow
|
||||
from documents.models import WorkflowAction
|
||||
from documents.models import WorkflowTrigger
|
||||
from documents.search import get_backend
|
||||
from documents.signals.handlers import run_workflows
|
||||
from documents.tests.utils import ConsumeTaskMixin
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
@@ -56,8 +57,6 @@ from paperless_testing.http import read_streaming_response
|
||||
from paperless_testing.permissions import grant_all_global
|
||||
from paperless_testing.permissions import grant_global
|
||||
from paperless_testing.permissions import grant_object
|
||||
from paperless_testing.samples import SIMPLE_DIGITAL_PDF
|
||||
from paperless_testing.samples import THUMBNAIL_WEBP
|
||||
|
||||
|
||||
class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
@@ -68,6 +67,70 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
self.client.force_authenticate(user=self.user)
|
||||
cache.clear()
|
||||
|
||||
def test_detail_save_indexes_final_workflow_state(self) -> None:
|
||||
viewer = UserFactory()
|
||||
grant_global(viewer, "view_document")
|
||||
inbox = TagFactory(is_inbox_tag=True)
|
||||
doc = DocumentFactory(owner=self.user, content="distinctiveword")
|
||||
doc.tags.add(inbox)
|
||||
trigger = WorkflowTrigger.objects.create(
|
||||
type=WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED,
|
||||
)
|
||||
action = WorkflowAction.objects.create(assign_title="Workflow title")
|
||||
action.assign_view_users.add(viewer)
|
||||
action.remove_view_users.add(viewer)
|
||||
workflow = Workflow.objects.create(name="Update document")
|
||||
workflow.triggers.add(trigger)
|
||||
workflow.actions.add(action)
|
||||
backend = get_backend()
|
||||
backend.add_or_update(doc)
|
||||
|
||||
for action_type in (
|
||||
WorkflowAction.WorkflowActionType.ASSIGNMENT,
|
||||
WorkflowAction.WorkflowActionType.REMOVAL,
|
||||
WorkflowAction.WorkflowActionType.MOVE_TO_TRASH,
|
||||
):
|
||||
with self.subTest(action_type=action_type):
|
||||
grant = action_type == WorkflowAction.WorkflowActionType.ASSIGNMENT
|
||||
action.type = action_type
|
||||
action.save()
|
||||
trigger.filter_has_not_tags.set([inbox] if grant else [])
|
||||
trigger.filter_has_tags.set([] if grant else [inbox])
|
||||
self.client.force_authenticate(self.user)
|
||||
response = self.client.patch(
|
||||
f"/api/documents/{doc.pk}/",
|
||||
{"tags": [] if grant else [inbox.pk]},
|
||||
format="json",
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.client.force_authenticate(viewer)
|
||||
self.assertEqual(
|
||||
self.client.get(f"/api/documents/{doc.pk}/").status_code,
|
||||
status.HTTP_200_OK if grant else status.HTTP_404_NOT_FOUND,
|
||||
)
|
||||
# Check the index directly: the API's DB permission filtering
|
||||
# would otherwise hide stale grants and trashed index entries.
|
||||
self.assertEqual(
|
||||
list(backend.search_ids("distinctiveword", user=viewer)),
|
||||
[doc.pk] if grant else [],
|
||||
)
|
||||
if grant:
|
||||
response = self.client.get(
|
||||
"/api/documents/",
|
||||
{"query": "distinctiveword AND title:workflow"},
|
||||
)
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(
|
||||
[result["id"] for result in response.data["results"]],
|
||||
[doc.pk],
|
||||
)
|
||||
elif action_type == WorkflowAction.WorkflowActionType.MOVE_TO_TRASH:
|
||||
self.assertFalse(Document.objects.filter(pk=doc.pk).exists())
|
||||
self.assertEqual(
|
||||
list(backend.search_ids("distinctiveword", user=None)),
|
||||
[],
|
||||
)
|
||||
|
||||
def testDocuments(self) -> None:
|
||||
response = self.client.get("/api/documents/").data
|
||||
|
||||
@@ -1854,11 +1917,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
id=str(uuid.uuid4()),
|
||||
)
|
||||
|
||||
with SimpleUploadedFile(
|
||||
"simple.pdf",
|
||||
SIMPLE_DIGITAL_PDF.read_bytes(),
|
||||
content_type="application/pdf",
|
||||
) as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{"document": f},
|
||||
@@ -1886,7 +1945,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
|
||||
payload = SimpleUploadedFile(
|
||||
"../../outside.pdf",
|
||||
SIMPLE_DIGITAL_PDF.read_bytes(),
|
||||
(Path(__file__).parent / "samples" / "simple.pdf").read_bytes(),
|
||||
content_type="application/pdf",
|
||||
)
|
||||
|
||||
@@ -1915,7 +1974,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
id=str(uuid.uuid4()),
|
||||
)
|
||||
|
||||
pdf_bytes = SIMPLE_DIGITAL_PDF.read_bytes()
|
||||
pdf_bytes = (Path(__file__).parent / "samples" / "simple.pdf").read_bytes()
|
||||
boundary = "paperless-boundary"
|
||||
payload = (
|
||||
(
|
||||
@@ -1991,7 +2050,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
def test_upload_insufficient_permissions(self) -> None:
|
||||
self.client.force_authenticate(user=UserFactory(username="testuser2"))
|
||||
|
||||
with SIMPLE_DIGITAL_PDF.open("rb") as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{"document": f},
|
||||
@@ -2004,11 +2063,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
id=str(uuid.uuid4()),
|
||||
)
|
||||
|
||||
with SimpleUploadedFile(
|
||||
"simple.pdf",
|
||||
SIMPLE_DIGITAL_PDF.read_bytes(),
|
||||
content_type="application/pdf",
|
||||
) as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{
|
||||
@@ -2041,7 +2096,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
id=str(uuid.uuid4()),
|
||||
)
|
||||
|
||||
with SIMPLE_DIGITAL_PDF.open("rb") as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{"documenst": f},
|
||||
@@ -2067,7 +2122,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
id=str(uuid.uuid4()),
|
||||
)
|
||||
|
||||
with SIMPLE_DIGITAL_PDF.open("rb") as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{"document": f, "title": "my custom title"},
|
||||
@@ -2087,7 +2142,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
)
|
||||
|
||||
c = Correspondent.objects.create(name="test-corres")
|
||||
with SIMPLE_DIGITAL_PDF.open("rb") as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{"document": f, "correspondent": c.id},
|
||||
@@ -2106,7 +2161,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
id=str(uuid.uuid4()),
|
||||
)
|
||||
|
||||
with SIMPLE_DIGITAL_PDF.open("rb") as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{"document": f, "correspondent": 3456},
|
||||
@@ -2121,7 +2176,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
)
|
||||
|
||||
dt = DocumentType.objects.create(name="invoice")
|
||||
with SIMPLE_DIGITAL_PDF.open("rb") as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{"document": f, "document_type": dt.id},
|
||||
@@ -2140,7 +2195,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
id=str(uuid.uuid4()),
|
||||
)
|
||||
|
||||
with SIMPLE_DIGITAL_PDF.open("rb") as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{"document": f, "document_type": 34578},
|
||||
@@ -2155,7 +2210,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
)
|
||||
|
||||
sp = StoragePath.objects.create(name="invoices")
|
||||
with SIMPLE_DIGITAL_PDF.open("rb") as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{"document": f, "storage_path": sp.id},
|
||||
@@ -2174,7 +2229,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
id=str(uuid.uuid4()),
|
||||
)
|
||||
|
||||
with SIMPLE_DIGITAL_PDF.open("rb") as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{"document": f, "storage_path": 34578},
|
||||
@@ -2190,7 +2245,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
|
||||
t1 = Tag.objects.create(name="tag1")
|
||||
t2 = Tag.objects.create(name="tag2")
|
||||
with SIMPLE_DIGITAL_PDF.open("rb") as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{"document": f, "tags": [t2.id, t1.id]},
|
||||
@@ -2211,7 +2266,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
|
||||
t1 = Tag.objects.create(name="tag1")
|
||||
t2 = Tag.objects.create(name="tag2")
|
||||
with SIMPLE_DIGITAL_PDF.open("rb") as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{"document": f, "tags": [t2.id, t1.id, 734563]},
|
||||
@@ -2235,7 +2290,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
0,
|
||||
tzinfo=zoneinfo.ZoneInfo("America/Los_Angeles"),
|
||||
)
|
||||
with SIMPLE_DIGITAL_PDF.open("rb") as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{"document": f, "created": created},
|
||||
@@ -2251,11 +2306,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
id=str(uuid.uuid4()),
|
||||
)
|
||||
|
||||
with SimpleUploadedFile(
|
||||
"simple.pdf",
|
||||
SIMPLE_DIGITAL_PDF.read_bytes(),
|
||||
content_type="application/pdf",
|
||||
) as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{"document": f, "archive_serial_number": 500},
|
||||
@@ -2282,11 +2333,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
data_type=CustomField.FieldDataType.STRING,
|
||||
)
|
||||
|
||||
with SimpleUploadedFile(
|
||||
"simple.pdf",
|
||||
SIMPLE_DIGITAL_PDF.read_bytes(),
|
||||
content_type="application/pdf",
|
||||
) as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{
|
||||
@@ -2341,7 +2388,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
w1.actions.add(action1)
|
||||
w1.save()
|
||||
|
||||
with SIMPLE_DIGITAL_PDF.open("rb") as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{
|
||||
@@ -2382,11 +2429,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
data_type=CustomField.FieldDataType.INT,
|
||||
)
|
||||
|
||||
with SimpleUploadedFile(
|
||||
"simple.pdf",
|
||||
SIMPLE_DIGITAL_PDF.read_bytes(),
|
||||
content_type="application/pdf",
|
||||
) as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{
|
||||
@@ -2435,7 +2478,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
]
|
||||
|
||||
for payload in error_payloads:
|
||||
with SIMPLE_DIGITAL_PDF.open("rb") as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
data = {"document": f, **payload}
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
@@ -2493,7 +2536,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
id=str(uuid.uuid4()),
|
||||
)
|
||||
|
||||
with SIMPLE_DIGITAL_PDF.open("rb") as f:
|
||||
with (Path(__file__).parent / "samples" / "simple.pdf").open("rb") as f:
|
||||
response = self.client.post(
|
||||
"/api/documents/post_document/",
|
||||
{"document": f, "from_webui": True},
|
||||
@@ -2532,8 +2575,14 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
archive_filename="archive.pdf",
|
||||
)
|
||||
|
||||
source_file: Path = THUMBNAIL_WEBP
|
||||
archive_file: Path = SIMPLE_DIGITAL_PDF
|
||||
source_file: Path = (
|
||||
Path(__file__).parent
|
||||
/ "samples"
|
||||
/ "documents"
|
||||
/ "thumbnails"
|
||||
/ "0000001.webp"
|
||||
)
|
||||
archive_file: Path = Path(__file__).parent / "samples" / "simple.pdf"
|
||||
|
||||
shutil.copy(source_file, doc.source_path)
|
||||
shutil.copy(archive_file, doc.archive_path)
|
||||
@@ -2566,7 +2615,7 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
mime_type="application/pdf",
|
||||
)
|
||||
|
||||
shutil.copy(SIMPLE_DIGITAL_PDF, doc.source_path)
|
||||
shutil.copy(Path(__file__).parent / "samples" / "simple.pdf", doc.source_path)
|
||||
|
||||
response = self.client.get(f"/api/documents/{doc.pk}/metadata/")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
@@ -4332,8 +4381,8 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase):
|
||||
filename="test2.pdf",
|
||||
)
|
||||
|
||||
archive_file = SIMPLE_DIGITAL_PDF
|
||||
source_file = SIMPLE_DIGITAL_PDF
|
||||
archive_file = Path(__file__).parent / "samples" / "simple.pdf"
|
||||
source_file = Path(__file__).parent / "samples" / "simple.pdf"
|
||||
|
||||
shutil.copy(archive_file, doc.archive_path)
|
||||
shutil.copy(source_file, doc2.source_path)
|
||||
|
||||
@@ -12,9 +12,6 @@ from documents.tests.utils import SampleDirMixin
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.permissions import grant_global
|
||||
from paperless_testing.samples import MULTI_PAGE_DIGITAL_PDF
|
||||
from paperless_testing.samples import SIMPLE_DIGITAL_PDF
|
||||
from paperless_testing.samples import WITH_FORM_PDF
|
||||
|
||||
|
||||
class TestEmail(DirectoriesMixin, SampleDirMixin, APITestCase):
|
||||
@@ -45,15 +42,15 @@ class TestEmail(DirectoriesMixin, SampleDirMixin, APITestCase):
|
||||
|
||||
# Copy sample files to document paths (using different files to distinguish versions)
|
||||
shutil.copy(
|
||||
SIMPLE_DIGITAL_PDF,
|
||||
self.SAMPLE_DIR / "documents" / "originals" / "0000001.pdf",
|
||||
self.doc1.archive_path,
|
||||
)
|
||||
shutil.copy(
|
||||
MULTI_PAGE_DIGITAL_PDF,
|
||||
self.SAMPLE_DIR / "documents" / "originals" / "0000002.pdf",
|
||||
self.doc1.source_path,
|
||||
)
|
||||
shutil.copy(
|
||||
WITH_FORM_PDF,
|
||||
self.SAMPLE_DIR / "documents" / "originals" / "0000003.pdf",
|
||||
self.doc2.source_path,
|
||||
)
|
||||
|
||||
@@ -380,7 +377,7 @@ class TestEmail(DirectoriesMixin, SampleDirMixin, APITestCase):
|
||||
checksum="3",
|
||||
filename="test3.pdf",
|
||||
)
|
||||
shutil.copy(self.SIMPLE_PDF, doc3.source_path)
|
||||
shutil.copy(self.SAMPLE_DIR / "simple.pdf", doc3.source_path)
|
||||
|
||||
doc4 = Document.objects.create(
|
||||
title="test1",
|
||||
@@ -389,7 +386,7 @@ class TestEmail(DirectoriesMixin, SampleDirMixin, APITestCase):
|
||||
checksum="4",
|
||||
filename="test4.pdf",
|
||||
)
|
||||
shutil.copy(self.SIMPLE_PDF, doc4.source_path)
|
||||
shutil.copy(self.SAMPLE_DIR / "simple.pdf", doc4.source_path)
|
||||
|
||||
response = self.client.post(
|
||||
self.ENDPOINT,
|
||||
|
||||
@@ -169,7 +169,7 @@ class TestBarcode(
|
||||
- No barcodes detected
|
||||
- No pages to split on
|
||||
"""
|
||||
test_file = self.SIMPLE_PDF
|
||||
test_file = self.SAMPLE_DIR / "simple.pdf"
|
||||
with self.get_reader(test_file) as reader:
|
||||
reader.detect()
|
||||
separator_page_numbers = reader.get_separation_pages()
|
||||
@@ -461,7 +461,7 @@ class TestBarcode(
|
||||
THEN:
|
||||
- Nothing happens
|
||||
"""
|
||||
test_file = self.SIMPLE_PDF
|
||||
test_file = self.SAMPLE_DIR / "simple.pdf"
|
||||
|
||||
with self.get_reader(test_file) as reader:
|
||||
try:
|
||||
|
||||
@@ -29,9 +29,6 @@ from documents.permissions import set_permissions_for_objects
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import DocumentFactory
|
||||
from paperless_testing.permissions import grant_object
|
||||
from paperless_testing.samples import MULTI_PAGE_DIGITAL_PDF
|
||||
from paperless_testing.samples import SIMPLE_DIGITAL_PDF
|
||||
from paperless_testing.samples import WITH_FORM_PDF
|
||||
|
||||
|
||||
class TestBulkEdit(DirectoriesMixin, TestCase):
|
||||
@@ -709,27 +706,47 @@ class TestPDFActions(DirectoriesMixin, TestCase):
|
||||
super().setUp()
|
||||
sample1 = self.dirs.scratch_dir / "sample.pdf"
|
||||
shutil.copy(
|
||||
SIMPLE_DIGITAL_PDF,
|
||||
Path(__file__).parent
|
||||
/ "samples"
|
||||
/ "documents"
|
||||
/ "originals"
|
||||
/ "0000001.pdf",
|
||||
sample1,
|
||||
)
|
||||
sample1_archive = self.dirs.archive_dir / "sample_archive.pdf"
|
||||
shutil.copy(
|
||||
SIMPLE_DIGITAL_PDF,
|
||||
Path(__file__).parent
|
||||
/ "samples"
|
||||
/ "documents"
|
||||
/ "originals"
|
||||
/ "0000001.pdf",
|
||||
sample1_archive,
|
||||
)
|
||||
sample2 = self.dirs.scratch_dir / "sample2.pdf"
|
||||
shutil.copy(
|
||||
MULTI_PAGE_DIGITAL_PDF,
|
||||
Path(__file__).parent
|
||||
/ "samples"
|
||||
/ "documents"
|
||||
/ "originals"
|
||||
/ "0000002.pdf",
|
||||
sample2,
|
||||
)
|
||||
sample2_archive = self.dirs.archive_dir / "sample2_archive.pdf"
|
||||
shutil.copy(
|
||||
MULTI_PAGE_DIGITAL_PDF,
|
||||
Path(__file__).parent
|
||||
/ "samples"
|
||||
/ "documents"
|
||||
/ "originals"
|
||||
/ "0000002.pdf",
|
||||
sample2_archive,
|
||||
)
|
||||
sample3 = self.dirs.scratch_dir / "sample3.pdf"
|
||||
shutil.copy(
|
||||
WITH_FORM_PDF,
|
||||
Path(__file__).parent
|
||||
/ "samples"
|
||||
/ "documents"
|
||||
/ "originals"
|
||||
/ "0000003.pdf",
|
||||
sample3,
|
||||
)
|
||||
self.doc1 = Document.objects.create(
|
||||
@@ -763,7 +780,11 @@ class TestPDFActions(DirectoriesMixin, TestCase):
|
||||
)
|
||||
img_doc_archive = self.dirs.archive_dir / "sample_image.pdf"
|
||||
shutil.copy(
|
||||
SIMPLE_DIGITAL_PDF,
|
||||
Path(__file__).parent
|
||||
/ "samples"
|
||||
/ "documents"
|
||||
/ "originals"
|
||||
/ "0000001.pdf",
|
||||
img_doc_archive,
|
||||
)
|
||||
self.img_doc = Document.objects.create(
|
||||
|
||||
@@ -39,9 +39,6 @@ from paperless_testing.factories import TagFactory
|
||||
from paperless_testing.factories import UserFactory
|
||||
from paperless_testing.fakes.progress import FakeProgressManager
|
||||
from paperless_testing.permissions import grant_object
|
||||
from paperless_testing.samples import MULTI_PAGE_DIGITAL_PDF
|
||||
from paperless_testing.samples import MULTI_PAGE_IMAGES_PDF
|
||||
from paperless_testing.samples import SIMPLE_DIGITAL_PDF
|
||||
|
||||
|
||||
class _BaseNewStyleParser:
|
||||
@@ -118,7 +115,9 @@ class _BaseNewStyleParser:
|
||||
|
||||
|
||||
class DummyParser(_BaseNewStyleParser):
|
||||
_ARCHIVE_SRC = MULTI_PAGE_IMAGES_PDF
|
||||
_ARCHIVE_SRC = (
|
||||
Path(__file__).parent / "samples" / "documents" / "archive" / "0000001.pdf"
|
||||
)
|
||||
|
||||
def parse(self, document_path, mime_type, *, produce_archive: bool = True) -> None:
|
||||
self._text = "The Text"
|
||||
@@ -204,19 +203,33 @@ class TestConsumer(
|
||||
self.addCleanup(patcher.stop)
|
||||
|
||||
def get_test_file(self):
|
||||
src = SIMPLE_DIGITAL_PDF
|
||||
src = (
|
||||
Path(__file__).parent
|
||||
/ "samples"
|
||||
/ "documents"
|
||||
/ "originals"
|
||||
/ "0000001.pdf"
|
||||
)
|
||||
dst = self.dirs.scratch_dir / "sample.pdf"
|
||||
shutil.copy(src, dst)
|
||||
return dst
|
||||
|
||||
def get_test_file2(self):
|
||||
src = MULTI_PAGE_DIGITAL_PDF
|
||||
src = (
|
||||
Path(__file__).parent
|
||||
/ "samples"
|
||||
/ "documents"
|
||||
/ "originals"
|
||||
/ "0000002.pdf"
|
||||
)
|
||||
dst = self.dirs.scratch_dir / "sample2.pdf"
|
||||
shutil.copy(src, dst)
|
||||
return dst
|
||||
|
||||
def get_test_archive_file(self):
|
||||
src = MULTI_PAGE_IMAGES_PDF
|
||||
src = (
|
||||
Path(__file__).parent / "samples" / "documents" / "archive" / "0000001.pdf"
|
||||
)
|
||||
dst = self.dirs.scratch_dir / "sample_archive.pdf"
|
||||
shutil.copy(src, dst)
|
||||
return dst
|
||||
@@ -1111,7 +1124,7 @@ class TestConsumer(
|
||||
@mock.patch("documents.consumer.get_parser_registry")
|
||||
def test_similar_filenames(self, m) -> None:
|
||||
shutil.copy(
|
||||
SIMPLE_DIGITAL_PDF,
|
||||
Path(__file__).parent / "samples" / "simple.pdf",
|
||||
settings.CONSUMPTION_DIR / "simple.pdf",
|
||||
)
|
||||
shutil.copy(
|
||||
@@ -1652,7 +1665,13 @@ class TestConsumerRemoteOCR(
|
||||
self.addCleanup(patcher.stop)
|
||||
|
||||
def _consume(self, *, overrides: DocumentMetadataOverrides | None = None) -> bool:
|
||||
src = SIMPLE_DIGITAL_PDF
|
||||
src = (
|
||||
Path(__file__).parent
|
||||
/ "samples"
|
||||
/ "documents"
|
||||
/ "originals"
|
||||
/ "0000001.pdf"
|
||||
)
|
||||
dst = self.dirs.scratch_dir / "sample.pdf"
|
||||
shutil.copy(src, dst)
|
||||
|
||||
|
||||
@@ -37,15 +37,12 @@ class TestDoubleSided(
|
||||
self.double_sided_dir.mkdir()
|
||||
self.staging_file = self.dirs.scratch_dir / STAGING_FILE_NAME
|
||||
|
||||
def _sample(self, name: str) -> Path:
|
||||
return self.SIMPLE_PDF if name == "simple.pdf" else self.SAMPLE_DIR / name
|
||||
|
||||
def consume_file(self, srcname, dstname: str | Path = "foo.pdf"):
|
||||
"""
|
||||
Starts the consume process and also ensures the
|
||||
destination file does not exist afterwards
|
||||
"""
|
||||
src = self._sample(srcname)
|
||||
src = self.SAMPLE_DIR / srcname
|
||||
dst = self.double_sided_dir / dstname
|
||||
dst.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy(src, dst)
|
||||
@@ -60,7 +57,7 @@ class TestDoubleSided(
|
||||
return msg
|
||||
|
||||
def create_staging_file(self, src="double-sided-odd.pdf", datetime=None) -> None:
|
||||
shutil.copy(self._sample(src), self.staging_file)
|
||||
shutil.copy(self.SAMPLE_DIR / src, self.staging_file)
|
||||
if datetime is None:
|
||||
datetime = dt.datetime.now()
|
||||
os.utime(str(self.staging_file), (datetime.timestamp(),) * 2)
|
||||
|
||||
@@ -23,9 +23,8 @@ from documents.tasks import update_document_content_maybe_archive_file
|
||||
from paperless_testing.assertions import FileSystemAssertsMixin
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import DocumentFactory
|
||||
from paperless_testing.samples import SIMPLE_DIGITAL_PDF
|
||||
|
||||
sample_file: Path = SIMPLE_DIGITAL_PDF
|
||||
sample_file: Path = Path(__file__).parent / "samples" / "simple.pdf"
|
||||
|
||||
|
||||
@pytest.mark.management
|
||||
|
||||
@@ -59,7 +59,6 @@ from paperless_testing.dirs import paperless_environment
|
||||
from paperless_testing.factories import DocumentBarcodeFactory
|
||||
from paperless_testing.factories import DocumentFactory
|
||||
from paperless_testing.permissions import grant_object
|
||||
from paperless_testing.samples import install_document_samples
|
||||
|
||||
|
||||
@pytest.mark.management
|
||||
@@ -205,7 +204,10 @@ class TestExportImport(
|
||||
|
||||
def test_exporter(self, *, use_filename_format=False) -> None:
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
num_permission_objects = Permission.objects.count()
|
||||
|
||||
@@ -309,7 +311,10 @@ class TestExportImport(
|
||||
|
||||
def test_exporter_with_filename_format(self) -> None:
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
with override_settings(
|
||||
FILENAME_FORMAT="{created_year}/{correspondent}/{title}",
|
||||
@@ -318,7 +323,10 @@ class TestExportImport(
|
||||
|
||||
def test_exporter_includes_share_links_and_bundles(self) -> None:
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
share_link = ShareLink.objects.create(
|
||||
slug="share-link-slug",
|
||||
@@ -417,7 +425,10 @@ class TestExportImport(
|
||||
|
||||
def test_update_export_changed_time(self) -> None:
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
self._do_export()
|
||||
self.assertIsFile(self.target / "manifest.json")
|
||||
@@ -453,7 +464,10 @@ class TestExportImport(
|
||||
|
||||
def test_update_export_changed_checksum(self) -> None:
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
self._do_export()
|
||||
|
||||
@@ -480,7 +494,10 @@ class TestExportImport(
|
||||
|
||||
def test_update_export_deleted_document(self) -> None:
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
manifest = self._do_export()
|
||||
|
||||
@@ -512,7 +529,10 @@ class TestExportImport(
|
||||
@override_settings(FILENAME_FORMAT="{title}/{correspondent}")
|
||||
def test_update_export_changed_location(self) -> None:
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
self._do_export(use_filename_format=True)
|
||||
self.assertIsFile(self.target / "wow1" / "c.pdf")
|
||||
@@ -554,7 +574,10 @@ class TestExportImport(
|
||||
- Zipfile contains exported files
|
||||
"""
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
args = ["document_exporter", self.target, "--zip"]
|
||||
|
||||
@@ -583,7 +606,10 @@ class TestExportImport(
|
||||
- Zipfile contains exported files
|
||||
"""
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
args = ["document_exporter", self.target, "--zip", "--use-filename-format"]
|
||||
|
||||
@@ -619,7 +645,10 @@ class TestExportImport(
|
||||
- The existing file and directory in target are removed
|
||||
"""
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
# Create stuff in target directory
|
||||
existing_file = self.target / "test.txt"
|
||||
@@ -715,7 +744,10 @@ class TestExportImport(
|
||||
- Documents can be imported again
|
||||
"""
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
manifest = self._do_export()
|
||||
has_archive = False
|
||||
@@ -758,7 +790,10 @@ class TestExportImport(
|
||||
- Documents can be imported again
|
||||
"""
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
manifest = self._do_export()
|
||||
has_thumbnail = False
|
||||
@@ -803,7 +838,10 @@ class TestExportImport(
|
||||
- Documents can be imported again
|
||||
"""
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
manifest = self._do_export(split_manifest=True)
|
||||
has_document = False
|
||||
@@ -828,7 +866,10 @@ class TestExportImport(
|
||||
|
||||
def _export_import_barcodes(self, *, split_manifest: bool) -> None:
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
DocumentBarcodeFactory(document=self.d1, value="https://example.com")
|
||||
DocumentBarcodeFactory(document=self.d2, page=2, value="DE8937")
|
||||
|
||||
@@ -864,7 +905,10 @@ class TestExportImport(
|
||||
- Documents can be imported again
|
||||
"""
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
self._do_export(use_folder_prefix=True)
|
||||
|
||||
@@ -891,7 +935,10 @@ class TestExportImport(
|
||||
- Documents can be imported again
|
||||
"""
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
self._do_export(use_folder_prefix=True, split_manifest=True)
|
||||
|
||||
@@ -918,7 +965,10 @@ class TestExportImport(
|
||||
"""
|
||||
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
num_content_type_objects = ContentType.objects.count()
|
||||
num_permission_objects = Permission.objects.count()
|
||||
@@ -955,7 +1005,10 @@ class TestExportImport(
|
||||
|
||||
def test_exporter_with_auditlog_disabled(self) -> None:
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
with override_settings(
|
||||
AUDIT_LOG_ENABLED=False,
|
||||
@@ -975,7 +1028,10 @@ class TestExportImport(
|
||||
survive the round-trip with deleted_at preserved
|
||||
"""
|
||||
shutil.rmtree(Path(self.dirs.media_dir) / "documents")
|
||||
install_document_samples(Path(self.dirs.media_dir) / "documents")
|
||||
shutil.copytree(
|
||||
Path(__file__).parent / "samples" / "documents",
|
||||
Path(self.dirs.media_dir) / "documents",
|
||||
)
|
||||
|
||||
# d1 has self.note and self.cfi1 attached via setUp
|
||||
self.d1.delete()
|
||||
@@ -1019,7 +1075,10 @@ class TestExportImport(
|
||||
"""
|
||||
|
||||
shutil.rmtree(self.dirs.media_dir / "documents")
|
||||
install_document_samples(self.dirs.media_dir / "documents")
|
||||
shutil.copytree(
|
||||
self.SAMPLE_DIR / "documents",
|
||||
self.dirs.media_dir / "documents",
|
||||
)
|
||||
|
||||
_ = self._do_export(data_only=True)
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ from documents.models import Document
|
||||
from documents.parsers import get_default_thumbnail
|
||||
from paperless_testing.assertions import FileSystemAssertsMixin
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.samples import SIMPLE_DIGITAL_PDF
|
||||
|
||||
|
||||
@pytest.mark.management
|
||||
@@ -25,7 +24,7 @@ class TestMakeThumbnails(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
|
||||
filename="test.pdf",
|
||||
)
|
||||
shutil.copy(
|
||||
SIMPLE_DIGITAL_PDF,
|
||||
Path(__file__).parent / "samples" / "simple.pdf",
|
||||
self.d1.source_path,
|
||||
)
|
||||
|
||||
@@ -37,7 +36,7 @@ class TestMakeThumbnails(DirectoriesMixin, FileSystemAssertsMixin, TestCase):
|
||||
filename="test2.pdf",
|
||||
)
|
||||
shutil.copy(
|
||||
SIMPLE_DIGITAL_PDF,
|
||||
Path(__file__).parent / "samples" / "simple.pdf",
|
||||
self.d2.source_path,
|
||||
)
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ from documents.tests.helpers import dummy_preprocess
|
||||
from paperless_testing.assertions import FileSystemAssertsMixin
|
||||
from paperless_testing.dirs import DirectoriesMixin
|
||||
from paperless_testing.factories import DocumentFactory
|
||||
from paperless_testing.samples import SIMPLE_DIGITAL_PDF
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -230,12 +229,20 @@ class TestUpdateContent(DirectoriesMixin, TestCase):
|
||||
"""
|
||||
sample1 = self.dirs.scratch_dir / "sample.pdf"
|
||||
shutil.copy(
|
||||
SIMPLE_DIGITAL_PDF,
|
||||
Path(__file__).parent
|
||||
/ "samples"
|
||||
/ "documents"
|
||||
/ "originals"
|
||||
/ "0000001.pdf",
|
||||
sample1,
|
||||
)
|
||||
sample1_archive = self.dirs.archive_dir / "sample_archive.pdf"
|
||||
shutil.copy(
|
||||
SIMPLE_DIGITAL_PDF,
|
||||
Path(__file__).parent
|
||||
/ "samples"
|
||||
/ "documents"
|
||||
/ "originals"
|
||||
/ "0000001.pdf",
|
||||
sample1_archive,
|
||||
)
|
||||
doc = Document.objects.create(
|
||||
@@ -263,7 +270,11 @@ class TestUpdateContent(DirectoriesMixin, TestCase):
|
||||
"""
|
||||
sample1 = self.dirs.scratch_dir / "sample.pdf"
|
||||
shutil.copy(
|
||||
SIMPLE_DIGITAL_PDF,
|
||||
Path(__file__).parent
|
||||
/ "samples"
|
||||
/ "documents"
|
||||
/ "originals"
|
||||
/ "0000001.pdf",
|
||||
sample1,
|
||||
)
|
||||
doc = Document.objects.create(
|
||||
@@ -279,7 +290,14 @@ class TestUpdateContent(DirectoriesMixin, TestCase):
|
||||
|
||||
def _create_root_with_version(self) -> tuple[Document, Document]:
|
||||
sample1 = self.dirs.scratch_dir / "sample.pdf"
|
||||
shutil.copy(SIMPLE_DIGITAL_PDF, sample1)
|
||||
shutil.copy(
|
||||
Path(__file__).parent
|
||||
/ "samples"
|
||||
/ "documents"
|
||||
/ "originals"
|
||||
/ "0000001.pdf",
|
||||
sample1,
|
||||
)
|
||||
root = DocumentFactory(content="root content", mime_type="application/pdf")
|
||||
version = DocumentFactory(
|
||||
content="my document",
|
||||
|
||||
@@ -178,7 +178,7 @@ class TestWorkflows(
|
||||
self.assertEqual(action.__str__(), "WorkflowAction 1")
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -290,7 +290,7 @@ class TestWorkflows(
|
||||
w.save()
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -409,7 +409,7 @@ class TestWorkflows(
|
||||
w2.save()
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -478,7 +478,7 @@ class TestWorkflows(
|
||||
w.save()
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -531,7 +531,7 @@ class TestWorkflows(
|
||||
w.save()
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -608,7 +608,7 @@ class TestWorkflows(
|
||||
w.save()
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -687,7 +687,7 @@ class TestWorkflows(
|
||||
w.save()
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -765,7 +765,7 @@ class TestWorkflows(
|
||||
w.save()
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -876,7 +876,7 @@ class TestWorkflows(
|
||||
w.save()
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -928,7 +928,7 @@ class TestWorkflows(
|
||||
generated = generate_unique_filename(doc)
|
||||
destination = (settings.ORIGINALS_DIR / generated).resolve()
|
||||
create_source_path_directory(destination)
|
||||
shutil.copy(self.SIMPLE_PDF, destination)
|
||||
shutil.copy(self.SAMPLE_DIR / "simple.pdf", destination)
|
||||
Document.objects.filter(pk=doc.pk).update(filename=generated.as_posix())
|
||||
doc.refresh_from_db()
|
||||
|
||||
@@ -2023,7 +2023,7 @@ class TestWorkflows(
|
||||
superuser = UserFactory(username="superuser", superuser=True)
|
||||
self.client.force_authenticate(user=superuser)
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
tasks.consume_file(
|
||||
@@ -3009,7 +3009,7 @@ class TestWorkflows(
|
||||
generated = generate_unique_filename(doc)
|
||||
destination = (settings.ORIGINALS_DIR / generated).resolve()
|
||||
create_source_path_directory(destination)
|
||||
shutil.copy(self.SIMPLE_PDF, destination)
|
||||
shutil.copy(self.SAMPLE_DIR / "simple.pdf", destination)
|
||||
Document.objects.filter(pk=doc.pk).update(filename=generated.as_posix())
|
||||
doc.refresh_from_db()
|
||||
doc.tags.set([self.t1, self.t2])
|
||||
@@ -3073,7 +3073,7 @@ class TestWorkflows(
|
||||
generated = generate_unique_filename(doc)
|
||||
destination = (settings.ORIGINALS_DIR / generated).resolve()
|
||||
create_source_path_directory(destination)
|
||||
shutil.copy(self.SIMPLE_PDF, destination)
|
||||
shutil.copy(self.SAMPLE_DIR / "simple.pdf", destination)
|
||||
Document.objects.filter(pk=doc.pk).update(filename=generated.as_posix())
|
||||
doc.refresh_from_db()
|
||||
doc.tags.set([self.t1])
|
||||
@@ -3222,7 +3222,7 @@ class TestWorkflows(
|
||||
w.save()
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -3346,7 +3346,7 @@ class TestWorkflows(
|
||||
w.save()
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -3496,7 +3496,7 @@ class TestWorkflows(
|
||||
workflow.actions.set([assignment_action, email_action])
|
||||
|
||||
temp_working_copy = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "working-copy.pdf",
|
||||
)
|
||||
|
||||
@@ -3596,7 +3596,7 @@ class TestWorkflows(
|
||||
|
||||
# move the file
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -3704,7 +3704,7 @@ class TestWorkflows(
|
||||
generated = generate_unique_filename(doc)
|
||||
destination = (settings.ORIGINALS_DIR / generated).resolve()
|
||||
create_source_path_directory(destination)
|
||||
shutil.copy(self.SIMPLE_PDF, destination)
|
||||
shutil.copy(self.SAMPLE_DIR / "simple.pdf", destination)
|
||||
Document.objects.filter(pk=doc.pk).update(filename=generated.as_posix())
|
||||
|
||||
run_workflows(WorkflowTrigger.WorkflowTriggerType.DOCUMENT_UPDATED, doc)
|
||||
@@ -3915,7 +3915,7 @@ class TestWorkflows(
|
||||
w.save()
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -4036,7 +4036,7 @@ class TestWorkflows(
|
||||
w.save()
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -4387,7 +4387,7 @@ class TestWorkflows(
|
||||
w.save()
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -4835,7 +4835,7 @@ class TestWorkflows(
|
||||
w.save()
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -5027,7 +5027,7 @@ class TestWorkflows(
|
||||
|
||||
# Create a test file to be consumed
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
test_file_path = Path(test_file)
|
||||
@@ -5091,7 +5091,7 @@ class TestWorkflows(
|
||||
|
||||
# Create a test file to be consumed
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple2.pdf",
|
||||
)
|
||||
test_file_path = Path(test_file)
|
||||
@@ -5529,7 +5529,7 @@ class TestDateWorkflowLocalization(
|
||||
)
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
tmp_path / "simple.pdf",
|
||||
)
|
||||
|
||||
@@ -5596,7 +5596,7 @@ class TestRemoteOCRWorkflowAction(DirectoriesMixin, SampleDirMixin, APITestCase)
|
||||
self._make_workflow(WorkflowTrigger.WorkflowTriggerType.CONSUMPTION)
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
overrides = DocumentMetadataOverrides()
|
||||
@@ -5814,7 +5814,7 @@ class TestApplyAISuggestionsWorkflowAction(
|
||||
)
|
||||
|
||||
test_file = shutil.copy(
|
||||
self.SIMPLE_PDF,
|
||||
self.SAMPLE_DIR / "simple.pdf",
|
||||
self.dirs.scratch_dir / "simple.pdf",
|
||||
)
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ from documents.data_models import ConsumableDocument
|
||||
from documents.data_models import DocumentMetadataOverrides
|
||||
from documents.data_models import DocumentSource
|
||||
from paperless_testing.fakes.progress import FakeProgressManager
|
||||
from paperless_testing.samples import SIMPLE_DIGITAL_PDF
|
||||
|
||||
|
||||
class ConsumeTaskMixin:
|
||||
@@ -54,8 +53,6 @@ class SampleDirMixin:
|
||||
|
||||
BARCODE_SAMPLE_DIR = SAMPLE_DIR / "barcodes"
|
||||
|
||||
SIMPLE_PDF = SIMPLE_DIGITAL_PDF
|
||||
|
||||
|
||||
class GetConsumerMixin:
|
||||
@contextmanager
|
||||
|
||||
@@ -1304,13 +1304,19 @@ class DocumentViewSet(
|
||||
|
||||
from documents.search import get_backend
|
||||
|
||||
get_backend().add_or_update(refreshed_doc)
|
||||
|
||||
document_updated.send(
|
||||
sender=self.__class__,
|
||||
document=refreshed_doc,
|
||||
)
|
||||
|
||||
# Index the final workflow state, including deletion.
|
||||
backend = get_backend()
|
||||
final_doc = Document.objects.filter(pk=root_doc.pk).first()
|
||||
if final_doc is None:
|
||||
backend.remove(root_doc.pk)
|
||||
else:
|
||||
backend.add_or_update(final_doc)
|
||||
|
||||
return response
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
|
||||
@@ -432,6 +432,30 @@ def tesseract_samples_dir(parser_samples_dir: Path) -> Path:
|
||||
return parser_samples_dir / "tesseract"
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def multi_page_images_pdf_file(tesseract_samples_dir: Path) -> Path:
|
||||
"""Path to a multi-page PDF with images.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Path
|
||||
Absolute path to ``tesseract/multi-page-images.pdf``.
|
||||
"""
|
||||
return tesseract_samples_dir / "multi-page-images.pdf"
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def simple_digital_pdf_file(tesseract_samples_dir: Path) -> Path:
|
||||
"""Path to a simple digital PDF sample file.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Path
|
||||
Absolute path to ``tesseract/simple-digital.pdf``.
|
||||
"""
|
||||
return tesseract_samples_dir / "simple-digital.pdf"
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def simple_no_dpi_png_file(tesseract_samples_dir: Path) -> Path:
|
||||
"""Path to a simple PNG without DPI information.
|
||||
@@ -456,18 +480,6 @@ def simple_png_file(tesseract_samples_dir: Path) -> Path:
|
||||
return tesseract_samples_dir / "simple.png"
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def rotated_pdf_file(tesseract_samples_dir: Path) -> Path:
|
||||
"""Path to a landscape (rotated) PDF sample file.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Path
|
||||
Absolute path to ``tesseract/rotated.pdf``.
|
||||
"""
|
||||
return tesseract_samples_dir / "rotated.pdf"
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Tesseract parser instance and settings helpers
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
@@ -161,11 +161,11 @@ class TestGetPageCount:
|
||||
def test_single_page_pdf(
|
||||
self,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
simple_digital_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
assert (
|
||||
tesseract_parser.get_page_count(
|
||||
simple_digital_pdf_file,
|
||||
tesseract_samples_dir / "simple-digital.pdf",
|
||||
"application/pdf",
|
||||
)
|
||||
== 1
|
||||
@@ -188,7 +188,7 @@ class TestGetPageCount:
|
||||
self,
|
||||
mocker: MockerFixture,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
simple_digital_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
caplog,
|
||||
) -> None:
|
||||
"""
|
||||
@@ -204,7 +204,7 @@ class TestGetPageCount:
|
||||
|
||||
with caplog.at_level(logging.WARNING):
|
||||
page_count = tesseract_parser.get_page_count(
|
||||
simple_digital_pdf_file,
|
||||
tesseract_samples_dir / "simple-digital.pdf",
|
||||
"application/pdf",
|
||||
)
|
||||
assert page_count is None
|
||||
@@ -273,26 +273,26 @@ class TestGetThumbnail:
|
||||
def test_thumbnail_is_file(
|
||||
self,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
simple_digital_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
thumb = tesseract_parser.get_thumbnail(
|
||||
simple_digital_pdf_file,
|
||||
tesseract_samples_dir / "simple-digital.pdf",
|
||||
"application/pdf",
|
||||
)
|
||||
assert thumb.is_file()
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("sample_fixture", "expected_height"),
|
||||
("filename", "expected_height"),
|
||||
[
|
||||
pytest.param("simple_digital_pdf_file", 647, id="portrait-letter"),
|
||||
pytest.param("rotated_pdf_file", 386, id="landscape"),
|
||||
pytest.param("simple-digital.pdf", 647, id="portrait-letter"),
|
||||
pytest.param("rotated.pdf", 386, id="landscape"),
|
||||
],
|
||||
)
|
||||
def test_thumbnail_is_correct_format_and_size(
|
||||
self,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
request: pytest.FixtureRequest,
|
||||
sample_fixture: str,
|
||||
tesseract_samples_dir: Path,
|
||||
filename: str,
|
||||
expected_height: int,
|
||||
) -> None:
|
||||
"""
|
||||
@@ -304,7 +304,7 @@ class TestGetThumbnail:
|
||||
- A 500px wide WebP keeping the page's aspect ratio
|
||||
"""
|
||||
thumb = tesseract_parser.get_thumbnail(
|
||||
request.getfixturevalue(sample_fixture),
|
||||
tesseract_samples_dir / filename,
|
||||
"application/pdf",
|
||||
)
|
||||
with Image.open(thumb) as im:
|
||||
@@ -316,7 +316,7 @@ class TestGetThumbnail:
|
||||
self,
|
||||
mocker: MockerFixture,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
simple_digital_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
@@ -326,7 +326,7 @@ class TestGetThumbnail:
|
||||
THEN:
|
||||
- The PDF is repaired with qpdf and a real thumbnail is rendered
|
||||
"""
|
||||
original = simple_digital_pdf_file
|
||||
original = tesseract_samples_dir / "simple-digital.pdf"
|
||||
|
||||
def _fail_on_original(in_path: Path, out_path: Path, **kwargs) -> None:
|
||||
if in_path == original:
|
||||
@@ -368,11 +368,11 @@ class TestExtractText:
|
||||
def test_extract_text_from_digital_pdf(
|
||||
self,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
simple_digital_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
text = tesseract_parser.extract_text(
|
||||
None,
|
||||
simple_digital_pdf_file,
|
||||
tesseract_samples_dir / "simple-digital.pdf",
|
||||
)
|
||||
assert text is not None
|
||||
assert "This is a test document." in text.strip()
|
||||
@@ -387,7 +387,7 @@ class TestParsePdf:
|
||||
def test_simple_digital_creates_archive(
|
||||
self,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
multi_page_digital_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
@@ -401,7 +401,7 @@ class TestParsePdf:
|
||||
- Text is extracted
|
||||
"""
|
||||
tesseract_parser.parse(
|
||||
multi_page_digital_pdf_file,
|
||||
tesseract_samples_dir / "multi-page-digital.pdf",
|
||||
"application/pdf",
|
||||
)
|
||||
assert tesseract_parser.archive_path is not None
|
||||
@@ -416,10 +416,10 @@ class TestParsePdf:
|
||||
def test_with_form_default(
|
||||
self,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
with_form_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
tesseract_parser.parse(
|
||||
with_form_pdf_file,
|
||||
tesseract_samples_dir / "with-form.pdf",
|
||||
"application/pdf",
|
||||
)
|
||||
assert tesseract_parser.archive_path is not None
|
||||
@@ -432,11 +432,11 @@ class TestParsePdf:
|
||||
def test_with_form_redo_no_archive_when_not_requested(
|
||||
self,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
with_form_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
tesseract_parser.settings.mode = ModeChoices.REDO
|
||||
tesseract_parser.parse(
|
||||
with_form_pdf_file,
|
||||
tesseract_samples_dir / "with-form.pdf",
|
||||
"application/pdf",
|
||||
produce_archive=False,
|
||||
)
|
||||
@@ -449,11 +449,11 @@ class TestParsePdf:
|
||||
def test_with_form_force(
|
||||
self,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
with_form_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
tesseract_parser.settings.mode = ModeChoices.FORCE
|
||||
tesseract_parser.parse(
|
||||
with_form_pdf_file,
|
||||
tesseract_samples_dir / "with-form.pdf",
|
||||
"application/pdf",
|
||||
)
|
||||
assert_ordered_substrings(
|
||||
@@ -494,7 +494,7 @@ class TestParsePdf:
|
||||
self,
|
||||
mocker: MockerFixture,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
simple_digital_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
mocker.patch(
|
||||
"ocrmypdf.ocr",
|
||||
@@ -502,7 +502,7 @@ class TestParsePdf:
|
||||
)
|
||||
with pytest.raises(ParseError):
|
||||
tesseract_parser.parse(
|
||||
simple_digital_pdf_file,
|
||||
tesseract_samples_dir / "simple-digital.pdf",
|
||||
"application/pdf",
|
||||
)
|
||||
|
||||
@@ -578,10 +578,10 @@ class TestParseMultiPage:
|
||||
def test_multi_page_digital(
|
||||
self,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
multi_page_digital_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
tesseract_parser.parse(
|
||||
multi_page_digital_pdf_file,
|
||||
tesseract_samples_dir / "multi-page-digital.pdf",
|
||||
"application/pdf",
|
||||
)
|
||||
assert tesseract_parser.archive_path is not None
|
||||
@@ -605,12 +605,12 @@ class TestParseMultiPage:
|
||||
self,
|
||||
mode: str,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
multi_page_digital_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
tesseract_parser.settings.pages = 2
|
||||
tesseract_parser.settings.mode = mode
|
||||
tesseract_parser.parse(
|
||||
multi_page_digital_pdf_file,
|
||||
tesseract_samples_dir / "multi-page-digital.pdf",
|
||||
"application/pdf",
|
||||
)
|
||||
assert tesseract_parser.archive_path is not None
|
||||
@@ -624,11 +624,11 @@ class TestParseMultiPage:
|
||||
def test_multi_page_images_skip(
|
||||
self,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
multi_page_images_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
tesseract_parser.settings.mode = ModeChoices.AUTO
|
||||
tesseract_parser.parse(
|
||||
multi_page_images_pdf_file,
|
||||
tesseract_samples_dir / "multi-page-images.pdf",
|
||||
"application/pdf",
|
||||
)
|
||||
assert tesseract_parser.archive_path is not None
|
||||
@@ -642,7 +642,7 @@ class TestParseMultiPage:
|
||||
def test_multi_page_images_redo_pages_2(
|
||||
self,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
multi_page_images_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
@@ -657,7 +657,7 @@ class TestParseMultiPage:
|
||||
tesseract_parser.settings.pages = 2
|
||||
tesseract_parser.settings.mode = ModeChoices.REDO
|
||||
tesseract_parser.parse(
|
||||
multi_page_images_pdf_file,
|
||||
tesseract_samples_dir / "multi-page-images.pdf",
|
||||
"application/pdf",
|
||||
)
|
||||
assert tesseract_parser.archive_path is not None
|
||||
@@ -670,7 +670,7 @@ class TestParseMultiPage:
|
||||
def test_multi_page_images_force_page_1(
|
||||
self,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
multi_page_images_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
@@ -685,7 +685,7 @@ class TestParseMultiPage:
|
||||
tesseract_parser.settings.pages = 1
|
||||
tesseract_parser.settings.mode = ModeChoices.FORCE
|
||||
tesseract_parser.parse(
|
||||
multi_page_images_pdf_file,
|
||||
tesseract_samples_dir / "multi-page-images.pdf",
|
||||
"application/pdf",
|
||||
)
|
||||
assert tesseract_parser.archive_path is not None
|
||||
@@ -781,7 +781,7 @@ class TestSkipArchive:
|
||||
def test_skip_noarchive_with_text_layer(
|
||||
self,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
multi_page_digital_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
@@ -795,7 +795,7 @@ class TestSkipArchive:
|
||||
"""
|
||||
tesseract_parser.settings.mode = ModeChoices.AUTO
|
||||
tesseract_parser.parse(
|
||||
multi_page_digital_pdf_file,
|
||||
tesseract_samples_dir / "multi-page-digital.pdf",
|
||||
"application/pdf",
|
||||
produce_archive=False,
|
||||
)
|
||||
@@ -810,7 +810,7 @@ class TestSkipArchive:
|
||||
def test_skip_noarchive_image_only_creates_archive(
|
||||
self,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
multi_page_images_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
@@ -823,7 +823,7 @@ class TestSkipArchive:
|
||||
"""
|
||||
tesseract_parser.settings.mode = ModeChoices.AUTO
|
||||
tesseract_parser.parse(
|
||||
multi_page_images_pdf_file,
|
||||
tesseract_samples_dir / "multi-page-images.pdf",
|
||||
"application/pdf",
|
||||
)
|
||||
assert tesseract_parser.archive_path is not None
|
||||
@@ -835,29 +835,29 @@ class TestSkipArchive:
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("produce_archive", "sample_fixture", "expect_archive"),
|
||||
("produce_archive", "filename", "expect_archive"),
|
||||
[
|
||||
pytest.param(
|
||||
True,
|
||||
"multi_page_digital_pdf_file",
|
||||
"multi-page-digital.pdf",
|
||||
True,
|
||||
id="produce-archive-with-text",
|
||||
),
|
||||
pytest.param(
|
||||
True,
|
||||
"multi_page_images_pdf_file",
|
||||
"multi-page-images.pdf",
|
||||
True,
|
||||
id="produce-archive-no-text",
|
||||
),
|
||||
pytest.param(
|
||||
False,
|
||||
"multi_page_digital_pdf_file",
|
||||
"multi-page-digital.pdf",
|
||||
False,
|
||||
id="no-archive-with-text-layer",
|
||||
),
|
||||
pytest.param(
|
||||
False,
|
||||
"multi_page_images_pdf_file",
|
||||
"multi-page-images.pdf",
|
||||
False,
|
||||
id="no-archive-no-text-layer",
|
||||
),
|
||||
@@ -866,10 +866,10 @@ class TestSkipArchive:
|
||||
def test_produce_archive_flag(
|
||||
self,
|
||||
produce_archive: bool, # noqa: FBT001
|
||||
sample_fixture: str,
|
||||
filename: str,
|
||||
expect_archive: bool, # noqa: FBT001
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
request: pytest.FixtureRequest,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
@@ -882,9 +882,8 @@ class TestSkipArchive:
|
||||
- Text is always extracted
|
||||
"""
|
||||
tesseract_parser.settings.mode = ModeChoices.AUTO
|
||||
sample = request.getfixturevalue(sample_fixture)
|
||||
tesseract_parser.parse(
|
||||
sample,
|
||||
tesseract_samples_dir / filename,
|
||||
"application/pdf",
|
||||
produce_archive=produce_archive,
|
||||
)
|
||||
@@ -901,7 +900,7 @@ class TestSkipArchive:
|
||||
self,
|
||||
mocker: MockerFixture,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
simple_digital_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
@@ -917,7 +916,7 @@ class TestSkipArchive:
|
||||
tesseract_parser.settings.mode = ModeChoices.AUTO
|
||||
mock_ocr = mocker.patch("ocrmypdf.ocr")
|
||||
tesseract_parser.parse(
|
||||
simple_digital_pdf_file,
|
||||
tesseract_samples_dir / "simple-digital.pdf",
|
||||
"application/pdf",
|
||||
produce_archive=False,
|
||||
)
|
||||
@@ -956,7 +955,7 @@ class TestSkipArchive:
|
||||
def test_tagged_pdf_produces_pdfa_archive_without_ocr(
|
||||
self,
|
||||
tesseract_parser: RasterisedDocumentParser,
|
||||
simple_digital_pdf_file: Path,
|
||||
tesseract_samples_dir: Path,
|
||||
) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
@@ -971,7 +970,7 @@ class TestSkipArchive:
|
||||
"""
|
||||
tesseract_parser.settings.mode = ModeChoices.AUTO
|
||||
tesseract_parser.parse(
|
||||
simple_digital_pdf_file,
|
||||
tesseract_samples_dir / "simple-digital.pdf",
|
||||
"application/pdf",
|
||||
produce_archive=True,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
<p>Some Text</p>
|
||||
<p>
|
||||
<img src="cid:part1.pNdUSz0s.D3NqVtPg@example.de" alt="Has to be rewritten to work..">
|
||||
<img src="http://localhost:8080/assets/logo_full_white.svg" alt="This image should not be shown.">
|
||||
</p>
|
||||
|
||||
<p>and an embedded image.<br>
|
||||
</p>
|
||||
<p id="changeme">Paragraph unchanged.</p>
|
||||
<scRipt>
|
||||
document.getElementById("changeme").innerHTML = "Paragraph changed via Java Script.";
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 32 KiB |
@@ -18,6 +18,8 @@ from paperless.parsers.utils import read_file_handle_unicode_errors
|
||||
if TYPE_CHECKING:
|
||||
from pytest_mock import MockerFixture
|
||||
|
||||
SAMPLES = Path(__file__).parent / "samples" / "tesseract"
|
||||
|
||||
|
||||
class TestReadFileHandleUnicodeErrors:
|
||||
def test_plain_utf8(self, tmp_path: Path) -> None:
|
||||
@@ -55,11 +57,11 @@ class TestReadFileHandleUnicodeErrors:
|
||||
|
||||
|
||||
class TestIsTaggedPdf:
|
||||
def test_tagged_pdf_returns_true(self, simple_digital_pdf_file: Path) -> None:
|
||||
assert is_tagged_pdf(simple_digital_pdf_file) is True
|
||||
def test_tagged_pdf_returns_true(self) -> None:
|
||||
assert is_tagged_pdf(SAMPLES / "simple-digital.pdf") is True
|
||||
|
||||
def test_untagged_pdf_returns_false(self, multi_page_images_pdf_file: Path) -> None:
|
||||
assert is_tagged_pdf(multi_page_images_pdf_file) is False
|
||||
def test_untagged_pdf_returns_false(self) -> None:
|
||||
assert is_tagged_pdf(SAMPLES / "multi-page-images.pdf") is False
|
||||
|
||||
def test_nonexistent_path_returns_false(self) -> None:
|
||||
assert is_tagged_pdf(Path("/nonexistent/file.pdf")) is False
|
||||
@@ -93,7 +95,7 @@ class TestGetPdfFirstPageSizePoints:
|
||||
pdf.save(path)
|
||||
return path
|
||||
|
||||
def test_letter_sample(self, simple_digital_pdf_file: Path) -> None:
|
||||
def test_letter_sample(self) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
- A US Letter sample PDF with no CropBox and no rotation
|
||||
@@ -102,7 +104,7 @@ class TestGetPdfFirstPageSizePoints:
|
||||
THEN:
|
||||
- The MediaBox size in points is returned
|
||||
"""
|
||||
assert get_pdf_first_page_size_points(simple_digital_pdf_file) == (
|
||||
assert get_pdf_first_page_size_points(SAMPLES / "simple-digital.pdf") == (
|
||||
612.0,
|
||||
792.0,
|
||||
)
|
||||
@@ -197,7 +199,6 @@ class TestGetPdfFirstPageSizePoints:
|
||||
def test_pdfinfo_not_installed_returns_none(
|
||||
self,
|
||||
mocker: MockerFixture,
|
||||
simple_digital_pdf_file: Path,
|
||||
) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
@@ -208,7 +209,7 @@ class TestGetPdfFirstPageSizePoints:
|
||||
- None is returned and nothing is raised
|
||||
"""
|
||||
mocker.patch("subprocess.run", side_effect=FileNotFoundError("pdfinfo"))
|
||||
assert get_pdf_first_page_size_points(simple_digital_pdf_file) is None
|
||||
assert get_pdf_first_page_size_points(SAMPLES / "simple-digital.pdf") is None
|
||||
|
||||
def test_degenerate_box_returns_none(self, tmp_path: Path) -> None:
|
||||
"""
|
||||
@@ -250,7 +251,7 @@ class TestGetPdfFirstPageSizePoints:
|
||||
bad.write_bytes(b"not a pdf")
|
||||
assert get_pdf_first_page_size_points(bad) is None
|
||||
|
||||
def test_encrypted_pdf_returns_none(self, parser_samples_dir: Path) -> None:
|
||||
def test_encrypted_pdf_returns_none(self) -> None:
|
||||
"""
|
||||
GIVEN:
|
||||
- A password protected PDF
|
||||
@@ -259,8 +260,7 @@ class TestGetPdfFirstPageSizePoints:
|
||||
THEN:
|
||||
- None is returned and nothing is raised
|
||||
"""
|
||||
encrypted = parser_samples_dir / "tesseract" / "encrypted.pdf"
|
||||
assert get_pdf_first_page_size_points(encrypted) is None
|
||||
assert get_pdf_first_page_size_points(SAMPLES / "encrypted.pdf") is None
|
||||
|
||||
|
||||
class TestPostProcessText:
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
"""Test sample files shared across tests.
|
||||
|
||||
A sample used by a single app stays in that app's ``tests/samples`` tree.
|
||||
Samples needed by more than one app, or stored under more than one name, live
|
||||
here exactly once.
|
||||
"""
|
||||
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
SHARED_SAMPLES_DIR = (Path(__file__).parent / "sample_files").resolve()
|
||||
|
||||
SIMPLE_DIGITAL_PDF = SHARED_SAMPLES_DIR / "simple-digital.pdf"
|
||||
MULTI_PAGE_DIGITAL_PDF = SHARED_SAMPLES_DIR / "multi-page-digital.pdf"
|
||||
WITH_FORM_PDF = SHARED_SAMPLES_DIR / "with-form.pdf"
|
||||
MULTI_PAGE_IMAGES_PDF = SHARED_SAMPLES_DIR / "multi-page-images.pdf"
|
||||
THUMBNAIL_WEBP = SHARED_SAMPLES_DIR / "thumbnail.webp"
|
||||
|
||||
# The fake media tree under documents/tests/samples/documents keeps only the
|
||||
# files unique to it. The files that duplicate a shared sample are laid back
|
||||
# down under their historical opaque names (DB rows and exporter manifests
|
||||
# refer to them) by install_document_samples().
|
||||
_DOCUMENT_SAMPLES_DIR = (
|
||||
Path(__file__).parent.parent / "documents" / "tests" / "samples" / "documents"
|
||||
).resolve()
|
||||
|
||||
_SHARED_AS_MEDIA = (
|
||||
("originals/0000001.pdf", SIMPLE_DIGITAL_PDF),
|
||||
("originals/0000002.pdf", MULTI_PAGE_DIGITAL_PDF),
|
||||
("originals/0000003.pdf", WITH_FORM_PDF),
|
||||
("archive/0000001.pdf", MULTI_PAGE_IMAGES_PDF),
|
||||
("thumbnails/0000001.webp", THUMBNAIL_WEBP),
|
||||
("thumbnails/0000002.webp", THUMBNAIL_WEBP),
|
||||
("thumbnails/0000003.webp", THUMBNAIL_WEBP),
|
||||
("thumbnails/0000004.webp", THUMBNAIL_WEBP),
|
||||
)
|
||||
|
||||
|
||||
def install_document_samples(dest: Path) -> None:
|
||||
"""Populate ``dest`` with the full fake media tree.
|
||||
|
||||
Replaces ``shutil.copytree(<samples>/documents, dest)`` in tests.
|
||||
"""
|
||||
shutil.copytree(_DOCUMENT_SAMPLES_DIR, dest, dirs_exist_ok=True)
|
||||
for relpath, source in _SHARED_AS_MEDIA:
|
||||
target = dest / relpath
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(source, target)
|
||||