UNPKG

@sync-in/server

Version:

The secure, open-source platform for file storage, sharing, collaboration, and sync

119 lines (118 loc) 5.96 kB
/* * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com> * This file is part of Sync-in | The open source file sync and share solution * See the LICENSE file for licensing details */ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const _common = require("@nestjs/common"); const _nodecluster = /*#__PURE__*/ _interop_require_default(require("node:cluster")); const _nodefs = /*#__PURE__*/ _interop_require_default(require("node:fs")); const _nodeos = /*#__PURE__*/ _interop_require_default(require("node:os")); const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path")); const _nodeprocess = /*#__PURE__*/ _interop_require_default(require("node:process")); const _appservice = require("./app.service"); const _configconstants = require("./configuration/config.constants"); const _configenvironment = require("./configuration/config.environment"); const _clusteradapter = require("@socket.io/cluster-adapter"); function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } jest.mock('@socket.io/cluster-adapter', ()=>({ setupPrimary: jest.fn() })); describe(_appservice.AppService.name, ()=>{ let appService; beforeAll(async ()=>{ appService = new _appservice.AppService(); _common.Logger.overrideLogger([ 'fatal' ]); }); it('should be defined', ()=>{ expect(appService).toBeDefined(); }); it('should clusterize', ()=>{ // --- MASTER, adapter='cluster' -> covers setupPrimary() _configenvironment.configuration.websocket.adapter = 'cluster'; _configenvironment.configuration.server.restartOnFailure = true; const bootstrap = jest.fn(); // IMPORTANT: do NOT call bootstrap() from fork mock const fakeWorker = { process: { pid: 1 } }; _nodecluster.default.fork = jest.fn(()=>fakeWorker); const spyExit = jest.spyOn(_nodecluster.default, 'on'); // 1) master path (cluster.isPrimary true by default) expect(()=>_appservice.AppService.clusterize(bootstrap)).not.toThrow(); // setupPrimary() must have run once (covers the “line 21” site) expect(_clusteradapter.setupPrimary).toHaveBeenCalledTimes(1); // fork called exactly workers times expect(_nodecluster.default.fork.mock.calls.length).toBe(_configenvironment.configuration.server.workers); // --- Test exit handler with ONLY ONE registered handler // TRUE branch: restart twice -> fork called +2 const forkCallsAfterMaster = _nodecluster.default.fork.mock.calls.length; _appservice.AppService.schedulerPID = 1; _nodecluster.default.emit('exit', { process: { pid: 1 } }, 1, 'SIGKILL'); _appservice.AppService.schedulerPID = 0; _nodecluster.default.emit('exit', { process: { pid: 2 } }, 1, 'SIGKILL'); expect(_nodecluster.default.fork.mock.calls.length).toBe(forkCallsAfterMaster + 2); // FALSE branch: no restart -> fork unchanged _configenvironment.configuration.server.restartOnFailure = false; const forkCallsAfterTrue = _nodecluster.default.fork.mock.calls.length; _nodecluster.default.emit('exit', { process: { pid: 3 } }, 1, 'SIGKILL'); expect(_nodecluster.default.fork.mock.calls.length).toBe(forkCallsAfterTrue); // --- MASTER again, adapter != 'cluster' -> covers the FALSE side of the adapter check _configenvironment.configuration.websocket.adapter = null; expect(()=>_appservice.AppService.clusterize(bootstrap)).not.toThrow(); // setupPrimary should NOT be called again expect(_clusteradapter.setupPrimary).toHaveBeenCalledTimes(1); // --- WORKER path (else branch): bootstrap should be called exactly once here jest.replaceProperty(_nodecluster.default, 'isPrimary', false); bootstrap.mockClear(); // isolate bootstrap count for a worker branch expect(()=>_appservice.AppService.clusterize(bootstrap)).not.toThrow(); expect(bootstrap).toHaveBeenCalledTimes(1); spyExit.mockClear(); }); it(`should use ${_configconstants.ENVIRONMENT_PREFIX} environment variables to override the configuration`, ()=>{ let conf = (0, _configenvironment.exportConfiguration)(); expect(conf.logger.stdout).toBe(true); expect(conf.logger.colorize).toBe(true); const tmpSecretFile = _nodepath.default.join(_nodeos.default.tmpdir(), 'secret'); _nodefs.default.writeFileSync(tmpSecretFile, 'fooBAR8888'); _nodeprocess.default.env[`${_configconstants.ENVIRONMENT_PREFIX}APPLICATIONS_FILES_ONLYOFFICE_SECRET`] = 'fooBAR'; _nodeprocess.default.env[`${_configconstants.ENVIRONMENT_PREFIX}LOGGER_STDOUT`] = 'false'; _nodeprocess.default.env[`${_configconstants.ENVIRONMENT_PREFIX}LOGGER_COLORIZE`] = '"false"'; _nodeprocess.default.env[`${_configconstants.ENVIRONMENT_PREFIX}APPLICATIONS_FILES_MAXUPLOADSIZE`] = '8888'; // docker compose secret file _nodeprocess.default.env[`${_configconstants.ENVIRONMENT_PREFIX}AUTH_TOKEN_ACCESS_SECRET_FILE`] = tmpSecretFile; conf = (0, _configenvironment.exportConfiguration)(true); expect(conf.applications.files.onlyoffice.secret).toBe('fooBAR'); expect(conf.logger.stdout).toBe(false); expect(conf.logger.colorize).toBe(false); expect(conf.applications.files.maxUploadSize).toBe(8888); expect(conf.auth.token.access.secret).toBe('fooBAR8888'); // clean up secret file _nodefs.default.promises.rm(tmpSecretFile, { force: true }).catch(console.error); }); }); //# sourceMappingURL=app.service.spec.js.map