Share funktion

This commit is contained in:
2026-07-16 17:13:37 +02:00
parent 52c9dfb472
commit c7c1864fc6
9 changed files with 311 additions and 27 deletions

View File

@@ -0,0 +1,82 @@
import { detectLoginWall, extractHtmlImageCandidates, fetchOgImageFromUrl } from '../../utils/shareIntent';
describe('shareIntent login wall handling', () => {
const originalFetch = global.fetch;
afterEach(() => {
global.fetch = originalFetch;
jest.restoreAllMocks();
});
const mockFetchHtml = (html: string, ok = true) => {
global.fetch = jest.fn().mockResolvedValue({
ok,
text: async () => html,
}) as unknown as typeof fetch;
};
describe('detectLoginWall', () => {
it('detects Instagram login wall markers', () => {
expect(detectLoginWall('<a href="/accounts/login/?next=%2Fp%2Fabc">Log in</a>')).toBe(true);
expect(detectLoginWall('{"page":"LoginAndSignupPage"}')).toBe(true);
expect(detectLoginWall('<form id="loginForm">')).toBe(true);
expect(detectLoginWall('<body class="not-logged-in">')).toBe(true);
});
it('does not flag regular post pages', () => {
expect(detectLoginWall('<meta property="og:image" content="https://cdn.example.com/post.jpg" />')).toBe(false);
});
});
describe('extractHtmlImageCandidates', () => {
const baseUrl = 'https://www.instagram.com/p/abc/';
it('decodes HTML entities in og:image URLs so signed CDN params survive', () => {
const html = '<meta property="og:image" content="https://scontent.cdninstagram.com/v/t51/img.jpg?stp=dst-jpg_s640x640&amp;_nc_ohc=token&amp;oh=hash&amp;oe=expiry" />';
const [candidate] = extractHtmlImageCandidates(html, baseUrl);
expect(candidate).toBe('https://scontent.cdninstagram.com/v/t51/img.jpg?stp=dst-jpg_s640x640&_nc_ohc=token&oh=hash&oe=expiry');
expect(candidate).not.toContain('&amp;');
});
it('skips inline base64 placeholder images from HTML', () => {
const html = '<img width="80px" src="data:image/png;base64,iVBORw0KGgo=" /><meta property="og:image" content="https://cdn.example.com/post.jpg" />';
const candidates = extractHtmlImageCandidates(html, baseUrl);
expect(candidates).toEqual(['https://cdn.example.com/post.jpg']);
});
it('prefers the og:image over small profile pictures', () => {
const html = [
'<meta property="og:image" content="https://cdn.example.com/v/post.jpg?stp=dst-jpg_s640x640" />',
'<img src="https://cdn.example.com/v/profile_pic_s150x150.jpg" />',
].join('');
const candidates = extractHtmlImageCandidates(html, baseUrl);
expect(candidates[0]).toContain('s640x640');
});
});
describe('fetchOgImageFromUrl', () => {
it('returns login_wall when the page is a login wall without usable images', async () => {
mockFetchHtml('<html><body><form id="loginForm">accounts/login</form></body></html>');
const result = await fetchOgImageFromUrl('https://www.instagram.com/p/abc/');
expect(result).toEqual({ failureReason: 'login_wall' });
});
it('returns no_image when the page has no images and no login markers', async () => {
mockFetchHtml('<html><body><p>Nothing here</p></body></html>');
const result = await fetchOgImageFromUrl('https://example.com/post');
expect(result).toEqual({ failureReason: 'no_image' });
});
it('returns no_image when the response is not ok', async () => {
mockFetchHtml('', false);
const result = await fetchOgImageFromUrl('https://example.com/missing');
expect(result).toEqual({ failureReason: 'no_image' });
});
it('returns no_image when the fetch throws', async () => {
global.fetch = jest.fn().mockRejectedValue(new Error('network down')) as unknown as typeof fetch;
const result = await fetchOgImageFromUrl('https://example.com/offline');
expect(result).toEqual({ failureReason: 'no_image' });
});
});
});