Код: Выделить всё
// payment/stream/+server.ts
export const GET = async ({ request }) => {
const headers = new Headers({
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Access-Control-Allow-Origin': '*'
});
const body = new ReadableStream({
start(controller) {
// Send an initial "ping" event
controller.enqueue('event: ping\ndata: connected\n\n');
request.signal.addEventListener('abort', () => {
console.log("Client disconnected");
controller.close();
controller = undefined;
})
sendStatus = (status: string) => {
if (controller) {
controller.enqueue(`event: payment-status\ndata: ${JSON.stringify({ status })}\n\n`);
} else {
console.error("No active SSE connection");
throw new Error("No active SSE connection");
}
}
}
})
return new Response(body, { headers });
}
export async function POST({ request }) {
const new_status = (await request.json()).status;
try {
sendStatus(new_status);
} catch (error) {
return new Response(JSON.stringify({ error: 'Error sending payment status' }), { status: 500 });
}
return new Response(JSON.stringify({ success: true }), { status: 200 });
}
Код: Выделить всё
let connection;
function startSSEConnection() {
if (connection) {
connection.close();
connection = null;
}
connection = new EventSource('/payment/stream');
connection.onopen = () => {
console.log('SSE connection opened');
payment_status = '';
};
connection.onerror = (e) => {
console.error('error with sse: ', e);
};
connection.addEventListener('ping', (e) => {
if (e.data == 'connected') {
axios
.post('/payment/initialize', {
amount: calcTotalPrice().toFixed(2)
})
.then((response) => {
if (response.status !== 200) {
title = 'Payment cannot be processed at the moment.';
subtitle = 'Please try again later.';
cancelOrder();
}
});
}
});
connection.addEventListener('payment-status', (e) => {
payment_status = JSON.parse(e.data).status;
});
}
Для тестирования бэкэнд, я думаю просто создать объект EventSource и посмотреть, запускаются ли на нем события. Однако, похоже, мне придется полностью издеваться над EventSource? Я запутался.
Для тестирования интерфейса я подумываю о том, чтобы имитировать объект EventSource и отправлять ему поддельные события. Однако я не могу как следует издеваться над этим (я новичок в насмешках).
Если кому-то приходилось тестировать SSE, как вы это делали? Есть ли лучший способ настроить мой SSE, более удобный для тестирования?
Я попробовал издеваться над EventSource следующим образом:
Код: Выделить всё
global.EventSource = vi.fn(() => ({
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
close: vi.fn(),
onerror: null,
onopen: null
}));
Код: Выделить всё
connection = global.EventSource.mock.results[0]?.value;
Подробнее здесь: https://stackoverflow.com/questions/793 ... it-testing