Skip to content

Commit b696ade

Browse files
authored
Merge pull request #30 from BaljinderHothi/testing
Testing
2 parents e656f38 + 2f1d0c8 commit b696ade

25 files changed

+608
-82
lines changed

.DS_Store

8 KB
Binary file not shown.

.github/workflows/cipipeline.yml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
name: CI Test Pipeline
2+
3+
on:
4+
pull_request:
5+
branches: [ main ]
6+
7+
jobs:
8+
test:
9+
runs-on: ubuntu-latest
10+
continue-on-error: false
11+
12+
env:
13+
PYTHONPATH: ${{ github.workspace }}
14+
NEXT_PUBLIC_MOCK_GEMINI: true
15+
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
16+
NEXT_PUBLIC_SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }}
17+
18+
steps:
19+
- name: 🧾 Checkout code
20+
uses: actions/checkout@v3
21+
22+
- name: ⚙️ Setup Node.js
23+
uses: actions/setup-node@v3
24+
with:
25+
node-version: 18
26+
27+
- name: ⚙️ Setup Python
28+
uses: actions/setup-python@v4
29+
with:
30+
python-version: '3.10'
31+
32+
- name: ♻️ Cache Python dependencies
33+
uses: actions/cache@v3
34+
with:
35+
path: ~/.cache/pip
36+
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
37+
restore-keys: ${{ runner.os }}-pip-
38+
39+
- name: ♻️ Cache Node modules
40+
uses: actions/cache@v3
41+
with:
42+
path: ./fitcheck/node_modules
43+
key: ${{ runner.os }}-node-${{ hashFiles('fitcheck/package-lock.json') }}
44+
restore-keys: ${{ runner.os }}-node-
45+
46+
- name: Install Python dependencies
47+
run: |
48+
python -m pip install --upgrade pip
49+
pip install -r requirements.txt
50+
pip install pytest pytest-cov playwright
51+
playwright install
52+
53+
- name: Install frontend dependencies
54+
working-directory: ./fitcheck
55+
run: npm install
56+
57+
- name: Build Next.js app
58+
working-directory: ./fitcheck
59+
env:
60+
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
61+
NEXT_PUBLIC_SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }}
62+
NEXT_PUBLIC_MOCK_GEMINI: true
63+
run: npm run build
64+
65+
- name: Start Next.js server in background
66+
working-directory: ./fitcheck
67+
env:
68+
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
69+
NEXT_PUBLIC_SUPABASE_KEY: ${{ secrets.SUPABASE_KEY }}
70+
NEXT_PUBLIC_MOCK_GEMINI: true
71+
run: |
72+
nohup npm start > ../nextjs.log 2>&1 &
73+
74+
- name: Wait for server to be ready
75+
run: |
76+
for i in {1..10}; do
77+
curl --fail http://localhost:3000/login && break || sleep 3
78+
done || (echo "Server failed to start or /login not reachable" && cat fitcheck/../nextjs.log && exit 1)
79+
80+
- name: Run Python tests with coverage
81+
run: pytest --cov=./ --cov-report=html
82+
83+
- name: Run Playwright E2E test (Login + Dashboard)
84+
run: python tests/test_login_e2e.py
85+
86+
- name: Run Playwright E2E test (Extension UI)
87+
run: xvfb-run -a python tests/test_popup_ui.py
88+
89+
- name: Upload coverage report
90+
uses: actions/upload-artifact@v4
91+
with:
92+
name: coverage-report
93+
path: htmlcov

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,5 @@ node_modules/
4343
babel.config.js
4444
.env.local
4545

46+
__pycache__/
47+
*.py[cod]

fitcheck/pages/api/user_rec/getRec.js

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
import supabase from '../../../utils/supabase/config';
33
import recommendationService from '../../../utils/supabase/recommendationService';
44

