const { assert } = require('chai'); const { findLinks, getTitleMetaTag, getImageMetaTag, isLinkSafeToPreview, isLinkInWhitelist, isLinkSneaky, isMediaLinkInWhitelist, } = require('../../js/modules/link_previews'); describe('Link previews', () => { describe('#isLinkSafeToPreview', () => { it('returns false for invalid URLs', () => { assert.isFalse(isLinkSafeToPreview('')); assert.isFalse(isLinkSafeToPreview('https')); assert.isFalse(isLinkSafeToPreview('https://')); assert.isFalse(isLinkSafeToPreview('https://bad url')); assert.isFalse(isLinkSafeToPreview('example.com')); }); it('returns false for non-HTTPS URLs', () => { assert.isFalse(isLinkSafeToPreview('http://example.com')); assert.isFalse(isLinkSafeToPreview('ftp://example.com')); assert.isFalse(isLinkSafeToPreview('file://example')); }); it('returns false if the link is "sneaky"', () => { // See `isLinkSneaky` tests below for more thorough checking. assert.isFalse(isLinkSafeToPreview('https://user:pass@example.com')); assert.isFalse(isLinkSafeToPreview('https://aquí.example')); assert.isFalse(isLinkSafeToPreview('https://aqu%C3%AD.example')); }); it('returns true for "safe" urls', () => { assert.isTrue(isLinkSafeToPreview('https://example.com')); assert.isTrue( isLinkSafeToPreview('https://example.com/foo/bar?query=string#hash') ); }); }); describe('#isLinkInWhitelist', () => { it('returns true for valid links', () => { assert.strictEqual(isLinkInWhitelist('https://youtube.com/blah'), true); assert.strictEqual( isLinkInWhitelist('https://www.youtube.com/blah'), true ); assert.strictEqual(isLinkInWhitelist('https://m.youtube.com/blah'), true); assert.strictEqual(isLinkInWhitelist('https://youtu.be/blah'), true); assert.strictEqual(isLinkInWhitelist('https://reddit.com/blah'), true); assert.strictEqual( isLinkInWhitelist('https://www.reddit.com/blah'), true ); assert.strictEqual(isLinkInWhitelist('https://m.reddit.com/blah'), true); assert.strictEqual(isLinkInWhitelist('https://imgur.com/blah'), true); assert.strictEqual(isLinkInWhitelist('https://www.imgur.com/blah'), true); assert.strictEqual(isLinkInWhitelist('https://m.imgur.com/blah'), true); assert.strictEqual(isLinkInWhitelist('https://instagram.com/blah'), true); assert.strictEqual( isLinkInWhitelist('https://www.instagram.com/blah'), true ); assert.strictEqual( isLinkInWhitelist('https://m.instagram.com/blah'), true ); assert.strictEqual(isLinkInWhitelist('https://pinterest.com/blah'), true); assert.strictEqual( isLinkInWhitelist('https://www.pinterest.com/blah'), true ); assert.strictEqual(isLinkInWhitelist('https://pin.it/blah'), true); }); it('returns false for subdomains', () => { assert.strictEqual( isLinkInWhitelist('https://any.subdomain.youtube.com/blah'), false ); assert.strictEqual( isLinkInWhitelist('https://any.subdomain.instagram.com/blah'), false ); }); it('returns false for http links', () => { assert.strictEqual(isLinkInWhitelist('http://instagram.com/blah'), false); assert.strictEqual(isLinkInWhitelist('http://youtube.com/blah'), false); }); it('returns false for links with no protocol', () => { assert.strictEqual(isLinkInWhitelist('instagram.com/blah'), false); assert.strictEqual(isLinkInWhitelist('youtube.com/blah'), false); }); it('returns false for link to root path', () => { assert.strictEqual(isLinkInWhitelist('https://instagram.com'), false); assert.strictEqual(isLinkInWhitelist('https://youtube.com'), false); assert.strictEqual(isLinkInWhitelist('https://instagram.com/'), false); assert.strictEqual(isLinkInWhitelist('https://youtube.com/'), false); }); it('returns false for other well-known sites', () => { assert.strictEqual(isLinkInWhitelist('https://facebook.com/blah'), false); assert.strictEqual(isLinkInWhitelist('https://twitter.com/blah'), false); }); it('returns false for links that look like our target links', () => { assert.strictEqual( isLinkInWhitelist('https://evil.site.com/.instagram.com/blah'), false ); assert.strictEqual( isLinkInWhitelist('https://evil.site.com/.instagram.com/blah'), false ); assert.strictEqual( isLinkInWhitelist('https://sinstagram.com/blah'), false ); }); }); describe('#isMediaLinkInWhitelist', () => { it('returns true for valid links', () => { assert.strictEqual( isMediaLinkInWhitelist( 'https://i.ytimg.com/vi/bZHShcCEH3I/hqdefault.jpg' ), true ); assert.strictEqual( isMediaLinkInWhitelist('https://random.cdninstagram.com/blah'), true ); assert.strictEqual( isMediaLinkInWhitelist('https://preview.redd.it/something'), true ); assert.strictEqual( isMediaLinkInWhitelist('https://i.imgur.com/something'), true ); assert.strictEqual( isMediaLinkInWhitelist('https://pinimg.com/something'), true ); }); it('returns false for insecure protocol', () => { assert.strictEqual( isMediaLinkInWhitelist( 'http://i.ytimg.com/vi/bZHShcCEH3I/hqdefault.jpg' ), false ); assert.strictEqual( isMediaLinkInWhitelist('http://random.cdninstagram.com/blah'), false ); assert.strictEqual( isMediaLinkInWhitelist('http://preview.redd.it/something'), false ); assert.strictEqual( isMediaLinkInWhitelist('http://i.imgur.com/something'), false ); assert.strictEqual( isMediaLinkInWhitelist('http://pinimg.com/something'), false ); }); it('returns false for other domains', () => { assert.strictEqual( isMediaLinkInWhitelist('https://www.youtube.com/something'), false ); assert.strictEqual( isMediaLinkInWhitelist('https://youtu.be/something'), false ); assert.strictEqual( isMediaLinkInWhitelist('https://www.instagram.com/something'), false ); assert.strictEqual( isMediaLinkInWhitelist('https://cnn.com/something'), false ); }); }); describe('#_getMetaTag', () => { it('returns html-decoded tag contents from Youtube', () => { const youtube = ` `; assert.strictEqual( 'Randomness is Random - Numberphile', getTitleMetaTag(youtube) ); assert.strictEqual( 'https://i.ytimg.com/vi/tP-Ipsat90c/maxresdefault.jpg', getImageMetaTag(youtube) ); }); it('returns html-decoded tag contents from Instagram', () => { const instagram = ` `; assert.strictEqual( 'Walter "MFPallytime" on Instagram: “Lol gg”', getTitleMetaTag(instagram) ); assert.strictEqual( 'https://scontent-lax3-1.cdninstagram.com/vp/1c69aa381c2201720c29a6c28de42ffd/5CD49B5B/t51.2885-15/e35/47690175_2275988962411653_1145978227188801192_n.jpg?_nc_ht=scontent-lax3-1.cdninstagram.com', getImageMetaTag(instagram) ); }); it('returns html-decoded tag contents from Imgur', () => { const imgur = ` `; assert.strictEqual('', getTitleMetaTag(imgur)); assert.strictEqual( 'https://i.imgur.com/Y3wjlwY.jpg?fb', getImageMetaTag(imgur) ); }); it('returns html-decoded tag contents from Pinterest', () => { const pinterest = ` `; assert.strictEqual( 'Inexpensive Landscaping Ideas', getTitleMetaTag(pinterest) ); assert.strictEqual( 'https://i.pinimg.com/736x/9a/9e/64/9a9e64ed6b42b0a0e480dded4579d940--yard-sale-mulches.jpg', getImageMetaTag(pinterest) ); }); it('returns only the first tag', () => { const html = ` `; assert.strictEqual('First Second Third', getTitleMetaTag(html)); }); it('handles a newline in attribute value', () => { const html = ` `; assert.strictEqual( 'First thing\r\nSecond thing\nThird thing', getTitleMetaTag(html) ); }); }); describe('#findLinks', () => { it('returns all links if no caretLocation is provided', () => { const text = 'Check out this link: https://github.com/signalapp/Signal-Desktop\nAnd this one too: https://github.com/signalapp/Signal-Android'; const expected = [ 'https://github.com/signalapp/Signal-Desktop', 'https://github.com/signalapp/Signal-Android', ]; const actual = findLinks(text); assert.deepEqual(expected, actual); }); it('includes all links if cursor is not in a link', () => { const text = 'Check out this link: https://github.com/signalapp/Signal-Desktop\nAnd this one too: https://github.com/signalapp/Signal-Android'; const caretLocation = 10; const expected = [ 'https://github.com/signalapp/Signal-Desktop', 'https://github.com/signalapp/Signal-Android', ]; const actual = findLinks(text, caretLocation); assert.deepEqual(expected, actual); }); it('excludes a link not at the end if the caret is inside of it', () => { const text = 'Check out this link: https://github.com/signalapp/Signal-Desktop\nAnd this one too: https://github.com/signalapp/Signal-Android'; const caretLocation = 30; const expected = ['https://github.com/signalapp/Signal-Android']; const actual = findLinks(text, caretLocation); assert.deepEqual(expected, actual); }); it('excludes a link not at the end if the caret is at its end', () => { const text = 'Check out this link: https://github.com/signalapp/Signal-Desktop\nAnd this one too: https://github.com/signalapp/Signal-Android'; const caretLocation = 64; const expected = ['https://github.com/signalapp/Signal-Android']; const actual = findLinks(text, caretLocation); assert.deepEqual(expected, actual); }); it('excludes a link at the end of the caret is inside of it', () => { const text = 'Check out this link: https://github.com/signalapp/Signal-Desktop\nAnd this one too: https://github.com/signalapp/Signal-Android'; const caretLocation = 100; const expected = ['https://github.com/signalapp/Signal-Desktop']; const actual = findLinks(text, caretLocation); assert.deepEqual(expected, actual); }); it('includes link at the end if cursor is at its end', () => { const text = 'Check out this link: https://github.com/signalapp/Signal-Desktop\nAnd this one too: https://github.com/signalapp/Signal-Android'; const caretLocation = text.length; const expected = [ 'https://github.com/signalapp/Signal-Desktop', 'https://github.com/signalapp/Signal-Android', ]; const actual = findLinks(text, caretLocation); assert.deepEqual(expected, actual); }); }); describe('#isLinkSneaky', () => { it('returns false for all-latin domain', () => { const link = 'https://www.amazon.com'; const actual = isLinkSneaky(link); assert.strictEqual(actual, false); }); it('returns true for Latin + Cyrillic domain', () => { const link = 'https://www.aмazon.com'; const actual = isLinkSneaky(link); assert.strictEqual(actual, true); }); it('returns true for Latin + Greek domain', () => { const link = 'https://www.αpple.com'; const actual = isLinkSneaky(link); assert.strictEqual(actual, true); }); it('returns true for ASCII and non-ASCII mix', () => { const link = 'https://www.аррӏе.com'; const actual = isLinkSneaky(link); assert.strictEqual(actual, true); }); it('returns true for Latin + High Greek domain', () => { const link = `https://www.apple${String.fromCodePoint(0x101a0)}.com`; const actual = isLinkSneaky(link); assert.strictEqual(actual, true); }); it('returns true for =', () => { const link = 'r.id=s.id'; assert.strictEqual(isLinkSneaky(link), true); }); it('returns true for $', () => { const link = 'r.id$s.id'; assert.strictEqual(isLinkSneaky(link), true); }); it('returns true for +', () => { const link = 'r.id+s.id'; assert.strictEqual(isLinkSneaky(link), true); }); it('returns true for ^', () => { const link = 'r.id^s.id'; assert.strictEqual(isLinkSneaky(link), true); }); it('returns true for auth (or pretend auth)', () => { const link = 'http://whatever.com&login=someuser@77777777'; assert.strictEqual(isLinkSneaky(link), true); }); it("returns true if the domain doesn't contain a .", () => { assert.isTrue(isLinkSneaky('https://example')); assert.isTrue(isLinkSneaky('https://localhost')); assert.isTrue(isLinkSneaky('https://localhost:3000')); }); it('returns true if the domain has any empty labels', () => { assert.isTrue(isLinkSneaky('https://example.')); assert.isTrue(isLinkSneaky('https://example.com.')); assert.isTrue(isLinkSneaky('https://.example.com')); assert.isTrue(isLinkSneaky('https://..example.com')); }); it('returns true if the domain is longer than 2048 UTF-16 code points', () => { const domain = `${'a'.repeat(2041)}.example`; assert.lengthOf(domain, 2049, 'Test domain is the incorrect length'); const link = `https://${domain}/foo/bar`; assert.isTrue(isLinkSneaky(link)); }); it('returns false for regular @ in url', () => { const link = 'https://lbry.tv/@ScammerRevolts:b0/DELETING-EVERY-FILE-OFF-A-SCAMMERS-LAPTOP-Destroyed:1'; assert.strictEqual(isLinkSneaky(link), false); }); }); });