“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.
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 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) ; }