diff --git a/fillpdf.info b/fillpdf.info
index 19520dbba43b9362a72c3b26ef1e8b0c9426ba9b..5ac058993b153e66c49f322dacd4207d4398112a 100644
--- a/fillpdf.info
+++ b/fillpdf.info
@@ -8,8 +8,11 @@ test_dependencies[] = webform
 test_dependencies[] = features
 test_dependencies[] = webform_features
 ; Note: Tests require PHP 5.4.
-files[] = tests/FillPdfLinkContextTestCase.test
+files[] = tests/FillPdfEntityTestCase.test
+files[] = tests/FillPdfLinkBooleansTestCase.test
 files[] = tests/FillPdfMergeTestCase.test
+files[] = tests/FillPdfNodeTestCase.test
 files[] = tests/FillPdfTestCase.test
 files[] = tests/FillPdfTestHelper.test
+files[] = tests/FillPdfWebformTestCase.test
 configure = admin/config/media/fillpdf
diff --git a/tests/FillPdfEntityTestCase.test b/tests/FillPdfEntityTestCase.test
new file mode 100644
index 0000000000000000000000000000000000000000..a293c0efe15ab0301eb462bf2599d266ca828f16
--- /dev/null
+++ b/tests/FillPdfEntityTestCase.test
@@ -0,0 +1,211 @@
+<?php
+
+/**
+ * Tests parsing links for entities.
+ */
+class FillPdfEntityTestCase extends DrupalWebTestCase {
+
+  /**
+   * The profile to install as a basis for testing.
+   *
+   * @var string
+   */
+  protected $profile = 'minimal';
+
+  protected $nodes;
+  protected $terms;
+  protected $users;
+
+  /**
+   *
+   */
+  public static function getInfo() {
+    // Note: getInfo() strings are not translated with t().
+    return array(
+      'name' => 'FillPDF link creation for entities',
+      'description' => 'Ensure that FillPDF creates correct links for entities.',
+      'group' => 'FillPDF',
+    );
+  }
+
+  /**
+   *
+   */
+  public function setUp() {
+    // Enable any modules required for the test. This should be an array of
+    // module names.
+    parent::setUp(array('taxonomy', 'entity', 'fillpdf'));
+
+    // Create three test nodes with the IDs 1, 2, and 3.
+    $nodes = array();
+    for ($nid = 1; $nid <= 3; $nid++) {
+      $nodes[] = entity_create('node', array(
+        'type' => 'article',
+        'nid' => $nid,
+      ));
+    }
+    $this->nodes = $nodes;
+
+    // Create three test terms with the IDs 12, 23, and 34.
+    $terms = array();
+    for ($tid = 11; $tid <= 13; $tid++) {
+      $terms[] = entity_create('taxonomy_term', array(
+        'vocabulary_machine_name' => 'tags',
+        'tid' => $tid,
+      ));
+    }
+    $this->terms = $terms;
+
+    // Create three test users with the IDs 123, 234, and 345.
+    $users = array();
+    for ($uid = 111; $uid <= 113; $uid++) {
+      $users[] = entity_create('user', array(
+        'uid' => $uid,
+      ));
+    }
+    $this->users = $users;
+  }
+
+  /**
+   * Test fillpdf_context_to_link() and fillpdf_pdf_link() with entities.
+   */
+  public function testEntityLink() {
+    $base_context = array(
+      'nodes' => array(),
+      'webforms' => array(),
+      'uc_orders' => array(),
+      'uc_order_products' => array(),
+      'entities' => array(),
+    );
+    $message = "Test case %name:\n<br />%output (actual result) equals\n<br />%expected (expected).";
+
+    foreach ($this->dataProvider() as $test_case) {
+      list($name, $entities, $expected) = $test_case;
+
+      // Ensure links were correctly created from context.
+      $context = array(
+        'entities' => $entities,
+      ) + $base_context;
+      $output = rawurldecode(fillpdf_context_to_link(1, $context));
+
+      $this->assertEqual($expected, $output, t($message, array(
+        '%name' => $name,
+        '%output' => $output,
+        '%expected' => $expected,
+      )));
+    }
+  }
+
+  /**
+   * Data provider for testBooleans().
+   *
+   * @return array
+   *   Array of test cases.
+   */
+  public function dataProvider() {
+    $base_url = url('', array(
+      'absolute' => TRUE,
+    )) . 'fillpdf?fid=1';
+
+    $test_cases = array();
+
+    // Test case: single node.
+    $test_cases[] = array(
+      'Single node',
+      array(
+        'node' => array_slice($this->nodes, 0, 1),
+      ),
+      $base_url . '&entity_ids[]=node:1',
+    );
+
+    // Test case: multiple nodes.
+    $test_cases[] = [
+      'Multiple nodes',
+      array(
+        'node' => $this->nodes,
+      ),
+      $base_url . '&entity_ids[]=node:1&entity_ids[]=node:2&entity_ids[]=node:3',
+    ];
+
+    // Test case: multiple nodes in reverse order.
+    $test_cases[] = [
+      'Multiple nodes (in reverse order)',
+      array(
+        'node' => array_reverse($this->nodes),
+      ),
+      $base_url . '&entity_ids[]=node:3&entity_ids[]=node:2&entity_ids[]=node:1',
+    ];
+
+    // Test case: single term.
+    $test_cases[] = array(
+      'Single term',
+      array(
+        'taxonomy_term' => array_slice($this->terms, 0, 1),
+      ),
+      $base_url . '&entity_ids[]=taxonomy_term:11',
+    );
+
+    // Test case: multiple terms.
+    $test_cases[] = [
+      'Multiple terms',
+      array(
+        'taxonomy_term' => $this->terms,
+      ),
+      $base_url . '&entity_ids[]=taxonomy_term:11&entity_ids[]=taxonomy_term:12&entity_ids[]=taxonomy_term:13',
+    ];
+
+    // Test case: single user.
+    $test_cases[] = array(
+      'Single user',
+      array(
+        'user' => array_slice($this->users, 0, 1),
+      ),
+      $base_url . '&entity_ids[]=user:111',
+    );
+
+    // Test case: multiple users.
+    $test_cases[] = [
+      'Multiple users',
+      array(
+        'user' => $this->users,
+      ),
+      $base_url . '&entity_ids[]=user:111&entity_ids[]=user:112&entity_ids[]=user:113',
+    ];
+
+    // Test case: node, term, user.
+    $test_cases[] = array(
+      'Node, term, user',
+      array(
+        'node' => array_slice($this->nodes, 0, 1),
+        'taxonomy_term' => array_slice($this->terms, 0, 1),
+        'user' => array_slice($this->users, 0, 1),
+      ),
+      $base_url . '&entity_ids[]=node:1&entity_ids[]=taxonomy_term:11&entity_ids[]=user:111',
+    );
+
+    // Test case: user, term, multiple nodes.
+    $test_cases[] = array(
+      'user, term, multiple nodes',
+      array(
+        'user' => array_slice($this->users, 0, 1),
+        'taxonomy_term' => array_slice($this->terms, 0, 1),
+        'node' => $this->nodes,
+      ),
+      $base_url . '&entity_ids[]=user:111&entity_ids[]=taxonomy_term:11&entity_ids[]=node:1&entity_ids[]=node:2&entity_ids[]=node:3',
+    );
+
+    // Test case: user, multiple nodes in reverse order, term.
+    $test_cases[] = array(
+      'user, multiple nodes (in reverse order), term',
+      array(
+        'user' => array_slice($this->users, 0, 1),
+        'node' => array_reverse($this->nodes),
+        'taxonomy_term' => array_slice($this->terms, 0, 1),
+      ),
+      $base_url . '&entity_ids[]=user:111&entity_ids[]=node:3&entity_ids[]=node:2&entity_ids[]=node:1&entity_ids[]=taxonomy_term:11',
+    );
+
+    return $test_cases;
+  }
+
+}
diff --git a/tests/FillPdfLinkContextTestCase.test b/tests/FillPdfLinkBooleansTestCase.test
similarity index 92%
rename from tests/FillPdfLinkContextTestCase.test
rename to tests/FillPdfLinkBooleansTestCase.test
index fdfec971ee70fa844d546aa401fbafd336cbc1b4..a4efdd708158adbb69159c15eaf44fb18c468273 100644
--- a/tests/FillPdfLinkContextTestCase.test
+++ b/tests/FillPdfLinkBooleansTestCase.test
@@ -3,15 +3,15 @@
 /**
  * Tests some unit test cases.
  */
