diff --git a/backend/src/middleware/notifications/extractMentions.js b/backend/src/middleware/notifications/extractMentions.js new file mode 100644 index 000000000..f2b28444f --- /dev/null +++ b/backend/src/middleware/notifications/extractMentions.js @@ -0,0 +1,17 @@ +import cheerio from 'cheerio' +const ID_REGEX = /\/profile\/([\w\-.!~*'"(),]+)/g + +export default function (content) { + const $ = cheerio.load(content) + const urls = $('.mention').map((_, el) => { + return $(el).attr('href') + }).get() + const ids = [] + urls.forEach((url) => { + let match + while ((match = ID_REGEX.exec(url)) != null) { + ids.push(match[1]) + } + }) + return ids +} diff --git a/backend/src/middleware/notifications/extractMentions.spec.js b/backend/src/middleware/notifications/extractMentions.spec.js new file mode 100644 index 000000000..625b1d8fe --- /dev/null +++ b/backend/src/middleware/notifications/extractMentions.spec.js @@ -0,0 +1,46 @@ +import extractIds from './extractMentions' + +describe('extract', () => { + describe('searches through links', () => { + it('ignores links without .mention class', () => { + const content = '
Something inspirational about @bob-der-baumeister and @jenny-rostock.
' + expect(extractIds(content)).toEqual([]) + }) + + describe('given a link with .mention class', () => { + it('extracts ids', () => { + const content = 'Something inspirational about @bob-der-baumeister and @jenny-rostock.
' + expect(extractIds(content)).toEqual(['u2', 'u3']) + }) + + describe('handles links', () => { + it('with slug and id', () => { + const content = 'Something inspirational about @bob-der-baumeister and @jenny-rostock.
' + expect(extractIds(content)).toEqual(['u2', 'u3']) + }) + + it('with domains', () => { + const content = 'Something inspirational about @bob-der-baumeister and @jenny-rostock.
' + expect(extractIds(content)).toEqual(['u2', 'u3']) + }) + + it('special characters', () => { + const content = 'Something inspirational about @bob-der-baumeister and @jenny-rostock.
' + expect(extractIds(content)).toEqual(['u!*(),2', 'u.~-3']) + }) + }) + + describe('does not crash if', () => { + it('`href` contains no user id', () => { + const content = 'Something inspirational about @bob-der-baumeister and @jenny-rostock.
' + expect(extractIds(content)).toEqual([]) + }) + + it('`href` is empty or invalid', () => { + const content = 'Something inspirational about @bob-der-baumeister and @jenny-rostock.
' + expect(extractIds(content)).toEqual([]) + }) + }) + }) + }) +}) diff --git a/backend/src/middleware/notifications/index.js b/backend/src/middleware/notifications/index.js index 159f055f3..0efd140d2 100644 --- a/backend/src/middleware/notifications/index.js +++ b/backend/src/middleware/notifications/index.js @@ -1,11 +1,11 @@ -import { extractSlugs } from './mentions' +import extractIds from './extractMentions' const notify = async (resolve, root, args, context, resolveInfo) => { const post = await resolve(root, args, context, resolveInfo) const session = context.driver.session() const { content, id: postId } = post - const slugs = extractSlugs(content) + const slugs = extractIds(content) const createdAt = (new Date()).toISOString() const cypher = ` match(u:User) where u.slug in $slugs diff --git a/backend/src/middleware/notifications/mentions.js b/backend/src/middleware/notifications/mentions.js deleted file mode 100644 index 137c23f1c..000000000 --- a/backend/src/middleware/notifications/mentions.js +++ /dev/null @@ -1,10 +0,0 @@ -const MENTION_REGEX = /\s@([\w_-]+)/g - -export function extractSlugs (content) { - let slugs = [] - let match - while ((match = MENTION_REGEX.exec(content)) != null) { - slugs.push(match[1]) - } - return slugs -} diff --git a/backend/src/middleware/notifications/mentions.spec.js b/backend/src/middleware/notifications/mentions.spec.js deleted file mode 100644 index 3e70514b7..000000000 --- a/backend/src/middleware/notifications/mentions.spec.js +++ /dev/null @@ -1,18 +0,0 @@ -import { extractSlugs } from './mentions' - -describe('extract', () => { - describe('searches through links', () => { - it('ignores links without .mention class', () => { - const content = 'Something inspirational about @bob-der-baumeister and @jenny-rostock.
' - expect(extractSlugs(content)).toEqual([]) - }) - - describe('given a link with .mention class', () => { - const content = 'Something inspirational about @bob-der-baumeister and @jenny-rostock.
' - - it('extracts ID', () => { - expect(extractSlugs(content)).toEqual(['u2', 'u3']) - }) - }) - }) -})