This page excerpts the README of activitypub-testing. Find the entirety of the source code in the repository.


tools for testing implementations of ActivityPub, a decentralized social networking protocol.

How to use the activitypub-testing CLI


Ad-hoc Usage

If you have npx installed (which comes with npm), you can use the activitypub-testing cli without downloading the source code or installing the package globally.

This can be useful to quickly use the tool, but it also can be a bit slow, so see below for how to install the activitypub-testing CLI for direct usage.

Throughout this README, is used in code blocks to indicate a shell prompt. Yours might be $. Copy the rest of the command other than the shell prompt to follow along.

⚡ npx activitypub-testing help


  activitypub-testing is a cli for testing implementations of ActivityPub[0]

  # browse all the tests
  activitypub-testing get tests [--output=<mediaType>]

  # inspect a single test
  activitypub-testing get test (--uuid=<uuid>|--slug=<slug>) [--output=<mediaType>]

  # run a test
  activitypub-testing run test (--uuid=<uuid>|--slug=<slug>) --input.anyInputName=<input.anyInputName>

  # run tests on a specific ActivityPub Actor
  activitypub-testing test actor <actor-uri> [--output=<mediaType>]

  # print this help
  activitypub-testing [--help|-h] [help]

  -h --help        Show this help text.
  -o --output      Choose output media type (default `text`, also allows `json`, `yaml`)
  --slug           slug (aka URL-path-friendly human-readable name) of selection
  --uuid           UUID (rfc4122) identifier of selection

  # runs test inbox-must-be-an-orderedcollection[1] against a valid actor fetched via https
  activitypub-testing \
    test \
    --uuid '5e94d155-ed4a-4d71-b797-d7c387736ecf' \
    --input.object="$(curl -s '')"

  # run tests on a specific ActivityPub Actor (pipe to `jq` to pretty print JSON)
  activitypub-testing \
    test actor \


Installing activitypub-testing on your PATH

You can install activitypub-testing for usage without having to type npx:

⚡ npm install -g activitypub-testing

npm install -g installs activitypub-testing to your shell PATH. Then the following should work in your command prompt:

⚡ activitypub-testing help

Test an ActivityPub Actor

⚡ activitypub-testing test actor

As tests are run, newline-delimited JSON (aka ndjson) descriptions of the results are streamed to stdout.

That means you can compose activitypub-testing with other tools in a pipeline.

e.g. head can truncate output:

⚡ activitypub-testing test actor | head -n1
{"type":["Assertion"],"result":{"outcome":"passed"},"test":{"slug":"following-collection-must-be-a-collection","url":"","description":"tests whether an ActivityPub Object has a `following`` collection with an appropriate Collection type","name":"An ActivityPub Actor Object's `following` Collection Must be a Collection","uuid":"018c3e17-a1bd-7040-8007-4cd3b9063288"},"input":{"object":"{\n  \"type\": [\n    \"Organization\"\n  ],\n  \"inbox\": \"\",\n  \"outbox\": \"\",\n  \"followers\": {\n    \"type\": \"OrderedCollection\"\n  },\n  \"following\": {\n    \"type\": \"OrderedCollection\"\n  },\n  \"liked\": {\n    \"type\": \"OrderedCollection\"\n  },\n  \"likes\": {\n    \"type\": \"OrderedCollection\"\n  },\n  \"shares\": {\n    \"type\": \"OrderedCollection\"\n  },\n  \"id\": \"\",\n  \"@context\": [\n    \"\"\n  ]\n}"},"@context":["",""]}
stdout closed w/ EPIPE

Processing Results with jq

jq is very useful for processing JSON, and it's a recommended companion to activitypub-testing.

