@@ -152,15 +152,274 @@ describe("Performance measurements", () => {
152152 // Allow more variation due to system noise, optimization differences, and convenience overhead
153153 const tolerance = 1.0 ; // Allow 100% variation
154154 const expectedEvaluateTime = compileTime + executeTime ;
155-
155+
156156 // Log the actual ratios to help with debugging
157157 const ratio = evaluateTime / expectedEvaluateTime ;
158- console . log ( `One-step evaluation was ${ ratio . toFixed ( 2 ) } x the separate steps` ) ;
159-
158+ console . log (
159+ `One-step evaluation was ${ ratio . toFixed ( 2 ) } x the separate steps` ,
160+ ) ;
161+
160162 // Only fail if the difference is extreme
161163 expect ( evaluateTime ) . toBeGreaterThan (
162164 expectedEvaluateTime * ( 1 - tolerance ) ,
163165 ) ;
164166 expect ( evaluateTime ) . toBeLessThan ( expectedEvaluateTime * ( 2 + tolerance ) ) ;
165167 } ) ;
166168} ) ;
169+
170+ describe ( "Timestamp Functions" , ( ) => {
171+ it ( "should correctly parse and compare timestamps" , async ( ) => {
172+ const expr = `[
173+ // Test 1: Compare UTC timestamp with itself
174+ timestamp('2025-04-28T12:00:00Z') == timestamp('2025-04-28T12:00:00Z'),
175+ // Test 2: Compare UTC timestamp with equivalent EDT timestamp
176+ timestamp('2025-04-28T12:00:00Z') == timestamp('2025-04-28T08:00:00-04:00'),
177+ // Test 3: Compare timestamps one day apart
178+ timestamp('2025-04-28T12:00:00Z') < timestamp('2025-04-29T12:00:00Z'),
179+ // Test 4: Get components from UTC timestamp
180+ timestamp('2025-04-28T12:00:00Z').getMonth(),
181+ timestamp('2025-04-28T12:00:00Z').getDayOfMonth(),
182+ timestamp('2025-04-28T12:00:00Z').getHours(),
183+ timestamp('2025-04-28T12:00:00Z').getDayOfWeek() // 1==Monday
184+ ]` ;
185+ const result = await evaluate ( expr , { } ) ;
186+ expect ( result ) . toEqual ( [ true , true , true , 3 , 27 , 12 , 1 ] ) ;
187+ } ) ;
188+ } ) ;
189+
190+ describe ( "Travel Reservation Rules" , ( ) => {
191+ describe ( "Premium Discount Eligibility" , ( ) => {
192+ // Tests a complex pricing rule that considers:
193+ // - Total package cost across flight, hotel, and car
194+ // - Customer loyalty tier
195+ // - Seasonal booking (summer months)
196+ const expr = `
197+ // Calculate total package cost
198+ double(reservation.flight.price) +
199+ double(reservation.hotel.nightlyRate) * int(reservation.hotel.nights) +
200+ double(reservation.car.dailyRate) * int(reservation.car.days) >= 2000.0 &&
201+ // Check loyalty tier
202+ reservation.customer.loyaltyTier in ['GOLD', 'PLATINUM'] &&
203+ // Check if booking is in summer months (0-based: 5=June, 6=July, 7=August)
204+ timestamp(reservation.bookingDate).getMonth() in [5, 6, 7]
205+ ` ;
206+ let program : CelProgram ;
207+
208+ beforeEach ( async ( ) => {
209+ program = await CelProgram . compile ( expr ) ;
210+ } ) ;
211+
212+ it ( "should qualify for premium discount with valid summer booking" , async ( ) => {
213+ const result = await program . execute ( {
214+ reservation : {
215+ flight : { price : 1000.0 } ,
216+ hotel : { nightlyRate : 200.0 , nights : 4 } ,
217+ car : { dailyRate : 100.0 , days : 4 } ,
218+ customer : { loyaltyTier : "PLATINUM" } ,
219+ bookingDate : "2025-07-15T00:00:00Z" ,
220+ } ,
221+ } ) ;
222+ expect ( result ) . toBe ( true ) ;
223+ } ) ;
224+
225+ it ( "should not qualify outside summer months" , async ( ) => {
226+ const result = await program . execute ( {
227+ reservation : {
228+ flight : { price : 1000.0 } ,
229+ hotel : { nightlyRate : 200.0 , nights : 4 } ,
230+ car : { dailyRate : 100.0 , days : 4 } ,
231+ customer : { loyaltyTier : "PLATINUM" } ,
232+ bookingDate : "2025-12-15T00:00:00Z" ,
233+ } ,
234+ } ) ;
235+ expect ( result ) . toBe ( false ) ;
236+ program = await CelProgram . compile ( expr ) ;
237+ } ) ;
238+ } ) ;
239+
240+ describe ( "Multi-condition Booking Validation" , ( ) => {
241+ // Tests complex booking validation rules that ensure:
242+ // - All required components are present
243+ // - Logical time sequence of events
244+ // - Location consistency
245+ // - Capacity constraints
246+ const expr = `
247+ has(reservation.flight) &&
248+ timestamp(reservation.flight.departureTime) < timestamp(reservation.hotel.checkIn) &&
249+ timestamp(reservation.hotel.checkIn) < timestamp(reservation.hotel.checkOut) &&
250+ (timestamp(reservation.hotel.checkOut) - timestamp(reservation.hotel.checkIn)) > duration("1h") &&
251+ timestamp(reservation.hotel.checkOut) < timestamp(reservation.flight.returnTime) &&
252+ (reservation.car.pickupLocation == reservation.flight.arrivalAirport ||
253+ reservation.car.pickupLocation == reservation.hotel.address.city) &&
254+ size(reservation.travelers) <= reservation.hotel.maxOccupancy &&
255+ size(reservation.travelers) <= reservation.car.capacity
256+ ` ;
257+ let program : CelProgram ;
258+
259+ beforeEach ( async ( ) => {
260+ program = await CelProgram . compile ( expr ) ;
261+ } ) ;
262+
263+ it ( "should validate a well-formed booking" , async ( ) => {
264+ const result = await program . execute ( {
265+ reservation : {
266+ flight : {
267+ departureTime : "2025-05-01T10:00:00Z" ,
268+ returnTime : "2025-05-05T15:00:00Z" ,
269+ arrivalAirport : "LAX" ,
270+ } ,
271+ hotel : {
272+ checkIn : "2025-05-01T15:00:00Z" ,
273+ checkOut : "2025-05-05T11:00:00Z" ,
274+ maxOccupancy : 4 ,
275+ address : { city : "Los Angeles" } ,
276+ } ,
277+ car : {
278+ pickupLocation : "LAX" ,
279+ capacity : 5 ,
280+ } ,
281+ travelers : [ "person1" , "person2" , "person3" ] ,
282+ } ,
283+ } ) ;
284+ expect ( result ) . toBe ( true ) ;
285+ } ) ;
286+
287+ it ( "should reject invalid time sequence" , async ( ) => {
288+ const result = await program . execute ( {
289+ reservation : {
290+ flight : {
291+ departureTime : "2025-05-01T16:00:00Z" , // Later than check-in
292+ returnTime : "2025-05-05T15:00:00Z" ,
293+ arrivalAirport : "LAX" ,
294+ } ,
295+ hotel : {
296+ checkIn : "2025-05-01T15:00:00Z" ,
297+ checkOut : "2025-05-05T11:00:00Z" ,
298+ maxOccupancy : 4 ,
299+ address : { city : "Los Angeles" } ,
300+ } ,
301+ car : {
302+ pickupLocation : "LAX" ,
303+ capacity : 5 ,
304+ } ,
305+ travelers : [ "person1" , "person2" , "person3" ] ,
306+ } ,
307+ } ) ;
308+ expect ( result ) . toBe ( false ) ;
309+ } ) ;
310+ } ) ;
311+
312+ describe . skip ( "Dynamic Pricing with Seasonal Adjustments" , ( ) => {
313+ // Tests complex pricing calculations including:
314+ // - Base rates for all components
315+ // - Seasonal multipliers
316+ // - Loyalty discounts
317+ const expr = `
318+ let basePrice = double(reservation.flight.price) +
319+ double(reservation.hotel.nightlyRate) * int(reservation.hotel.nights) +
320+ double(reservation.car.dailyRate) * int(reservation.car.days);
321+ let seasonalPrice = basePrice * (timestamp(reservation.hotel.checkIn).getMonth() in [11, 0, 1] ? 1.25 : 1.0);
322+ seasonalPrice * (1.0 - {'BRONZE': 0.05, 'SILVER': 0.10, 'GOLD': 0.15, 'PLATINUM': 0.20}[reservation.customer.loyaltyTier])
323+ ` ;
324+ let program : CelProgram ;
325+
326+ beforeEach ( async ( ) => {
327+ program = await CelProgram . compile ( expr ) ;
328+ } ) ;
329+
330+ it ( "should calculate winter pricing with loyalty discount" , async ( ) => {
331+ const result = await program . execute ( {
332+ reservation : {
333+ flight : { price : 1000.0 } ,
334+ hotel : {
335+ nightlyRate : 200.0 ,
336+ nights : 4 ,
337+ checkIn : "2025-01-15T15:00:00Z" , // January
338+ } ,
339+ car : { dailyRate : 100.0 , days : 4 } ,
340+ customer : { loyaltyTier : "GOLD" } ,
341+ } ,
342+ } ) ;
343+ // Base: 1000 + (200 * 4) + (100 * 4) = 2200
344+ // Winter multiplier: 2200 * 1.25 = 2750
345+ // Gold discount (15%): 2750 * 0.85 = 2337.5
346+ expect ( result ) . toBe ( 2337.5 ) ;
347+ } ) ;
348+
349+ it ( "should calculate summer pricing with loyalty discount" , async ( ) => {
350+ const result = await program . execute ( {
351+ reservation : {
352+ flight : { price : 1000.0 } ,
353+ hotel : {
354+ nightlyRate : 200.0 ,
355+ nights : 4 ,
356+ checkIn : "2025-07-15T15:00:00Z" , // July
357+ } ,
358+ car : { dailyRate : 100.0 , days : 4 } ,
359+ customer : { loyaltyTier : "PLATINUM" } ,
360+ } ,
361+ } ) ;
362+ // Base: 1000 + (200 * 4) + (100 * 4) = 2200
363+ // No seasonal multiplier
364+ // Platinum discount (20%): 2200 * 0.80 = 1760
365+ expect ( result ) . toBe ( 1760.0 ) ;
366+ } ) ;
367+ } ) ;
368+
369+ describe ( "Room Upgrade Eligibility" , ( ) => {
370+ // Tests complex upgrade eligibility rules considering:
371+ // - Customer loyalty tier
372+ // - Stay duration
373+ // - Hotel occupancy
374+ // - Existing offers
375+ // - Total spend
376+ // - Current booking class
377+ const expr = `
378+ reservation.customer.loyaltyTier in ['GOLD', 'PLATINUM'] &&
379+ reservation.hotel.nights >= 3 &&
380+ reservation.hotel.occupancyRate < 0.80 &&
381+ !(reservation.specialOffers.exists(o, o.type == 'ROOM_UPGRADE')) &&
382+ reservation.totalSpend > 5000.0 &&
383+ [reservation.flight.class, reservation.hotel.roomType].all(t, t != 'ECONOMY')
384+ ` ;
385+ let program : CelProgram ;
386+
387+ beforeEach ( async ( ) => {
388+ program = await CelProgram . compile ( expr ) ;
389+ } ) ;
390+
391+ it ( "should qualify eligible platinum member for upgrade" , async ( ) => {
392+ const result = await program . execute ( {
393+ reservation : {
394+ customer : { loyaltyTier : "PLATINUM" } ,
395+ hotel : {
396+ nights : 4 ,
397+ occupancyRate : 0.7 ,
398+ roomType : "DELUXE" ,
399+ } ,
400+ flight : { class : "BUSINESS" } ,
401+ specialOffers : [ ] ,
402+ totalSpend : 6000.0 ,
403+ } ,
404+ } ) ;
405+ expect ( result ) . toBe ( true ) ;
406+ } ) ;
407+
408+ it ( "should reject upgrade when conditions not met" , async ( ) => {
409+ const result = await program . execute ( {
410+ reservation : {
411+ customer : { loyaltyTier : "PLATINUM" } ,
412+ hotel : {
413+ nights : 4 ,
414+ occupancyRate : 0.85 , // Too high occupancy
415+ roomType : "DELUXE" ,
416+ } ,
417+ flight : { class : "BUSINESS" } ,
418+ specialOffers : [ ] ,
419+ totalSpend : 6000.0 ,
420+ } ,
421+ } ) ;
422+ expect ( result ) . toBe ( false ) ;
423+ } ) ;
424+ } ) ;
425+ } ) ;
0 commit comments