---
base:
  '#initialize': [
    [
      'MUST initialize',
      [],
      [[], {}]
    ]
  ]
  '#clear': [
    [
      'MUST clear the root',
      [
        ['set', '/setup/driver/uuid', 'cc88b93a-3556-4e44-9b81-c45aa1ba9604'],
        ['set', '/setup/driver/connected', true],
        ['clear']
      ],
      [[], {}]
    ]
  ]
  '#set': [
    [
      'MUST set a single value "/a", true',
      [
        ['set', '/a', true]
      ],
      [['a'], true]
    ],
    [
      'MUST set a single value "/a/b", true',
      [
        ['set', '/a/b', true]
      ],
      [['a', 'b'], true]
    ],
    [
      'MUST set a single value "/a/b/c", true',
      [
        ['set', '/a/b/c', true]
      ],
      [['a', 'b', 'c'], true]
    ]
  ]
  '#get': [
    [
      'MUST return a #set value at a path',
      [['set', '/setup/driver/uuid', 'cc88b93a-3556-4e44-9b81-c45aa1ba9604']],
      ['get', '/setup/driver/uuid', 'cc88b93a-3556-4e44-9b81-c45aa1ba9604']
    ],
    [
      'MUST return nil for a #delete(d) value at a path',
      [
        ['set', '/setup/driver/uuid', 'cc88b93a-3556-4e44-9b81-c45aa1ba9604'],
        ['delete', '/setup/driver/uuid']
      ],
      ['get', '/setup/driver/uuid', undefined]
    ]
  ]
  '#delete': [
    [
      'MUST set a single value "/a", true',
      [
        ['set', '/a', true],
        ['delete', '/a']
      ],
      [[], {}]
    ],
    [
      'MUST delete a single value "/a/b", true',
      [
        ['set', '/a/b', true],
        ['delete', '/a/b']
      ],
      [[], {}]
    ],
    [
      'MUST delete a single value "/a/b/c", true',
      [
        ['set', '/a/b/c', true],
        ['delete', '/a/b/c']
      ],
      [[], {}]
    ],
    [
      'MUST not clear the root when deleting a root key',
      [
        ['set', '/a1', true],
        ['set', '/a2', true],
        ['delete', '/a2']
      ],
      [[], { 'a1': true }]
    ]
  ]
convenience:
  '#each': [
    [
      'MUST call with the elements of an array',
      [['each', '/setup/rooms/1/area_paths']],
      ['/areas/1', '/areas/2']
    ]
  ]
  '#has': [
    ['MUST return false when path does not exist', ['has', '/setup/areas/2'], false],
    ['MUST return true when path does exist', ['has', '/setup/rooms/1/name'], true],
    ['MUST return true when path does exist but is an empty hash', ['has', '/setup/components'], true]
  ]
  '#includes': [
    ['MUST return true if the found array has a value', ['includes', '/setup/rooms/1/area_paths', '/areas/1'], true],
    ['MUST return false if the found value is not an array', ['includes', '/setup/areas/1', '/rooms/11'], false],
    ['MUST return false if the found array does not have a value', ['includes', '/setup/areas/1/room_paths', '/rooms/11'], false]
  ]
  '#any': [
    ['MUST return true if node is a hash and is not empty', ['any', '/setup/rooms/1'], true],
    ['MUST return false if node is an empty hash', ['any', '/setup/drivers'], false],
    ['MUST return false if node is an array', ['any', '/setup/areas/1/room_paths'], false],
    ['MUST return false if node is an empty hash', ['any', '/setup/areas/1/name'], false]
  ]
  '#keys': [
    ['MUST return an array of the keys at a node', ['keys', '/setup/rooms'], ['1', '2']],
    ['MUST return an empty array if the node is primitive', ['keys', '/setup/areas/1/name'], []],
    ['MUST return an empty array if the node is an array', ['keys', '/setup/areas/1/room_paths'], []]
  ]
  '#branchPaths': [
    ['MUST return branch paths that exist at a passed path', ['branchPaths', '/setup/components/1'], ['/components/1', '/components/1/displays/1']]
  ]
  '#push': [
    [
      "'/setup/rooms/2/area_paths', '/areas/2'",
      [['push', '/setup/rooms/1/area_paths', '/areas/2']],
      [['/setup/rooms/1/area_paths', ['/areas/1', '/areas/2']]]
    ]
  ]
  '#pull': [
    [
      "'/setup/rooms/2/area_paths', '/areas/2'",
      [['pull', '/setup/rooms/1/area_paths', '/areas/2']],
      [['/setup/rooms/1/area_paths', ['/areas/1']]]
    ]
  ]
  '#add': [
    [
      "'/setup/rooms', { name: 'Dining Room' }",
      [['add', '/setup/rooms', { 'name': 'Dining Room'}]],
      [['/setup/rooms/3', { 'name': 'Dining Room' }]]
    ],
    [
      "'/setup/components', { 'name': 'Component 3' }",
      [['add', '/setup/components', { 'name': 'Component 3'}]],
      [['/setup/components/3', { 'name': 'Component 3' }]]
    ]
  ]
