import test from 'node:test'; import assert from 'node:assert/strict'; import { briefing, getHot, getRedditConfig, getToken } from '../apis/sources/reddit.mjs'; test('Reddit reports missing OAuth credentials without network access', async () => { let calls = 0; const data = await briefing({ env: {}, delayMs: 0, fetchImpl: async () => { calls++; throw new Error('unexpected network access'); }, }); assert.equal(calls, 0); assert.equal(data.status, 'no_credentials'); assert.equal(data.error, 'missing_reddit_oauth_credentials'); assert.deepEqual(data.missing, ['REDDIT_CLIENT_ID', 'REDDIT_CLIENT_SECRET']); }); test('Reddit hot posts require OAuth token and never use public JSON fallback', async () => { const originalFetch = globalThis.fetch; let calledUrl = null; globalThis.fetch = async url => { calledUrl = url; throw new Error('unexpected public fallback'); }; try { const data = await getHot('worldnews'); assert.equal(calledUrl, null); assert.equal(data.status, 'no_credentials'); assert.equal(data.error, 'reddit_oauth_required'); } finally { globalThis.fetch = originalFetch; } }); test('Reddit classifies OAuth HTTP failure without exposing secrets', async () => { const result = await getToken({ env: { REDDIT_CLIENT_ID: 'client-id', REDDIT_CLIENT_SECRET: 'client-secret' }, fetchImpl: async () => ({ ok: false, status: 401, text: async () => 'invalid client', }), }); assert.equal(result.ok, false); assert.equal(result.status, 'auth_failed'); assert.equal(result.error, 'reddit_oauth_http_401'); assert.doesNotMatch(JSON.stringify(result), /client-secret/); }); test('Reddit fetches hot posts through oauth.reddit.com when configured', async () => { const originalFetch = globalThis.fetch; const urls = []; globalThis.fetch = async url => { urls.push(String(url)); if (String(url).includes('/api/v1/access_token')) { return { ok: true, status: 200, json: async () => ({ access_token: 'test-token' }), }; } return { ok: true, status: 200, headers: { get: () => 'application/json' }, text: async () => JSON.stringify({ data: { children: [ { data: { title: 'Market stress headline', score: 42, num_comments: 7, url: 'https://example.test/post', created_utc: 1700000000, }, }, ], }, }), }; }; try { const data = await briefing({ env: { REDDIT_CLIENT_ID: 'client-id', REDDIT_CLIENT_SECRET: 'client-secret' }, subreddits: ['worldnews'], delayMs: 0, }); assert.equal(data.status, 'ok'); assert.equal(data.subreddits.worldnews[0].title, 'Market stress headline'); assert.ok(urls.some(url => url === 'https://www.reddit.com/api/v1/access_token')); assert.ok(urls.some(url => url.startsWith('https://oauth.reddit.com/r/worldnews/hot'))); assert.equal(urls.some(url => url.includes('hot.json')), false); } finally { globalThis.fetch = originalFetch; } }); test('Reddit config reports partial credential state', () => { assert.deepEqual(getRedditConfig({ REDDIT_CLIENT_ID: 'id' }).missing, ['REDDIT_CLIENT_SECRET']); });