@@ -10,6 +10,7 @@ import {
1010} from './helpers' ;
1111import createOrGetConnection from '../src/db' ;
1212import { ArticlePost } from '../src/entity/posts/ArticlePost' ;
13+ import { FreeformPost } from '../src/entity/posts/FreeformPost' ;
1314import { ChannelDigest } from '../src/entity/ChannelDigest' ;
1415import { ChannelHighlightDefinition } from '../src/entity/ChannelHighlightDefinition' ;
1516import { HighlightsCanonical } from '../src/entity/HighlightsCanonical' ;
@@ -303,9 +304,9 @@ const CHANNEL_DIGEST_CONFIGURATIONS_QUERY = `
303304 }
304305` ;
305306
306- const DAILY_HIGHLIGHTS_QUERY = `
307- query DailyHighlights ($first: Int, $after: String) {
308- dailyHighlights (first: $first, after: $after) {
307+ const DAILY_HEADLINES_QUERY = `
308+ query DailyHeadlines ($first: Int, $after: String) {
309+ dailyHeadlines (first: $first, after: $after) {
309310 pageInfo {
310311 hasNextPage
311312 endCursor
@@ -314,21 +315,14 @@ const DAILY_HIGHLIGHTS_QUERY = `
314315 cursor
315316 node {
316317 id
317- channel
318- highlightedAt
319- headline
320- significance
321- post {
322- id
323- title
324- }
318+ title
325319 }
326320 }
327321 }
328322 }
329323` ;
330324
331- describe ( 'query dailyHighlights ' , ( ) => {
325+ describe ( 'query dailyHeadlines ' , ( ) => {
332326 const saveDigestSource = ( id : string ) =>
333327 con . getRepository ( Source ) . save ( {
334328 id,
@@ -340,6 +334,38 @@ describe('query dailyHighlights', () => {
340334 private : false ,
341335 } ) ;
342336
337+ const saveChannelDigest = ( key : string , sourceId : string , channel : string ) =>
338+ con . getRepository ( ChannelDigest ) . save ( {
339+ key,
340+ sourceId,
341+ channel,
342+ targetAudience : 'devs' ,
343+ frequency : 'daily' ,
344+ enabled : true ,
345+ } ) ;
346+
347+ const saveDigestPost = (
348+ id : string ,
349+ sourceId : string ,
350+ title : string ,
351+ createdAt : Date ,
352+ ) =>
353+ con . getRepository ( FreeformPost ) . save ( {
354+ id,
355+ shortId : id ,
356+ sourceId,
357+ type : PostType . Freeform ,
358+ title,
359+ content : title ,
360+ contentHtml : `<p>${ title } </p>` ,
361+ visible : true ,
362+ visibleAt : createdAt ,
363+ createdAt,
364+ metadataChangedAt : createdAt ,
365+ showOnFeed : true ,
366+ private : false ,
367+ } ) ;
368+
343369 const subscribeToDigest = ( sourceId : string ) =>
344370 con . getRepository ( NotificationPreferenceSource ) . save ( {
345371 userId : '1' ,
@@ -351,126 +377,72 @@ describe('query dailyHighlights', () => {
351377
352378 beforeEach ( async ( ) => {
353379 await saveFixtures ( con , User , usersFixture ) ;
354- await createTestPosts ( ) ;
355380 } ) ;
356381
357382 it ( 'should require authentication' , ( ) =>
358383 testQueryErrorCode (
359384 client ,
360- { query : DAILY_HIGHLIGHTS_QUERY } ,
385+ { query : DAILY_HEADLINES_QUERY } ,
361386 'UNAUTHENTICATED' ,
362387 ) ) ;
363388
364- it ( 'should return the top highlight of the day per subscribed channel' , async ( ) => {
389+ it ( 'should return the latest digest post per subscribed channel' , async ( ) => {
365390 loggedUser = '1' ;
366391
367392 await saveDigestSource ( 'backend_digest' ) ;
368393 await saveDigestSource ( 'career_digest' ) ;
369- await con . getRepository ( ChannelDigest ) . save ( [
370- {
371- key : 'backend' ,
372- sourceId : 'backend_digest' ,
373- channel : 'backend' ,
374- targetAudience : 'backend devs' ,
375- frequency : 'daily' ,
376- enabled : true ,
377- } ,
378- {
379- key : 'career' ,
380- sourceId : 'career_digest' ,
381- channel : 'career' ,
382- targetAudience : 'everyone' ,
383- frequency : 'daily' ,
384- enabled : true ,
385- } ,
386- ] ) ;
394+ await saveDigestSource ( 'backend_digest_b' ) ;
395+ await saveChannelDigest ( 'backend' , 'backend_digest' , 'backend' ) ;
396+ await saveChannelDigest ( 'career' , 'career_digest' , 'career' ) ;
397+ await saveChannelDigest ( 'backendb' , 'backend_digest_b' , 'backendb' ) ;
387398 await subscribeToDigest ( 'backend_digest' ) ;
388399 await subscribeToDigest ( 'career_digest' ) ;
389400
390- const today = new Date ( ) ;
391- today . setUTCHours ( 12 , 0 , 0 , 0 ) ;
392- const earlierToday = new Date ( today . getTime ( ) - 60 * 60 * 1000 ) ;
393- const yesterday = new Date ( today . getTime ( ) - 2 * 24 * 60 * 60 * 1000 ) ;
394-
395- await saveCanonicalHighlights ( [
396- {
397- id : '11111111-1111-1111-1111-111111111111' ,
398- postId : 'h1' ,
399- channel : 'backend' ,
400- highlightedAt : today ,
401- headline : 'Backend major' ,
402- significance : HighlightSignificance . Major ,
403- } ,
404- {
405- id : '22222222-2222-2222-2222-222222222222' ,
406- postId : 'h2' ,
407- channel : 'backend' ,
408- highlightedAt : earlierToday ,
409- headline : 'Backend breaking' ,
410- significance : HighlightSignificance . Breaking ,
411- } ,
412- {
413- id : '33333333-3333-3333-3333-333333333333' ,
414- postId : 'h3' ,
415- channel : 'career' ,
416- highlightedAt : today ,
417- headline : 'Career notable' ,
418- significance : HighlightSignificance . Notable ,
419- } ,
420- {
421- id : '44444444-4444-4444-4444-444444444444' ,
422- postId : 'h4' ,
423- channel : 'backend' ,
424- highlightedAt : yesterday ,
425- headline : 'Backend stale breaking' ,
426- significance : HighlightSignificance . Breaking ,
427- } ,
428- ] ) ;
401+ await saveDigestPost (
402+ 'bd-old' ,
403+ 'backend_digest' ,
404+ 'Backend old' ,
405+ new Date ( '2026-06-19T08:00:00.000Z' ) ,
406+ ) ;
407+ await saveDigestPost (
408+ 'bd-new' ,
409+ 'backend_digest' ,
410+ 'Backend latest' ,
411+ new Date ( '2026-06-19T12:00:00.000Z' ) ,
412+ ) ;
413+ await saveDigestPost (
414+ 'career-d' ,
415+ 'career_digest' ,
416+ 'Career latest' ,
417+ new Date ( '2026-06-19T10:00:00.000Z' ) ,
418+ ) ;
419+ await saveDigestPost (
420+ 'bdb-d' ,
421+ 'backend_digest_b' ,
422+ 'Unsubscribed' ,
423+ new Date ( '2026-06-19T13:00:00.000Z' ) ,
424+ ) ;
429425
430- const res = await client . query ( DAILY_HIGHLIGHTS_QUERY ) ;
426+ const res = await client . query ( DAILY_HEADLINES_QUERY ) ;
431427
432428 expect ( res . errors ) . toBeFalsy ( ) ;
433- // backend → breaking (beats today's major); career → notable; stale excluded.
434- // ordered by highlightedAt desc: career @12:00 then backend @11:00.
435- expect (
436- res . data . dailyHighlights . edges . map ( ( { node } ) => ( {
437- channel : node . channel ,
438- headline : node . headline ,
439- postId : node . post . id ,
440- } ) ) ,
441- ) . toEqual ( [
442- { channel : 'career' , headline : 'Career notable' , postId : 'h3' } ,
443- { channel : 'backend' , headline : 'Backend breaking' , postId : 'h2' } ,
429+ expect ( res . data . dailyHeadlines . edges . map ( ( { node } ) => node . id ) ) . toEqual ( [
430+ 'bd-new' ,
431+ 'career-d' ,
444432 ] ) ;
445433 } ) ;
446434
447435 it ( 'should return empty when the user has no subscriptions' , async ( ) => {
448436 loggedUser = '1' ;
449437
450438 await saveDigestSource ( 'backend_digest' ) ;
451- await con . getRepository ( ChannelDigest ) . save ( {
452- key : 'backend' ,
453- sourceId : 'backend_digest' ,
454- channel : 'backend' ,
455- targetAudience : 'backend devs' ,
456- frequency : 'daily' ,
457- enabled : true ,
458- } ) ;
459- await saveCanonicalHighlights ( [
460- {
461- id : '55555555-5555-5555-5555-555555555555' ,
462- postId : 'h1' ,
463- channel : 'backend' ,
464- highlightedAt : new Date ( ) ,
465- headline : 'Backend today' ,
466- significance : HighlightSignificance . Major ,
467- } ,
468- ] ) ;
439+ await saveChannelDigest ( 'backend' , 'backend_digest' , 'backend' ) ;
440+ await saveDigestPost ( 'bd-1' , 'backend_digest' , 'Backend' , new Date ( ) ) ;
469441
470- const res = await client . query ( DAILY_HIGHLIGHTS_QUERY ) ;
442+ const res = await client . query ( DAILY_HEADLINES_QUERY ) ;
471443
472444 expect ( res . errors ) . toBeFalsy ( ) ;
473- expect ( res . data . dailyHighlights . edges ) . toEqual ( [ ] ) ;
445+ expect ( res . data . dailyHeadlines . edges ) . toEqual ( [ ] ) ;
474446 } ) ;
475447} ) ;
476448
0 commit comments