2026-05-17 19:36:46 +07:00

155 lines
5.4 KiB
JavaScript

/**
* SCENARIO: auth-flow.js
* Register → Login → Refresh Token → Logout flow
*
* Tujuan: Stress test auth endpoints yang dipakai setiap user saat app dibuka.
* Target: p95 auth latency < 800ms, error rate < 1%
*/
import { sleep, check } from "k6";
import {
DEFAULT_THRESHOLDS,
handleSummary,
pickThresholds,
} from "../modules/metrics-helper.js";
import * as api from "../modules/api-client.js";
import { testData } from "../modules/test-data.js";
import { registerAndLogin, doRefreshToken } from "../modules/auth-helper.js";
const RUN_ID = __ENV.RUN_ID || `${Date.now()}`;
// ── Konfigurasi test — override via --config atau env ───────────────────────
export const options = {
scenarios: {
auth_flow: {
executor: "ramping-vus",
startVUs: 0,
stages: [
{ duration: "30s", target: 10 }, // warm-up
{ duration: "60s", target: 30 }, // ramp-up
{ duration: "60s", target: 30 }, // sustain
{ duration: "30s", target: 0 }, // ramp-down
],
gracefulRampDown: "15s",
},
},
thresholds: pickThresholds(
__ENV.BENCH_PROFILE === "local"
? { walkguide_auth_latency_ms: ["p(95)<35000", "p(99)<40000"] }
: {
...DEFAULT_THRESHOLDS,
walkguide_auth_latency_ms: ["p(95)<800", "p(99)<1500"],
},
),
};
// ── Main VU function ──────────────────────────────────────────────────────────
export default function authFlow() {
const vuId = __VU;
// ── Step 1: Register user baru (setiap VU punya unique email) ───────────────
const role = vuId % 2 === 0 ? "ROLE_GUARDIAN" : "ROLE_USER";
const suffix = `${RUN_ID}_${vuId}_${__ITER}`;
const payload =
role === "ROLE_GUARDIAN"
? testData.guardianRegisterPayload(suffix)
: testData.userRegisterPayload(suffix);
const regRes = api.register(payload);
check(regRes, {
"register: status 200": (r) => r.status === 200,
"register: has accessToken": (r) => {
const b = api.parseBody(r);
return b && b.data && !!b.data.accessToken;
},
});
let tokens = null;
if (regRes.status === 200) {
const body = api.parseBody(regRes);
if (body && body.data) tokens = body.data;
}
sleep(0.5);
// ── Step 2: Login ulang dengan credentials yang sama ────────────────────────
const loginRes = api.login(payload.email, payload.password);
check(loginRes, {
"login: status 200": (r) => r.status === 200,
"login: accessToken set": (r) => {
const b = api.parseBody(r);
return b && b.data && !!b.data.accessToken;
},
"login: refreshToken set": (r) => {
const b = api.parseBody(r);
return b && b.data && !!b.data.refreshToken;
},
"login: role correct": (r) => {
const b = api.parseBody(r);
return b && b.data && b.data.role === role;
},
});
if (loginRes.status === 200) {
const body = api.parseBody(loginRes);
if (body && body.data) tokens = body.data;
}
sleep(0.3);
// ── Step 3: Refresh token (simulasi token expire) ───────────────────────────
if (tokens && tokens.refreshToken) {
const refreshRes = api.refreshToken(tokens.refreshToken);
check(refreshRes, {
"refresh: status 200": (r) => r.status === 200,
"refresh: new accessToken": (r) => {
const b = api.parseBody(r);
return b && b.data && !!b.data.accessToken;
},
});
// Update access token
if (refreshRes.status === 200) {
const body = api.parseBody(refreshRes);
if (body && body.data) tokens.accessToken = body.data.accessToken;
}
}
sleep(0.3);
// ── Step 4: Update FCM token (dilakukan tiap login di production) ───────────
if (tokens && tokens.accessToken) {
const fakeFcm = `fcm_${Math.random().toString(36).slice(2, 30)}:APA91b${Math.random().toString(36).slice(2, 50)}`;
const fcmRes = api.updateFcmToken(tokens.accessToken, fakeFcm);
check(fcmRes, {
"fcm-token: status 2xx": (r) => r.status >= 200 && r.status < 300,
});
}
sleep(0.2);
// ── Step 5: Logout ──────────────────────────────────────────────────────────
if (tokens && tokens.accessToken) {
const logoutRes = api.logout(tokens.accessToken);
check(logoutRes, {
"logout: status 2xx": (r) => r.status >= 200 && r.status < 300,
});
}
// ── Think time: user nyata butuh beberapa detik antar aksi ──────────────────
sleep(testData.randomFloat(0.5, 1.5, 1));
}
// ── Health check sebelum test dimulai ────────────────────────────────────────
export function setup() {
const res = api.ping();
if (res.status !== 200) {
throw new Error(
`Backend tidak reachable. Ping returned ${res.status}. URL: ${__ENV.BASE_URL || "http://202.46.28.160:8080"}`,
);
}
console.log("✅ Backend reachable. Auth flow test starting.");
}
export { handleSummary };