3.20. Lesezeichen/Bookmarks und Sprungziele

Überblick

Lesezeichen/Bookmarks dienen der schnellen Navigation innerhalb eines PDF-Dokumentes oder auch nach außen. Der Gebrauchswert eines Buches sinkt erheblich, wenn die einzelnen Kapitel nicht über ein Lesezeichen erreichbar sind. Mit den folgenden Tests sollen eventuelle Probleme frühzeitig erkannt werden:

// Simple methods:
.hasNumberOfBookmarks(..) 
.hasBookmark()     // Test for one bookmark
.hasBookmarks()    // Test for all bookmarks

// Tests for one bookmark:
.hasBookmark().withLabel(..) 
.hasBookmark().withLabelLinkingToPage(..) 
.hasBookmark().withLinkToName(..) 
.hasBookmark().withLinkToPage(..) 
.hasBookmark().withLinkToURI(..) 

// Tests for all bookmarks:
.hasBookmarks().withDestinations()
.hasBookmarks().withoutDuplicateNames()

Betrachtet man Lesezeichen als Absprungmarken, dann sind Named Destinations die Sprungziele. Sprungziele können von Lesezeichen genutzt werden, dienen aber auch als Ziel für HTML-Links. So kann aus einer Webseite direkt an eine bestimmte Stelle innerhalb eines PDF-Dokumentes gesprungen werden.

Für Sprungziele (Named Destinations) gibt es die Testmethoden:

.hasNamedDestination()
.hasNamedDestination().withName(..)

Sprunziele, Named Destinations

Namen von Sprungzielen können einfach getestet werden:

@Test
public void hasNamedDestination_WithName() throws Exception {
  String filename = "documentUnderTest.pdf";

  AssertThat.document(filename)
            .hasNamedDestination().withName("Seventies")
            .hasNamedDestination().withName("Eighties")
            .hasNamedDestination().withName("1999")
            .hasNamedDestination().withName("2000")
  ;
}

Da die Namen auch über externe Links funktionieren müssen, dürfen sie keine Leerzeichen enthalten. Wird beispielsweise innerhalb von LibreOffice eine Sprungmarke mit Leerzeichen "Export to PDF" erstellt, erzeugt LibreOffice daraus beim Export nach PDF die Sprungmarke "First2520Bookmark". Der Test muss dann diese Zeichenkette benutzen:

@Test
public void hasNamedDestination_ContainingBlanks() throws Exception {
  String filename = "documentUnderTest.pdf";

  AssertThat.document(filename)
            .hasNamedDestination().withName("First2520Bookmark")  1
  ;
}

1

'2520' steht für '%20', was wiederum einem Leerzeichen entspricht.

Existenz von Lesezeichen/Bookmarks

Am einfachsten kann die Existenz von Lesezeichen überprüft werden:

@Test
public void hasBookmarks() throws Exception {
  String filename = "documentUnderTest.pdf";
  
  AssertThat.document(filename)
            .hasBookmarks()
  ;
}

Anzahl

Nach dem Test, ob ein PDF-Dokument überhaupt Lesezeichen hat, ist die Anzahl der Lesezeichen prüfenswert:

@Test
public void hasNumberOfBookmarks() throws Exception {
  String filename = "documentUnderTest.pdf";
  
  AssertThat.document(filename)
            .hasNumberOfBookmarks(19)
  ; 
}

Text eines Lesezeichens (Label)

Eine wichtige Eigenschaft eines Lesezeichens ist das, was der Leser sieht: das Label. Deshalb sollten Sie testen, ob ein bestimmtes Lesezeichen genauso heißt, wie Sie es erwarten:

@Test
public void hasBookmark_WithLabel() throws Exception {
  String filename = "documentUnderTest.pdf";

  AssertThat.document(filename)
            .hasBookmark().withLabel("Content on page 3.")
  ;
}

Sprungziele von Lesezeichen

Lesezeichen können sehr unterschiedliche Sprungziele haben. Deshalb gibt es für jedes Ziel geeignete Testmethoden.

Zielt ein bestimmtes Lesezeichen auf die gewünschte Seitenzahl:

@Test
public void hasBookmark_WithLabelLinkingToPage() throws Exception {
  String filename = "documentUnderTest.pdf";
  
  AssertThat.document(filename)
            .hasBookmark().withLabelLinkingToPage("Content on first page.", 1)
  ; 
}

Gibt es irgendein Lesezeichen zu einer gewünschten Seitenzahl:

@Test 
public void hasBookmark_WithLinkToPage() throws Exception {
  String filename = "documentUnderTest.pdf";
  
  AssertThat.document(filename)
            .hasBookmark().withLinkToPage(1)
  ; 
}

Gibt es ein Lesezeichen, das zu einer bestimmten Sprungmarke zeigt:

@Test 
public void hasBookmark_WithLinkToName() throws Exception {
  String filename = "documentUnderTest.pdf";
  
  AssertThat.document(filename)
            .hasBookmark().withLinkToName("Destination on Page 1")
  ; 
}

Gibt es ein Lesezeichen, dessen Ziel eine bestimmte URI ist:

@Test 
public void hasBookmark_WithLinkToURI() throws Exception {
  String filename = "documentUnderTest.pdf";
  
  AssertThat.document(filename)
            .hasBookmark().withLinkToURI("http://www.wikipedia.org/")
  ; 
}

PDFUnit greift während der Tests nicht auf Webseiten zu. Es wird nicht geprüft, ob eine Webseite tatsächlich existiert, sondern nur, ob das Lesezeichen ein Link ist.

Und als Letztes soll überprüft werden, dass jedes Lesezeichen auf ein irgendein Ziel verweist:

@Test 
public void hasBookmarkWithDestinations() throws Exception {
  String filename = "documentUnderTest.pdf";
  
  AssertThat.document(filename)
            .hasBookmarks().withDestinations()
  ; 
}