@@ -7,29 +7,139 @@ describe('API Tests', () => {
77 db . close ( ) ;
88 } ) ;
99
10- test ( 'GET /api/products returns products' , async ( ) => {
11- const res = await request ( app ) . get ( '/api/products' ) ;
12- expect ( res . statusCode ) . toBe ( 200 ) ;
13- expect ( Array . isArray ( res . body ) ) . toBe ( true ) ;
14- expect ( res . body . length ) . toBeGreaterThan ( 0 ) ;
15- expect ( res . body [ 0 ] ) . toHaveProperty ( 'name' ) ;
10+ // ───────────────── GET /api/products ─────────────────
11+ describe ( 'GET /api/products' , ( ) => {
12+ test ( 'returns 200 status code' , async ( ) => {
13+ const res = await request ( app ) . get ( '/api/products' ) ;
14+ expect ( res . statusCode ) . toBe ( 200 ) ;
15+ } ) ;
16+
17+ test ( 'returns an array of products' , async ( ) => {
18+ const res = await request ( app ) . get ( '/api/products' ) ;
19+ expect ( Array . isArray ( res . body ) ) . toBe ( true ) ;
20+ expect ( res . body . length ) . toBeGreaterThan ( 0 ) ;
21+ } ) ;
22+
23+ test ( 'each product has required fields' , async ( ) => {
24+ const res = await request ( app ) . get ( '/api/products' ) ;
25+ for ( const product of res . body ) {
26+ expect ( product ) . toHaveProperty ( 'id' ) ;
27+ expect ( product ) . toHaveProperty ( 'name' ) ;
28+ expect ( product ) . toHaveProperty ( 'price' ) ;
29+ expect ( product ) . toHaveProperty ( 'image_url' ) ;
30+ }
31+ } ) ;
32+
33+ test ( 'product price is a positive number' , async ( ) => {
34+ const res = await request ( app ) . get ( '/api/products' ) ;
35+ for ( const product of res . body ) {
36+ expect ( typeof product . price ) . toBe ( 'number' ) ;
37+ expect ( product . price ) . toBeGreaterThan ( 0 ) ;
38+ }
39+ } ) ;
40+
41+ test ( 'returns JSON content type' , async ( ) => {
42+ const res = await request ( app ) . get ( '/api/products' ) ;
43+ expect ( res . headers [ 'content-type' ] ) . toMatch ( / j s o n / ) ;
44+ } ) ;
1645 } ) ;
1746
18- test ( 'POST /api/checkout works' , async ( ) => {
19- const res = await request ( app )
20- . post ( '/api/checkout' )
21- . send ( { items : [ { productId : 1 , quantity : 2 } ] } ) ;
22-
23- expect ( res . statusCode ) . toBe ( 200 ) ;
24- expect ( res . body ) . toHaveProperty ( 'message' , 'Checkout successful' ) ;
25- expect ( res . body ) . toHaveProperty ( 'total' ) ;
47+ // ───────────────── POST /api/checkout ─────────────────
48+ describe ( 'POST /api/checkout' , ( ) => {
49+ test ( 'returns 200 with valid cart items' , async ( ) => {
50+ const res = await request ( app )
51+ . post ( '/api/checkout' )
52+ . send ( { items : [ { productId : 1 , quantity : 2 } ] } ) ;
53+
54+ expect ( res . statusCode ) . toBe ( 200 ) ;
55+ expect ( res . body ) . toHaveProperty ( 'message' , 'Checkout successful' ) ;
56+ expect ( res . body ) . toHaveProperty ( 'total' ) ;
57+ expect ( res . body ) . toHaveProperty ( 'orderId' ) ;
58+ } ) ;
59+
60+ test ( 'calculates total correctly for single item' , async ( ) => {
61+ const productsRes = await request ( app ) . get ( '/api/products' ) ;
62+ const firstProduct = productsRes . body [ 0 ] ;
63+ const quantity = 3 ;
64+
65+ const res = await request ( app )
66+ . post ( '/api/checkout' )
67+ . send ( { items : [ { productId : firstProduct . id , quantity } ] } ) ;
68+
69+ expect ( res . statusCode ) . toBe ( 200 ) ;
70+ const expectedTotal = firstProduct . price * quantity ;
71+ expect ( res . body . total ) . toBeCloseTo ( expectedTotal , 2 ) ;
72+ } ) ;
73+
74+ test ( 'calculates total correctly for multiple items' , async ( ) => {
75+ const productsRes = await request ( app ) . get ( '/api/products' ) ;
76+ const products = productsRes . body ;
77+
78+ const cartItems = [
79+ { productId : products [ 0 ] . id , quantity : 1 } ,
80+ { productId : products [ 1 ] . id , quantity : 2 } ,
81+ ] ;
82+
83+ const res = await request ( app )
84+ . post ( '/api/checkout' )
85+ . send ( { items : cartItems } ) ;
86+
87+ const expectedTotal =
88+ products [ 0 ] . price * 1 + products [ 1 ] . price * 2 ;
89+ expect ( res . statusCode ) . toBe ( 200 ) ;
90+ expect ( res . body . total ) . toBeCloseTo ( expectedTotal , 2 ) ;
91+ } ) ;
92+
93+ test ( 'returns 400 with empty items array' , async ( ) => {
94+ const res = await request ( app )
95+ . post ( '/api/checkout' )
96+ . send ( { items : [ ] } ) ;
97+
98+ expect ( res . statusCode ) . toBe ( 400 ) ;
99+ expect ( res . body ) . toHaveProperty ( 'error' ) ;
100+ } ) ;
101+
102+ test ( 'returns 400 with missing items field' , async ( ) => {
103+ const res = await request ( app )
104+ . post ( '/api/checkout' )
105+ . send ( { } ) ;
106+
107+ expect ( res . statusCode ) . toBe ( 400 ) ;
108+ expect ( res . body ) . toHaveProperty ( 'error' , 'Invalid cart contents' ) ;
109+ } ) ;
110+
111+ test ( 'returns 400 when items is not an array' , async ( ) => {
112+ const res = await request ( app )
113+ . post ( '/api/checkout' )
114+ . send ( { items : 'not-an-array' } ) ;
115+
116+ expect ( res . statusCode ) . toBe ( 400 ) ;
117+ } ) ;
118+
119+ test ( 'returns orderId as a number' , async ( ) => {
120+ const res = await request ( app )
121+ . post ( '/api/checkout' )
122+ . send ( { items : [ { productId : 1 , quantity : 1 } ] } ) ;
123+
124+ expect ( typeof res . body . orderId ) . toBe ( 'number' ) ;
125+ } ) ;
126+
127+ test ( 'handles non-existent product id gracefully' , async ( ) => {
128+ const res = await request ( app )
129+ . post ( '/api/checkout' )
130+ . send ( { items : [ { productId : 99999 , quantity : 1 } ] } ) ;
131+
132+ // Should succeed but total should be 0 (product not found)
133+ expect ( res . statusCode ) . toBe ( 200 ) ;
134+ expect ( res . body . total ) . toBe ( 0 ) ;
135+ } ) ;
26136 } ) ;
27137
28- test ( 'POST /api/checkout fails with empty items' , async ( ) => {
29- const res = await request ( app )
30- . post ( ' /api/checkout' )
31- . send ( { items : [ ] } ) ;
32-
33- expect ( res . statusCode ) . toBe ( 400 ) ;
138+ // ───────────────── Unknown routes ─────────────────
139+ describe ( 'Unknown routes' , ( ) => {
140+ test ( 'GET /api/unknown returns 404' , async ( ) => {
141+ const res = await request ( app ) . get ( '/api/unknown' ) ;
142+ expect ( res . statusCode ) . toBe ( 404 ) ;
143+ } ) ;
34144 } ) ;
35145} ) ;
0 commit comments