174 lines
5.5 KiB
JavaScript
174 lines
5.5 KiB
JavaScript
/**
|
|
* SCENARIO: notification-send.js
|
|
* Mass notification broadcast — Guardian kirim pesan ke User.
|
|
*
|
|
* Simulasi banyak Guardian mengirim notifikasi serentak + User membaca.
|
|
* Termasuk test mark-read dan unread-count endpoints.
|
|
*
|
|
* Target: p95 < 500ms, error rate < 1%
|
|
*/
|
|
import { sleep, check } from "k6";
|
|
import {
|
|
DEFAULT_THRESHOLDS,
|
|
handleSummary,
|
|
} from "../modules/metrics-helper.js";
|
|
import * as api from "../modules/api-client.js";
|
|
import { testData } from "../modules/test-data.js";
|
|
|
|
export const options = {
|
|
scenarios: {
|
|
// Scenario A: Guardian send notifications
|
|
guardian_send: {
|
|
executor: "constant-vus",
|
|
vus: 25,
|
|
duration: "120s",
|
|
exec: "guardianSend",
|
|
tags: { scenario: "guardian_send" },
|
|
},
|
|
// Scenario B: User read notifications (mulai setelah 10s)
|
|
user_read: {
|
|
executor: "constant-vus",
|
|
vus: 25,
|
|
duration: "100s",
|
|
startTime: "10s",
|
|
exec: "userRead",
|
|
tags: { scenario: "user_read" },
|
|
},
|
|
},
|
|
thresholds: {
|
|
...DEFAULT_THRESHOLDS,
|
|
walkguide_notif_latency_ms: ["p(95)<500", "p(99)<1000"],
|
|
},
|
|
};
|
|
|
|
// ── Shared VU states ──────────────────────────────────────────────────────────
|
|
let guardianVuToken = null;
|
|
let userVuToken = null;
|
|
|
|
// ── EXEC: Guardian send notifications ────────────────────────────────────────
|
|
export function guardianSend() {
|
|
if (!guardianVuToken) {
|
|
const suffix = `notif_g_${__VU}_${Date.now()}`;
|
|
const res = api.register(testData.guardianRegisterPayload(suffix));
|
|
if (res.status === 200) {
|
|
const b = api.parseBody(res);
|
|
if (b && b.data) guardianVuToken = b.data.accessToken;
|
|
}
|
|
if (!guardianVuToken) {
|
|
sleep(2);
|
|
return;
|
|
}
|
|
sleep(0.3);
|
|
}
|
|
|
|
// Kirim 1-3 notifikasi per iterasi
|
|
const count = testData.randomInt(1, 3);
|
|
for (let i = 0; i < count; i++) {
|
|
const payload = testData.sendNotificationPayload();
|
|
const res = api.sendNotification(guardianVuToken, payload);
|
|
|
|
check(res, {
|
|
"send-notif: status 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
"send-notif: latency < 500": (r) => r.timings.duration < 500,
|
|
});
|
|
|
|
sleep(0.2);
|
|
}
|
|
|
|
// Cek activity log guardian
|
|
if (__ITER % 5 === 0) {
|
|
const logsRes = api.getActivityLogsGuardian(guardianVuToken);
|
|
check(logsRes, {
|
|
"guardian-logs: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
});
|
|
}
|
|
|
|
sleep(testData.randomFloat(0.5, 1.5, 1));
|
|
}
|
|
|
|
// ── EXEC: User read notifications ─────────────────────────────────────────────
|
|
export function userRead() {
|
|
if (!userVuToken) {
|
|
const suffix = `notif_u_${__VU}_${Date.now()}`;
|
|
const res = api.register(testData.userRegisterPayload(suffix));
|
|
if (res.status === 200) {
|
|
const b = api.parseBody(res);
|
|
if (b && b.data) userVuToken = b.data.accessToken;
|
|
}
|
|
if (!userVuToken) {
|
|
sleep(2);
|
|
return;
|
|
}
|
|
sleep(0.3);
|
|
}
|
|
|
|
// ── Step 1: Cek unread count ─────────────────────────────────────────────
|
|
const unreadRes = api.getUnreadCount(userVuToken);
|
|
check(unreadRes, {
|
|
"unread-count: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
"unread-count: has data": (r) => {
|
|
const b = api.parseBody(r);
|
|
return b && b.data !== undefined;
|
|
},
|
|
});
|
|
|
|
sleep(0.2);
|
|
|
|
// ── Step 2: Get notification list ────────────────────────────────────────
|
|
const page = __ITER % 3; // test pagination
|
|
const notifRes = api.getNotifications(userVuToken, page, 20);
|
|
check(notifRes, {
|
|
"get-notifs: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
"get-notifs: has list": (r) => {
|
|
const b = api.parseBody(r);
|
|
return b && b.data !== undefined;
|
|
},
|
|
});
|
|
|
|
// Extract first notif id untuk test mark-read
|
|
let firstNotifId = null;
|
|
if (notifRes.status >= 200 && notifRes.status < 300) {
|
|
const body = api.parseBody(notifRes);
|
|
if (
|
|
body &&
|
|
body.data &&
|
|
Array.isArray(body.data.content) &&
|
|
body.data.content.length > 0
|
|
) {
|
|
firstNotifId = body.data.content[0].id;
|
|
}
|
|
}
|
|
|
|
sleep(0.2);
|
|
|
|
// ── Step 3: Mark individual notification read (jika ada) ─────────────────
|
|
if (firstNotifId) {
|
|
const markRes = api.markOneRead(userVuToken, firstNotifId);
|
|
check(markRes, {
|
|
"mark-one-read: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
});
|
|
sleep(0.2);
|
|
}
|
|
|
|
// ── Step 4: Mark all read (setiap 5 iterasi) ─────────────────────────────
|
|
if (__ITER % 5 === 0) {
|
|
const markAllRes = api.markAllRead(userVuToken);
|
|
check(markAllRes, {
|
|
"mark-all-read: 2xx": (r) => r.status >= 200 && r.status < 300,
|
|
});
|
|
}
|
|
|
|
sleep(testData.randomFloat(0.5, 2.0, 1));
|
|
}
|
|
|
|
export function setup() {
|
|
const res = api.ping();
|
|
if (res.status !== 200)
|
|
throw new Error(`Backend not reachable: ${res.status}`);
|
|
console.log(
|
|
"📬 Notification send/read test starting (2 parallel scenarios).",
|
|
);
|
|
}
|
|
|
|
export { handleSummary };
|