diff --git a/app/utils/opengraph.test.ts b/app/utils/opengraph.test.ts index 6816dd9cb..6d0b32e41 100644 --- a/app/utils/opengraph.test.ts +++ b/app/utils/opengraph.test.ts @@ -1,7 +1,19 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import {getDistanceBW2Points, getNearestPoint} from './opengraph'; +import {getDistanceBW2Points, getNearestPoint, fetchOpenGraph, testExports} from './opengraph'; + +const {fetchRaw, getFavIcon} = testExports; + +let mockedFetch: jest.SpyInstance; + +beforeEach(() => { + mockedFetch = jest.spyOn(global, 'fetch'); +}); + +afterEach(() => { + jest.clearAllMocks(); +}); describe('Utility Functions', () => { describe('getDistanceBW2Points', () => { @@ -62,3 +74,121 @@ describe('Utility Functions', () => { }); }); }); + +describe('fetchRaw', () => { + it('should fetch raw HTML from a URL', async () => { + const mockResponse = { + ok: true, + text: jest.fn().mockResolvedValue(''), + }; + mockedFetch.mockResolvedValue(mockResponse as any); + + const result = await fetchRaw('http://example.com'); + expect(fetch).toHaveBeenCalledWith('http://example.com', { + headers: { + 'User-Agent': 'OpenGraph', + 'Cache-Control': 'no-cache', + Accept: '*/*', + Connection: 'keep-alive', + }, + }); + expect(result).toBe(''); + }); + + it('should return response if not ok', async () => { + const mockResponse = { + ok: false, + }; + mockedFetch.mockResolvedValue(mockResponse as any); + + const result = await fetchRaw('http://example.com'); + expect(result).toBe(mockResponse); + }); + + it('should return error message on fetch failure', async () => { + const mockError = new Error('Network error'); + mockedFetch.mockRejectedValue(mockError); + + const result = await fetchRaw('http://example.com'); + expect(result).toEqual({message: 'Network error'}); + }); +}); + +describe('getFavIcon', () => { + it('should return the largest favicon URL', () => { + const mockHtml = ''; + const result = getFavIcon('http://example.com', mockHtml); + expect(result).toBe('http://example.com/favicon-32x32.png'); + }); + + it('should return default favicon URL if no icons found', () => { + const mockHtml = ''; + const result = getFavIcon('http://example.com', mockHtml); + expect(result).toBe('http://example.com/favicon.ico'); + }); + + it('should handle shortcut icon rel attribute', () => { + const mockHtml = ''; + const result = getFavIcon('http://example.com', mockHtml); + expect(result).toBe('http://example.com/favicon.png'); + }); + + it('should handle absolute URLs in href', () => { + const mockHtml = ''; + const result = getFavIcon('http://example.com', mockHtml); + expect(result).toBe('https://cdn.example.com/favicon.png'); + }); + + it('should handle icons without sizes attribute', () => { + const mockHtml = ''; + const result = getFavIcon('http://example.com', mockHtml); + expect(result).toBe('http://example.com/favicon-32x32.png'); + }); +}); + +describe('fetchOpenGraph', () => { + it('should fetch OpenGraph data from a URL', async () => { + const mockHtml = 'Example'; + const mockResponse = { + ok: true, + text: jest.fn().mockResolvedValue(mockHtml), + }; + mockedFetch.mockResolvedValue(mockResponse as any); + + const result = await fetchOpenGraph('http://example.com', true); + expect(result).toEqual({ + link: 'http://example.com', + imageURL: 'http://example.com/image.png', + favIcon: 'http://example.com/favicon.ico', + title: 'OpenGraph Title', + }); + }); + + it('should return error if fetchRaw fails', async () => { + const mockError = {message: 'Network error'}; + mockedFetch.mockRejectedValue(mockError); + + const result = await fetchOpenGraph('http://example.com'); + expect(result).toEqual({ + link: 'http://example.com', + error: new Error('Network error'), + }); + }); + + it('should return default title if og:title is not found', async () => { + const mockHtml = 'Example'; + const mockResponse = { + ok: true, + text: jest.fn().mockResolvedValue(mockHtml), + }; + mockedFetch.mockResolvedValue(mockResponse as any); + + const result = await fetchOpenGraph('http://example.com'); + expect(result).toEqual({ + link: 'http://example.com', + imageURL: null, + favIcon: undefined, + title: 'Example', + }); + }); +}); diff --git a/app/utils/opengraph.ts b/app/utils/opengraph.ts index 19fa1c6e2..bfa20b274 100644 --- a/app/utils/opengraph.ts +++ b/app/utils/opengraph.ts @@ -188,3 +188,8 @@ export const fetchOpenGraph = async (url: string, includeFavIcon = false): Promi }; } }; + +export const testExports = { + fetchRaw, + getFavIcon, +};