- 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
191 lines
5.7 KiB
JavaScript
191 lines
5.7 KiB
JavaScript
import { describe, test, expect, mock, beforeEach } from "bun:test";
|
|
|
|
const SocketIOAdapter = require("./socketio-adapter.js");
|
|
|
|
// EventEmitter minimal pour simuler un socket.io
|
|
function createFakeSocket() {
|
|
const listeners = {};
|
|
|
|
const socket = {
|
|
on(event, fn) { (listeners[event] ??= []).push(fn); },
|
|
once(event, fn) {
|
|
const wrapper = (...args) => {
|
|
socket.off(event, wrapper);
|
|
fn(...args);
|
|
};
|
|
(listeners[event] ??= []).push(wrapper);
|
|
},
|
|
off(event, fn) {
|
|
if (fn) {
|
|
listeners[event] = (listeners[event] || []).filter(f => f !== fn);
|
|
} else {
|
|
delete listeners[event];
|
|
}
|
|
},
|
|
emit: mock(() => {}),
|
|
disconnect: mock(() => {}),
|
|
connected: true,
|
|
|
|
// Helper test : déclencher un event côté "serveur"
|
|
_fire(event, ...args) {
|
|
(listeners[event] || []).slice().forEach(fn => fn(...args));
|
|
},
|
|
};
|
|
return socket;
|
|
}
|
|
|
|
describe("SocketIOAdapter", () => {
|
|
let adapter, socket;
|
|
|
|
beforeEach(() => {
|
|
socket = null;
|
|
const factory = (url, opts) => {
|
|
socket = createFakeSocket();
|
|
return socket;
|
|
};
|
|
adapter = new SocketIOAdapter("http://localhost:8004", factory);
|
|
});
|
|
|
|
test("état initial = disconnected", () => {
|
|
expect(adapter.state).toBe("disconnected");
|
|
});
|
|
|
|
test("connect() passe en connecting puis connected sur login_ok", async () => {
|
|
const states = [];
|
|
adapter.onStateChange((s) => states.push(s));
|
|
|
|
const p = adapter.connect("1234", "pass", "2001");
|
|
socket._fire("login_ok", { accessCode: "1234", firstName: "Test", lastName: "User", connList: [] });
|
|
|
|
const result = await p;
|
|
|
|
expect(states).toEqual(["connecting", "connected"]);
|
|
expect(adapter.state).toBe("connected");
|
|
expect(result.accessCode).toBe("1234");
|
|
});
|
|
|
|
test("connect() rejette sur login_error", async () => {
|
|
const p = adapter.connect("1234", "wrong", "2001");
|
|
socket._fire("login_error", { message: "Mot de passe incorrect" });
|
|
|
|
expect(p).rejects.toThrow("Mot de passe incorrect");
|
|
expect(adapter.state).toBe("error");
|
|
});
|
|
|
|
test("connect() rejette sur connect_error", async () => {
|
|
const p = adapter.connect("1234", "pass", "2001");
|
|
socket._fire("connect_error", new Error("Connection refused"));
|
|
|
|
expect(p).rejects.toThrow("Connection refused");
|
|
expect(adapter.state).toBe("error");
|
|
});
|
|
|
|
test("déconnexion temporaire passe en reconnecting", async () => {
|
|
const p = adapter.connect("1234", "pass", "2001");
|
|
socket._fire("login_ok", { accessCode: "1234" });
|
|
await p;
|
|
|
|
socket._fire("disconnect", "transport close");
|
|
|
|
expect(adapter.state).toBe("reconnecting");
|
|
});
|
|
|
|
test("reconnexion après déconnexion repasse en connected", async () => {
|
|
const p = adapter.connect("1234", "pass", "2001");
|
|
socket._fire("login_ok", { accessCode: "1234" });
|
|
await p;
|
|
|
|
socket._fire("disconnect", "transport close");
|
|
expect(adapter.state).toBe("reconnecting");
|
|
|
|
socket._fire("login_ok", { accessCode: "1234" });
|
|
expect(adapter.state).toBe("connected");
|
|
});
|
|
|
|
test("logoff() émet logout et passe en disconnected sur logout_ok", async () => {
|
|
const p = adapter.connect("1234", "pass", "2001");
|
|
socket._fire("login_ok", { accessCode: "1234" });
|
|
await p;
|
|
|
|
const logoffP = adapter.logoff();
|
|
socket._fire("logout_ok");
|
|
await logoffP;
|
|
|
|
expect(socket.emit).toHaveBeenCalledWith("logout");
|
|
expect(adapter.state).toBe("disconnected");
|
|
});
|
|
|
|
test("onStateChange est appelé à chaque transition", async () => {
|
|
const states = [];
|
|
adapter.onStateChange((s) => states.push(s));
|
|
|
|
const p = adapter.connect("1234", "pass", "2001");
|
|
socket._fire("login_ok", { accessCode: "1234" });
|
|
await p;
|
|
|
|
socket._fire("disconnect", "transport close");
|
|
socket._fire("login_ok", { accessCode: "1234" });
|
|
|
|
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);
|
|
});
|
|
});
|