61 lines
2.0 KiB
JavaScript
61 lines
2.0 KiB
JavaScript
// k6 load-test: authentication login flow.
|
|
//
|
|
// Profile: 50 VUs ramping over 30s, holding briefly to gather a stable
|
|
// percentile sample. The login endpoint is the most security-critical write
|
|
// path, so the failure-rate threshold is tighter than the read path and the
|
|
// p(99) latency budget covers password hashing + session creation.
|
|
//
|
|
// Run:
|
|
// K6_TARGET_URL=http://localhost:3000 k6 run tests/load/login.js
|
|
//
|
|
// Optional env:
|
|
// LOAD_LOGIN_EMAIL test account email (default: load-test@example.com)
|
|
// LOAD_LOGIN_PASSWORD test account password (default: load-test-password)
|
|
|
|
import http from "k6/http";
|
|
import { check, group } from "k6";
|
|
|
|
export const options = {
|
|
scenarios: {
|
|
login: {
|
|
executor: "ramping-vus",
|
|
startVUs: 0,
|
|
stages: [
|
|
{ duration: "30s", target: 50 },
|
|
{ duration: "30s", target: 50 },
|
|
{ duration: "10s", target: 0 },
|
|
],
|
|
gracefulRampDown: "10s",
|
|
tags: { suite: "login" },
|
|
},
|
|
},
|
|
thresholds: {
|
|
http_req_failed: ["rate<0.05"],
|
|
http_req_duration: ["p(99)<800"],
|
|
"http_req_duration{name:login}": ["p(95)<400"],
|
|
},
|
|
// Avoid surprising the local server with default 100s connection lifetimes
|
|
// when this script is run as part of the composite suite.
|
|
noConnectionReuse: false,
|
|
discardResponseBodies: true,
|
|
};
|
|
|
|
const TARGET_URL = __ENV.K6_TARGET_URL || "http://localhost:3000";
|
|
const EMAIL = __ENV.LOAD_LOGIN_EMAIL || "load-test@example.com";
|
|
const PASSWORD = __ENV.LOAD_LOGIN_PASSWORD || "load-test-password";
|
|
|
|
export default function loginScenario() {
|
|
group("login", function () {
|
|
const payload = JSON.stringify({ email: EMAIL, password: PASSWORD });
|
|
const params = {
|
|
headers: { "content-type": "application/json" },
|
|
tags: { name: "login" },
|
|
};
|
|
const res = http.post(`${TARGET_URL}/v1/auth/login`, payload, params);
|
|
check(res, {
|
|
"status is 200 or 401": (r) => r.status === 200 || r.status === 401,
|
|
"has body": (r) => r.body === null || r.body !== undefined,
|
|
});
|
|
});
|
|
}
|