feat: aligner event handler Socket.IO sur le contrat snake_case (#20)
- Ecouter call_event au lieu de ipbx_event - Lire event_code, queue_name, terminal en snake_case - handleCallPickedUp/handleCallHungUp utilisent event.queue_name - renderer.js lit data.queue_name - 3 tests unitaires ajoutés dans socketio-adapter.test.js
This commit is contained in:
@@ -43,7 +43,7 @@ bun test # 8 tests unitaires socketio-adapter
|
||||
- **Sessions webview isolées** : partition Electron unique par centre, auto-connexion via preload script
|
||||
- **Socket.IO reconnexion** : illimitée (2s→10s backoff)
|
||||
- **IPC principal** : `login-agent`, `get-terminal-list`, `server-status`, `switch-to-center`, `release-center`
|
||||
- **Protocole serveur** : auth au handshake, events `login_ok`/`login_error`/`ipbx_event`/`logout`→`logout_ok`
|
||||
- **Protocole serveur** : auth au handshake, events `login_ok`/`login_error`/`call_event`/`logout`→`logout_ok` (champs snake_case : `event_code`, `queue_name`, `terminal`)
|
||||
- **Terminaux** : REST `GET /terminals?provider=RDVPREM` (pas Socket.IO)
|
||||
- **Logs** : `~/.simpleconnect-ng/socketio.log`
|
||||
- **Notes** : sauvegarde auto après 2s d'inactivité, 50 versions, sync localStorage + fichier
|
||||
|
||||
18
main.js
18
main.js
@@ -208,19 +208,19 @@ function handleCallPickedUp(event) {
|
||||
if (!mainWindow || !agentConnectionInfo) return;
|
||||
|
||||
const centres = processApplicationUrls(agentConnectionInfo.connList);
|
||||
const centre = centres.find(c => c.queueName === event.queueName);
|
||||
const centre = centres.find(c => c.queueName === event.queue_name);
|
||||
|
||||
if (centre) {
|
||||
log(`Basculement vers le centre: ${centre.nom}`);
|
||||
mainWindow.webContents.send('switch-to-center', {
|
||||
centreId: centre.id,
|
||||
centreName: centre.nom,
|
||||
queueName: event.queueName,
|
||||
queue_name: event.queue_name,
|
||||
terminal: event.terminal,
|
||||
eventType: 'call_pickup'
|
||||
});
|
||||
} else {
|
||||
log(`${c.yellow}Aucun centre trouvé pour la file: ${event.queueName}${c.reset}`);
|
||||
log(`${c.yellow}Aucun centre trouvé pour la file: ${event.queue_name}${c.reset}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,9 +228,9 @@ function handleCallPickedUp(event) {
|
||||
function handleCallHungUp(event) {
|
||||
if (!mainWindow) return;
|
||||
|
||||
log(`Fin d'appel sur la file: ${event.queueName}`);
|
||||
log(`Fin d'appel sur la file: ${event.queue_name}`);
|
||||
mainWindow.webContents.send('release-center', {
|
||||
queueName: event.queueName,
|
||||
queue_name: event.queue_name,
|
||||
terminal: event.terminal,
|
||||
eventType: 'call_hangup'
|
||||
});
|
||||
@@ -245,9 +245,9 @@ function setupEventHandlers() {
|
||||
serviceProvider: config.socketio.serviceProvider
|
||||
});
|
||||
|
||||
// Ecouter les evenements d'appels IPBX
|
||||
adapter.on('ipbx_event', (data) => {
|
||||
log('ipbx_event recu', data);
|
||||
// Ecouter les evenements d'appels IPBX (contrat snake_case du serveur)
|
||||
adapter.on('call_event', (data) => {
|
||||
log('call_event recu', data);
|
||||
|
||||
if (!agentConnectionInfo) return;
|
||||
|
||||
@@ -257,7 +257,7 @@ function setupEventHandlers() {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (data.eventCode) {
|
||||
switch (data.event_code) {
|
||||
case 1:
|
||||
handleCallPickedUp(data);
|
||||
break;
|
||||
|
||||
@@ -153,7 +153,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
|
||||
// Écouter la libération de centre après raccrochage
|
||||
ipcRenderer.on('release-center', (event, data) => {
|
||||
console.log('Libération de la file:', data.queueName);
|
||||
console.log('Libération de la file:', data.queue_name);
|
||||
|
||||
// Mettre à jour le statut
|
||||
updateAgentStatus('DISPONIBLE');
|
||||
|
||||
@@ -128,4 +128,63 @@ describe("SocketIOAdapter", () => {
|
||||
|
||||
expect(states).toEqual(["connecting", "connected", "reconnecting", "connected"]);
|
||||
});
|
||||
|
||||
test("on('call_event') recoit les champs snake_case du serveur", async () => {
|
||||
const received = [];
|
||||
adapter.on('call_event', (data) => received.push(data));
|
||||
|
||||
const p = adapter.connect("1234", "pass", "2001");
|
||||
socket._fire("login_ok", { accessCode: "1234" });
|
||||
await p;
|
||||
|
||||
// Le serveur envoie un call_event avec champs snake_case
|
||||
socket._fire("call_event", {
|
||||
event_code: 1,
|
||||
queue_name: "FILE_CENTRE_A",
|
||||
terminal: "2001",
|
||||
});
|
||||
|
||||
expect(received).toHaveLength(1);
|
||||
expect(received[0].event_code).toBe(1);
|
||||
expect(received[0].queue_name).toBe("FILE_CENTRE_A");
|
||||
expect(received[0].terminal).toBe("2001");
|
||||
});
|
||||
|
||||
test("on('call_event') enregistré avant connect() est dispatché après connexion", async () => {
|
||||
const received = [];
|
||||
// Enregistrer le handler AVANT connect (comme le fait main.js)
|
||||
adapter.on('call_event', (data) => received.push(data));
|
||||
|
||||
const p = adapter.connect("1234", "pass", "2001");
|
||||
socket._fire("login_ok", { accessCode: "1234" });
|
||||
await p;
|
||||
|
||||
// Le serveur envoie un call_event
|
||||
socket._fire("call_event", {
|
||||
event_code: 2,
|
||||
queue_name: "FILE_CENTRE_B",
|
||||
terminal: "2001",
|
||||
});
|
||||
|
||||
expect(received).toHaveLength(1);
|
||||
expect(received[0].event_code).toBe(2);
|
||||
expect(received[0].queue_name).toBe("FILE_CENTRE_B");
|
||||
});
|
||||
|
||||
test("off('call_event') supprime le handler", async () => {
|
||||
const received = [];
|
||||
adapter.on('call_event', (data) => received.push(data));
|
||||
|
||||
const p = adapter.connect("1234", "pass", "2001");
|
||||
socket._fire("login_ok", { accessCode: "1234" });
|
||||
await p;
|
||||
|
||||
// Supprimer le handler
|
||||
adapter.off('call_event');
|
||||
|
||||
// L'event ne devrait plus être capté
|
||||
socket._fire("call_event", { event_code: 1, queue_name: "FILE", terminal: "2001" });
|
||||
|
||||
expect(received).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user