backend/test/scenarios/e2e/user-profile-flow.js

370 lines
8.6 KiB
JavaScript
Raw Normal View History

2025-11-07 07:44:23 +00:00
/**
* 使用者資料管理流程端到端場景
*
* 此模組提供完整的使用者資料管理流程場景組合多個 API 場景形成業務流程
*
* 使用方式
* import { getAndUpdateProfileFlow, emailVerificationFlow, phoneVerificationFlow, passwordChangeFlow } from './scenarios/e2e/user-profile-flow.js';
*/
import * as auth from '../apis/auth.js';
import * as user from '../apis/user.js';
import { sleep } from 'k6';
/**
* 取得並更新個人資料流程
* @param {Object} options - 配置選項
* @param {string} options.baseUrl - API 基礎 URL
* @param {string} options.accessToken - Access Token
* @param {Object} options.updateData - 要更新的資料
* @param {Object} options.customMetrics - 自定義指標對象可選
* @returns {Object} 流程結果
*/
export function getAndUpdateProfileFlow(options = {}) {
const {
baseUrl = __ENV.BASE_URL || 'https://localhost:8888',
accessToken,
updateData = {
nickname: `TestUser_${Date.now()}`,
preferred_language: 'zh-tw',
},
customMetrics = null,
} = options;
if (!accessToken) {
throw new Error('accessToken is required');
}
// 步驟 1: 取得使用者資訊
const getInfoResult = user.getUserInfo({
baseUrl,
accessToken,
customMetrics,
});
if (!getInfoResult.success) {
return {
success: false,
step: 'get_info',
error: 'Get user info failed',
getInfoResult,
};
}
// 短暫等待
sleep(1);
// 步驟 2: 更新使用者資訊
const updateInfoResult = user.updateUserInfo({
baseUrl,
accessToken,
updateData,
customMetrics,
});
if (!updateInfoResult.success) {
return {
success: false,
step: 'update_info',
error: 'Update user info failed',
getInfoResult,
updateInfoResult,
};
}
return {
success: true,
getInfoResult,
updateInfoResult,
originalData: getInfoResult.response,
updatedData: updateInfoResult.response,
};
}
/**
* 完整 Email 驗證流程請求 提交
* @param {Object} options - 配置選項
* @param {string} options.baseUrl - API 基礎 URL
* @param {string} options.accessToken - Access Token
* @param {string} options.verifyCode - 驗證碼在實際測試中可能需要從外部獲取
* @returns {Object} 流程結果
*/
export function emailVerificationFlow(options = {}) {
const {
baseUrl = __ENV.BASE_URL || 'https://localhost:8888',
accessToken,
verifyCode,
} = options;
if (!accessToken) {
throw new Error('accessToken is required');
}
// 步驟 1: 請求 Email 驗證碼
const requestResult = user.requestVerificationCode({
baseUrl,
accessToken,
purpose: 'email_verification',
});
if (!requestResult.success) {
return {
success: false,
step: 'request',
error: 'Request email verification code failed',
requestResult,
};
}
// 短暫等待,模擬用戶收到驗證碼的時間
sleep(2);
// 步驟 2: 提交驗證碼
if (!verifyCode) {
return {
success: false,
step: 'submit',
error: 'verifyCode is required but not provided',
requestResult,
note: 'In real testing, verifyCode should be retrieved from external source (DB, email service, etc.)',
};
}
const submitResult = user.submitVerificationCode({
baseUrl,
accessToken,
purpose: 'email_verification',
verifyCode,
});
if (!submitResult.success) {
return {
success: false,
step: 'submit',
error: 'Submit email verification code failed',
requestResult,
submitResult,
};
}
return {
success: true,
requestResult,
submitResult,
};
}
/**
* 完整手機驗證流程請求 提交
* @param {Object} options - 配置選項
* @param {string} options.baseUrl - API 基礎 URL
* @param {string} options.accessToken - Access Token
* @param {string} options.verifyCode - 驗證碼在實際測試中可能需要從外部獲取
* @returns {Object} 流程結果
*/
export function phoneVerificationFlow(options = {}) {
const {
baseUrl = __ENV.BASE_URL || 'https://localhost:8888',
accessToken,
verifyCode,
} = options;
if (!accessToken) {
throw new Error('accessToken is required');
}
// 步驟 1: 請求手機驗證碼
const requestResult = user.requestVerificationCode({
baseUrl,
accessToken,
purpose: 'phone_verification',
});
if (!requestResult.success) {
return {
success: false,
step: 'request',
error: 'Request phone verification code failed',
requestResult,
};
}
// 短暫等待,模擬用戶收到驗證碼的時間
sleep(2);
// 步驟 2: 提交驗證碼
if (!verifyCode) {
return {
success: false,
step: 'submit',
error: 'verifyCode is required but not provided',
requestResult,
note: 'In real testing, verifyCode should be retrieved from external source (DB, SMS service, etc.)',
};
}
const submitResult = user.submitVerificationCode({
baseUrl,
accessToken,
purpose: 'phone_verification',
verifyCode,
});
if (!submitResult.success) {
return {
success: false,
step: 'submit',
error: 'Submit phone verification code failed',
requestResult,
submitResult,
};
}
return {
success: true,
requestResult,
submitResult,
};
}
/**
* 登入狀態下修改密碼流程
* @param {Object} options - 配置選項
* @param {string} options.baseUrl - API 基礎 URL
* @param {string} options.accessToken - Access Token
* @param {string} options.currentPassword - 當前密碼
* @param {string} options.newPassword - 新密碼
* @returns {Object} 流程結果
*/
export function passwordChangeFlow(options = {}) {
const {
baseUrl = __ENV.BASE_URL || 'https://localhost:8888',
accessToken,
currentPassword,
newPassword = 'NewPassword123!',
} = options;
if (!accessToken || !currentPassword) {
throw new Error('accessToken and currentPassword are required');
}
// 步驟 1: 修改密碼
const updatePasswordResult = user.updatePassword({
baseUrl,
accessToken,
currentPassword,
newPassword,
});
if (!updatePasswordResult.success) {
return {
success: false,
step: 'update_password',
error: 'Update password failed',
updatePasswordResult,
};
}
// 短暫等待
sleep(1);
// 步驟 2: 使用新密碼登入驗證(可選)
// 注意:這需要知道 loginId可能需要從 getUserInfo 獲取
// 這裡僅作為示例,實際使用時可能需要調整
return {
success: true,
updatePasswordResult,
};
}
/**
* 完整的使用者資料初始化流程註冊 登入 取得資訊 更新資訊
* @param {Object} options - 配置選項
* @param {string} options.baseUrl - API 基礎 URL
* @param {string} options.loginId - 登入 ID
* @param {string} options.password - 密碼
* @param {Object} options.updateData - 要更新的資料
* @param {Object} options.customMetrics - 自定義指標對象可選
* @returns {Object} 流程結果
*/
export function userProfileInitializationFlow(options = {}) {
const {
baseUrl = __ENV.BASE_URL || 'https://localhost:8888',
loginId = `test_${Date.now()}@example.com`,
password = 'Test123456!',
updateData = {
nickname: `TestUser_${Date.now()}`,
preferred_language: 'zh-tw',
currency: 'TWD',
},
customMetrics = null,
} = options;
// 步驟 1: 註冊
const registerResult = auth.registerWithCredentials({
baseUrl,
loginId,
password,
customMetrics,
});
if (!registerResult.success || !registerResult.tokens) {
return {
success: false,
step: 'register',
error: 'Registration failed',
registerResult,
};
}
sleep(1);
// 步驟 2: 取得使用者資訊
const getInfoResult = user.getUserInfo({
baseUrl,
accessToken: registerResult.tokens.accessToken,
customMetrics,
});
if (!getInfoResult.success) {
return {
success: false,
step: 'get_info',
error: 'Get user info failed',
registerResult,
getInfoResult,
};
}
sleep(1);
// 步驟 3: 更新使用者資訊
const updateInfoResult = user.updateUserInfo({
baseUrl,
accessToken: registerResult.tokens.accessToken,
updateData,
customMetrics,
});
if (!updateInfoResult.success) {
return {
success: false,
step: 'update_info',
error: 'Update user info failed',
registerResult,
getInfoResult,
updateInfoResult,
};
}
return {
success: true,
registerResult,
getInfoResult,
updateInfoResult,
tokens: registerResult.tokens,
};
}