⚡ activitypub-testing test actor | jq 
  "type": [
  "result": {
    "outcome": "passed"
  "test": {
    "slug": "following-collection-must-be-a-collection",
    "url": "",
    "description": "tests whether an ActivityPub Object has a `following`` collection with an appropriate Collection type",
    "name": "An ActivityPub Actor Object's `following` Collection Must be a Collection",
    "uuid": "018c3e17-a1bd-7040-8007-4cd3b9063288"
  "input": {
    "object": "{\n  \"type\": [\n    \"Organization\"\n  ],\n  \"inbox\": \"\",\n  \"outbox\": \"\",\n  \"followers\": {\n    \"type\": \"OrderedCollection\"\n  },\n  \"following\": {\n    \"type\": \"OrderedCollection\"\n  },\n  \"liked\": {\n    \"type\": \"OrderedCollection\"\n  },\n  \"likes\": {\n    \"type\": \"OrderedCollection\"\n  },\n  \"shares\": {\n    \"type\": \"OrderedCollection\"\n  },\n  \"id\": \"\",\n  \"@context\": [\n    \"\"\n  ]\n}"
  "@context": [
# more JSON objects omitted for README brevity

If you want to slurp all the output objects into a single JSON array, you can do that with jq's --slurp aka -s flag.

⚡ activitypub-testing test actor | jq -s
    "type": [
# more JSON omitted for README brevity

Get Tests Collection

activitypub-testing get tests will get a collection of available tests. The default behavior is to format it to be readable by a human. Pass -o json for json output.

⚡ activitypub-testing get tests
name: ActivityPub Tests
  - Collection
  - slug: actor-objects-must-have-inbox-outbox-properties
    uuid: acaacb5f-8f7e-4f28-8d81-c7955070a767
    id: urn:uuid:acaacb5f-8f7e-4f28-8d81-c7955070a767
  - slug: actor-must-serve-as2-object-to-get
    uuid: e7ee491d-88d7-4e67-80c8-f74781bb247c
    id: urn:uuid:e7ee491d-88d7-4e67-80c8-f74781bb247c
  - slug: inbox-must-be-an-orderedcollection
    uuid: 5e94d155-ed4a-4d71-b797-d7c387736ecf
    id: urn:uuid:5e94d155-ed4a-4d71-b797-d7c387736ecf
  - slug: outbox-must-be-an-orderedcollection
    uuid: 4af549f4-3797-4d99-a151-67c3d8feaa46
    id: urn:uuid:4af549f4-3797-4d99-a151-67c3d8feaa46
  - slug: shares-collection-must-be-a-collection
    uuid: b03a5245-1072-426d-91b3-a3d412d45ae8
    id: urn:uuid:b03a5245-1072-426d-91b3-a3d412d45ae8
  - slug: likes-collection-must-be-a-collection
    uuid: 200b9bc8-aae3-46f2-a6ab-5366042c0f6e
    id: urn:uuid:200b9bc8-aae3-46f2-a6ab-5366042c0f6e
  - slug: liked-collection-must-be-a-collection
    uuid: 018c3df2-d6d8-7f62-805b-b71a96cc6170
    id: urn:uuid:018c3df2-d6d8-7f62-805b-b71a96cc6170
  - slug: followers-collection-must-be-a-collection
    uuid: 018c3e08-611f-7e56-9f45-2fe5e4877d4e
    id: urn:uuid:018c3e08-611f-7e56-9f45-2fe5e4877d4e
  - slug: following-collection-must-be-a-collection
    uuid: 018c3e17-a1bd-7040-8007-4cd3b9063288
    id: urn:uuid:018c3e17-a1bd-7040-8007-4cd3b9063288
  - slug: outbox-post-servers-must-return-a-201-created-http-code
    uuid: 723afcbb-118d-433e-8ab4-560ffca93582
    id: urn:uuid:723afcbb-118d-433e-8ab4-560ffca93582

Get a single Test

Get a Test by Slug

Every test has a human-readable slug, which can be useful for identifying and selecting specific tests.

Get all info about a specific teest

⚡ activitypub-testing get test --slug actor-must-serve-as2-object-to-get
  - TestCase
description: This rule checks that URLs of ActivityPub objects can be resolved
  to a representation with well-known media type for further processing.
  - name: nginx 404 response body
      time: T1M
# lots more yaml omitted

See here for full example output from the above command.

Every test has a human-readable description of the test in markdown as a markdown property

⚡ activitypub-testing get test \
    --slug actor-must-serve-as2-object-to-get \
    -o json \
  | jq -r .markdown

Get a Test by UUID

⚡ activitypub-testing get test --uuid e7ee491d-88d7-4e67-80c8-f74781bb247c

Get Test Input Description

⚡ activitypub-testing get test \
    --slug actor-must-serve-as2-object-to-get \
    -o json \
  | jq -r .inputs  
  "id": {
    "help": "identifier of an ActivityPub Object hosted at an ActivityPub Server",
    "type": "xsd:anyUri",
    "rangeIncludes": [
    "required": true
  "authorization": {
    "help": "proof of authorization to retrieve the object identified by input `id`"
  "time": {
    "help": "amount of time allowed to run test. This is meant to configure the limit for how long this test will wait for network requests. MUST be an [RFC3339 `dur-time`](",
    "required": true,
    "type": [

Run a Single Test

The run test command takes a test selector and --input.{inputName}={inputValue} flags that get parsed to build the test input, which is then provided to the test to run. See Get Test Input Description for how to describe the input for a test.

run test by slug

In this example, the time and id inputs are defined by the test selected by the --slug flag.

⚡ activitypub-testing run test \
  --slug actor-must-serve-as2-object-to-get \
  --input.time="T1M" \""
  "type": "Assertion",
  "test": {
    "id": "urn:uuid:e7ee491d-88d7-4e67-80c8-f74781bb247c",
    "uuid": "e7ee491d-88d7-4e67-80c8-f74781bb247c",
    "url": "",
    "slug": "actor-must-serve-as2-object-to-get"
  "input": {
    "time": "T1M",
    "id": ""
  "result": {
    "outcome": "passed"
  "@context": [

Developing this Repository


Some directory names are loosely inspired by linux equivalents.

Developing ActivityPub Test Cases

Each test case has a directory in ./src/activitypub-tests/ named by its slug. In each test case directory, there is:

Developing the activitypub-testing CLI

See ./src/cli.js for the source code.

You should be able to run the cli.js script like

⚡ ./src/cli.js --uuid=test-uuid
no test found with uuid of test-uuid

npm scripts

These are in ./package.json and each has a name. Run like npm run <name>