Files
NodeBB/test/activitypub/analytics.js

157 lines
4.3 KiB
JavaScript

'use strict';
const assert = require('assert');
const nconf = require('nconf');
const db = require('../../src/database');
const controllers = require('../../src/controllers');
const middleware = require('../../src/middleware');
const activitypub = require('../../src/activitypub');
const utils = require('../../src/utils');
const user = require('../../src/user');
const categories = require('../../src/categories');
const topics = require('../../src/topics');
const analytics = require('../../src/analytics');
const api = require('../../src/api');
describe('Analytics', () => {
let cid;
let uid;
let postData;
before(async () => {
nconf.set('runJobs', 1);
({ cid } = await categories.create({ name: utils.generateUUID().slice(0, 8) }));
const remoteUser = {
'@context': 'https://www.w3.org/ns/activitystreams',
id: 'https://example.org/user/foobar',
url: 'https://example.org/user/foobar',
type: 'Person',
name: 'Foo Bar',
preferredUsername: 'foobar',
publicKey: {
id: 'https://example.org/user/foobar#key',
owner: 'https://example.org/user/foobar',
publicKeyPem: 'publickey',
},
};
activitypub._cache.set(`0;https://example.org/user/foobar`, remoteUser);
});
after(async () => {
nconf.set('runJobs', undefined);
});
beforeEach(async () => {
uid = await user.create({ username: utils.generateUUID().slice(0, 8) });
({ postData } = await topics.post({
uid,
cid,
title: utils.generateUUID(),
content: utils.generateUUID(),
}));
});
it('should record the incoming activity if successfully processed', async () => {
const id = `https://example.org/activity/${utils.generateUUID()}`;
await controllers.activitypub.postInbox({
body: {
id,
type: 'Like',
actor: 'https://example.org/user/foobar',
object: {
type: 'Note',
id: `${nconf.get('url')}/post/${postData.pid}`,
},
},
}, { sendStatus: () => {} });
const processed = await db.isSortedSetMember('activities:datetime', id);
assert(processed);
});
it('should not process the activity if received again', async () => {
// Specifically, the controller would update the score, but the request should be caught in middlewares and ignored
const id = `https://example.org/activity/${utils.generateUUID()}`;
await controllers.activitypub.postInbox({
body: {
id,
type: 'Like',
actor: 'https://example.org/user/foobar',
object: {
type: 'Note',
id: `${nconf.get('url')}/post/${postData.pid}`,
},
},
}, { sendStatus: () => {} });
await middleware.activitypub.assertPayload({
body: {
id,
type: 'Like',
actor: 'https://example.org/user/foobar',
object: {
type: 'Note',
id: `${nconf.get('url')}/post/${postData.pid}`,
},
},
}, {
sendStatus: (statusCode) => {
assert.strictEqual(statusCode, 200);
},
});
});
it('should increment the last seen time of that domain', async () => {
const id = `https://example.org/activity/${utils.generateUUID()}`;
const before = await db.sortedSetScore('instances:lastSeen', 'example.org');
await controllers.activitypub.postInbox({
body: {
id,
type: 'Like',
actor: 'https://example.org/user/foobar',
object: {
type: 'Note',
id: `${nconf.get('url')}/post/${postData.pid}`,
},
},
}, { sendStatus: () => {} });
const after = await db.sortedSetScore('instances:lastSeen', 'example.org');
assert(before && after);
assert(before < after);
});
it('should increment various metrics', async () => {
let counters;
analytics.pause = true;
({ counters } = analytics.peek());
const before = { ...counters };
const id = `https://example.org/activity/${utils.generateUUID()}`;
await controllers.activitypub.postInbox({
body: {
id,
type: 'Like',
actor: 'https://example.org/user/foobar',
object: {
type: 'Note',
id: `${nconf.get('url')}/post/${postData.pid}`,
},
},
}, { sendStatus: () => {} });
({ counters } = analytics.peek());
const after = { ...counters };
const metrics = ['activities', 'activities:byType:Like', 'activities:byHost:example.org'];
metrics.forEach((metric) => {
before[metric] = before[metric] || 0;
assert(before.hasOwnProperty(metric) && after.hasOwnProperty(metric), JSON.stringify({ before, after }, null, 2));
assert(before[metric] < after[metric]);
});
analytics.pause = false;
});
});