Skip to content

Commit 3e0a4ae

Browse files
committed
enable AI
1 parent 60164f4 commit 3e0a4ae

2 files changed

Lines changed: 45 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project
6+
7+
`com.codeborne:pdf-test` — a small Java library for asserting on the contents of PDF files in tests. It exposes both a Hamcrest matcher API (`PDF.containsText(...)` etc.) and an AssertJ API (`Assertions.assertThat(pdf).containsText(...)`), plus AssertJ soft assertions via `PdfSoftAssertions`. PDF parsing is delegated to Apache PDFBox.
8+
9+
## Common commands
10+
11+
Build and run all checks (the `defaultTasks` are `check publishToMavenLocal`):
12+
13+
```
14+
./gradlew
15+
```
16+
17+
Other useful tasks:
18+
19+
```
20+
./gradlew test # run tests only
21+
./gradlew test --tests <FQCN> # run a single test class
22+
./gradlew test --tests <FQCN>.<method> # run a single test method
23+
./gradlew jacocoTestReport # coverage report at build/reports/jacoco/
24+
./gradlew publishToMavenLocal # install to ~/.m2 for local consumption
25+
```
26+
27+
Java 17 is required (toolchain pinned in `gradle/compilation.gradle`).
28+
29+
## Architecture
30+
31+
The public surface is intentionally tiny — three packages under `src/main/java/com/codeborne/pdftest`:
32+
33+
- **`PDF`** is the central value object. Its constructors eagerly parse a PDF (from `File`, `URL`, `URI`, `byte[]`, or `InputStream`, optionally with a page range) and freeze the extracted state into `public final` fields: `text`, `numberOfPages`, document-info fields (`author`, `title`, `creator`, ...), and signature fields (`signed`, `signerName`, `signatureTime`). All later assertions read these fields — there is no lazy parsing. Any parse failure is rethrown as `IllegalArgumentException("Invalid PDF file: ...")`. URL reads use a 10 s connect/read timeout.
34+
- **`matchers/`** holds Hamcrest `TypeSafeMatcher<PDF>` implementations, all extending `PDFMatcher`. `PDF` exposes them as static factories (`containsText`, `doesNotContainText`, `containsExactText`, `doesNotContainExactText`, `containsTextCaseInsensitive`, `matchesText`).
35+
- **`assertj/`** mirrors the same checks as an AssertJ `PdfAssert extends AbstractAssert<PdfAssert, PDF>`, with `Assertions.assertThat(PDF)` as the entry point and `PdfSoftAssertions` for soft assertions (uses AssertJ's `proxy(...)`).
36+
37+
**Whitespace handling is the key invariant.** `Spaces.reduce(text)` collapses any run of whitespace (including ` ` non-breaking space and newlines) to a single space and trims. The `containsText` / `containsTextCaseInsensitive` / `matchesText` / `doesNotContainText` paths apply `Spaces.reduce` to BOTH the PDF text and the expected argument(s); the `*Exact*` variants do not. Both API surfaces (Hamcrest matchers and `PdfAssert`) must keep this behavior consistent — when adding a new matcher, decide explicitly whether it is an "exact" or whitespace-normalized variant and apply `Spaces.reduce` accordingly on both sides.
38+
39+
Adding a new check usually means: a new `PDFMatcher` subclass, a static factory on `PDF`, a method on `PdfAssert`, and tests under both `src/test/java/com/codeborne/pdftest/matchers/` and `src/test/java/com/codeborne/pdftest/assertj/`.
40+
41+
## Tests
42+
43+
JUnit 5 (Jupiter). Test PDFs live in `src/test/resources/` (`minimal.pdf`, `50quickideas.pdf`, `transaction.pdf`, `statement.pdf`, `file-with-images.pdf`, two `PO_*.pdf` purchase orders). Reuse these rather than committing new fixtures unless a new edge case really requires one.

CLAUDE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# CLAUDE.md
2+
@AGENTS.md

0 commit comments

Comments
 (0)