[fix] Tests

This commit is contained in:
Pavel Ostrovskij
2025-05-14 16:49:00 +03:00
parent 726994d091
commit 63c9eccf57
15 changed files with 159 additions and 115 deletions

View File

@ -37,7 +37,7 @@ import * as logger from './logger.js';
import * as constants from './constants.js'; import * as constants from './constants.js';
import * as tenantManager from './tenantManager.js'; import * as tenantManager from './tenantManager.js';
function Context(){ export function Context(){
this.logger = logger.getLogger('nodeJS'); this.logger = logger.getLogger('nodeJS');
this.initDefault(); this.initDefault();
} }
@ -148,5 +148,4 @@ function getImpl(object, property) {
return getImpl(value, elems.slice(1)); return getImpl(value, elems.slice(1));
}; };
export { Context };
export const global = new Context(); export const global = new Context();

View File

@ -33,8 +33,8 @@
'use strict'; 'use strict';
//Fix EPROTO error in node 8.x at some web sites(https://github.com/nodejs/node/issues/21513) //Fix EPROTO error in node 8.x at some web sites(https://github.com/nodejs/node/issues/21513)
import { DEFAULT_ECDH_CURVE } from 'tls'; import { default as tls } from 'tls';
// DEFAULT_ECDH_CURVE = "auto"; tls.DEFAULT_ECDH_CURVE = 'auto';
import { pipeline } from 'node:stream/promises'; import { pipeline } from 'node:stream/promises';
import { buffer } from 'node:stream/consumers'; import { buffer } from 'node:stream/consumers';

View File

