diff --git a/src/_zkapauthorizer/tests/strategies.py b/src/_zkapauthorizer/tests/strategies.py
index 6cf2806d56c0f48ac6af30517bf33869284e33c9..dc8763acd552c258d9bab1db243a506b8c62f8b2 100644
--- a/src/_zkapauthorizer/tests/strategies.py
+++ b/src/_zkapauthorizer/tests/strategies.py
@@ -61,6 +61,58 @@ from ..model import (
     Voucher,
 )
 
+_POSIX_EPOCH = datetime.utcfromtimestamp(0)
+
+
+def posix_safe_datetimes():
+    """
+    Build datetime instances in a range that can be represented as floats
+    without losing microsecond precision.
+    """
+    return datetimes(
+        # I don't know that time-based parts of the system break down
+        # before the POSIX epoch but I don't know that they work, either.
+        # Don't time travel with this code.
+        min_value=_POSIX_EPOCH,
+        # Once we get far enough into the future we lose the ability to
+        # represent a timestamp with microsecond precision in a floating point
+        # number, which we do with any POSIX timestamp-like API (eg
+        # twisted.internet.task.Clock).  So don't go far enough into the
+        # future.  Furthermore, once we don't fit into an unsigned 4 byte
+        # integers, we can't round-trip through all the things that expect a
+        # time_t.  Stay back from the absolute top to give tests a little
+        # space to advance time, too.
+        max_value=datetime.utcfromtimestamp(2 ** 31),
+    )
+
+
+def posix_timestamps():
+    """
+    Build floats in a range that can represent time without losing microsecond
+    precision.
+    """
+    return posix_safe_datetimes().map(
+        lambda when: (when - _POSIX_EPOCH).total_seconds(),
+    )
+
+
+def clocks(now=posix_timestamps()):
+    """
+    Build ``twisted.internet.task.Clock`` instances set to a time built by
+    ``now``.
+
+    :param now: A strategy that builds POSIX timestamps (ie, ints or floats in
+        the range of time_t).
+    """
+
+    def clock_at_time(when):
+        c = Clock()
+        c.advance(when)
+        return c
+
+    return now.map(clock_at_time)
+
+
 # Sizes informed by
 # https://github.com/brave-intl/challenge-bypass-ristretto/blob/2f98b057d7f353c12b2b12d0f5ae9ad115f1d0ba/src/oprf.rs#L18-L33
 
