251 lines
7.7 KiB
JavaScript
251 lines
7.7 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Automated E2E Flow Test for Service Finder Frontend
|
|
*
|
|
* This script simulates:
|
|
* 1. Logging in and getting a token
|
|
* 2. Setting the Profile Mode (Personal/Fleet)
|
|
* 3. Fetching the User's Garage
|
|
* 4. Fetching Gamification stats
|
|
*
|
|
* Usage: node automated_flow_test.js
|
|
*/
|
|
|
|
import axios from 'axios'
|
|
import { fileURLToPath } from 'url'
|
|
import { dirname } from 'path'
|
|
|
|
const __filename = fileURLToPath(import.meta.url)
|
|
const __dirname = dirname(__filename)
|
|
|
|
// Configuration
|
|
const API_BASE_URL = process.env.VITE_API_BASE_URL || 'https://dev.servicefinder.hu'
|
|
const TEST_USER_EMAIL = process.env.TEST_USER_EMAIL || 'test@example.com'
|
|
const TEST_USER_PASSWORD = process.env.TEST_USER_PASSWORD || 'password123'
|
|
|
|
// Create axios instance
|
|
const api = axios.create({
|
|
baseURL: API_BASE_URL,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
})
|
|
|
|
// Test state
|
|
let authToken = null
|
|
let userId = null
|
|
|
|
async function sleep(ms) {
|
|
return new Promise(resolve => setTimeout(resolve, ms))
|
|
}
|
|
|
|
async function testLogin() {
|
|
console.log('🔐 Testing login...')
|
|
|
|
try {
|
|
// First, check if we need to register a test user
|
|
// For now, we'll try to login with provided credentials
|
|
const response = await api.post('/api/v2/auth/login', {
|
|
email: TEST_USER_EMAIL,
|
|
password: TEST_USER_PASSWORD,
|
|
})
|
|
|
|
if (response.data.access_token) {
|
|
authToken = response.data.access_token
|
|
userId = response.data.user_id
|
|
console.log('✅ Login successful')
|
|
console.log(` Token: ${authToken.substring(0, 20)}...`)
|
|
console.log(` User ID: ${userId}`)
|
|
|
|
// Set auth header for subsequent requests
|
|
api.defaults.headers.common['Authorization'] = `Bearer ${authToken}`
|
|
return true
|
|
}
|
|
} catch (error) {
|
|
console.error('❌ Login failed:', error.response?.data || error.message)
|
|
|
|
// If login fails due to invalid credentials, try to register
|
|
if (error.response?.status === 401 || error.response?.status === 404) {
|
|
console.log('⚠️ Attempting to register test user...')
|
|
try {
|
|
const registerResponse = await api.post('/api/v2/auth/register', null, {
|
|
params: {
|
|
email: TEST_USER_EMAIL,
|
|
password: TEST_USER_PASSWORD,
|
|
first_name: 'Test',
|
|
last_name: 'User',
|
|
phone: '+36123456789',
|
|
}
|
|
})
|
|
|
|
if (registerResponse.data.access_token) {
|
|
authToken = registerResponse.data.access_token
|
|
userId = registerResponse.data.user_id
|
|
console.log('✅ Test user registered and logged in')
|
|
api.defaults.headers.common['Authorization'] = `Bearer ${authToken}`
|
|
return true
|
|
}
|
|
} catch (registerError) {
|
|
console.error('❌ Registration failed:', registerError.response?.data || registerError.message)
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
async function testSetProfileMode() {
|
|
console.log('\n🎯 Testing profile mode setting...')
|
|
|
|
try {
|
|
// First, get current user to check existing mode
|
|
const userResponse = await api.get('/api/v1/users/me')
|
|
console.log(` Current UI mode: ${userResponse.data.ui_mode || 'not set'}`)
|
|
|
|
// Set mode to 'personal' (private_garage)
|
|
const modeToSet = 'personal'
|
|
const response = await api.patch('/api/v1/users/me/preferences', {
|
|
ui_mode: modeToSet
|
|
})
|
|
|
|
console.log(`✅ Profile mode set to: ${modeToSet}`)
|
|
|
|
// Verify the mode was set
|
|
const verifyResponse = await api.get('/api/v1/users/me')
|
|
if (verifyResponse.data.ui_mode === modeToSet) {
|
|
console.log(`✅ Mode verified: ${verifyResponse.data.ui_mode}`)
|
|
return true
|
|
} else {
|
|
console.error(`❌ Mode mismatch: expected ${modeToSet}, got ${verifyResponse.data.ui_mode}`)
|
|
return false
|
|
}
|
|
} catch (error) {
|
|
console.error('❌ Failed to set profile mode:', error.response?.data || error.message)
|
|
return false
|
|
}
|
|
}
|
|
|
|
async function testFetchGarage() {
|
|
console.log('\n🚗 Testing garage fetch...')
|
|
|
|
try {
|
|
const response = await api.get('/api/v1/vehicles/my-garage')
|
|
|
|
if (Array.isArray(response.data)) {
|
|
console.log(`✅ Garage fetched successfully: ${response.data.length} vehicle(s)`)
|
|
if (response.data.length > 0) {
|
|
console.log(' Sample vehicle:', {
|
|
id: response.data[0].id,
|
|
make: response.data[0].make,
|
|
model: response.data[0].model,
|
|
license_plate: response.data[0].license_plate,
|
|
})
|
|
}
|
|
return true
|
|
} else {
|
|
console.error('❌ Unexpected garage response format:', response.data)
|
|
return false
|
|
}
|
|
} catch (error) {
|
|
// Garage might be empty (404) or other error
|
|
if (error.response?.status === 404) {
|
|
console.log('✅ Garage is empty (expected for new user)')
|
|
return true
|
|
}
|
|
console.error('❌ Failed to fetch garage:', error.response?.data || error.message)
|
|
return false
|
|
}
|
|
}
|
|
|
|
async function testFetchGamification() {
|
|
console.log('\n🏆 Testing gamification fetch...')
|
|
|
|
try {
|
|
// Test achievements endpoint
|
|
const achievementsResponse = await api.get('/api/v1/gamification/achievements')
|
|
console.log(`✅ Achievements fetched: ${achievementsResponse.data.achievements?.length || 0} total`)
|
|
|
|
// Test user stats
|
|
const statsResponse = await api.get('/api/v1/gamification/me')
|
|
console.log('✅ User stats fetched:', {
|
|
xp: statsResponse.data.xp,
|
|
level: statsResponse.data.level,
|
|
rank: statsResponse.data.rank,
|
|
})
|
|
|
|
// Test badges
|
|
const badgesResponse = await api.get('/api/v1/gamification/my-badges')
|
|
console.log(`✅ Badges fetched: ${badgesResponse.data?.length || 0} earned`)
|
|
|
|
return true
|
|
} catch (error) {
|
|
// Gamification might not be fully implemented
|
|
if (error.response?.status === 404 || error.response?.status === 501) {
|
|
console.log('⚠️ Gamification endpoints not fully implemented (expected during development)')
|
|
return true
|
|
}
|
|
console.error('❌ Failed to fetch gamification:', error.response?.data || error.message)
|
|
return false
|
|
}
|
|
}
|
|
|
|
async function runAllTests() {
|
|
console.log('🚀 Starting Service Finder E2E Flow Test')
|
|
console.log('=========================================')
|
|
console.log(`API Base URL: ${API_BASE_URL}`)
|
|
console.log(`Test User: ${TEST_USER_EMAIL}`)
|
|
console.log('')
|
|
|
|
const results = {
|
|
login: false,
|
|
profileMode: false,
|
|
garage: false,
|
|
gamification: false,
|
|
}
|
|
|
|
// Run tests sequentially
|
|
results.login = await testLogin()
|
|
if (!results.login) {
|
|
console.error('\n❌ Login failed, aborting further tests')
|
|
return results
|
|
}
|
|
|
|
await sleep(1000) // Small delay between tests
|
|
|
|
results.profileMode = await testSetProfileMode()
|
|
|
|
await sleep(500)
|
|
|
|
results.garage = await testFetchGarage()
|
|
|
|
await sleep(500)
|
|
|
|
results.gamification = await testFetchGamification()
|
|
|
|
// Summary
|
|
console.log('\n📊 Test Summary')
|
|
console.log('===============')
|
|
console.log(`Login: ${results.login ? '✅ PASS' : '❌ FAIL'}`)
|
|
console.log(`Profile Mode: ${results.profileMode ? '✅ PASS' : '❌ FAIL'}`)
|
|
console.log(`Garage Fetch: ${results.garage ? '✅ PASS' : '❌ FAIL'}`)
|
|
console.log(`Gamification: ${results.gamification ? '✅ PASS' : '❌ FAIL'}`)
|
|
|
|
const allPassed = Object.values(results).every(r => r)
|
|
console.log(`\n${allPassed ? '🎉 ALL TESTS PASSED' : '⚠️ SOME TESTS FAILED'}`)
|
|
|
|
return results
|
|
}
|
|
|
|
// Run tests if script is executed directly
|
|
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
runAllTests().then(results => {
|
|
const allPassed = Object.values(results).every(r => r)
|
|
process.exit(allPassed ? 0 : 1)
|
|
}).catch(error => {
|
|
console.error('💥 Unhandled error in test runner:', error)
|
|
process.exit(1)
|
|
})
|
|
}
|
|
|
|
export { runAllTests } |