@sync-in/server
Version:
The secure, open-source platform for file storage, sharing, collaboration, and sync
119 lines (118 loc) • 5.96 kB
JavaScript
/*
* 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