/* @odoo-module */ import { startServer } from "@bus/../tests/helpers/mock_python_environment"; import { patchWebsocketWorkerWithCleanup } from "@bus/../tests/helpers/mock_websocket"; import { addBusServicesToRegistry } from "@bus/../tests/helpers/test_utils"; import { waitUntilSubscribe } from "@bus/../tests/helpers/websocket_event_deferred"; import { AWAY_DELAY as ACTUAL_AWAY_DELAY, imStatusService } from "@bus/im_status_service"; import { makeTestEnv } from "@web/../tests/helpers/mock_env"; import { mockTimeout, nextTick, patchWithCleanup } from "@web/../tests/helpers/utils"; import { registerCleanup } from "@web/../tests/helpers/cleanup"; import { assertSteps, step } from "@web/../tests/utils"; import { browser } from "@web/core/browser/browser"; import { registry } from "@web/core/registry"; import { session } from "@web/session"; // Delays can slighly differ since time is not frozen. Let's tolerate 1000ms // of difference. const TOLERANCE = 1000; const AWAY_DELAY = ACTUAL_AWAY_DELAY + TOLERANCE; function assertAlmostEqual(a, b) { QUnit.assert.ok(Math.abs(a - b) < TOLERANCE, `${a} and ${b} should be almost equal`); } QUnit.module("IM status", { async beforeEach() { addBusServicesToRegistry(); patchWebsocketWorkerWithCleanup(); registry.category("services").add("im_status", imStatusService); const pyEnv = await startServer(); patchWithCleanup(session, { partner_id: pyEnv.currentPartner.id }); registry.category("mock_server").add("res.users/has_group", (route, args) => { return args[0] === "base.group_public"; }); registerCleanup(() => registry.category("mock_server").remove("res.users/has_group")); }, }); QUnit.test( "update presence if IM status changes to offline while this device is online", async () => { const pyEnv = await startServer(); const env = await makeTestEnv({ activateMockServer: true }); patchWithCleanup(env.services.bus_service, { send: (type) => step(type) }); env.services.bus_service.start(); await waitUntilSubscribe(); await assertSteps(["update_presence"]); pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "bus.bus/im_status_updated", { im_status: "offline", partner_id: pyEnv.currentPartner.id, }); await assertSteps(["update_presence"]); } ); QUnit.test("update presence if IM status changes to away while this device is online", async () => { const pyEnv = await startServer(); const env = await makeTestEnv({ activateMockServer: true }); patchWithCleanup(env.services.bus_service, { send: (type) => step(type) }); patchWithCleanup(env.services.presence, { getLastPresence: () => new Date().getTime() }); env.services.bus_service.start(); await assertSteps(["update_presence"]); pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "bus.bus/im_status_updated", { im_status: "away", partner_id: pyEnv.currentPartner.id, }); await assertSteps(["update_presence"]); }); QUnit.test( "do not update presence if IM status changes to away while this device is away", async () => { const pyEnv = await startServer(); const env = await makeTestEnv({ activateMockServer: true }); patchWithCleanup(env.services.bus_service, { send: (type) => step(type) }); patchWithCleanup(env.services.presence, { getLastPresence: () => new Date().getTime() - AWAY_DELAY, }); env.services.bus_service.start(); await assertSteps(["update_presence"]); pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "bus.bus/im_status_updated", { im_status: "away", partner_id: pyEnv.currentPartner.id, }); await nextTick(); await assertSteps([]); } ); QUnit.test("do not update presence if other user's IM status changes to away", async () => { const pyEnv = await startServer(); const env = await makeTestEnv({ activateMockServer: true }); patchWithCleanup(env.services.bus_service, { send: (type) => step(type) }); patchWithCleanup(env.services.presence, { getLastPresence: () => new Date().getTime() }); env.services.bus_service.start(); await assertSteps(["update_presence"]); pyEnv["bus.bus"]._sendone(pyEnv.currentPartner, "bus.bus/im_status_updated", { im_status: "away", partner_id: pyEnv.publicPartnerId, }); await nextTick(); await assertSteps([]); }); QUnit.test("update presence when user comes back from away", async () => { const env = await makeTestEnv(); patchWithCleanup(env.services.bus_service, { send: (type, payload) => { if (type === "update_presence") { assertAlmostEqual(expectedInactivityPeriod, payload.inactivity_period); step("update_presence"); } }, }); patchWithCleanup(env.services.presence, { getLastPresence: () => new Date().getTime() - AWAY_DELAY, }); let expectedInactivityPeriod = AWAY_DELAY; env.services.bus_service.start(); await assertSteps(["update_presence"]); const event = new StorageEvent("storage", { key: "presence.lastPresence", newValue: new Date().getTime(), }); patchWithCleanup(env.services.presence, { getLastPresence: () => new Date().getTime() }); expectedInactivityPeriod = 0; browser.dispatchEvent(event); await assertSteps(["update_presence"]); }); QUnit.test("update presence when user status changes to away", async () => { const { advanceTime } = mockTimeout(); const env = await makeTestEnv(); let expectedInactivityPeriod = 0; patchWithCleanup(env.services.bus_service, { send: (type, payload) => { if (type === "update_presence") { assertAlmostEqual(expectedInactivityPeriod, payload.inactivity_period); step("update_presence"); } }, }); env.services.bus_service.start(); await assertSteps(["update_presence"]); expectedInactivityPeriod = AWAY_DELAY; patchWithCleanup(env.services.presence, { getLastPresence: () => new Date().getTime() - AWAY_DELAY, }); advanceTime(AWAY_DELAY); await assertSteps(["update_presence"]); });