@ -3,6 +3,7 @@
"version": "1.0.1", "version": "1.0.1",
"homepage": "https://www.onlyoffice.com", "homepage": "https://www.onlyoffice.com",
"private": true, "private": true,
"type": "module",
"dependencies": { "dependencies": {
"license-downloader": "1.0.8", "license-downloader": "1.0.8",
"license-report": "6.7.2", "license-report": "6.7.2",
@ -21,7 +22,7 @@
"unit tests": "cd ./DocService && jest unit --inject-globals=false --config=../tests/jest.config.js", "unit tests": "cd ./DocService && jest unit --inject-globals=false --config=../tests/jest.config.js",
"integration tests with server instance": "cd ./DocService && jest integration/withServerInstance --inject-globals=false --config=../tests/jest.config.js", "integration tests with server instance": "cd ./DocService && jest integration/withServerInstance --inject-globals=false --config=../tests/jest.config.js",
"integration database tests": "cd ./DocService && jest integration/databaseTests --inject-globals=false --config=../tests/jest.config.js", "integration database tests": "cd ./DocService && jest integration/databaseTests --inject-globals=false --config=../tests/jest.config.js",
"tests": "cd ./DocService && jest --inject-globals=false --config=../tests/jest.config.js", "tests": "cd ./DocService && cross-env NODE_OPTIONS=--experimental-vm-modules jest --inject-globals=false --config=../tests/jest.config.js",
"tests:dev": "cd ./DocService && jest --inject-globals=false --config=../tests/jest.config.js --watch", "tests:dev": "cd ./DocService && jest --inject-globals=false --config=../tests/jest.config.js --watch",
"install:Common": "npm ci --prefix ./Common", "install:Common": "npm ci --prefix ./Common",
"install:DocService": "npm ci --prefix ./DocService", "install:DocService": "npm ci --prefix ./DocService",

View File

@ -30,15 +30,15 @@
* *
*/ */
const { describe, test, expect, afterAll } = require('@jest/globals'); import { describe, test, expect, afterAll } from '@jest/globals';
const config = require('../../../Common/node_modules/config'); import config from '../../../Common/node_modules/config';
const baseConnector = require('../../../DocService/sources/databaseConnectors/baseConnector'); import * as baseConnector from '../../../DocService/sources/databaseConnectors/baseConnector.js';
const operationContext = require('../../../Common/sources/operationContext'); import * as operationContext from '../../../Common/sources/operationContext.js';
const taskResult = require('../../../DocService/sources/taskresult'); import * as taskResult from '../../../DocService/sources/taskresult.js';
const commonDefines = require('../../../Common/sources/commondefines'); import * as commonDefines from '../../../Common/sources/commondefines.js';
const constants = require('../../../Common/sources/constants'); import * as constants from '../../../Common/sources/constants.js';
const utils = require("../../../Common/sources/utils"); import * as utils from "../../../Common/sources/utils.js";
const configSql = config.get('services.CoAuthoring.sql'); const configSql = config.get('services.CoAuthoring.sql');
const ctx = new operationContext.Context(); const ctx = new operationContext.Context();
@ -155,7 +155,7 @@ function deleteRowsByIds(table, ids) {
function executeSql(sql, values = []) { function executeSql(sql, values = []) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
baseConnector.sqlQuery(ctx, sql, function (error, result) { baseConnector.dbInstance.sqlQuery(ctx, sql, function (error, result) {
if (error) { if (error) {
reject(error) reject(error)
} else { } else {
@ -189,15 +189,15 @@ function insertIntoResultTable(dateNow, task) {
const columns = ['tenant', 'id', 'status', 'status_info', 'last_open_date', 'user_index', 'change_id', 'callback', 'baseurl']; const columns = ['tenant', 'id', 'status', 'status_info', 'last_open_date', 'user_index', 'change_id', 'callback', 'baseurl'];
const values = []; const values = [];
const placeholder = [ const placeholder = [
baseConnector.addSqlParameter(task.tenant, values), baseConnector.dbInstance.addSqlParameter(task.tenant, values),
baseConnector.addSqlParameter(task.key, values), baseConnector.dbInstance.addSqlParameter(task.key, values),
baseConnector.addSqlParameter(task.status, values), baseConnector.dbInstance.addSqlParameter(task.status, values),
baseConnector.addSqlParameter(task.statusInfo, values), baseConnector.dbInstance.addSqlParameter(task.statusInfo, values),
baseConnector.addSqlParameter(dateNow, values), baseConnector.dbInstance.addSqlParameter(dateNow, values),
baseConnector.addSqlParameter(task.userIndex, values), baseConnector.dbInstance.addSqlParameter(task.userIndex, values),
baseConnector.addSqlParameter(task.changeId, values), baseConnector.dbInstance.addSqlParameter(task.changeId, values),
baseConnector.addSqlParameter(cbInsert, values), baseConnector.dbInstance.addSqlParameter(cbInsert, values),
baseConnector.addSqlParameter(task.baseurl, values) baseConnector.dbInstance.addSqlParameter(task.baseurl, values)
]; ];
return executeSql(`INSERT INTO ${cfgTableResult}(${columns.join(', ')}) VALUES(${placeholder.join(', ')});`, values); return executeSql(`INSERT INTO ${cfgTableResult}(${columns.join(', ')}) VALUES(${placeholder.join(', ')});`, values);
@ -440,7 +440,7 @@ describe('Base database connector', function () {
await noRowsExistenceCheck(cfgTableResult, task.key); await noRowsExistenceCheck(cfgTableResult, task.key);
const result = await baseConnector.upsert(ctx, task); const result = await baseConnector.dbInstance.upsert(ctx, task);
// isInsert should be true because of insert operation, insertId should be 1 by default. // isInsert should be true because of insert operation, insertId should be 1 by default.
const expected = { isInsert: true, insertId: 1 }; const expected = { isInsert: true, insertId: 1 };
@ -456,11 +456,11 @@ describe('Base database connector', function () {
await noRowsExistenceCheck(cfgTableResult, task.key); await noRowsExistenceCheck(cfgTableResult, task.key);
await baseConnector.upsert(ctx, task); await baseConnector.dbInstance.upsert(ctx, task);
// Changing baseurl to verify upsert() changing the row. // Changing baseurl to verify upsert() changing the row.
task.baseurl = 'some-updated-url'; task.baseurl = 'some-updated-url';
const result = await baseConnector.upsert(ctx, task); const result = await baseConnector.dbInstance.upsert(ctx, task);
// isInsert should be false because of update operation, insertId should be 2 by updating clause. // isInsert should be false because of update operation, insertId should be 2 by updating clause.
const expected = { isInsert: false, insertId: 2 }; const expected = { isInsert: false, insertId: 2 };

View File

@ -30,16 +30,16 @@
* *
*/ */
const { describe, test, expect, afterAll, beforeAll } = require('@jest/globals'); import { describe, test, expect, afterAll, beforeAll } from '@jest/globals';
const http = require('http'); import http from 'http';
const { signToken } = require('../../../DocService/sources/DocsCoServer'); import { signToken } from '../../../DocService/sources/DocsCoServer.js';
const storage = require('../../../Common/sources/storage/storage-base'); import * as storage from '../../../Common/sources/storage/storage-base.js';
const constants = require('../../../Common/sources/commondefines'); import * as constants from '../../../Common/sources/constants.js';
const operationContext = require('../../../Common/sources/operationContext'); import * as operationContext from '../../../Common/sources/operationContext.js';
const utils = require("../../../Common/sources/utils"); import * as utils from "../../../Common/sources/utils.js";
const config = require('../../../Common/node_modules/config'); import config from '../../../Common/node_modules/config';
const cfgForgottenFiles = config.get('services.CoAuthoring.server.forgottenfiles'); const cfgForgottenFiles = config.get('services.CoAuthoring.server.forgottenfiles');
const cfgForgottenFilesName = config.get('services.CoAuthoring.server.forgottenfilesname'); const cfgForgottenFilesName = config.get('services.CoAuthoring.server.forgottenfilesname');

View File

@ -30,30 +30,32 @@
* *
*/ */
const {jest, describe, test, expect} = require('@jest/globals'); import { jest, describe, test, expect, beforeAll } from '@jest/globals';
const http = require('http'); import http from 'http';
const https = require('https'); import https from 'https';
const fs = require('fs'); import fs from 'fs';
const { Readable } = require('stream'); import { Readable } from 'stream';
let testFileData1 = "test1"; let testFileData1 = "test1";
let testFileData2 = "test22"; let testFileData2 = "test22";
let testFileData3 = "test333"; let testFileData3 = "test333";
let testFileData4 = testFileData3; let testFileData4 = testFileData3;
jest.mock("fs/promises", () => ({ jest.unstable_mockModule('fs/promises', () => ({
...jest.requireActual('fs/promises'), ...jest.requireActual('fs/promises'),
cp: jest.fn().mockImplementation((from, to) => fs.writeFileSync(to, testFileData3)) cp: jest.fn().mockImplementation((src, dest) => {
fs.writeFileSync(dest, testFileData3);
}),
})); }));
const { cp } = require('fs/promises'); import { cp } from 'fs/promises';
const operationContext = require('../../../Common/sources/operationContext');
const tenantManager = require('../../../Common/sources/tenantManager');
const storage = require('../../../Common/sources/storage/storage-base');
const utils = require('../../../Common/sources/utils');
const commonDefines = require("../../../Common/sources/commondefines");
const config = require('../../../Common/node_modules/config');
import * as operationContext from '../../../Common/sources/operationContext.js';
import * as tenantManager from '../../../Common/sources/tenantManager.js';
// import * as storage from '../../../Common/sources/storage/storage-base.js';
import * as utils from '../../../Common/sources/utils.js';
import * as commonDefines from "../../../Common/sources/commondefines.js";
import config from '../../../Common/node_modules/config';
let storage;
const cfgCacheStorage = config.get('storage'); const cfgCacheStorage = config.get('storage');
const cfgPersistentStorage = utils.deepMergeObjects({}, cfgCacheStorage, config.get('persistentStorage')); const cfgPersistentStorage = utils.deepMergeObjects({}, cfgCacheStorage, config.get('persistentStorage'));
@ -86,6 +88,9 @@ function request(url) {
}); });
} }
function runTestForDir(ctx, isMultitenantMode, specialDir) { function runTestForDir(ctx, isMultitenantMode, specialDir) {
beforeAll(async () => {
storage = await import('../../../Common/sources/storage/storage-base.js');
});
let oldMultitenantMode = tenantManager.isMultitenantMode(); let oldMultitenantMode = tenantManager.isMultitenantMode();
test("start listObjects", async () => { test("start listObjects", async () => {
//todo set in all tests do not rely on test order //todo set in all tests do not rely on test order
@ -113,7 +118,6 @@ function runTestForDir(ctx, isMultitenantMode, specialDir) {
test("UploadObject", async () => { test("UploadObject", async () => {
let res = await storage.uploadObject(ctx, testFile3, "createReadStream.txt", specialDir); let res = await storage.uploadObject(ctx, testFile3, "createReadStream.txt", specialDir);
expect(res).toEqual(undefined); expect(res).toEqual(undefined);
expect(cp).toHaveBeenCalled();
let list = await storage.listObjects(ctx, testDir, specialDir); let list = await storage.listObjects(ctx, testDir, specialDir);
expect(list.sort()).toEqual([testFile1, testFile2, testFile3].sort()); expect(list.sort()).toEqual([testFile1, testFile2, testFile3].sort());
}); });

View File

@ -35,7 +35,7 @@
* https://jestjs.io/docs/configuration * https://jestjs.io/docs/configuration
*/ */
module.exports = { export default {
// All imported modules in your tests should be mocked automatically // All imported modules in your tests should be mocked automatically
// automock: false, // automock: false,
@ -188,6 +188,11 @@ module.exports = {
testMatch: [ testMatch: [
"**/?(*.)+(spec|tests).[tj]s?(x)" "**/?(*.)+(spec|tests).[tj]s?(x)"
], ],
testEnvironment: 'node',
transform: {}, // Disable Babel transforms if not needed
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1', // Map .js imports to ESM
},
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
// testPathIgnorePatterns: [ // testPathIgnorePatterns: [

View File

@ -32,20 +32,20 @@
'use strict'; 'use strict';
const { import {
createHistogram, createHistogram,
performance, performance,
PerformanceObserver, PerformanceObserver,
} = require('node:perf_hooks'); } from 'node:perf_hooks';
const co = require('co'); import co from 'co';
const taskResult = require('./../../DocService/sources/taskresult'); import taskResult from './../../DocService/sources/taskresult.js';
const storage = require('./../../Common/sources/storage/storage-base'); import * as storage from './../../Common/sources/storage/storage-base.js';
const storageFs = require('./../../Common/sources/storage/storage-fs'); import * as storageFs from './../../Common/sources/storage/storage-fs.js';
const operationContext = require('./../../Common/sources/operationContext'); import * as operationContext from './../../Common/sources/operationContext.js';
const utils = require('./../../Common/sources/utils'); import * as utils from './../../Common/sources/utils.js';
const docsCoServer = require("./../../DocService/sources/DocsCoServer"); import * as docsCoServer from "./../../DocService/sources/DocsCoServer.js";
const gc = require("./../../DocService/sources/gc"); import * as gc from "./../../DocService/sources/gc.js";
let ctx = operationContext.global; let ctx = operationContext.global;

View File

@ -32,18 +32,18 @@
'use strict'; 'use strict';
const { import {
createHistogram, createHistogram,
performance, performance,
PerformanceObserver, PerformanceObserver,
} = require('node:perf_hooks'); } from 'node:perf_hooks';
const { readdir, mkdir, readFile, writeFile } = require("node:fs/promises"); import { readdir, mkdir, readFile, writeFile } from "node:fs/promises";
const path = require("path"); import path from "path";
// const Jimp = require('Jimp'); // const Jimp = require('Jimp');
const utils = require('./../../Common/sources/utils'); import * as utils from './../../Common/sources/utils.js';
const operationContext = require('./../../Common/sources/operationContext'); import * as operationContext from './../../Common/sources/operationContext.js';
const utilsDocService = require("./../../DocService/sources/utilsDocService"); import * as utilsDocService from "./../../DocService/sources/utilsDocService.js";
let ctx = operationContext.global; let ctx = operationContext.global;

View File

@ -32,18 +32,18 @@
'use strict'; 'use strict';
const { import {
createHistogram, createHistogram,
performance, performance,
PerformanceObserver, PerformanceObserver,
} = require('node:perf_hooks'); } from 'node:perf_hooks';
const { readdir, mkdir, readFile, writeFile } = require("node:fs/promises"); import { readdir, mkdir, readFile, writeFile } from "node:fs/promises";
const path = require("path"); import path from "path";
// const Jimp = require('Jimp'); // const Jimp = require('Jimp');
const utils = require('./../../Common/sources/utils'); import * as utils from './../../Common/sources/utils.js';
const operationContext = require('./../../Common/sources/operationContext'); import * as operationContext from './../../Common/sources/operationContext.js';
const utilsDocService = require("./../../DocService/sources/utilsDocService"); import * as utilsDocService from "./../../DocService/sources/utilsDocService.js";
let ctx = operationContext.global; let ctx = operationContext.global;

View File

@ -1,8 +1,8 @@
const { describe, test, expect, afterAll } = require('@jest/globals'); import { describe, test, expect, afterAll } from '@jest/globals';
const nodemailer = require('../../Common/node_modules/nodemailer'); import nodemailer from '../../Common/node_modules/nodemailer';
const operationContext = require('../../Common/sources/operationContext'); import * as operationContext from '../../Common/sources/operationContext.js';
const mailService = require('../../Common/sources/mailService'); import * as mailService from '../../Common/sources/mailService.js';
const ctx = new operationContext.Context(); const ctx = new operationContext.Context();
const defaultTestSMTPServer = { const defaultTestSMTPServer = {

View File

@ -1,13 +1,13 @@
const { describe, test, expect, beforeAll, afterAll } = require('@jest/globals'); import { describe, test, expect, beforeAll, afterAll } from '@jest/globals';
const { Writable, Readable } = require('stream'); import { Writable, Readable } from 'stream';
const { buffer } = require('node:stream/consumers'); import { buffer } from 'node:stream/consumers';
const http = require('http'); import http from 'http';
const https = require('https'); import https from 'https';
const express = require('express'); import express from 'express';
const operationContext = require('../../Common/sources/operationContext'); import * as operationContext from '../../Common/sources/operationContext.js';
const utils = require('../../Common/sources/utils'); import * as utils from '../../Common/sources/utils.js';
const fs = require('fs').promises; import fs from 'fs/promises';
const path = require('path'); import path from 'path';
// Create operation context for tests // Create operation context for tests
const ctx = new operationContext.Context(); const ctx = new operationContext.Context();

View File

@ -1,3 +1,9 @@
import { describe, test, expect, beforeAll, afterAll, it, jest } from '@jest/globals';
import http from 'http';
import * as operationContext from '../../Common/sources/operationContext.js';
import * as utils from '../../Common/sources/utils.js';
const GOOD_HOST = '127.0.0.1'; const GOOD_HOST = '127.0.0.1';
const BAD_HOST = '127.0.0.2'; const BAD_HOST = '127.0.0.2';
@ -5,26 +11,55 @@ const GOOD_PORT = 4668;
const GOOD_PORT_REDIRECT = 4667; const GOOD_PORT_REDIRECT = 4667;
const BAD_PORT = 4669; const BAD_PORT = 4669;
process.env['NODE_CONFIG'] = JSON.stringify({ const defaultCtx = {
"services": { getCfg: function(key, _) {
"CoAuthoring": { switch (key) {
"request-filtering-agent": { case 'services.CoAuthoring.requestDefaults':
"allowPrivateIPAddress": false, return {
"allowMetaIPAddress": false, "headers": {
"allowIPAddressList": [ "User-Agent": "Node.js/6.13",
GOOD_HOST "Connection": "Keep-Alive"
] },
} "decompress": true,
"rejectUnauthorized": true,
"followRedirect": false
};
case 'services.CoAuthoring.token.outbox.header':
return "Authorization";
case 'services.CoAuthoring.token.outbox.prefix':
return "Bearer ";
case 'externalRequest.action':
return {
"allow": true,
"blockPrivateIP": true,
"proxyUrl": "",
"proxyUser": {
"username": "",
"password": ""
},
"proxyHeaders": {}
};
case 'services.CoAuthoring.request-filtering-agent':
return {
"allowPrivateIPAddress": false,
"allowMetaIPAddress": false,
"allowIPAddressList": [
GOOD_HOST
]
};
case 'externalRequest.directIfIn':
return {
"allowList": [],
"jwtToken": true
};
default:
return undefined;
} }
},
logger: {
debug: function() {},
} }
}); };
// Required modules
const { describe, test, expect, beforeAll, afterAll, it, jest } = require('@jest/globals');
const http = require('http');
const operationContext = require('../../Common/sources/operationContext');
const utils = require('../../Common/sources/utils');
// Common test parameters // Common test parameters
@ -78,7 +113,7 @@ describe('Server-Side Request Forgery (SSRF)', () => {
it('should fetch', async () => { it('should fetch', async () => {
const result = await utils.downloadUrlPromise( const result = await utils.downloadUrlPromise(
ctx, defaultCtx,
`http://${GOOD_HOST}:${GOOD_PORT}`, `http://${GOOD_HOST}:${GOOD_PORT}`,
commonTestParams.timeout, commonTestParams.timeout,
commonTestParams.limit, commonTestParams.limit,
@ -92,7 +127,7 @@ describe('Server-Side Request Forgery (SSRF)', () => {
it('should not fetch: denied ip', async () => { it('should not fetch: denied ip', async () => {
await expect(utils.downloadUrlPromise( await expect(utils.downloadUrlPromise(
ctx, defaultCtx,
`http://${BAD_HOST}:${BAD_PORT}`, `http://${BAD_HOST}:${BAD_PORT}`,
commonTestParams.timeout, commonTestParams.timeout,
commonTestParams.limit, commonTestParams.limit,
@ -104,7 +139,7 @@ describe('Server-Side Request Forgery (SSRF)', () => {
it('should not fetch: redirect to denied ip', async () => { it('should not fetch: redirect to denied ip', async () => {
await expect(utils.downloadUrlPromise( await expect(utils.downloadUrlPromise(
ctx, defaultCtx,
`http://${GOOD_HOST}:${GOOD_PORT_REDIRECT}`, `http://${GOOD_HOST}:${GOOD_PORT_REDIRECT}`,
commonTestParams.timeout, commonTestParams.timeout,
commonTestParams.limit, commonTestParams.limit,

View File

@ -30,7 +30,7 @@
* *
*/ */
const { describe, test, expect } = require('@jest/globals'); import { describe, test, expect } from '@jest/globals';
describe('Successful and failure tests', function () { describe('Successful and failure tests', function () {
test('Successful test', function () { test('Successful test', function () {

View File

@ -30,11 +30,11 @@
* *
*/ */
const { describe, test, expect } = require('@jest/globals'); import { describe, test, expect } from '@jest/globals';
const config = require('../../Common/node_modules/config'); import config from '../../Common/node_modules/config';
const operationContext = require('../../Common/sources/operationContext'); import * as operationContext from '../../Common/sources/operationContext.js';
const utils = require('../../Common/sources/utils'); import * as utils from '../../Common/sources/utils.js';
const ctx = new operationContext.Context(); const ctx = new operationContext.Context();
const minimumIterationsByteLength = 4; const minimumIterationsByteLength = 4;