5-
6-
75
export default async function handler(req, res) {
86
if (req.method !== 'GET') {
97
return res.status(405).json({ error: 'Only GET supported' });
@@ -14,53 +12,59 @@ export default async function handler(req, res) {
1412
return res.status(401).json({ error: 'Missing or invalid Authorization header' });
1513
}
1614

17-
const token = authHeader.split('Bearer ')[1];
18-
const { data: userData, error: userError } = await supabase.auth.getUser(token);
15+
try {
16+
const token = authHeader.split('Bearer ')[1];
17+
const { data: userData, error: userError } = await supabase.auth.getUser(token);
1918

20-
if (userError || !userData?.user) {
21-
return res.status(401).json({ error: 'Invalid or expired token' });
22-
}
19+
if (userError || !userData?.user) {
20+
console.error('Auth error:', userError?.message || 'No user data');
21+
return res.status(401).json({ error: 'Invalid or expired token' });
22+
}
2323

24-
const email = userData.user.email;
24+
const email = userData.user.email;
2525

26-
// Get user ID from 'users' table
27-
const { data: userRow, error: userLookupError } = await supabase
28-
.from('users')
29-
.select('userid')
30-
.eq('email', email)
31-
.single();
26+
const { data: userRow, error: userLookupError } = await supabase
27+
.from('users')
28+
.select('userid')
29+
.eq('email', email)
30+
.single();
3231

33-
if (userLookupError || !userRow) {
34-
return res.status(404).json({ error: 'User not found' });
35-
}
32+
if (userLookupError || !userRow) {
33+
console.error('User lookup failed:', userLookupError?.message || 'User not found');
34+
return res.status(404).json({ error: 'User not found' });
35+
}
3636

37-
// Get sentiment reviews
38-
const { data: sentimentData, error: sentimentError } = await supabase
39-
.from('sentiment')
40-
.select('*')
41-
.eq('userid', userRow.userid)
42-
.order('created_at', { ascending: false });
37+
const { data: sentimentData, error: sentimentError } = await supabase
38+
.from('sentiment')
39+
.select('*')
40+
.eq('userid', userRow.userid)
41+
.order('created_at', { ascending: false });
4342

44-
if (sentimentError) {
45-
return res.status(500).json({ error: 'Failed to fetch sentiment data' });
46-
}
43+
if (sentimentError) {
44+
console.error('Sentiment fetch error:', sentimentError.message);
45+
return res.status(500).json({ error: 'Failed to fetch sentiment data' });
46+
}
47+
48+
const reviews = sentimentData.map(item => ({
49+
productName: item.product_name,
50+
rating: item.star_rating,
51+
likedFeatures: item.sentiment_label === 'positive' ? 'style, comfort' : '',
52+
dislikedFeatures: item.sentiment_label === 'negative' ? 'fit, quality' : '',
53+
comment: item.review_text
54+
}));
4755

48-
// Transform reviews into Gemini-compatible format
49-
const reviews = sentimentData.map(item => ({
50-
productName: item.product_name,
51-
rating: item.star_rating,
52-
likedFeatures: item.sentiment_label === 'positive' ? 'style, comfort' : '',
53-
dislikedFeatures: item.sentiment_label === 'negative' ? 'fit, quality' : '',
54-
comment: item.review_text
55-
}));
56+
const userPayload = {
57+
reviews: reviews.slice(0, 3),
58+
stylePreferences: {},
59+
purchaseHistory: [],
60+
budget: { weeklyAmount: 100, spentAmount: 0 }
61+
};
5662

57-
const userPayload = {
58-
reviews: reviews.slice(0, 3), // ✅ limit to 3 to avoid token limit
59-
stylePreferences: {},
60-
purchaseHistory: [],
61-
budget: { weeklyAmount: 100, spentAmount: 0 }
62-
};
63+
const recommendations = await recommendationService.generateRecommendations(userPayload);
64+
return res.status(200).json({ recommendations });
6365

64-
const recommendations = await recommendationService.generateRecommendations(userPayload);
65-
return res.status(200).json({ recommendations });
66+
} catch (err) {
67+
console.error('Unexpected server error in getReviews:', err);
68+
return res.status(500).json({ error: 'Internal Server Error' });
69+
}
6670
}
-3.02 KB
Binary file not shown.

fitcheck/tests/test_login.py

Lines changed: 0 additions & 40 deletions
This file was deleted.

requirements.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
fastapi
2+
requests
3+
pytest
4+
pytest-cov
5+
pytest-asyncio
6+
pytest-tornasync
7+
pytest-trio
8+
pytest-twisted
9+
playwright
10+
python-dotenv
11+
twisted
12+
git+https://github.com/supabase-community/supabase-py.git
Binary file not shown.
Binary file not shown.
1.48 KB
Binary file not shown.

0 commit comments

Comments
 (0)