external:
  '#read': [
    [
      'MUST read a datastore node when passed a standard topic, "/setup"',
      [
        ['set', '/setup/rooms/1/name', 'Kitchen'],
        ['set', '/setup/rooms/2/name', 'Breakfast Room']
      ],
      ['read', '/setup', { 'rooms': { '1': { 'name': 'Kitchen' }, '2': { 'name': 'Breakfast Room' }}}]
    ],
    [
      'MUST read a coppiced datastore node when passed a standard topic "/setup" and { coppiced: true }',
      [
        ['set', '/setup/rooms/1/name', 'Kitchen'],
        ['set', '/setup/rooms/2/name', 'Breakfast Room']
      ],
      ['read', '/setup', { coppiced: true }, { '/setup/rooms/1/name': 'Kitchen', '/setup/rooms/2/name': 'Breakfast Room' }]
    ],
    [
      'MUST read a coppiced datastore node when passed a MQTT topic, "/setup/rooms/+/name"',
      [
        ['set', '/setup/rooms/1/name', 'Kitchen'],
        ['set', '/setup/rooms/2/name', 'Breakfast Room']
      ],
      ['read', '/setup/rooms/+/name', { '/setup/rooms/1/name': 'Kitchen', '/setup/rooms/2/name': 'Breakfast Room' }]
    ],
    [
      'MUST read a coppiced datastore node when passed a standard topic "/setup/rooms/+/name" and { coppiced: true }',
      [
        ['set', '/setup/rooms/1/name', 'Kitchen'],
        ['set', '/setup/rooms/2/name', 'Breakfast Room']
      ],
      ['read', '/setup/rooms/+/name', { coppiced: true }, { '/setup/rooms/1/name': 'Kitchen', '/setup/rooms/2/name': 'Breakfast Room' }]
    ],
    [
      'MUST return an empty value when MQTT topic is deeper than existing data "/setup/rooms/+/+/#"',
      [
        ['set', '/setup/rooms/1/name', 'Kitchen'],
        ['set', '/setup/rooms/2/name', 'Breakfast Room']
      ],
      ['read', '/setup/rooms/+/+/#', {}]
    ],
    [
      'MUST return an empty value when MQTT topic is deeper than existing data "/setup/rooms/+/+/+"',
      [
        ['set', '/setup/rooms/1/name', 'Kitchen'],
        ['set', '/setup/rooms/2/name', 'Breakfast Room']
      ],
      ['read', '/setup/rooms/+/+/+', {}]
    ],
    [
      'MUST return an empty value when MQTT topic is deeper than existing data "/setup/rooms/+/+/*"',
      [
        ['set', '/setup/rooms/1/name', 'Kitchen'],
        ['set', '/setup/rooms/2/name', 'Breakfast Room']
      ],
      ['read', '/setup/rooms/+/+/*', {}]
    ],
    [
      'MUST read a coppiced datastore node when passed a MQTT topic, "systems/local/setup/components/+/displays/+/name"',
      [],
      ['read', 'systems/local/setup/components/+/displays/+/name', {
        '/systems/local/setup/components/1/displays/1/name': 'Kitchen Display',
        '/systems/local/setup/components/2/displays/1/name': 'Breakfast Room Display'
      }]
    ]
  ]
  '#search': [
    [
      'MUST find a single matched primitive from a standard topic "setup/rooms/1/name"',
      [
        ['set', '/setup/rooms/1/name', 'Kitchen'],
        ['set', '/setup/rooms/2/name', 'Breakfast Room']
      ],
      ['search', 'setup/rooms/1/name', { '/setup/rooms/1/name': 'Kitchen' }]
    ],
    [
      'MUST find a multiple matched primitives from a MQTT topic "setup/rooms/+/name"',
      [
        ['set', '/setup/rooms/1/name', 'Kitchen'],
        ['set', '/setup/rooms/2/name', 'Breakfast Room']
      ],
      ['search', 'setup/rooms/+/name', { '/setup/rooms/1/name': 'Kitchen', '/setup/rooms/2/name': 'Breakfast Room' }]
    ],
    [
      'MUST find a multiple matched primitives from a MQTT topic "setup/rooms/#"',
      [
        ['set', '/setup/rooms/1/name', 'Kitchen'],
        ['set', '/setup/rooms/2/name', 'Breakfast Room']
      ],
      ['search', 'setup/rooms/#', { '/setup/rooms/1/name': 'Kitchen', '/setup/rooms/2/name': 'Breakfast Room' }]
    ]
  ]
  '#write': [
    [
      'MUST overwrite a datastore node "setup/rooms/1/name"',
      [
        ['set', '/setup/rooms/1/name', 'Kitchen'],
        ['set', '/setup/rooms/2/name', 'Breakfast Room'],
        ['write', '/setup/rooms', { '1': { 'name': 'Dining Room' }}]
      ],
      ['read', 'setup/rooms', { '1': { 'name': 'Dining Room' } }]
    ]
  ]
  '#merge': [
    [
      'MUST integrate value paths in a datastore node setup/rooms/1/name',
      [
        ['set', '/setup/rooms/1/name', 'Kitchen'],
        ['set', '/setup/rooms/2/name', 'Breakfast Room'],
        ['merge', '/setup/rooms', { '3': { 'name': 'Dining Room' } }]
      ],
      ['read', 'setup/rooms', { '1': { 'name': 'Kitchen' }, '2': { 'name': 'Breakfast Room' }, '3': { 'name': 'Dining Room' } }]
    ],
    [
      'MUST set values to a new node',
      [
        ['merge', '/state/components/1/calendars/1/update/organizer/email', 'spec@controlenvy.com']
      ],
      ['read', '/state/components/1/calendars/1/update/organizer/email', 'spec@controlenvy.com']
    ],
    [
      'MUST overwrite primitive values',
      [
        ['merge', '/state/components/1/calendars/1/update/organizer/email', 'rspec@controlenvy.com'],
        ['merge', '/state/components/1/calendars/1/update/organizer/email', 'spec@controlenvy.com']
      ],
      ['read', '/state/components/1/calendars/1/update/organizer/email', 'spec@controlenvy.com']
    ],
    [
      'MUST overwrite primitive values',
      [
        ['merge', '/state/components/1/calendars/1/update/organizer/email', 'spec@controlenvy.com'],
        ['merge', '/state/components/1/calendars/1/update/organizer', 'controlenvy']
      ],
      ['read', '/state/components/1/calendars/1/update/organizer', 'controlenvy']
    ],
    [
      'MUST overwrite nodes when the path becomes a primitive value',
      [
        ['merge', '/state/components/1/calendars/1/update/organizer/email', 'spec@controlenvy.com'],
        ['merge', '/state/components/1/calendars/1/update/organizer', 'controlenvy']
      ],
      ['read', '/state/components/1/calendars/1/update/organizer', 'controlenvy']
    ],
    [
      'MUST overwrite primitive values when the path becomes a node',
      [
        ['merge', '/state/components/1/calendars/1/update/organizer', 'controlenvy'],
        ['merge', '/state/components/1/calendars/1/update/organizer/email', 'spec@controlenvy.com']
      ],
      ['read', '/state/components/1/calendars/1/update/organizer', { 'email': 'spec@controlenvy.com' }]
    ]
  ]
