Ricardo SIGNES 😄
and 2 contributors


JMAP::Tester - a JMAP client made for testing JMAP servers


version 0.014


Achtung! This library is in its really early days, so use it with that in mind.

JMAP::Tester is for testing JMAP servers. Okay? Okay!

JMAP::Tester calls the whole thing you get back from a JMAP server a "response" if it's an HTTP 200. Every JSON Array (of three entries -- go read the spec if you need to!) is called a Sentence. Runs of Sentences with the same client id are called Paragraphs.

You use the test client like this:

  my $jtest = JMAP::Tester->new({
    api_uri => 'https://jmap.local/account/123',

  my $response = $jtest->request([
    [ getMailboxes => {} ],
    [ getMessageUpdates => { sinceState => "123" } ],

  # This returns two Paragraph objects if there are exactly two paragraphs.
  # Otherwise, it throws an exception.
  my ($mbx_p, $msg_p) = $response->assert_n_paragraphs(2);

  # These get the single Sentence of each paragraph, asserting that there is
  # exactly one Sentence in each Paragraph, and that it's of the given type.
  my $mbx = $mbx_p->single('mailboxes');
  my $msg = $msg_p->single('messageUpdates');

  is( @{ $mbx->arguments->{list} }, 10, "we expect 10 mailboxes");
  ok( ! $msg->arguments->{hasMoreUpdates}, "we got all the msg updates needed");

By default, all the structures returned have been passed through JSON::Typist, so you may want to strip their type data before using normal Perl code on them. You can do that with:

  my $struct = $response->as_struct;   # gets the complete JSON data
  $jtest->strip_json_types( $struct ); # strips all the JSON::Typist types

Or more simply:

  my $struct = $response->as_stripped_struct;

There is also "as_stripped_pairs" in JMAP::Tester::Response.



This is a hashref of arguments to be put into each method call. It's especially useful for setting a default accountId. Values given in methods passed to request will override defaults. If the value is a reference to undef, then no value will be passed for that key.

In other words, in this situation:

  my $tester = JMAP::Tester->new({
    default_arguments => { a => 1, b => 2, c => 3 },

    [ eatPies => { a => 100, b => \undef } ],

The request will effectively be:

  [ [ "eatPies", { "a": 100, "c": 3 }, "a" ] ]



  my $result = $jtest->request([
    [ methodOne => { ... } ],
    [ methodTwo => { ... } ],

This method takes an arrayref of method calls and sends them to the JMAP server. If the method calls have a third element (a client id) then it's left as-is. If no client id is given, one is generated. You can mix explicit and autogenerated client ids. They will never conflict.

The arguments to methods are JSON-encoded with a JSON::Typist-aware encoder, so JSON::Typist types can be used to ensure string or number types in the generated JSON. If an argument is a reference to undef, it will be removed before the method call is made. This lets you override a default by omission.

The return value is an object that does the JMAP::Tester::Result role, meaning it's got an is_success method that returns true or false. For now, at least, failures are JMAP::Tester::Result::Failure objects. More refined failure objects may exist in the future. Successful requests return JMAP::Tester::Response objects.


  my $result = $tester->upload($mime_type, $blob_ref, \%arg);

This uploads the given blob, which should be given as a reference to a string.

The return value will either be a failure object or an upload result.


  my $result = $tester->download(\%arg);

Valid arguments are:

  blobId    - the blob to download (no default)
  accountId - the account for which we're downloading (no default)
  name      - the name we want the server to provide back (default: "download")

If the download URI template has a blobId or accountId placeholder but no argument for that is given to download, an exception will be thrown.

The return value will either be a failure object or an upload result.


  my $auth_struct = $tester->simple_auth($username, $password);



This method fetches the content at the authentication endpoint and uses it to configure the tester's target URIs and signing keys.



Given a client session object (like those stored in an Auth result), this reconfigures the testers access token, signing keys, URIs, and so forth. This method is used internally when logging in.



This method attempts to log out from the server by sending a DELETE request to the authentication URI.


Ricardo SIGNES <rjbs@cpan.org>


  • Alfie John <alfiej@fastmail.fm>

  • Matthew Horsfall <wolfsage@gmail.com>


This software is copyright (c) 2016 by FastMail, Ltd.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.