99 lines
3.1 KiB
JavaScript
99 lines
3.1 KiB
JavaScript
// Test script: Exam events through Kafka → push-gateway → WebSocket (v2)
|
|
// Verifies that the 3 exam events (ExamExtended, ExamForceSubmitted,
|
|
// ExamQuestionReordered) traverse the new edu.notify.notification.sent topic
|
|
// and reach the WebSocket client with correct event_type passthrough.
|
|
//
|
|
// Usage: node services/push-gateway/scripts/test-exam-events.mjs
|
|
|
|
import WebSocket from "ws";
|
|
import { Kafka } from "kafkajs";
|
|
|
|
const WS_URL = "ws://localhost:8081/ws?token=dev-token";
|
|
const KAFKA_BROKER = "localhost:9092";
|
|
const TOPIC = "edu.notify.notification.sent";
|
|
const USER_ID = "dev-user";
|
|
|
|
const examEvents = [
|
|
{
|
|
event_type: "ExamExtended",
|
|
data: { examId: "exam-001", extendedMinutes: 15, reason: "special needs" },
|
|
},
|
|
{
|
|
event_type: "ExamForceSubmitted",
|
|
data: { examId: "exam-001", reason: "time_expired", submissionId: "sub-001" },
|
|
},
|
|
{
|
|
event_type: "ExamQuestionReordered",
|
|
data: { examId: "exam-001", questionIds: ["q-3", "q-1", "q-2"] },
|
|
},
|
|
];
|
|
|
|
console.log("[exam-test] connecting WebSocket to", WS_URL);
|
|
const ws = new WebSocket(WS_URL);
|
|
const received = [];
|
|
|
|
ws.on("open", async () => {
|
|
console.log("[exam-test] WebSocket connected, publishing 3 exam events...");
|
|
const kafka = new Kafka({ brokers: [KAFKA_BROKER] });
|
|
const producer = kafka.producer();
|
|
await producer.connect();
|
|
|
|
for (const ev of examEvents) {
|
|
const payload = {
|
|
event_id: `evt-exam-${ev.event_type}-${Date.now()}`,
|
|
user_id: USER_ID,
|
|
event_type: ev.event_type,
|
|
channel: "ws",
|
|
title: `Exam event: ${ev.event_type}`,
|
|
content: `Verification of ${ev.event_type} passthrough`,
|
|
data: ev.data,
|
|
broadcast: false,
|
|
occurred_at: Date.now(),
|
|
};
|
|
await producer.send({
|
|
topic: TOPIC,
|
|
messages: [{ value: JSON.stringify(payload) }],
|
|
});
|
|
console.log(`[exam-test] published ${ev.event_type}`);
|
|
}
|
|
await producer.disconnect();
|
|
|
|
// Wait up to 15 seconds for all 3 messages.
|
|
const deadline = Date.now() + 15000;
|
|
while (Date.now() < deadline && received.length < 3) {
|
|
await new Promise((r) => setTimeout(r, 200));
|
|
}
|
|
|
|
if (received.length < 3) {
|
|
console.error(`[exam-test] FAIL: only ${received.length}/3 messages received`);
|
|
process.exit(1);
|
|
}
|
|
const got = received.map((m) => m.event).sort();
|
|
const want = examEvents.map((e) => e.event_type).sort();
|
|
if (JSON.stringify(got) === JSON.stringify(want)) {
|
|
console.log("[exam-test] PASS: all 3 exam events received with correct event_type");
|
|
console.log("[exam-test] events:", got.join(", "));
|
|
process.exit(0);
|
|
} else {
|
|
console.error("[exam-test] FAIL: event mismatch");
|
|
console.error(" got:", got);
|
|
console.error(" want:", want);
|
|
process.exit(1);
|
|
}
|
|
});
|
|
|
|
ws.on("message", (data) => {
|
|
const msg = JSON.parse(data.toString());
|
|
console.log("[exam-test] received:", JSON.stringify(msg));
|
|
received.push(msg);
|
|
});
|
|
ws.on("error", (err) => {
|
|
console.error("[exam-test] WebSocket error:", err.message);
|
|
process.exit(1);
|
|
});
|
|
|
|
setTimeout(() => {
|
|
console.error("[exam-test] FAIL: overall timeout 20s");
|
|
process.exit(1);
|
|
}, 20000);
|