Prepare v0.4 release and open source docs
This commit is contained in:
52
Tests/IHatePDFsCoreTests/PDFDocumentBookmarksTests.swift
Normal file
52
Tests/IHatePDFsCoreTests/PDFDocumentBookmarksTests.swift
Normal file
@@ -0,0 +1,52 @@
|
||||
import XCTest
|
||||
@testable import IHatePDFsCore
|
||||
|
||||
final class PDFDocumentBookmarksTests: XCTestCase {
|
||||
func testUpsertReplacesExistingBookmark() {
|
||||
let first = PDFDocumentBookmark(id: "first", pageIndex: 4, pageLabel: "5", title: "Old")
|
||||
let second = PDFDocumentBookmark(id: "second", pageIndex: 1, pageLabel: "2", title: "Second")
|
||||
let replacement = PDFDocumentBookmark(id: "replacement", pageIndex: 4, pageLabel: "5", title: "New")
|
||||
|
||||
let result = PDFDocumentBookmarks.upsert(replacement, in: [first, second])
|
||||
|
||||
XCTAssertEqual(result.map(\.id), ["replacement"])
|
||||
XCTAssertEqual(result.first?.title, "New")
|
||||
}
|
||||
|
||||
func testRemovingBookmarkCollapsesDirtyMultipleBookmarkData() {
|
||||
let first = PDFDocumentBookmark(id: "first", pageIndex: 0, pageLabel: "1", title: "First")
|
||||
let second = PDFDocumentBookmark(id: "second", pageIndex: 1, pageLabel: "2", title: "Second")
|
||||
|
||||
let result = PDFDocumentBookmarks.removing(id: "first", from: [first, second])
|
||||
|
||||
XCTAssertEqual(result.map(\.id), ["second"])
|
||||
}
|
||||
|
||||
func testClampedDropsInvalidBookmarksAndKeepsOneBookmark() {
|
||||
let older = PDFDocumentBookmark(
|
||||
id: "older",
|
||||
pageIndex: 0,
|
||||
pageLabel: "1",
|
||||
title: "Older",
|
||||
createdAt: Date(timeIntervalSince1970: 100)
|
||||
)
|
||||
let newer = PDFDocumentBookmark(
|
||||
id: "newer",
|
||||
pageIndex: 1,
|
||||
pageLabel: "2",
|
||||
title: "Newer",
|
||||
createdAt: Date(timeIntervalSince1970: 200)
|
||||
)
|
||||
let invalid = PDFDocumentBookmark(
|
||||
id: "invalid",
|
||||
pageIndex: 4,
|
||||
pageLabel: "5",
|
||||
title: "Invalid",
|
||||
createdAt: Date(timeIntervalSince1970: 300)
|
||||
)
|
||||
|
||||
let result = PDFDocumentBookmarks.clamped([invalid, older, newer], pageCount: 2)
|
||||
|
||||
XCTAssertEqual(result.map(\.id), ["newer"])
|
||||
}
|
||||
}
|
||||
58
Tests/IHatePDFsCoreTests/PDFRecentDocumentsTests.swift
Normal file
58
Tests/IHatePDFsCoreTests/PDFRecentDocumentsTests.swift
Normal file
@@ -0,0 +1,58 @@
|
||||
import XCTest
|
||||
@testable import IHatePDFsCore
|
||||
|
||||
final class PDFRecentDocumentsTests: XCTestCase {
|
||||
func testFilteredPDFsKeepsExistingPDFsOnly() {
|
||||
let pdf = URL(fileURLWithPath: "/Users/test/Documents/reading.pdf")
|
||||
let upperPDF = URL(fileURLWithPath: "/Users/test/Documents/report.PDF")
|
||||
let text = URL(fileURLWithPath: "/Users/test/Documents/notes.txt")
|
||||
|
||||
let result = PDFRecentDocuments.filteredPDFs(
|
||||
from: [pdf, text, upperPDF],
|
||||
limit: 10,
|
||||
fileExists: { $0 == pdf || $0 == upperPDF }
|
||||
)
|
||||
|
||||
XCTAssertEqual(result, [pdf, upperPDF])
|
||||
}
|
||||
|
||||
func testFilteredPDFsDeduplicatesExcludesCurrentAndHonorsLimit() {
|
||||
let first = URL(fileURLWithPath: "/Users/test/Documents/first.pdf")
|
||||
let second = URL(fileURLWithPath: "/Users/test/Documents/second.pdf")
|
||||
let third = URL(fileURLWithPath: "/Users/test/Documents/third.pdf")
|
||||
|
||||
let result = PDFRecentDocuments.filteredPDFs(
|
||||
from: [first, second, first, third],
|
||||
currentURL: second,
|
||||
limit: 1,
|
||||
fileExists: { _ in true }
|
||||
)
|
||||
|
||||
XCTAssertEqual(result, [first])
|
||||
}
|
||||
|
||||
func testProgressStoresPageByNormalizedDocumentKey() {
|
||||
let url = URL(fileURLWithPath: "/Users/test/Documents/../Documents/reading.pdf")
|
||||
let openedAt = Date(timeIntervalSince1970: 42)
|
||||
|
||||
let records = PDFRecentDocuments.updatedProgress(
|
||||
[:],
|
||||
url: url,
|
||||
pageIndex: 8,
|
||||
openedAt: openedAt
|
||||
)
|
||||
let progress = PDFRecentDocuments.progress(for: url, in: records)
|
||||
|
||||
XCTAssertEqual(progress?.pageIndex, 8)
|
||||
XCTAssertEqual(progress?.openedAt, openedAt)
|
||||
XCTAssertEqual(progress?.key, PDFRecentDocuments.documentKey(for: url))
|
||||
}
|
||||
|
||||
func testProgressClampsSavedPageToAvailablePageCount() {
|
||||
XCTAssertEqual(PDFRecentDocuments.clampedPageIndex(nil, pageCount: 20), 0)
|
||||
XCTAssertEqual(PDFRecentDocuments.clampedPageIndex(-4, pageCount: 20), 0)
|
||||
XCTAssertEqual(PDFRecentDocuments.clampedPageIndex(4, pageCount: 20), 4)
|
||||
XCTAssertEqual(PDFRecentDocuments.clampedPageIndex(99, pageCount: 20), 19)
|
||||
XCTAssertEqual(PDFRecentDocuments.clampedPageIndex(4, pageCount: 0), 0)
|
||||
}
|
||||
}
|
||||
46
Tests/IHatePDFsCoreTests/PerformanceBudgetTests.swift
Normal file
46
Tests/IHatePDFsCoreTests/PerformanceBudgetTests.swift
Normal file
@@ -0,0 +1,46 @@
|
||||
import AppKit
|
||||
import PDFKit
|
||||
import XCTest
|
||||
@testable import IHatePDFsCore
|
||||
|
||||
final class PerformanceBudgetTests: XCTestCase {
|
||||
func testLargeDocumentFullAnnotationSnapshotPerformance() {
|
||||
let document = makeLargeAnnotatedDocument(pageCount: 500, annotationEvery: 10)
|
||||
|
||||
measure {
|
||||
let snapshots = AnnotationReader.snapshots(in: document)
|
||||
XCTAssertEqual(snapshots.count, 50)
|
||||
}
|
||||
}
|
||||
|
||||
func testLargeDocumentPageScopedAnnotationRefreshPerformance() throws {
|
||||
let document = makeLargeAnnotatedDocument(pageCount: 500, annotationEvery: 10)
|
||||
let targetPage = try XCTUnwrap(document.page(at: 250))
|
||||
|
||||
measure {
|
||||
let snapshots = AnnotationReader.snapshots(in: document, pages: [targetPage])
|
||||
XCTAssertEqual(snapshots.count, 1)
|
||||
XCTAssertEqual(snapshots.first?.pageIndex, 250)
|
||||
}
|
||||
}
|
||||
|
||||
private func makeLargeAnnotatedDocument(pageCount: Int, annotationEvery stride: Int) -> PDFDocument {
|
||||
let document = PDFDocument()
|
||||
|
||||
for pageIndex in 0..<pageCount {
|
||||
let page = PDFPage()
|
||||
document.insert(page, at: pageIndex)
|
||||
|
||||
guard pageIndex.isMultiple(of: stride) else { continue }
|
||||
let insertion = AnnotationFactory.noteInsertion(
|
||||
on: page,
|
||||
near: CGPoint(x: 120, y: 160),
|
||||
comment: "Note on page \(pageIndex + 1)",
|
||||
author: "Professor"
|
||||
)
|
||||
page.addAnnotation(insertion.annotation)
|
||||
}
|
||||
|
||||
return document
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,30 @@ final class ReturnKeyCommitPolicyTests: XCTestCase {
|
||||
))
|
||||
}
|
||||
|
||||
func testCommandReturnCommitsWhenCommandReturnOnlyModeEnabled() {
|
||||
XCTAssertTrue(ReturnKeyCommitPolicy.shouldCommit(
|
||||
keyCode: 36,
|
||||
shift: false,
|
||||
option: false,
|
||||
command: true,
|
||||
control: false,
|
||||
isEditableMultilineText: true,
|
||||
commandReturnOnly: true
|
||||
))
|
||||
}
|
||||
|
||||
func testPlainReturnDoesNotCommitWhenCommandReturnOnlyModeEnabled() {
|
||||
XCTAssertFalse(ReturnKeyCommitPolicy.shouldCommit(
|
||||
keyCode: 36,
|
||||
shift: false,
|
||||
option: false,
|
||||
command: false,
|
||||
control: false,
|
||||
isEditableMultilineText: true,
|
||||
commandReturnOnly: true
|
||||
))
|
||||
}
|
||||
|
||||
func testKeypadEnterCommitsInEditableMultilineText() {
|
||||
XCTAssertTrue(ReturnKeyCommitPolicy.shouldCommit(
|
||||
keyCode: 76,
|
||||
|
||||
Reference in New Issue
Block a user