Merge pull request 'feat: aligner event handler Socket.IO sur le contrat snake_case (#20)' (#21) from feat/#20-snake-case-events into feat/prd-19-snake-case-events
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
|
- **Sessions webview isolées** : partition Electron unique par centre, auto-connexion via preload script
|
||||||
- **Socket.IO reconnexion** : illimitée (2s→10s backoff)
|
- **Socket.IO reconnexion** : illimitée (2s→10s backoff)
|
||||||
- **IPC principal** : `login-agent`, `get-terminal-list`, `server-status`, `switch-to-center`, `release-center`
|
- **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)
|
- **Terminaux** : REST `GET /terminals?provider=RDVPREM` (pas Socket.IO)
|
||||||
- **Logs** : `~/.simpleconnect-ng/socketio.log`
|
- **Logs** : `~/.simpleconnect-ng/socketio.log`
|
||||||
- **Notes** : sauvegarde auto après 2s d'inactivité, 50 versions, sync localStorage + fichier
|
- **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;
|
if (!mainWindow || !agentConnectionInfo) return;
|
||||||
|
|
||||||
const centres = processApplicationUrls(agentConnectionInfo.connList);
|
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) {
|
if (centre) {
|
||||||
log(`Basculement vers le centre: ${centre.nom}`);
|
log(`Basculement vers le centre: ${centre.nom}`);
|
||||||
mainWindow.webContents.send('switch-to-center', {
|
mainWindow.webContents.send('switch-to-center', {
|
||||||
centreId: centre.id,
|
centreId: centre.id,
|
||||||
centreName: centre.nom,
|
centreName: centre.nom,
|
||||||
queueName: event.queueName,
|
queue_name: event.queue_name,
|
||||||
terminal: event.terminal,
|
terminal: event.terminal,
|
||||||
eventType: 'call_pickup'
|
eventType: 'call_pickup'
|
||||||
});
|
});
|
||||||
} else {
|
} 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) {
|
function handleCallHungUp(event) {
|
||||||
if (!mainWindow) return;
|
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', {
|
mainWindow.webContents.send('release-center', {
|
||||||
queueName: event.queueName,
|
queue_name: event.queue_name,
|
||||||
terminal: event.terminal,
|
terminal: event.terminal,
|
||||||
eventType: 'call_hangup'
|
eventType: 'call_hangup'
|
||||||
});
|
});
|
||||||
@@ -245,9 +245,9 @@ function setupEventHandlers() {
|
|||||||
serviceProvider: config.socketio.serviceProvider
|
serviceProvider: config.socketio.serviceProvider
|
||||||
});
|
});
|
||||||
|
|
||||||
// Ecouter les evenements d'appels IPBX
|
// Ecouter les evenements d'appels IPBX (contrat snake_case du serveur)
|
||||||
adapter.on('ipbx_event', (data) => {
|
adapter.on('call_event', (data) => {
|
||||||
log('ipbx_event recu', data);
|
log('call_event recu', data);
|
||||||
|
|
||||||
if (!agentConnectionInfo) return;
|
if (!agentConnectionInfo) return;
|
||||||
|
|
||||||
@@ -257,7 +257,7 @@ function setupEventHandlers() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (data.eventCode) {
|
switch (data.event_code) {
|
||||||
case 1:
|
case 1:
|
||||||
handleCallPickedUp(data);
|
handleCallPickedUp(data);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||||||
|
|
||||||
// Écouter la libération de centre après raccrochage
|
// Écouter la libération de centre après raccrochage
|
||||||
ipcRenderer.on('release-center', (event, data) => {
|
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
|
// Mettre à jour le statut
|
||||||
updateAgentStatus('DISPONIBLE');
|
updateAgentStatus('DISPONIBLE');
|
||||||
|
|||||||
@@ -128,4 +128,63 @@ describe("SocketIOAdapter", () => {
|
|||||||
|
|
||||||
expect(states).toEqual(["connecting", "connected", "reconnecting", "connected"]);
|
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