pubsub:
  '#topic_tree': [
    [
      'MUST add MQTT topics to the topic tree "state/components/+/status"',
      [
        ['subscribe', 'state/components/+/status', '#subscriber', '#callback']
      ],
      [['state/components/1/status', 'state/components/+/status', '#subscriber']]
    ],
    [
      'MUST remove MQTT topic from the topic tree "state/components/+/status"',
      [
        ['subscribe', 'state/components/+/status', '#subscriber', '#callback'],
        ['unsubscribe', 'state/components/+/status', '#subscriber', '#callback']
      ],
      [['state/components/1/status', null]]
    ],
    [
      'MUST not affect other subscribers when identical topic is removed from the topic tree',
      [
        ['subscribe', 'state/components/1/status', '#subscriber_1', '#callback'],
        ['subscribe', 'state/components/1/status', '#subscriber_2', '#callback'],
        ['unsubscribe', 'state/components/1/status', '#subscriber_1', '#callback']
      ],
      [['state/components/1/status', 'state/components/1/status', '#subscriber_2']]
    ],
    [
      'MUST not affect other subscriber when one topic is removed from the topic tree',
      [
        ['subscribe', 'state/components/+/status', '#subscriber', '#callback'],
        ['subscribe', 'state/components/1/status', '#subscriber', '#callback'],
        ['unsubscribe', 'state/components/+/status', '#subscriber', '#callback']
      ],
      [['state/components/1/status', 'state/components/1/status', '#subscriber']]
    ]
  ]
  '#subscribe': [
    [
      'MUST publish a single matched exact topic "setup/rooms/1/name"',
      [
        ['subscribe', 'setup/rooms/1/name', '#subscriber', '#callback', { immediate: false }],
        ['set', '/setup/rooms/1/name', 'Kitchen']
      ],
      [
        ['setup/rooms/1/name', '/setup/rooms/1/name', 'Kitchen' ]
      ]
    ],
    [
      'MUST publish a single matched exact topic "setup/rooms/1/name" with immediate flag',
      [
        ['set', '/setup/rooms/1/name', 'Kitchen'],
        ['set', '/setup/rooms/2/name', 'Patio'],
        ['subscribe', 'setup/rooms/1/name', '#subscriber', '#callback']
      ],
      [
        ['setup/rooms/1/name', '/setup/rooms/1/name', 'Kitchen' ]
      ]
    ],
    [
      'MUST publish the root wildcard topic "#"',
      [
        ['subscribe', '#', '#subscriber', '#callback', { immediate: false }],
        ['set', '/setup/rooms/1/name', 'Kitchen']
      ],
      [
        ['#', '/setup', {}],
        ['#', '/setup/rooms', {}],
        ['#', '/setup/rooms/1', {}],
        ['#', '/setup/rooms/1/name', 'Kitchen']
      ]
    ],
    [
      'MUST publish a single matched wildcard topic containing "#", "setup/#"',
      [
        ['write', '/setup/rooms/1/name', 'Patio'],
        ['subscribe', 'setup/#', '#subscriber', '#callback', { immediate: false }],
        ['write', '/setup/rooms/1/name', 'Kitchen']
      ],
      [['setup/#', '/setup/rooms/1/name', 'Kitchen']]
    ],
    [
      'MUST publish a single matched wildcard topic containing "+", "setup/rooms/+/name"',
      [
        ['subscribe', 'setup/rooms/+/name', '#subscriber', '#callback', { immediate: false }],
        ['set', '/setup/rooms/1/name', 'Kitchen']
      ],
      [
        ['setup/rooms/+/name', '/setup/rooms/1/name', 'Kitchen' ]
      ]
    ],
    [
      'MUST publish a single matched wildcard topic containing "*", "setup/rooms/*"',
      [
        ['subscribe', 'setup/rooms/*', '#subscriber', '#callback', { immediate: false }],
        ['set', '/setup/rooms/1/name', 'Kitchen']
      ],
      [
        ['setup/rooms/*', '/setup/rooms', { '1': { } }],
        ['setup/rooms/*', '/setup/rooms', { '1': { 'name': 'Kitchen' } }]
      ]
    ],
    [
      'MUST publish a single matched wildcard topic ending with "+", "setup/rooms/1/+"',
      [
        ['subscribe', 'setup/rooms/1/+', '#subscriber', '#callback', { immediate: false }],
        ['set', '/setup/rooms/1/name', 'Kitchen']
      ],
      [
        ['setup/rooms/1/+', '/setup/rooms/1/name', 'Kitchen']
      ]
    ],
    [
      'MUST publish a wildcard topic with two "+", "setup/+/+"',
      [
        ['subscribe', 'setup/+/+', '#subscriber', '#callback', { immediate: false }],
        ['write', '/setup/rooms/1/name', 'Kitchen']
      ],
      [['setup/+/+', '/setup/rooms/1', {}]]
    ],
    [
      'MUST publish a wildcard topic with "+" and "#", "setup/+/#"',
      [
        ['subscribe', 'setup/+/#', '#subscriber', '#callback', { immediate: false }],
        ['write', '/setup/rooms/1/name', 'Kitchen']
      ],
      [
         ['setup/+/#', '/setup/rooms/1', {}],
         ['setup/+/#', '/setup/rooms/1/name', 'Kitchen']
      ]
    ],
    [
      'MUST publish a wildcard topic with "+" and "*", "setup/+/*"',
      [
        ['subscribe', 'setup/+/*', '#subscriber', '#callback', { immediate: false }],
        ['write', '/setup/rooms/1/name', 'Kitchen']
      ],
      [
         ['setup/+/*', '/setup/rooms', { '1': {} }],
         ['setup/+/*', '/setup/rooms', { '1': { 'name': 'Kitchen' }}]
      ]
    ],
    [
      'MUST publish the root wildcard topic "#" with immediate flag',
      [
        ['set', '/setup/rooms/1/name', 'Kitchen'],
        ['subscribe', '#', '#subscriber', '#callback']
      ],
      [['#', '/setup/rooms/1/name', 'Kitchen']]
    ],
    [
      'MUST publish multiple matching paths with immediate flag',
      [
        ['set', '/setup/rooms/1/name', 'Kitchen'],
        ['set', '/setup/rooms/2/name', 'Patio'],
        ['subscribe', '#', '#subscriber', '#callback']
      ],
      [
        ['#', '/setup/rooms/1/name', 'Kitchen'],
        ['#', '/setup/rooms/2/name', 'Patio']
      ]
    ],
    [
      'MUST publish multiple matched subscribers',
      [
        ['subscribe', 'setup/rooms/+/name', '#subscriber', '#callback', { immediate: false }],
        ['subscribe', 'setup/rooms/1/name', '#subscriber', '#callback', { immediate: false }],
        ['set', '/setup/rooms/1/name', 'Patio']
      ],
      [
        ['setup/rooms/1/name', '/setup/rooms/1/name', 'Patio'],
        ['setup/rooms/+/name', '/setup/rooms/1/name', 'Patio']
      ]
    ],
    [
      'FLAGGED > MUST publish a null value for a single matched wildcard topic ending in "*", "setup/*"',
      [
        ['write', '/setup/rooms/1/name', 'Kitchen'],
        ['subscribe', 'setup/*', '#subscriber', '#callback', { immediate: false }],
        ['write', '/setup/rooms/1', null]
      ],
      [
         ['setup/*', '/setup', null]
      ]
    ],
    [
      'FLAGGED > MUST publish a single matched topic if a parent node is deleted, "setup/rooms/1/name"',
      [
        ['write', '/setup/rooms/1/name', 'Kitchen'],
        ['subscribe', 'setup/rooms/1/name', '#subscriber', '#callback', { immediate: false }],
        ['write', '/setup/rooms/1', null]
      ],
      [['setup/rooms/+/name', '/setup/rooms/1/name', null]]
    ],
    [
      'FLAGGED > MUST publish a single matched wildcard topic if a parent node is deleted, "setup/rooms/1/name"',
      [
        ['write', '/setup/rooms/1/name', 'Kitchen'],
        ['subscribe', 'setup/rooms/+/name', '#subscriber', '#callback', { immediate: false }],
        ['write', '/setup/rooms/1', null]
      ],
      [['setup/rooms/+/name', '/setup/rooms/1/name', null]]
    ]
  ]
  '#unsubscribe': [
    [
      'MUST NOT error if pointer has no subscribers',
      [['subscribe', 'expected/to/error', '#subscriber', '#callback', { immediate: false }]],
      []
    ],
    [
      'MUST NOT error if pointer has no subscribers',
      [['subscribe', 'expected/to/error', '#subscriber', '#callback', { immediate: false }]],
      []
    ]
  ]