243 lines
5.5 KiB
JavaScript
243 lines
5.5 KiB
JavaScript
/**
|
||
* 認證流程端到端場景
|
||
*
|
||
* 此模組提供完整的認證流程場景,組合多個 API 場景形成業務流程。
|
||
*
|
||
* 使用方式:
|
||
* import { registerAndLoginFlow, loginAndRefreshFlow, passwordResetFlow } from './scenarios/e2e/authentication-flow.js';
|
||
*/
|
||
|
||
import * as auth from '../apis/auth.js';
|
||
import { sleep } from 'k6';
|
||
|
||
/**
|
||
* 註冊後立即登入流程
|
||
* @param {Object} options - 配置選項
|
||
* @param {string} options.baseUrl - API 基礎 URL
|
||
* @param {string} options.loginId - 登入 ID
|
||
* @param {string} options.password - 密碼
|
||
* @param {Object} options.customMetrics - 自定義指標對象(可選)
|
||
* @returns {Object} 流程結果
|
||
*/
|
||
export function registerAndLoginFlow(options = {}) {
|
||
const {
|
||
baseUrl = __ENV.BASE_URL || 'https://localhost:8888',
|
||
loginId = `test_${Date.now()}@example.com`,
|
||
password = 'Test123456!',
|
||
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 loginResult = auth.loginWithCredentials({
|
||
baseUrl,
|
||
loginId,
|
||
password,
|
||
customMetrics,
|
||
});
|
||
|
||
if (!loginResult.success || !loginResult.tokens) {
|
||
return {
|
||
success: false,
|
||
step: 'login',
|
||
error: 'Login failed after registration',
|
||
registerResult,
|
||
loginResult,
|
||
};
|
||
}
|
||
|
||
return {
|
||
success: true,
|
||
registerResult,
|
||
loginResult,
|
||
tokens: loginResult.tokens,
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 登入後刷新 Token 流程
|
||
* @param {Object} options - 配置選項
|
||
* @param {string} options.baseUrl - API 基礎 URL
|
||
* @param {string} options.loginId - 登入 ID
|
||
* @param {string} options.password - 密碼
|
||
* @param {Object} options.customMetrics - 自定義指標對象(可選)
|
||
* @returns {Object} 流程結果
|
||
*/
|
||
export function loginAndRefreshFlow(options = {}) {
|
||
const {
|
||
baseUrl = __ENV.BASE_URL || 'https://localhost:8888',
|
||
loginId,
|
||
password,
|
||
customMetrics = null,
|
||
} = options;
|
||
|
||
if (!loginId || !password) {
|
||
throw new Error('loginId and password are required');
|
||
}
|
||
|
||
// 步驟 1: 登入
|
||
const loginResult = auth.loginWithCredentials({
|
||
baseUrl,
|
||
loginId,
|
||
password,
|
||
customMetrics,
|
||
});
|
||
|
||
if (!loginResult.success || !loginResult.tokens) {
|
||
return {
|
||
success: false,
|
||
step: 'login',
|
||
error: 'Login failed',
|
||
loginResult,
|
||
};
|
||
}
|
||
|
||
// 短暫等待
|
||
sleep(1);
|
||
|
||
// 步驟 2: 刷新 Token
|
||
const refreshResult = auth.refreshToken({
|
||
baseUrl,
|
||
accessToken: loginResult.tokens.accessToken,
|
||
refreshToken: loginResult.tokens.refreshToken,
|
||
customMetrics,
|
||
});
|
||
|
||
if (!refreshResult.success || !refreshResult.tokens) {
|
||
return {
|
||
success: false,
|
||
step: 'refresh',
|
||
error: 'Token refresh failed',
|
||
loginResult,
|
||
refreshResult,
|
||
};
|
||
}
|
||
|
||
return {
|
||
success: true,
|
||
loginResult,
|
||
refreshResult,
|
||
tokens: refreshResult.tokens,
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 完整密碼重設流程(請求 → 驗證 → 重設)
|
||
* @param {Object} options - 配置選項
|
||
* @param {string} options.baseUrl - API 基礎 URL
|
||
* @param {string} options.identifier - 使用者帳號(email 或 phone)
|
||
* @param {string} options.accountType - 帳號類型(email/phone)
|
||
* @param {string} options.verifyCode - 驗證碼(在實際測試中可能需要從外部獲取)
|
||
* @param {string} options.newPassword - 新密碼
|
||
* @returns {Object} 流程結果
|
||
*/
|
||
export function passwordResetFlow(options = {}) {
|
||
const {
|
||
baseUrl = __ENV.BASE_URL || 'https://localhost:8888',
|
||
identifier,
|
||
accountType = 'email',
|
||
verifyCode,
|
||
newPassword = 'NewPassword123!',
|
||
} = options;
|
||
|
||
if (!identifier) {
|
||
throw new Error('identifier is required');
|
||
}
|
||
|
||
// 步驟 1: 請求密碼重設驗證碼
|
||
const requestResult = auth.requestPasswordReset({
|
||
baseUrl,
|
||
identifier,
|
||
accountType,
|
||
});
|
||
|
||
if (!requestResult.success) {
|
||
return {
|
||
success: false,
|
||
step: 'request',
|
||
error: 'Request password reset failed',
|
||
requestResult,
|
||
};
|
||
}
|
||
|
||
// 短暫等待,模擬用戶收到驗證碼的時間
|
||
sleep(2);
|
||
|
||
// 步驟 2: 驗證密碼重設驗證碼
|
||
if (!verifyCode) {
|
||
// 在實際測試中,驗證碼可能需要從外部獲取(如測試資料庫、郵件服務等)
|
||
return {
|
||
success: false,
|
||
step: 'verify',
|
||
error: 'verifyCode is required but not provided',
|
||
requestResult,
|
||
note: 'In real testing, verifyCode should be retrieved from external source (DB, email service, etc.)',
|
||
};
|
||
}
|
||
|
||
const verifyResult = auth.verifyPasswordResetCode({
|
||
baseUrl,
|
||
identifier,
|
||
verifyCode,
|
||
});
|
||
|
||
if (!verifyResult.success) {
|
||
return {
|
||
success: false,
|
||
step: 'verify',
|
||
error: 'Verify password reset code failed',
|
||
requestResult,
|
||
verifyResult,
|
||
};
|
||
}
|
||
|
||
// 短暫等待
|
||
sleep(1);
|
||
|
||
// 步驟 3: 執行密碼重設
|
||
const resetResult = auth.resetPassword({
|
||
baseUrl,
|
||
identifier,
|
||
verifyCode,
|
||
newPassword,
|
||
});
|
||
|
||
if (!resetResult.success) {
|
||
return {
|
||
success: false,
|
||
step: 'reset',
|
||
error: 'Reset password failed',
|
||
requestResult,
|
||
verifyResult,
|
||
resetResult,
|
||
};
|
||
}
|
||
|
||
return {
|
||
success: true,
|
||
requestResult,
|
||
verifyResult,
|
||
resetResult,
|
||
};
|
||
}
|
||
|