3.2.  Actions

Overview

Actions make PDF documents interactive and more complex. Complex means that they should be tested, especially when interactive documents are part of a workflow.

An action is a dictionary object inside PDF containing the keys /S and /Type. The key /Type always maps to the value Action. And the the key /S (Subtype) has different values:

// Types of actions:

GoTo:        Set the focus to a destination in the current PDF document
GoToR:       Set the focus to a destination in another PDF document
GoToE:       Go to a destination inside an embedded file
GoTo3DView:  Set the view to a 3D annotation
Hide:        Set the hidden flag of the specified annotation
ImportData:  Import data from a file to the current document
JavaScript:  Execute JavaScript code
Movie:       Play a specified movie
Named:       Execute an action, which is predefined by the PDF viewer
Rendition:   Control the playing of multimedia content
ResetForm:   Set the values of form fields to default
SetOCGState: Set the state of an OCG
Sound:       Play a specified sound
SubmitForm:  Send the form data to an URL
Launch:      Execute an application
Thread:      Set the viewer to the beginning of a specified article
Trans:       Update the display of a document, using a transition dictionary
URI:         Go to the remote URI

For a few of these actions PDFUnit provides test methods. Future releases will have more tests methods.

// Simple tests:

.hasNumberOfActions(..) 

// Action specific tests:

.hasJavaScriptAction()
.hasJavaScriptAction().containing(..)
.hasJavaScriptAction().containingSource(..)
.hasJavaScriptAction().equalsTo(..)
.hasJavaScriptAction().equalsToSource(..)
.hasJavaScriptAction().matchingRegex(..)

.hasLocalGotoAction()
.hasLocalGotoAction().toDestination(..)
.hasLocalGotoAction().toDestination(.., pageNumber)

The following sections show examples for these test methods.

JavaScript-Actions

Since JavaScript code is generally quite long, it makes sense to read the expected text for a JavaScript-Action test from a file:

@Test
public void hasJavaScriptAction_WithWhitespaceProcessing() throws Exception {
  String filename = "documentUnderTest.pdf";
  String scriptFileName = "javascript/javascriptAction_OneSimpleAlert.js";
  Reader scriptFileAsReader = new FileReader(scriptFileName);

  AssertThat.document(filename)
            .hasJavaScriptAction()
            .equalsToSource(scriptFileAsReader, WhitespaceProcessing.IGNORE)
  ;
}

The parameter of the method equalsToSource(..) (and also containingSource(..)) can be of type java.io.Reader, java.io.InputStream or java.lang.String.

The content of the JavaScript file is completely compared with the content of the JavaScript action. White spaces are ignored.

But parts of a JavaScript code can be checked as well:

@Test
public void hasJavaScript_ContainingText_FunctionNames() throws Exception {
  String filename = "javaScriptClock.pdf";
  
  AssertThat.document(filename)
            .hasJavaScript()
            .containing("StopWatchProc")
            .containing("SetFldEnable")
            .containing("DoTimers")
            .containing("ClockProc")
            .containing("CountDownProc")
            .containing("CDEnables")
            .containing("SWSetEnables")
  ;
}

Chapter 13.5: “Whitespace Processing” explains the flexible handling of whitespaces.

Goto-Actions

Goto-Actions need a destination in the same PDF document:

@Test
public void hasGotoAction_ToNamedDestination() throws Exception {
  String filename = "documentUnderTest.pdf";
  String destinationName21 = "destination2.1";
  
  AssertThat.document(filename)
            .hasLocalGotoAction()  
            .toDestination(destinationName21)
  ;
}

This test is successful if the tested PDF contains the expected destination destination2.1. Chapter 4.11: “Comparing Named Destinations” discusses how to test destinations together with bookmarks.

It is also possible to check whether a destination is located on a given page:

@Test
public void hasGotoAction_ToDestinationWithPage_Page3() throws Exception {
  String filename = "documentUnderTest.pdf";
  String destinationName21 = "destination2.1";
  int page3 = 3;
  
  AssertThat.document(filename)
            .hasLocalGotoAction()
            .toDestination(destinationName21, page3)
  ;
}