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

370 lines
8.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 使用者資料管理流程端到端場景
*
* 此模組提供完整的使用者資料管理流程場景,組合多個 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,
};
}