1+ /**
2+ * src/routes/__tests__/forecast.test.ts
3+ *
4+ * Legacy test file retained for regression coverage.
5+ * The main pagination-focused suite lives in src/routes/forecast.test.ts.
6+ */
7+
18import express from 'express' ;
29import request from 'supertest' ;
310import { createForecastRouter } from '../forecast.js' ;
411import { errorHandler } from '../../middleware/errorHandler.js' ;
12+ import { FORECAST_DEFAULT_LIMIT } from '../forecast.js' ;
513
6- describe ( '/api/forecast' , ( ) => {
7- it ( 'should return 200 with forecast data ' , async ( ) => {
14+ describe ( '/api/forecast — basic route smoke tests ' , ( ) => {
15+ it ( 'should return 200 with the paginated envelope ' , async ( ) => {
816 const app = express ( ) ;
917 app . use ( '/api/forecast' , createForecastRouter ( 5_000 ) ) ;
1018 app . use ( errorHandler ) ;
@@ -13,34 +21,35 @@ describe('/api/forecast', () => {
1321 expect ( res . status ) . toBe ( 200 ) ;
1422 expect ( res . body . success ) . toBe ( true ) ;
1523 expect ( res . body . data ) . toBeDefined ( ) ;
16- expect ( res . body . data . forecast ) . toBeDefined ( ) ;
17- expect ( Array . isArray ( res . body . data . forecast ) ) . toBe ( true ) ;
18- expect ( res . body . data . forecast . length ) . toBe ( 24 ) ;
19- expect ( res . body . data . generatedAt ) . toBeDefined ( ) ;
24+ // New shape: items, total, and optional next_cursor
25+ expect ( res . body . data . items ) . toBeDefined ( ) ;
26+ expect ( Array . isArray ( res . body . data . items ) ) . toBe ( true ) ;
27+ expect ( typeof res . body . data . total ) . toBe ( 'number' ) ;
2028 expect ( res . body . requestId ) . toBeDefined ( ) ;
2129 expect ( res . body . timestamp ) . toBeDefined ( ) ;
2230 } ) ;
2331
24- it ( 'should return forecast points with timestamp and value' , async ( ) => {
32+ it ( 'items contain timestamp and value fields ' , async ( ) => {
2533 const app = express ( ) ;
2634 app . use ( '/api/forecast' , createForecastRouter ( 5_000 ) ) ;
2735
2836 const res = await request ( app ) . get ( '/api/forecast' ) ;
29- for ( const point of res . body . data . forecast ) {
37+ for ( const point of res . body . data . items ) {
3038 expect ( point . timestamp ) . toBeDefined ( ) ;
3139 expect ( typeof point . timestamp ) . toBe ( 'string' ) ;
3240 expect ( point . value ) . toBeDefined ( ) ;
3341 expect ( typeof point . value ) . toBe ( 'number' ) ;
3442 }
3543 } ) ;
3644
37- it ( 'should return 504 when forecast calculation takes too long' , async ( ) => {
45+ it ( 'returns 504 when forecast calculation takes too long' , async ( ) => {
3846 const app = express ( ) ;
3947
4048 const router = createForecastRouter ( 1 ) ;
4149 router . get ( '/slow' , ( _req , res ) => {
4250 const now = Date . now ( ) ;
4351 while ( Date . now ( ) - now < 200 ) {
52+ /* spin */
4453 }
4554 res . json ( { ok : true } ) ;
4655 } ) ;
@@ -51,15 +60,23 @@ describe('/api/forecast', () => {
5160 expect ( res . body . error . code ) . toBe ( 'GATEWAY_TIMEOUT' ) ;
5261 } ) ;
5362
54- it ( 'should generate 24 forecast points' , async ( ) => {
63+ it ( 'default page has FORECAST_DEFAULT_LIMIT items' , async ( ) => {
64+ const app = express ( ) ;
65+ app . use ( '/api/forecast' , createForecastRouter ( 5_000 ) ) ;
66+
67+ const res = await request ( app ) . get ( '/api/forecast' ) ;
68+ expect ( res . body . data . items ) . toHaveLength ( FORECAST_DEFAULT_LIMIT ) ;
69+ } ) ;
70+
71+ it ( 'total equals 24 (full hourly forecast horizon)' , async ( ) => {
5572 const app = express ( ) ;
5673 app . use ( '/api/forecast' , createForecastRouter ( 5_000 ) ) ;
5774
5875 const res = await request ( app ) . get ( '/api/forecast' ) ;
59- expect ( res . body . data . forecast ) . toHaveLength ( 24 ) ;
76+ expect ( res . body . data . total ) . toBe ( 24 ) ;
6077 } ) ;
6178
62- it ( 'should include requestId in response' , async ( ) => {
79+ it ( 'includes requestId in response' , async ( ) => {
6380 const app = express ( ) ;
6481 app . use ( ( req , _res , next ) => {
6582 req . id = 'test-request-id' ;
@@ -71,7 +88,7 @@ describe('/api/forecast', () => {
7188 expect ( res . body . requestId ) . toBe ( 'test-request-id' ) ;
7289 } ) ;
7390
74- it ( 'should expose forecast as sub-route of /api in the router ' , async ( ) => {
91+ it ( 'mounts correctly as sub-route of /api' , async ( ) => {
7592 const app = express ( ) ;
7693 app . use ( '/api' , createForecastRouter ( 5_000 ) ) ;
7794
0 commit comments