An ActivityPub Actor Object's `followers` Collection Must be a Collection

Description

tests whether an ActivityPub Object has a `followers`` collection with an appropriate Collection type

Table of Contents

Identifiers

Use these identifiers to refer to this Test.

URI

urn:uuid:018c3e08-611f-7e56-9f45-2fe5e4877d4e

slug

This slug is memorable, but it is not guaranteed to be globally unique like a URI.

followers-collection-must-be-a-collection

Input

This describes the input that each test run will use to select test targets.

input.object

object with a `followers` property

required
true
range
https://www.w3.org/ns/activitystreams#Actor

input.object as json
{
  "help": "object with a `followers` property",
  "required": true,
  "rangeIncludes": [
    "https://www.w3.org/ns/activitystreams#Actor"
  ]
}

Input as JSON
{
  "object": {
    "help": "object with a `followers` property",
    "required": true,
    "rangeIncludes": [
      "https://www.w3.org/ns/activitystreams#Actor"
    ]
  }
}

Requirement Mapping

This Test has been derived from these specified requirements.

  • urn:uuid:abef3a0a-d3c4-4dee-a320-b28837d0bcd8

    content
    The followers collection MUST be either an OrderedCollection or a Collection
    origin
    {
      "source": "https://www.w3.org/TR/activitypub/",
      "section": {
        "id": "https://www.w3.org/TR/activitypub/#followers",
        "branch": [
          5,
          3
        ]
      },
      "selector": {
        "type": "TextQuoteSelector",
        "prefix": "Every actor SHOULD have a followers collection. This is a list of everyone who has sent a Follow activity for the actor, added as a side effect. This is where one would find a list of all the actors that are following the actor.\n",
        "exact": "The followers collection MUST be either an OrderedCollection or a Collection\n",
        "suffix": "and MAY be filtered on privileges of an authenticated user or as appropriate when no authentication is given.\n"
      }
    }
    JSON
    {
      "id": "urn:uuid:abef3a0a-d3c4-4dee-a320-b28837d0bcd8",
      "type": "Behavior",
      "uuid": "abef3a0a-d3c4-4dee-a320-b28837d0bcd8",
      "content": "The followers collection MUST be either an OrderedCollection or a Collection",
      "tag": [
        {
          "name": "ActivityPubServer",
          "id": "https://socialweb.coop/tag/ActivityPubServer"
        }
      ],
      "origin": {
        "source": "https://www.w3.org/TR/activitypub/",
        "section": {
          "id": "https://www.w3.org/TR/activitypub/#followers",
          "branch": [
            5,
            3
          ]
        },
        "selector": {
          "type": "TextQuoteSelector",
          "prefix": "Every actor SHOULD have a followers collection. This is a list of everyone who has sent a Follow activity for the actor, added as a side effect. This is where one would find a list of all the actors that are following the actor.\n",
          "exact": "The followers collection MUST be either an OrderedCollection or a Collection\n",
          "suffix": "and MAY be filtered on privileges of an authenticated user or as appropriate when no authentication is given.\n"
        }
      },
      "@context": [
        "https://www.w3.org/ns/activitystreams",
        "https://socialweb.coop/ns/testing/context.json"
      ]
    }

Part of

This test is part of the following Test Suites:

JSON

Test Case as JSON
{
  "input": {
    "object": {
      "help": "object with a `followers` property",
      "required": true,
      "rangeIncludes": [
        "https://www.w3.org/ns/activitystreams#Actor"
      ]
    }
  },
  "markdown": "---\n\ntype:\n- TestCase\ntags:\n- tests-activitypub-actor\nuuid:\n- 018c3e08-611f-7e56-9f45-2fe5e4877d4e\n\nrespec:\n  config:\n    editors:\n    - name: bengo\n      url: \"https://bengo.is\"\n      w3cid: 49026\n---\n\n# An ActivityPub Object `followers` Collection Must be a Collection\n\n## Background [<sup>?</sup>][test-background]\n\n[ActivityPub][activitypub] [ยง 5.3 Followers Collection](https://www.w3.org/TR/activitypub/#followers):\n\n> Every actor SHOULD have a followers collection.\n> This is a list of everyone who has sent a Follow activity for the actor,\n> added as a side effect.\n> This is where one would find a list of all the actors that are following the actor.\n> The followers collection MUST be either an OrderedCollection or a Collection\n\n## About This Test\n\nThis is a Test Case describing a rule to determine\nwhether an ActivityPub Object is in partial conformance with\nthe following behaviors required by [ActivityPub][activitypub].\n\n* [requirement abef3a0a-d3c4-4dee-a320-b28837d0bcd8][requirement-1] -\nThe followers collection MUST be either an OrderedCollection or a Collection\n\n### Identifier\n\nThe identifier of this test is `urn:uuid:018c3e08-611f-7e56-9f45-2fe5e4877d4e`.\n\n## Test Subject\n\nThe subject of this test is an ActivityPub Actor Object.\n\n## Input [<sup>?</sup>][test-input]\n\nThis test requires the following [inputs](act-rules-input)\nindicating parts of the test subject:\n\n1. `object` - the object whose `followers` property will be tested\n    * type: binary\n    * constraints\n        * should be JSON\n\n## Applicability [<sup>?</sup>][test-applicability]\n\nThis test applies to each of the followers collections derived\nfrom the values of the property on `object` named `followers`.\n\n### Prerequisites\n\n* `object` is a JSON object\n* `object` JSON object has a property named `followers`\n\n### How to Derive Test Targets from Input\n\n* let `targets` be a set\n* let `followersValues` be the result of\n    * if `object.followers` is an Array, return it\n    * else return an Array whose only item is the value of `object.followers`\n* for each item in `followersValues`\n    * if item is a string\n        * let itemFetched be the result of interpreting the string as\n          an ActivityPub Object Identifier and fetching the corresponding\n          ActivityPub Object.\n        * add itemFetched to `targets`\n    * else add item to `targets`\n* return `targets`\n\n## Expectations [<sup>?</sup>][test-expectations]\n\nFor every target `target`\n\n* `target` is a JSON object\n* `target` has a property named `type`\n* the values of the `target`'s `type` property must be one of\n    * an array containing the string \"Collection\"\n    * an array containing the string \"OrderedCollection\"\n    * the string \"Collection\"\n    * the string \"OrderedCollection\"\n\n## Assumptions [<sup>?</sup>][test-assumptions]\n\n## Test Cases [<sup>?</sup>][test-test-cases]\n\nWhat follows are some specific cases of applything this test.\n\n### Passed Example 1 - followers has type Collection\n\ninputs\n\n* `object`:\n\n  ```json\n  {\n    \"followers\": {\n      \"type\": \"Collection\"\n    }\n  }\n  ```\n\ntest targets\n\n* ```json\n  {\n    \"type\": \"Collection\"\n  }\n  ```\n\n    * outcome: `passed`\n\n### Passed Example 2 - followers has type OrderedCollection\n\ninputs\n\n* `object`:\n\n  ```json\n  {\n    \"followers\": {\n      \"type\": \"OrderedCollection\"\n    }\n  }\n  ```\n\ntest targets\n\n* ```json\n  {\n    \"type\": \"OrderedCollection\"\n  }\n  ```\n\n    * outcome: `passed`\n\n### Passed Example 3 - followers type includes OrderedCollection\n\ninputs\n\n* `object`:\n\n  ```json\n  {\n    \"followers\": {\n      \"type\": [\"FancyCollection\", \"OrderedCollection\"]\n    }\n  }\n  ```\n\ntest targets\n\n* ```json\n  {\n    \"type\": [\"FancyCollection\", \"OrderedCollection\"]\n  }\n  ```\n\n    * outcome: `passed`\n        * rationale\n            * `\"FancyCollection\"` is not well-defined here,\nbut this object still passes the test because at least one of the `type`\nproperty values is `OrderedCollection` and thus satisfies the requirement\nas interpreted.\n\n### Failed Example 1 - followers is a number\n\ninputs\n\n* `object`:\n\n  ```json\n  {\n    \"followers\": 1\n  }\n  ```\n\ntest targets\n\n* ```json\n  1\n  ```\n\n    * outcome: `failed`\n\n### Failed Example 2 - followers is an empty object\n\ninputs\n\n* `object`:\n\n  ```json\n  {\n    \"followers\": {}\n  }\n  ```\n\ntest targets\n\n* ```json\n  {}\n  ```\n\n    * outcome: `failed`\n\n### Failed Example 3 - followers object type is array including only `\"Link\"`\n\ninputs\n\n* `object`:\n\n  ```json\n  {\n    \"followers\": {\n      \"type\": [\"Link\"]\n    }\n  }\n  ```\n\ntest targets\n\n* ```json\n  {\n    \"type\": [\"Link\"]\n  }\n  ```\n\n    * outcome: `failed`\n\n### Inapplicable Example 1\n\ninputs\n\n* `object`:\n\n  ```json\n  1\n  ```\n\nresult\n\n* outcome: `inapplicable`\n\n### Inapplicable Example 2 - object has no followers property\n\ninputs\n\n* `object`:\n\n  ```json\n  { \"foo\": \"bar\" }\n  ```\n\nresult\n\n* outcome: `inapplicable`\n\n## Glossary [<sup>?</sup>](https://www.w3.org/TR/act-rules-format/#glossary)\n\n### `outcome`\n\nAn outcome is a conclusion that comes from evaluating a test on a test subject. An outcome can be one of the three following types:\n\n* `inapplicable`: No part of the test subject matches the applicability\n* `passed`: A test target meets all expectations\n* `failed`: A test target does not meet all expectations\n\n## Requirements Mapping [<sup>?</sup>][act-rules-requirements-mapping]\n\n* [ActivityPub requirement abef3a0a-d3c4-4dee-a320-b28837d0bcd8][requirement-1] - The followers collection MUST be either an OrderedCollection or a Collection\n    * Required for Conformance to [ActivityPub][activitypub]\n    * Outcome Mapping\n        * when every test target has outcome `passed`, the requirement is satisfied by the test subject\n        * when any test target has outcome `failed`, the requirement is not satisfied by the test subject\n        * when any test target has outcome `inapplicable`, further testing is needed to determine requirement satisfaction\n\n## Issues [<sup>?</sup>][test-issues-list]\n\n## Change Log\n\n* 2023-12-06T07:43:27.890Z - init\n* 2023-12-18T05:11:09.722Z - add test cases based on implementing\n\n[requirement-1]: https://socialweb.coop/activitypub/behaviors/abef3a0a-d3c4-4dee-a320-b28837d0bcd8/\n[act-rules-requirements-mapping]: https://www.w3.org/TR/act-rules-format/#accessibility-requirements-mapping\n[activitypub]: https://www.w3.org/TR/activitypub/\n[test-applicability]: https://www.w3.org/TR/act-rules-format/#applicability\n[test-assumptions]: https://www.w3.org/TR/act-rules-format/#assumptions\n[test-background]: https://www.w3.org/TR/act-rules-format/#background\n[test-expectations]: https://www.w3.org/TR/act-rules-format/#expectations\n[test-input]: https://www.w3.org/TR/act-rules-format/#input\n[test-issues-list]: https://www.w3.org/TR/act-rules-format/#issues-list\n[test-test-cases]: https://www.w3.org/TR/act-rules-format/#test-cases\n",
  "name": "An ActivityPub Actor Object's `followers` Collection Must be a Collection",
  "description": "tests whether an ActivityPub Object has a `followers`` collection with an appropriate Collection type",
  "slug": "followers-collection-must-be-a-collection",
  "inapplicableCases": [
    {
      "name": "Inapplicable Example 1 - object is a number",
      "result": {
        "outcome": "inapplicable"
      },
      "input": {
        "object": "42"
      }
    },
    {
      "name": "Inapplicable Example 2 - object has no followers property",
      "result": {
        "outcome": "inapplicable"
      },
      "input": {
        "object": "{ \"foo\": \"bar\" }"
      }
    },
    {
      "name": "inapplicable example 3 - html object",
      "input": {
        "object": "<!doctype html>hi"
      },
      "result": {
        "outcome": "inapplicable"
      }
    }
  ],
  "passedCases": [
    {
      "name": "Passed Example 1",
      "result": {
        "outcome": "passed"
      },
      "input": {
        "object": "\n        {\n          \"followers\": {\n            \"type\": \"Collection\"\n          }\n        }\n      "
      }
    },
    {
      "name": "Passed Example 2",
      "result": {
        "outcome": "passed"
      },
      "input": {
        "object": "\n        {\n          \"followers\": {\n            \"type\": \"OrderedCollection\"\n          }\n        }\n      "
      }
    }
  ],
  "failedCases": [
    {
      "name": "Failed Example 1 - followers is a number",
      "result": {
        "outcome": "failed"
      },
      "input": {
        "object": "\n        {\n          \"followers\": 42\n        }\n      "
      }
    },
    {
      "name": "Failed Example 2 - followers is an empty object",
      "result": {
        "outcome": "failed"
      },
      "input": {
        "object": "\n        {\n          \"followers\": {}\n        }\n      "
      }
    },
    {
      "name": "Failed Example 3 - followers object type is array including only `\"Link\"`",
      "result": {
        "outcome": "failed"
      },
      "input": {
        "object": "\n        {\n          \"followers\": {\n            \"type\": [\"Link\"]\n          }\n        }\n      "
      }
    }
  ],
  "uuid": "018c3e08-611f-7e56-9f45-2fe5e4877d4e",
  "isPartOf": [
    "https://socialweb.coop/activitypub/test-cases/"
  ],
  "requirementReference": [
    {
      "id": "urn:uuid:abef3a0a-d3c4-4dee-a320-b28837d0bcd8",
      "url": "https://socialweb.coop/activitypub/behaviors/abef3a0a-d3c4-4dee-a320-b28837d0bcd8"
    }
  ]
}