11/**
22 * index.test.js
33 *
4- * Tests for backend API endpoints.
5- * Validates route handling, error responses , and input validation.
4+ * Integration tests for backend API endpoints.
5+ * Tests actual route handling, database interactions , and input validation.
66 */
77
8- import { describe , it , expect , vi } from 'vitest' ;
8+ import { describe , it , expect , beforeAll } from 'vitest' ;
99import request from 'supertest' ;
1010import express from 'express' ;
1111import cors from 'cors' ;
12-
13- // Mock the supabase config to avoid requiring env vars
14- vi . mock ( './config/supabase.js' , ( ) => ( {
15- supabase : { }
16- } ) ) ;
17-
18- // Import routes AFTER mocking
19- const courseRoutes = await import ( './routes/courses.js' ) . then ( m => m . default ) ;
12+ import 'dotenv/config' ;
13+ import courseRoutes from './routes/courses.js' ;
2014
2115// Create test app instance
2216const app = express ( ) ;
@@ -52,6 +46,62 @@ describe('Backend API Tests', () => {
5246 } ) ;
5347} ) ;
5448
49+ describe ( 'API Routes Integration Tests' , ( ) => {
50+
51+ describe ( 'GET /api/courses' , ( ) => {
52+ it ( 'should return list of courses with ratings' , async ( ) => {
53+ const response = await request ( app )
54+ . get ( '/api/courses' )
55+ . expect ( 200 ) ;
56+
57+ expect ( response . body ) . toHaveProperty ( 'success' , true ) ;
58+ expect ( response . body ) . toHaveProperty ( 'data' ) ;
59+ expect ( Array . isArray ( response . body . data ) ) . toBe ( true ) ;
60+
61+ // Check structure of first course if any exist
62+ if ( response . body . data . length > 0 ) {
63+ const course = response . body . data [ 0 ] ;
64+ expect ( course ) . toHaveProperty ( 'id' ) ;
65+ expect ( course ) . toHaveProperty ( 'Course_name' ) ;
66+ expect ( course ) . toHaveProperty ( 'rating' ) ;
67+ expect ( course ) . toHaveProperty ( 'numReviews' ) ;
68+ }
69+ } ) ;
70+ } ) ;
71+
72+ describe ( 'GET /api/courses/:id' , ( ) => {
73+ it ( 'should return a single course with rating' , async ( ) => {
74+ const response = await request ( app )
75+ . get ( '/api/courses/1' )
76+ . expect ( 200 ) ;
77+
78+ expect ( response . body ) . toHaveProperty ( 'success' , true ) ;
79+ expect ( response . body . data ) . toHaveProperty ( 'id' , 1 ) ;
80+ expect ( response . body . data ) . toHaveProperty ( 'rating' ) ;
81+ expect ( response . body . data ) . toHaveProperty ( 'numReviews' ) ;
82+ } ) ;
83+
84+ it ( 'should return 404 for non-existent course' , async ( ) => {
85+ const response = await request ( app )
86+ . get ( '/api/courses/99999' )
87+ . expect ( 404 ) ;
88+
89+ expect ( response . body ) . toHaveProperty ( 'success' , false ) ;
90+ } ) ;
91+ } ) ;
92+
93+ describe ( 'GET /api/courses/:id/reviews' , ( ) => {
94+ it ( 'should return reviews for a course' , async ( ) => {
95+ const response = await request ( app )
96+ . get ( '/api/courses/1/reviews' )
97+ . expect ( 200 ) ;
98+
99+ expect ( response . body ) . toHaveProperty ( 'success' , true ) ;
100+ expect ( Array . isArray ( response . body . data ) ) . toBe ( true ) ;
101+ } ) ;
102+ } ) ;
103+ } ) ;
104+
55105describe ( 'Review Validation Tests' , ( ) => {
56106 it ( 'should reject review with missing rating' , async ( ) => {
57107 const response = await request ( app )
@@ -100,4 +150,62 @@ describe('Review Validation Tests', () => {
100150 expect ( response . body . success ) . toBe ( false ) ;
101151 expect ( response . body . error ) . toContain ( 'required' ) ;
102152 } ) ;
153+
154+ it ( 'should create a new review with valid data' , async ( ) => {
155+ const newReview = {
156+ rating : 5 ,
157+ comment : 'Automated test review - excellent course!' ,
158+ student_name : 'Test Student'
159+ } ;
160+
161+ const response = await request ( app )
162+ . post ( '/api/courses/1/reviews' )
163+ . send ( newReview )
164+ . expect ( 201 ) ;
165+
166+ expect ( response . body ) . toHaveProperty ( 'success' , true ) ;
167+ expect ( response . body . data ) . toHaveProperty ( 'id' ) ;
168+ expect ( response . body . data . rating ) . toBe ( 5 ) ;
169+ expect ( response . body . data . comment ) . toBe ( 'Automated test review - excellent course!' ) ;
170+ } ) ;
171+ } ) ;
172+
173+ describe ( 'Vote System Tests' , ( ) => {
174+ let testReviewId ;
175+
176+ // Get a review ID for testing votes
177+ beforeAll ( async ( ) => {
178+ const response = await request ( app ) . get ( '/api/courses/1/reviews' ) ;
179+ if ( response . body . data && response . body . data . length > 0 ) {
180+ testReviewId = response . body . data [ 0 ] . id ;
181+ }
182+ } ) ;
183+
184+ it ( 'should increment upvote count' , async ( ) => {
185+ if ( ! testReviewId ) {
186+ console . log ( 'Skipping upvote test - no reviews available' ) ;
187+ return ;
188+ }
189+
190+ const response = await request ( app )
191+ . post ( `/api/courses/1/reviews/${ testReviewId } /upvote` )
192+ . expect ( 200 ) ;
193+
194+ expect ( response . body ) . toHaveProperty ( 'success' , true ) ;
195+ expect ( response . body . data ) . toHaveProperty ( 'upvotes' ) ;
196+ } ) ;
197+
198+ it ( 'should increment downvote count' , async ( ) => {
199+ if ( ! testReviewId ) {
200+ console . log ( 'Skipping downvote test - no reviews available' ) ;
201+ return ;
202+ }
203+
204+ const response = await request ( app )
205+ . post ( `/api/courses/1/reviews/${ testReviewId } /downvote` )
206+ . expect ( 200 ) ;
207+
208+ expect ( response . body ) . toHaveProperty ( 'success' , true ) ;
209+ expect ( response . body . data ) . toHaveProperty ( 'downvotes' ) ;
210+ } ) ;
103211} ) ;
0 commit comments