/* eslint-env mocha */ /* eslint-disable func-names, prefer-arrow-callback */ /* eslint-disable import/no-absolute-path */ import { expect } from 'chai'; import { Meteor } from 'meteor/meteor'; import Comments from '/imports/api/Comments/Comments'; import getMediaFromContent from '/imports/api/Comments/mediaAnalyzers'; // `meteor test` skips server/main.js, so nothing registers the comment methods. // Importing the module runs its Meteor.methods({...}) so the handlers exist. import '/imports/api/Comments/server/methods'; // -- Embed detection (pure) -------------------------------------------------- describe('comment media analyzers', () => { it('detects an image url', () => { const media = getMediaFromContent('look at http://example.com/photo.jpg here'); expect(media.type).to.equal('image'); expect(media.content).to.match(/\.jpg$/); }); it('detects a youtube url and rewrites it to an embed url', () => { const media = getMediaFromContent('see https://www.youtube.com/watch?v=abc123 now'); expect(media).to.deep.equal({ type: 'youtube', content: 'https://www.youtube.com/embed/abc123' }); }); it('returns {} for plain text', () => { expect(getMediaFromContent('just some words with no media')).to.deep.equal({}); }); }); // -- Comment methods (server, via method handlers) --------------------------- // The methods gate on `this.userId`, so invoke the handlers with a fake // invocation context instead of going through a real login. describe('comment methods', () => { const ref = 'fire-ref-under-test'; const owner = 'user-owner'; const other = 'user-other'; const handlers = Meteor.server.method_handlers; const insert = (userId, content) => handlers['comments.insert'].apply({ userId }, [ref, content]); const edit = (userId, id, content) => handlers['comments.edit'].apply({ userId }, [id, content]); const remove = (userId, id) => handlers['comments.remove'].apply({ userId }, [id]); const like = (userId, id) => handlers['comments.like'].apply({ userId }, [id]); const dislike = (userId, id) => handlers['comments.dislike'].apply({ userId }, [id]); beforeEach(async () => { await Comments.removeAsync({ referenceId: ref }); }); it('insert creates an approved comment with detected media', async () => { const id = await insert(owner, 'hi http://example.com/pic.png'); const c = await Comments.findOneAsync(id); expect(c.userId).to.equal(owner); expect(c.referenceId).to.equal(ref); expect(c.status).to.equal('approved'); expect(c.media.type).to.equal('image'); expect(c.likes).to.deep.equal([]); expect(c.dislikes).to.deep.equal([]); }); it('insert requires a logged-in user', async () => { let threw = false; try { await handlers['comments.insert'].apply({}, [ref, 'nope']); } catch (e) { threw = true; } expect(threw).to.equal(true); }); it('insert rejects an empty comment', async () => { let threw = false; try { await insert(owner, ' '); } catch (e) { threw = true; } expect(threw).to.equal(true); }); it('edit is allowed for the owner and denied for others', async () => { const id = await insert(owner, 'original'); let threw = false; try { await edit(other, id, 'hijacked'); } catch (e) { threw = true; } expect(threw).to.equal(true); await edit(owner, id, 'edited'); expect((await Comments.findOneAsync(id)).content).to.equal('edited'); }); it('like then dislike toggles the arrays', async () => { const id = await insert(owner, 'toggle me'); await like(other, id); expect((await Comments.findOneAsync(id)).likes).to.include(other); await dislike(other, id); const c = await Comments.findOneAsync(id); expect(c.dislikes).to.include(other); expect(c.likes).to.not.include(other); }); it('remove is allowed for the owner only', async () => { const id = await insert(owner, 'delete me'); let threw = false; try { await remove(other, id); } catch (e) { threw = true; } expect(threw).to.equal(true); await remove(owner, id); expect(await Comments.findOneAsync(id)).to.equal(undefined); }); });