2023-06-21 11:56:59 +03:00
|
|
|
const assert = require('assert/strict');
|
2023-01-17 10:55:53 +03:00
|
|
|
const ObjectID = require('bson-objectid');
|
|
|
|
const Mention = require('../lib/Mention');
|
2023-08-31 17:57:18 +03:00
|
|
|
const cheerio = require('cheerio');
|
|
|
|
const sinon = require('sinon');
|
2023-01-17 10:55:53 +03:00
|
|
|
|
|
|
|
const validInput = {
|
|
|
|
source: 'https://source.com',
|
|
|
|
target: 'https://target.com',
|
|
|
|
sourceTitle: 'Title!',
|
|
|
|
sourceExcerpt: 'Excerpt!'
|
|
|
|
};
|
|
|
|
|
|
|
|
describe('Mention', function () {
|
|
|
|
describe('toJSON', function () {
|
|
|
|
it('Returns a object with the expected properties', async function () {
|
|
|
|
const mention = await Mention.create(validInput);
|
|
|
|
const actual = Object.keys(mention.toJSON());
|
|
|
|
const expected = [
|
|
|
|
'id',
|
|
|
|
'source',
|
|
|
|
'target',
|
|
|
|
'timestamp',
|
|
|
|
'payload',
|
|
|
|
'resourceId',
|
2023-02-21 08:02:47 +03:00
|
|
|
'resourceType',
|
2023-01-17 10:55:53 +03:00
|
|
|
'sourceTitle',
|
2023-01-18 08:32:37 +03:00
|
|
|
'sourceSiteTitle',
|
|
|
|
'sourceAuthor',
|
2023-01-17 10:55:53 +03:00
|
|
|
'sourceExcerpt',
|
|
|
|
'sourceFavicon',
|
2023-02-16 10:37:22 +03:00
|
|
|
'sourceFeaturedImage',
|
|
|
|
'verified'
|
2023-01-17 10:55:53 +03:00
|
|
|
];
|
|
|
|
assert.deepEqual(actual, expected);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2023-02-13 15:18:17 +03:00
|
|
|
describe('verify', function () {
|
2023-08-31 17:57:18 +03:00
|
|
|
afterEach(function () {
|
|
|
|
sinon.restore();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('can handle invalid HTML', async function () {
|
|
|
|
const mention = await Mention.create(validInput);
|
|
|
|
assert(!mention.verified);
|
|
|
|
|
|
|
|
sinon.stub(cheerio, 'load').throws(new Error('Invalid HTML'));
|
|
|
|
|
|
|
|
mention.verify('irrelevant', 'text/html');
|
|
|
|
assert(!mention.verified);
|
|
|
|
assert(!mention.isDeleted());
|
|
|
|
});
|
|
|
|
|
2023-02-13 15:18:17 +03:00
|
|
|
it('Does basic check for the target URL and updates verified property', async function () {
|
|
|
|
const mention = await Mention.create(validInput);
|
|
|
|
assert(!mention.verified);
|
|
|
|
|
2023-08-31 17:57:18 +03:00
|
|
|
mention.verify('<a href="https://target.com/">', 'text/html');
|
2023-02-13 15:18:17 +03:00
|
|
|
assert(mention.verified);
|
2023-08-31 17:57:18 +03:00
|
|
|
assert(!mention.isDeleted());
|
2023-02-13 15:18:17 +03:00
|
|
|
|
2023-08-31 17:57:18 +03:00
|
|
|
mention.verify('something else', 'text/html');
|
|
|
|
assert(mention.verified);
|
|
|
|
assert(mention.isDeleted());
|
|
|
|
});
|
|
|
|
it('detects differences', async function () {
|
|
|
|
const mention = await Mention.create(validInput);
|
2023-02-13 15:18:17 +03:00
|
|
|
assert(!mention.verified);
|
2023-08-31 17:57:18 +03:00
|
|
|
|
|
|
|
mention.verify('<a href="https://not-target.com/">', 'text/html');
|
|
|
|
assert(!mention.verified);
|
|
|
|
assert(!mention.isDeleted());
|
2023-02-13 15:18:17 +03:00
|
|
|
});
|
2023-02-17 14:56:44 +03:00
|
|
|
it('Does check for Image targets', async function () {
|
|
|
|
const mention = await Mention.create({
|
|
|
|
...validInput,
|
|
|
|
target: 'https://target.com/image.jpg'
|
|
|
|
});
|
|
|
|
assert(!mention.verified);
|
|
|
|
|
2023-08-31 17:57:18 +03:00
|
|
|
mention.verify('<img src="https://target.com/image.jpg">', 'text/html');
|
2023-02-17 14:56:44 +03:00
|
|
|
assert(mention.verified);
|
2023-08-31 17:57:18 +03:00
|
|
|
assert(!mention.isDeleted());
|
2023-02-17 14:56:44 +03:00
|
|
|
|
2023-08-31 17:57:18 +03:00
|
|
|
mention.verify('something else', 'text/html');
|
|
|
|
assert(mention.verified);
|
|
|
|
assert(mention.isDeleted());
|
2023-02-17 14:56:44 +03:00
|
|
|
});
|
|
|
|
it('Does check for Video targets', async function () {
|
|
|
|
const mention = await Mention.create({
|
|
|
|
...validInput,
|
|
|
|
target: 'https://target.com/video.mp4'
|
|
|
|
});
|
|
|
|
assert(!mention.verified);
|
|
|
|
|
2023-08-31 17:57:18 +03:00
|
|
|
mention.verify('<video src="https://target.com/video.mp4">', 'text/html');
|
|
|
|
assert(mention.verified);
|
|
|
|
assert(!mention.isDeleted());
|
|
|
|
|
|
|
|
mention.verify('something else', 'text/html');
|
2023-02-17 14:56:44 +03:00
|
|
|
assert(mention.verified);
|
2023-08-31 17:57:18 +03:00
|
|
|
assert(mention.isDeleted());
|
|
|
|
});
|
|
|
|
|
|
|
|
it('can verify links in JSON', async function () {
|
|
|
|
const mention = await Mention.create(validInput);
|
|
|
|
assert(!mention.verified);
|
|
|
|
|
|
|
|
mention.verify('{"url": "https://target.com/"}', 'application/json');
|
|
|
|
assert(mention.verified);
|
|
|
|
assert(!mention.isDeleted());
|
|
|
|
|
|
|
|
mention.verify('{}', 'application/json');
|
|
|
|
assert(mention.verified);
|
|
|
|
assert(mention.isDeleted());
|
|
|
|
});
|
|
|
|
|
|
|
|
it('can handle invalid JSON', async function () {
|
|
|
|
const mention = await Mention.create(validInput);
|
|
|
|
assert(!mention.verified);
|
2023-02-17 14:56:44 +03:00
|
|
|
|
2023-08-31 17:57:18 +03:00
|
|
|
mention.verify('{"url": "ht', 'application/json');
|
2023-02-17 14:56:44 +03:00
|
|
|
assert(!mention.verified);
|
2023-08-31 17:57:18 +03:00
|
|
|
assert(!mention.isDeleted());
|
2023-02-17 14:56:44 +03:00
|
|
|
});
|
2023-02-13 15:18:17 +03:00
|
|
|
});
|
|
|
|
|
2023-09-26 18:29:17 +03:00
|
|
|
describe('undelete', function () {
|
|
|
|
afterEach(function () {
|
|
|
|
sinon.restore();
|
|
|
|
});
|
|
|
|
|
|
|
|
it('can undelete a verified mention', async function () {
|
|
|
|
const mention = await Mention.create({
|
|
|
|
...validInput,
|
|
|
|
id: new ObjectID(),
|
|
|
|
deleted: true,
|
|
|
|
verified: true
|
|
|
|
});
|
|
|
|
assert(mention.verified);
|
|
|
|
assert(mention.deleted);
|
|
|
|
|
|
|
|
mention.verify('{"url": "https://target.com/"}', 'application/json');
|
|
|
|
assert(mention.verified);
|
|
|
|
assert(!mention.isDeleted());
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2023-01-17 10:55:53 +03:00
|
|
|
describe('create', function () {
|
|
|
|
it('Will error with invalid inputs', async function () {
|
|
|
|
const invalidInputs = [
|
|
|
|
{id: 'Not valid ID'},
|
|
|
|
{id: 123},
|
|
|
|
{source: 'Not a valid source'},
|
|
|
|
{target: 'Not a valid target'},
|
|
|
|
{timestamp: 'Not a valid timestamp'},
|
|
|
|
{resourceId: 'Invalid resourceId'},
|
|
|
|
{sourceTitle: 123},
|
|
|
|
{sourceExcerpt: 123},
|
|
|
|
{sourceFavicon: 'Invalid source favicon'},
|
|
|
|
{sourceFeaturedImage: 'Invalid source featured image'}
|
|
|
|
];
|
|
|
|
|
|
|
|
for (const invalidInput of invalidInputs) {
|
|
|
|
let errored = false;
|
|
|
|
try {
|
|
|
|
await Mention.create({
|
|
|
|
...validInput,
|
|
|
|
...invalidInput
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
errored = true;
|
|
|
|
} finally {
|
|
|
|
if (!errored) {
|
|
|
|
assert.fail(`Should have errored with invalid input ${JSON.stringify(invalidInput)}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Will not error with valid inputs', async function () {
|
|
|
|
const validInputs = [
|
|
|
|
{id: new ObjectID()},
|
|
|
|
{source: new URL('https://source.com/')},
|
|
|
|
{target: new URL('https://target.com/')},
|
|
|
|
{timestamp: new Date()},
|
|
|
|
{timestamp: '2023-01-01T00:00:00Z'},
|
|
|
|
{payload: {extra: 'shit'}},
|
|
|
|
{resourceId: new ObjectID()},
|
|
|
|
{sourceFavicon: 'https://source.com/favicon.ico'},
|
|
|
|
{sourceFavicon: new URL('https://source.com/favicon.ico')},
|
|
|
|
{sourceFeaturedImage: 'https://source.com/assets/image.jpg'},
|
|
|
|
{sourceFeaturedImage: new URL('https://source.com/assets/image.jpg')}
|
|
|
|
];
|
|
|
|
|
|
|
|
for (const localValidInput of validInputs) {
|
|
|
|
await Mention.create({
|
|
|
|
...validInput,
|
|
|
|
...localValidInput
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2023-01-19 15:07:01 +03:00
|
|
|
|
|
|
|
it('Will trim titles which are too long', async function () {
|
|
|
|
const mention = await Mention.create({
|
|
|
|
...validInput,
|
|
|
|
sourceTitle: Array.from({length: 3000}).join('A')
|
|
|
|
});
|
|
|
|
|
|
|
|
assert(mention.sourceTitle.length === 2000);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('Will default the title to the host of the source URL if missing', async function () {
|
|
|
|
const mention = await Mention.create({
|
|
|
|
...validInput,
|
|
|
|
sourceTitle: null
|
|
|
|
});
|
|
|
|
|
|
|
|
assert(mention.sourceTitle);
|
|
|
|
assert(mention.sourceTitle === 'source.com');
|
|
|
|
});
|
2023-01-17 10:55:53 +03:00
|
|
|
});
|
|
|
|
});
|