@@ -189,6 +189,113 @@ describe("computeTimeline", () => {
189189 } ) ;
190190 } ) ;
191191
192+ describe ( "future events" , ( ) => {
193+ it ( "places a single future event to the right of Now" , ( ) => {
194+ const events = [ makeEvent ( { id : "Q1" , year : 2030 } ) ] ;
195+ const result = computeTimeline ( events ) ;
196+ // Now should be at position 0, future event at position 100
197+ const nowMarker = result . markers . find ( m => m . event . id === "0" ) ;
198+ const eventMarker = result . markers . find ( m => m . event . id === "Q1" ) ;
199+ expect ( nowMarker ! . position ) . toBe ( 0 ) ;
200+ expect ( eventMarker ! . position ) . toBe ( 100 ) ;
201+ } ) ;
202+
203+ it ( "positions Now chronologically between past and future events" , ( ) => {
204+ const events = [
205+ makeEvent ( { id : "Q1" , year : 2000 } ) ,
206+ makeEvent ( { id : "Q2" , year : 2048 } ) ,
207+ ] ;
208+ const result = computeTimeline ( events ) ;
209+ // 2000 → 2024 → 2048, total span = 48 years
210+ const pastMarker = result . markers . find ( m => m . event . id === "Q1" ) ;
211+ const nowMarker = result . markers . find ( m => m . event . id === "0" ) ;
212+ const futureMarker = result . markers . find ( m => m . event . id === "Q2" ) ;
213+ expect ( pastMarker ! . position ) . toBe ( 0 ) ;
214+ expect ( nowMarker ! . position ) . toBe ( 50 ) ; // 24/48 = 50%
215+ expect ( futureMarker ! . position ) . toBe ( 100 ) ;
216+ } ) ;
217+
218+ it ( "handles all events in the future" , ( ) => {
219+ const events = [
220+ makeEvent ( { id : "Q1" , year : 2030 } ) ,
221+ makeEvent ( { id : "Q2" , year : 2040 } ) ,
222+ ] ;
223+ const result = computeTimeline ( events ) ;
224+ // Now (2024) → 2030 → 2040, total span = 16 years
225+ const nowMarker = result . markers . find ( m => m . event . id === "0" ) ;
226+ const event1 = result . markers . find ( m => m . event . id === "Q1" ) ;
227+ const event2 = result . markers . find ( m => m . event . id === "Q2" ) ;
228+ expect ( nowMarker ! . position ) . toBe ( 0 ) ;
229+ expect ( event1 ! . position ) . toBeCloseTo ( ( 6 / 16 ) * 100 , 1 ) ; // 6/16
230+ expect ( event2 ! . position ) . toBe ( 100 ) ;
231+ } ) ;
232+
233+ it ( "creates correct number of segments with mixed past/future" , ( ) => {
234+ const events = [
235+ makeEvent ( { id : "Q1" , year : 2000 } ) ,
236+ makeEvent ( { id : "Q2" , year : 2048 } ) ,
237+ ] ;
238+ const result = computeTimeline ( events ) ;
239+ // 3 points (event, now, event) → 2 segments
240+ expect ( result . segments ) . toHaveLength ( 2 ) ;
241+ expect ( result . markers ) . toHaveLength ( 3 ) ;
242+ } ) ;
243+
244+ it ( "segment percentages sum to 100 with future events" , ( ) => {
245+ const events = [
246+ makeEvent ( { id : "Q1" , year : 2000 } ) ,
247+ makeEvent ( { id : "Q2" , year : 2030 } ) ,
248+ makeEvent ( { id : "Q3" , year : 2048 } ) ,
249+ ] ;
250+ const result = computeTimeline ( events ) ;
251+ const sum = result . segments . reduce ( ( s , seg ) => s + seg . percentage , 0 ) ;
252+ expect ( sum ) . toBeCloseTo ( 100 , 5 ) ;
253+ } ) ;
254+
255+ it ( "sorts Now among markers in chronological order" , ( ) => {
256+ const events = [
257+ makeEvent ( { id : "Q1" , name : "Past" , year : 2000 } ) ,
258+ makeEvent ( { id : "Q2" , name : "Future" , year : 2030 } ) ,
259+ ] ;
260+ const result = computeTimeline ( events ) ;
261+ expect ( result . markers [ 0 ] . event . name ) . toBe ( "Past" ) ;
262+ expect ( result . markers [ 1 ] . event . name ) . toBe ( "Now" ) ;
263+ expect ( result . markers [ 2 ] . event . name ) . toBe ( "Future" ) ;
264+ } ) ;
265+ } ) ;
266+
267+ describe ( "hideNow" , ( ) => {
268+ it ( "excludes Now marker when hideNow is true and 2+ events" , ( ) => {
269+ const events = [
270+ makeEvent ( { id : "Q1" , year : 2000 } ) ,
271+ makeEvent ( { id : "Q2" , year : 2020 } ) ,
272+ ] ;
273+ const result = computeTimeline ( events , 2 , "en-US" , "Now" , undefined , true ) ;
274+ // Only event markers, no Now
275+ expect ( result . markers ) . toHaveLength ( 2 ) ;
276+ expect ( result . markers . every ( m => m . event . id !== "0" ) ) . toBe ( true ) ;
277+ } ) ;
278+
279+ it ( "keeps Now when hideNow is true but only 1 event" , ( ) => {
280+ const events = [ makeEvent ( { id : "Q1" , year : 2000 } ) ] ;
281+ const result = computeTimeline ( events , 2 , "en-US" , "Now" , undefined , true ) ;
282+ expect ( result . markers . some ( m => m . event . id === "0" ) ) . toBe ( true ) ;
283+ } ) ;
284+
285+ it ( "works with future events and hideNow" , ( ) => {
286+ const events = [
287+ makeEvent ( { id : "Q1" , year : 2000 } ) ,
288+ makeEvent ( { id : "Q2" , year : 2048 } ) ,
289+ ] ;
290+ const result = computeTimeline ( events , 2 , "en-US" , "Now" , undefined , true ) ;
291+ expect ( result . markers ) . toHaveLength ( 2 ) ;
292+ expect ( result . markers [ 0 ] . position ) . toBe ( 0 ) ;
293+ expect ( result . markers [ 1 ] . position ) . toBe ( 100 ) ;
294+ expect ( result . segments ) . toHaveLength ( 1 ) ;
295+ expect ( result . segments [ 0 ] . percentage ) . toBe ( 100 ) ;
296+ } ) ;
297+ } ) ;
298+
192299 describe ( "timespanFormat" , ( ) => {
193300 it ( "uses precise format by default (format 2)" , ( ) => {
194301 const events = [ makeEvent ( { id : "Q1" , year : 2000 , month : 6 , day : 15 } ) ] ;
0 commit comments