@@ -237,7 +289,10 @@ def zkapauthz_configuration(
         ``extra_configurations``.
     """
 
-    def merge(extra_configuration, allowed_public_keys):
+    def merge(
+        extra_configuration,
+        allowed_public_keys,
+    ):
         config = {
             u"default-token-count": u"32",
             u"allowed-public-keys": u",".join(allowed_public_keys),
@@ -266,21 +321,46 @@ def client_ristrettoredeemer_configurations():
     )
 
 
-def client_dummyredeemer_configurations():
+def client_dummyredeemer_configurations(
+    crawl_means=one_of(none(), posix_timestamps()),
+    crawl_ranges=one_of(none(), posix_timestamps()),
+    min_times_remaining=one_of(none(), posix_timestamps()),
+):
     """
     Build DummyRedeemer-using configuration values for the client-side plugin.
     """
 
+    def make_lease_config(crawl_mean, crawl_range, min_time_remaining):
+        config = {}
+        if crawl_mean is not None:
+            # Don't allow the mean to be 0
+            config["lease.crawl-interval.mean"] = str(int(crawl_mean) + 1)
+        if crawl_range is not None:
+            config["lease.crawl-interval.range"] = str(int(crawl_range))
+        if min_time_remaining is not None:
+            config["lease.min-time-remaining"] = str(int(min_time_remaining))
+        return config
+
     def share_a_key(allowed_keys):
-        return zkapauthz_configuration(
-            just(
+        lease_configs = builds(
+            make_lease_config,
+            crawl_means,
+            crawl_ranges,
+            min_times_remaining,
+        )
+        extra_config = lease_configs.map(
+            lambda config: config.update(
                 {
                     u"redeemer": u"dummy",
                     # Pick out one of the allowed public keys so that the dummy
                     # appears to produce usable tokens.
                     u"issuer-public-key": next(iter(allowed_keys)),
                 }
-            ),
+            )
+            or config,
+        )
+        return zkapauthz_configuration(
+            extra_config,
             allowed_public_keys=just(allowed_keys),
         )
 
@@ -895,58 +975,6 @@ def announcements():
     )
 
 
-_POSIX_EPOCH = datetime.utcfromtimestamp(0)
-
-
-def posix_safe_datetimes():
-    """
-    Build datetime instances in a range that can be represented as floats
-    without losing microsecond precision.
-    """
-    return datetimes(
-        # I don't know that time-based parts of the system break down
-        # before the POSIX epoch but I don't know that they work, either.
-        # Don't time travel with this code.
-        min_value=_POSIX_EPOCH,
-        # Once we get far enough into the future we lose the ability to
-        # represent a timestamp with microsecond precision in a floating point
-        # number, which we do with any POSIX timestamp-like API (eg
-        # twisted.internet.task.Clock).  So don't go far enough into the
-        # future.  Furthermore, once we don't fit into an unsigned 4 byte
-        # integers, we can't round-trip through all the things that expect a
-        # time_t.  Stay back from the absolute top to give tests a little
-        # space to advance time, too.
-        max_value=datetime.utcfromtimestamp(2 ** 31),
-    )
-
-
-def posix_timestamps():
-    """
-    Build floats in a range that can represent time without losing microsecond
-    precision.
-    """
-    return posix_safe_datetimes().map(
-        lambda when: (when - _POSIX_EPOCH).total_seconds(),
-    )
-
-
-def clocks(now=posix_timestamps()):
-    """
-    Build ``twisted.internet.task.Clock`` instances set to a time built by
-    ``now``.
-
-    :param now: A strategy that builds POSIX timestamps (ie, ints or floats in
-        the range of time_t).
-    """
-
-    def clock_at_time(when):
-        c = Clock()
-        c.advance(when)
-        return c
-
-    return now.map(clock_at_time)
-
-
 @implementer(IFilesystemNode)
 @attr.s(frozen=True)
 class _LeafNode(object):
diff --git a/src/_zkapauthorizer/tests/test_client_resource.py b/src/_zkapauthorizer/tests/test_client_resource.py
index 490665f4e0b2cf12830e117eb6ef207888d737e0..292c505241c7a479b64300c4117a424cf61cf661 100644
--- a/src/_zkapauthorizer/tests/test_client_resource.py
+++ b/src/_zkapauthorizer/tests/test_client_resource.py
@@ -96,6 +96,7 @@ from .json import loads
 from .matchers import Provides, between, matches_response
 from .strategies import (
     api_auth_tokens,
+    posix_timestamps,
     client_doublespendredeemer_configurations,
     client_dummyredeemer_configurations,
     client_errorredeemer_configurations,
@@ -746,12 +747,15 @@ class UnblindedTokenTests(TestCase):
         using_a_token = after(getting_initial_tokens, use_a_token)
         getting_tokens_after = after(using_a_token, get_tokens)
 
+        def check_tokens(before_and_after):
+            initial_tokens, tokens_after = before_and_after
+            return initial_tokens[1:] == tokens_after
+
         self.assertThat(
             gatherResults([getting_initial_tokens, getting_tokens_after]),
             succeeded(
                 MatchesPredicate(
-                    lambda (initial_tokens, tokens_after): initial_tokens[1:]
-                    == tokens_after,
+                    check_tokens,
                     u"initial, after (%s): initial[1:] != after",
                 ),
             ),
@@ -1586,30 +1590,36 @@ class CalculatePriceTests(TestCase):
         )
 
     @given(
-        # Make the share encoding parameters easily accessible without going
-        # through the Tahoe-LAFS configuration.
-        share_parameters().flatmap(
-            lambda params: tuples(
-                just(params),
-                tahoe_configs(shares=just(params)),
+        tuples(
+            # Make the share encoding parameters easily accessible without
+            # going through the Tahoe-LAFS configuration.
+            share_parameters(),
+            # Same goes for the minimum lease time remaining configuration.
+            posix_timestamps().map(int),
+        ).flatmap(
+            lambda share_and_lease_time: tuples(
+                just(share_and_lease_time),
+                direct_tahoe_configs(
+                    zkapauthz_v1_configuration=client_dummyredeemer_configurations(
+                        min_times_remaining=just(share_and_lease_time[1]),
+                    ),
+                    shares=just(share_and_lease_time[0]),
+                ),
             ),
         ),
         api_auth_tokens(),
         lists(integers(min_value=0)),
     )
-    def test_calculated_price(
-        self, encoding_params_and_get_config, api_auth_token, sizes
-    ):
+    def test_calculated_price(self, encoding_params_and_config, api_auth_token, sizes):
         """
         A well-formed request returns the price in ZKAPs as an integer and the
         storage period (the minimum allowed) that they pay for.
         """
-        encoding_params, get_config = encoding_params_and_get_config
+        (encoding_params, min_time_remaining), config = encoding_params_and_config
         shares_needed, shares_happy, shares_total = encoding_params
-
-        config = get_config_with_api_token(
-            self.useFixture(TempDir()),
-            get_config,
+        add_api_token_to_config(
+            self.useFixture(TempDir()).join(b"tahoe"),
+            config,
             api_auth_token,
         )
         root = root_from_config(config, datetime.now)
@@ -1639,7 +1649,7 @@ class CalculatePriceTests(TestCase):
                         Equals(
                             {
                                 u"price": expected_price,
-                                u"period": get_configured_lease_duration(config),
+                                u"period": 60 * 60 * 24 * 31 - min_time_remaining,
                             }
                         ),
                     ),