-class FillPdfLinkContextTestCase extends DrupalWebTestCase {
+class FillPdfLinkBooleansTestCase extends DrupalWebTestCase {
 
   /**
    * {@inheritdoc}
    */
   public static function getInfo() {
     return array(
-      'name' => 'FillPDF query parameter unit test',
-      'description' => 'Unit tests evaluation of query parameters.',
+      'name' => 'FillPDF Boolean query parameter unit test',
+      'description' => 'Unit tests evaluation of boolean query parameters.',
       'group' => 'FillPDF',
     );
   }
diff --git a/tests/FillPdfNodeTestCase.test b/tests/FillPdfNodeTestCase.test
new file mode 100644
index 0000000000000000000000000000000000000000..e4494535fa57a2701dddd43a4d4d05310d7b59fd
--- /dev/null
+++ b/tests/FillPdfNodeTestCase.test
@@ -0,0 +1,141 @@
+<?php
+
+/**
+ * Tests parsing links for nodes.
+ */
+class FillPdfNodeTestCase extends DrupalWebTestCase {
+
+  /**
+   * The profile to install as a basis for testing.
+   *
+   * @var string
+   */
+  protected $profile = 'minimal';
+
+  protected $nodes;
+  protected $message;
+
+  /**
+   *
+   */
+  public static function getInfo() {
+    // Note: getInfo() strings are not translated with t().
+    return array(
+      'name' => 'FillPDF link creation for nodes',
+      'description' => 'Ensure that FillPDF creates correct links for nodes.',
+      'group' => 'FillPDF',
+    );
+  }
+
+  /**
+   *
+   */
+  public function setUp() {
+    // Enable any modules required for the test. This should be an array of
+    // module names.
+    parent::setUp(array('node', 'fillpdf'));
+
+    // Create three test nodes with the IDs 123, 234, and 345.
+    $nodes = array();
+    for ($nid = 111; $nid <= 113; $nid++) {
+      $nodes[] = (object) array(
+        'nid' => $nid,
+        'type' => 'article',
+      );
+    }
+    $this->nodes = $nodes;
+
+    $this->message = "Test case %name:\n<br />%output (actual result) equals\n<br />%expected (expected).";
+  }
+
+  /**
+   * Test fillpdf_context_to_link() with nodes.
+   */
+  public function testNodeLink() {
+    $base_context = array(
+      'nodes' => array(),
+      'webforms' => array(),
+      'uc_orders' => array(),
+      'uc_order_products' => array(),
+      'entities' => array(),
+    );
+
+    foreach ($this->dataProvider() as $test_case) {
+      list($name, $nodes, $expected) = $test_case;
+
+      // Ensure links were correctly created from context.
+      $context = array(
+        'nodes' => $nodes,
+      ) + $base_context;
+      $output = rawurldecode(fillpdf_context_to_link(1, $context));
+
+      $this->assertEqual($expected, $output, t($this->message, array(
+        '%name' => $name,
+        '%output' => $output,
+        '%expected' => $expected,
+      )));
+    }
+  }
+
+  /**
+   * Test fillpdf_pdf_link() with a single node in legacy format.
+   *
+   * fillpdf_pdf_link() accepts a single nid being passed in as $nids. We're
+   * therefore separately testing single entity cases in this legacy format.
+   * All other cases are fully covered by testNodeLink().
+   */
+  public function testLegacyNodeLink() {
+    foreach ($this->dataProvider() as $test_case) {
+      list($name, $nodes, $expected) = $test_case;
+
+      if (count($nodes) == 1) {
+        $node = reset($nodes);
+        $output = rawurldecode(fillpdf_pdf_link(1, $node->nid));
+
+        $this->assertEqual($expected, $output, t($this->message, array(
+          '%name' => $name . ' (legacy format)',
+          '%output' => $output,
+          '%expected' => $expected,
+        )));
+      }
+    }
+  }
+
+  /**
+   * Data provider for testNodeLink().
+   *
+   * @return array
+   *   Array of test cases.
+   */
+  public function dataProvider() {
+    $base_url = url('', array(
+      'absolute' => TRUE,
+    )) . 'fillpdf?fid=1';
+
+    $test_cases = array();
+
+    // Test case: single node.
+    $test_cases[] = array(
+      'Single node',
+      array(reset($this->nodes)),
+      $base_url . '&nids[]=111',
+    );
+
+    // Test case: multiple nodes.
+    $test_cases[] = array(
+      'Multiple nodes',
+      $this->nodes,
+      $base_url . '&nids[]=111&nids[]=112&nids[]=113',
+    );
+
+    // Test case: multiple nodes in reverse order.
+    $test_cases[] = array(
+      'Multiple nodes (in reverse order)',
+      array_reverse($this->nodes),
+      $base_url . '&nids[]=113&nids[]=112&nids[]=111',
+    );
+
+    return $test_cases;
+  }
+
+}
diff --git a/tests/FillPdfTestCase.test b/tests/FillPdfTestCase.test
index 640aca86a05adf94779ccfcb377ca30835b05aa3..1dfde746c7dec68196ca682774f7b0eaea3efcfb 100644
--- a/tests/FillPdfTestCase.test
+++ b/tests/FillPdfTestCase.test
@@ -57,83 +57,6 @@ class FillPdfTestCase extends FileFieldTestCase {
     $this->assertFieldByXPath('//input[@id="edit-upload-pdf"][@type="file"][@accept="application/pdf"]', NULL, 'PDF upload component has appropriate attributes.');
   }
 
-  /**
-   * Ensure that fillpdf_link_from_context() functions properly.
-   *
-   * @throws \EntityMalformedException
-   */
-  public function testLinkFromContext() {
-    // @todo: flesh out with more combinations. This one was most broken,
-    // though.
-    $fid = 1;
-
-    $fake_webform = new stdClass();
-    $fake_webform->nid = 123;
-    $fake_submission = new stdClass();
-    $fake_submission->sid = 456;
-
-    $fake_context = array(
-      'nodes' => array(),
-      'webforms' => array(
-        array(
-          'webform' => $fake_webform,
-          'submission' => $fake_submission,
-        ),
-      ),
-      'uc_orders' => array(),
-      'uc_order_products' => array(),
-    );
-
-    // We also add the base domain to our expected link so that they come out
-    // the same.
-    $expected_link = url('', array('absolute' => TRUE)) . 'fillpdf?fid=1&webforms[0][nid]=123&webforms[0][sid]=456';
-    $actual_link = fillpdf_context_to_link($fid, $fake_context);
-
-    $this->assertEqual($expected_link, $actual_link, 'fillpdf_context_to_link() generates a link with a single Webform correctly.');
-
-    $fake_multiple_context = array(
-      'nodes' => array(),
-      'webforms' => array(
-        array(
-          'webform' => $fake_webform,
-          'submission' => $fake_submission,
-        ),
-        array(
-          'webform' => (object) array('nid' => 234),
-          'submission' => (object) array('sid' => 567),
-        ),
-        array(
-          'webform' => (object) array('nid' => 345),
-          'submission' => (object) array('sid' => 678),
-        ),
-      ),
-      'uc_orders' => array(),
-      'uc_order_products' => array(),
-    );
-
-    // We also add the base domain to our expected link so that they come out
-    // the same.
-    $expected_link2 = url('', array('absolute' => TRUE)) . 'fillpdf?fid=1&webforms[0][nid]=123&webforms[0][sid]=456&webforms[1][nid]=234&webforms[1][sid]=567&webforms[2][nid]=345&webforms[2][sid]=678';
-    $actual_link2 = fillpdf_context_to_link($fid, $fake_multiple_context);
-
-    $this->assertEqual($expected_link2, $actual_link2, 'fillpdf_context_to_link() generates a link with multiple Webforms correctly.');
-
-    $test_node = entity_create('node', array(
-      'type' => 'article',
-    ));
-    $test_node->nid = 123;
-    $fake_entity_context = array(
-      'entities' => array(
-        'node' => array($test_node),
-      ),
-    );
-
-    $expected_link3 = url('', array('absolute' => TRUE)) . 'fillpdf?fid=1&entity_ids[]=node:123';
-    $actual_link3 = fillpdf_context_to_link($fid, $fake_entity_context);
-
-    $this->assertEqual($expected_link3, $actual_link3, 'fillpdf_context_to_link() generates a link with entities correctly.');
-  }
-
   /**
    * Make sure that file access works properly.
    */
diff --git a/tests/FillPdfWebformTestCase.test b/tests/FillPdfWebformTestCase.test
new file mode 100644
index 0000000000000000000000000000000000000000..7d9fdcdc51d2a463821fa78241da228ea553c507
--- /dev/null
+++ b/tests/FillPdfWebformTestCase.test
@@ -0,0 +1,147 @@
+<?php
+
+/**
+ * Tests parsing links.
+ */
+class FillPdfWebformTestCase extends DrupalWebTestCase {
+
+  /**
+   * The profile to install as a basis for testing.
+   *
+   * @var string
+   */
+  protected $profile = 'minimal';
+
+  protected $webforms;
+  protected $message;
+
+  /**
+   *
+   */
+  public static function getInfo() {
+    // Note: getInfo() strings are not translated with t().
+    return array(
+      'name' => 'FillPDF link creation for Webform',
+      'description' => 'Ensure that FillPDF creates correct links for webforms.',
+      'group' => 'FillPDF',
+    );
+  }
+
+  /**
+   *
+   */
+  public function setUp() {
+    // Enable any modules required for the test. This should be an array of
+    // module names.
+    parent::setUp(array('fillpdf'));
+
+    // Create three sets of a webform with a submission each.
+    $webforms = array();
+    for ($nid = 111; $nid <= 113; $nid++) {
+      $webforms[] = array(
+        'webform' => (object) array('nid' => $nid),
+        'submission' => (object) array('sid' => $nid + 100),
+      );
+    }
+    $this->webforms = $webforms;
+
+    $this->message = "Test case %name:\n<br />%output (actual result) equals\n<br />%expected (expected).";
+  }
+
+  /**
+   * Test fillpdf_context_to_link() with webforms.
+   */
+  public function testWebformLink() {
+    $base_context = array(
+      'nodes' => array(),
+      'webforms' => array(),
+      'uc_orders' => array(),
+      'uc_order_products' => array(),
+      'entities' => array(),
+    );
+
+    foreach ($this->dataProvider() as $test_case) {
+      list($name, $webforms, $expected) = $test_case;
+
+      // Ensure links were correctly created from context.
+      $context = array(
+        'webforms' => $webforms,
+      ) + $base_context;
+      $output = rawurldecode(fillpdf_context_to_link(1, $context));
+
+      $this->assertEqual($expected, $output, t($this->message, array(
+        '%name' => $name,
+        '%output' => $output,
+        '%expected' => $expected,
+      )));
+    }
+  }
+
+  /**
+   * Test fillpdf_pdf_link() with a single webform in legacy format.
+   *
+   * fillpdf_pdf_link() accepts a single array of webform and submission being
+   * passed in as $webform_arr. We're therefore separately testing single
+   * webform cases in this legacy format. All other cases are fully covered
+   * by testWebformLink().
+   */
+  public function testLegacyWebformLink() {
+    foreach ($this->dataProvider() as $test_case) {
+      list($name, $webforms, $expected) = $test_case;
+
+      if (count($webforms) == 1) {
+        $webform = reset($webforms);
+        $webform_arr = array(
+          'nid' => $webform['webform']->nid,
+          'sid' => $webform['submission']->sid,
+        );
+        // fillpdf_pdf_link() also accepts a single webform
+        $output = rawurldecode(fillpdf_pdf_link(1, NULL, $webform_arr));
+
+        $this->assertEqual($expected, $output, t($this->message, array(
+          '%name' => $name . ' (legacy format)',
+          '%output' => $output,
+          '%expected' => $expected,
+        )));
+      }
+    }
+  }
+
+  /**
+   * Data provider for testBooleans().
+   *
+   * @return array
+   *   Array of test cases.
+   */
+  public function dataProvider() {
+    $base_url = url('', array(
+      'absolute' => TRUE,
+    )) . 'fillpdf?fid=1';
+
+    $test_cases = array();
+
+    // Test case: single webform.
+    $test_cases[] = array(
+      'Single webform',
+      array(reset($this->webforms)),
+      $base_url . '&webforms[0][nid]=111&webforms[0][sid]=211',
+    );
+
+    // Test case: multiple webforms.
+    $test_cases[] = array(
+      'Multiple webforms',
+      $this->webforms,
+      $base_url . '&webforms[0][nid]=111&webforms[0][sid]=211&webforms[1][nid]=112&webforms[1][sid]=212&webforms[2][nid]=113&webforms[2][sid]=213',
+    );
+
+    // Test case: multiple webforms in reverse order.
+    $test_cases[] = array(
+      'Multiple webforms (in reverse order)',
+      array_reverse($this->webforms),
+      $base_url . '&webforms[0][nid]=113&webforms[0][sid]=213&webforms[1][nid]=112&webforms[1][sid]=212&webforms[2][nid]=111&webforms[2][sid]=211',
+    );
+
+    return $test_cases;
+  }
+
+}