@@ -1777,24 +1777,17 @@ describe("email outbox pagination", () => {
17771777 expect ( response . status ) . toBe ( 400 ) ;
17781778 } ) ;
17791779
1780- it ( "should order emails with finishedSendingAt first (nulls last )" , async ( { expect } ) => {
1780+ it ( "should order emails by createdAt descending (newest first )" , async ( { expect } ) => {
17811781 await Project . createAndSwitch ( {
17821782 display_name : "Test Ordering Project" ,
17831783 config : {
17841784 email_config : testEmailConfig ,
17851785 } ,
17861786 } ) ;
17871787
1788- // Create a slow-rendering draft (so we have time to pause it)
17891788 const templateSource = deindent `
17901789 import { Container } from "@react-email/components";
1791- import { Subject, NotificationCategory, Props } from "@stackframe/emails";
1792-
1793- // Artificial delay to make the email slow to render
1794- const startTime = performance.now();
1795- while (performance.now() - startTime < 200) {
1796- // Busy wait
1797- }
1790+ import { Subject, NotificationCategory } from "@stackframe/emails";
17981791
17991792 export function EmailTemplate({ user, project }) {
18001793 return (
@@ -1832,8 +1825,8 @@ describe("email outbox pagination", () => {
18321825 expect ( createUserResponse . status ) . toBe ( 201 ) ;
18331826 const userId = createUserResponse . body . id ;
18341827
1835- // Send 2 emails to the user and wait for them to be sent
1836- for ( let i = 0 ; i < 2 ; i ++ ) {
1828+ // Send 3 emails sequentially (need distinct timestamps for ordering test)
1829+ for ( let i = 0 ; i < 3 ; i ++ ) {
18371830 const sendResponse = await niceBackendFetch ( "/api/v1/emails/send-email" , {
18381831 method : "POST" ,
18391832 accessType : "server" ,
@@ -1845,35 +1838,35 @@ describe("email outbox pagination", () => {
18451838 expect ( sendResponse . status ) . toBe ( 200 ) ;
18461839 }
18471840
1848- // Wait for email processing - they should be sent
1849- await wait ( 5_000 ) ;
1841+ // Poll until all 3 emails appear in outbox
1842+ const maxAttempts = 30 ;
1843+ const pollInterval = 200 ;
1844+ let emails : Array < { subject ?: string , created_at_millis : number } > = [ ] ;
18501845
1851- // Verify at least one email was sent
1852- const listResponse = await niceBackendFetch ( "/api/v1/emails/outbox" , {
1853- method : "GET" ,
1854- accessType : "server" ,
1855- } ) ;
1856- expect ( listResponse . status ) . toBe ( 200 ) ;
1857- const emails = listResponse . body . items . filter ( ( e : { subject ?: string } ) =>
1858- e . subject === "Ordering Test Email"
1859- ) ;
1846+ for ( let attempt = 0 ; attempt < maxAttempts ; attempt ++ ) {
1847+ const listResponse = await niceBackendFetch ( "/api/v1/emails/outbox" , {
1848+ method : "GET" ,
1849+ accessType : "server" ,
1850+ } ) ;
1851+ expect ( listResponse . status ) . toBe ( 200 ) ;
18601852
1861- // Check ordering: finished emails should come before non-finished ones
1862- // Statuses that have finishedSendingAt set (email has completed processing)
1863- const finishedStatuses = new Set ( [ "sent" , "opened" , "clicked" , "marked-as-spam" , "server-error" , "bounced" , "delivery-delayed" , "skipped" ] ) ;
1864- let foundNonFinished = false ;
1865- for ( const email of emails ) {
1866- const hasFinished = finishedStatuses . has ( email . status ) ;
1867- if ( ! hasFinished ) {
1868- foundNonFinished = true ;
1869- } else if ( foundNonFinished ) {
1870- // We found a finished email after a non-finished email - wrong ordering
1871- expect . fail ( `Wrong ordering: found '${ email . status } ' after non-finished emails` ) ;
1872- }
1853+ emails = listResponse . body . items . filter ( ( e : { subject ?: string } ) =>
1854+ e . subject === "Ordering Test Email"
1855+ ) ;
1856+
1857+ if ( emails . length >= 3 ) break ;
1858+ await wait ( pollInterval ) ;
1859+ }
1860+
1861+ // Verify we have our emails
1862+ expect ( emails . length ) . toBeGreaterThanOrEqual ( 3 ) ;
1863+
1864+ // Check ordering: emails should be ordered by createdAt descending (newest first)
1865+ for ( let i = 0 ; i < emails . length - 1 ; i ++ ) {
1866+ const current = emails [ i ] ;
1867+ const next = emails [ i + 1 ] ;
1868+ expect ( current . created_at_millis ) . toBeGreaterThanOrEqual ( next . created_at_millis ) ;
18731869 }
1874- // We should have at least one finished email
1875- const hasSentEmails = emails . some ( ( e : { status : string } ) => finishedStatuses . has ( e . status ) ) ;
1876- expect ( hasSentEmails ) . toBe ( true ) ;
18771870 } ) ;
18781871} ) ;
18791872
0 commit comments