Skip to content

Commit

Permalink
Add unit test for outbox
Browse files Browse the repository at this point in the history
  • Loading branch information
mike182uk committed Aug 30, 2024
1 parent e0b15f2 commit c4f0ba4
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 101 deletions.
2 changes: 0 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ services:
test: "mysql -ughost -ppassword activitypub -e 'select 1'"
interval: 1s
retries: 120
ports:
- "3308:3306"

wiremock:
image: wiremock/wiremock:latest
Expand Down
27 changes: 0 additions & 27 deletions features/outbox.feature

This file was deleted.

76 changes: 5 additions & 71 deletions features/step_definitions/stepdefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { BeforeAll, AfterAll, Before, After, Given, When, Then } from '@cucumber
import { v4 as uuidv4 } from 'uuid';
import { WireMock } from 'wiremock-captain';

async function createActivity(activityType, object, actor, name) {
async function createActivity(activityType, object, actor, remote = true) {
if (activityType === 'Follow') {
return {
'@context': [
Expand Down Expand Up @@ -40,7 +40,7 @@ async function createActivity(activityType, object, actor, name) {
'https://w3id.org/security/data-integrity/v1',
],
'type': 'Create',
'id': `http://wiremock:8080/create/${name || '1'}`,
'id': 'http://wiremock:8080/create/1',
'to': 'as:Public',
'object': object,
actor: actor,
Expand Down Expand Up @@ -166,6 +166,8 @@ BeforeAll(async function () {
database: process.env.MYSQL_DATABASE
}
});

await client('key_value').truncate();
});

BeforeAll(async function () {
Expand All @@ -178,7 +180,6 @@ AfterAll(async function () {

Before(async function () {
await captain.clearAllRequests();
await client('key_value').truncate();
});

Before(async function () {
Expand All @@ -205,7 +206,7 @@ Given('a {string} Activity {string} by {string}', async function (activityDef, n
const object = this.actors[objectName] ?? this.activities[objectName] ?? await createObject(objectName);
const actor = this.actors[actorName];

const activity = await createActivity(activityType, object, actor, name);
const activity = await createActivity(activityType, object, actor);

this.activities[name] = activity;
});
Expand Down Expand Up @@ -359,70 +360,3 @@ Then('{string} is in our Followers once only', async function (actorName) {

assert.equal(found.length, 1);
});

When('the contents of the outbox is requested', async function () {
const response = await fetch('http://activitypub-testing:8083/.ghost/activitypub/outbox/index', {
headers: {
'Content-Type': 'application/ld+json'
},
});

this.response = await response.json();
});

When('{string} adds {string} to the Outbox', async function (actorName, activityName) {
if (!this.actors[actorName]) {
throw new Error(`Could not find Actor ${actorName}`);
}
if (!this.activities[activityName]) {
throw new Error(`Could not find Activity ${activityName}`);
}

const activity = this.activities[activityName];

// Add activity to the db
const activityKey = JSON.stringify([activity.id]);

if (
(await client('key_value').select('value').where({ key: activityKey })).length === 0
) {
await client('key_value').insert({
key: activityKey,
value: JSON.stringify(activity)
})
}

// Add activity to the outbox
const outboxKey = JSON.stringify(["sites","activitypub-testing:8083","outbox"]);
const outbox = (
await client('key_value').select('value').where('key', outboxKey)
).map((item) => item.value)[0] || [];

outbox.push(activity.id)

if (outbox.length === 1) {
await client('key_value').insert({
key: outboxKey,
value: JSON.stringify(outbox)
})
} else {
await client('key_value')
.where({ key: outboxKey })
.update({
value: JSON.stringify(outbox)
})
}
});

Then(/^the outbox contains ([0-9]+) (activity|activities)$/, function (count, word) {
assert.equal(this.response.totalItems, count);
});

Then('the items in the outbox are in the order: {string}', function (order) {
order.split(",").map((item) => item.trim()).forEach((activityName, index) => {
assert.ok(
this.response.orderedItems[index].id.endsWith(activityName),
`${this.response.orderedItems[index].id} does not end with ${activityName} as expected`
)
})
});
76 changes: 75 additions & 1 deletion src/dispatchers.unit.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import assert from 'assert';
import sinon from 'sinon';
import {
actorDispatcher,
keypairDispatcher,
Expand All @@ -18,7 +19,7 @@ import {
acceptDispatcher,
createDispatcher,
} from './dispatchers';
import { RequestContext } from '@fedify/fedify';
import { Activity, RequestContext } from '@fedify/fedify';
import { ACTOR_DEFAULT_HANDLE } from './constants';

describe('dispatchers', function () {
Expand All @@ -35,4 +36,77 @@ describe('dispatchers', function () {
});
describe('keypairDispatcher', function () {});
describe('handleFollow', function () {});

describe('outboxDispatcher', function () {
const outboxActivities: Record<string, any> = {
'https://example.com/create/123': {
'@context': [
'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/data-integrity/v1',
],
id: 'https://example.com/create/123',
type: 'Create',
},
'https://example.com/announce/456': {
'@context': [
'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/data-integrity/v1',
],
type: 'Announce',
id: 'https://example.com/announce/456',
},
'https://example.com/accept/789': {
'@context': [
'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/data-integrity/v1',
],
type: 'Accept',
id: 'https://example.com/accept/789',
},
'https://example.com/like/987': {
'@context': [
'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/data-integrity/v1',
],
type: 'Like',
id: 'https://example.com/like/987',
},
};

const ctx = {
data: {
db: {
get: sinon.stub(),
},
globaldb: {
get: sinon.stub(),
},
},
} as RequestContext<any>;

beforeEach(function () {
ctx.data.db.get.withArgs(['outbox']).resolves(Object.keys(outboxActivities));

Object.keys(outboxActivities).forEach(key => {
ctx.data.globaldb.get.withArgs([key]).resolves(outboxActivities[key]);
});
});

it('returns relevant items from the outbox in the correct order', async function () {
const result = await outboxDispatcher(ctx, ACTOR_DEFAULT_HANDLE);

// Check items exist
assert.ok(result.items);

// Check correct items are returned in the correct order
assert.equal(result.items.length, 2);
assert.equal(result.items[0] instanceof Activity, true);
assert.equal(result.items[1] instanceof Activity, true);

// @ts-ignore: We know that this is the correct type because of the above assertions
assert.equal(result.items[0].id.toString(), 'https://example.com/announce/456');
// @ts-ignore: We know that this is the correct type because of the above assertions
assert.equal(result.items[1].id.toString(), 'https://example.com/create/123');
});
});
});

0 comments on commit c4f0ba4

Please sign in to comment.