Converted more tests.

This commit is contained in:
SamTV12345 2024-08-17 16:46:29 +02:00
parent 154e67315c
commit fa5e2357b7
26 changed files with 172 additions and 78 deletions

View file

@ -19,7 +19,7 @@
* limitations under the License. * limitations under the License.
*/ */
const db = require('./DB'); import db from './DB';
const CustomError = require('../utils/customError'); const CustomError = require('../utils/customError');
const hooks = require('../../static/js/pluginfw/hooks'); const hooks = require('../../static/js/pluginfw/hooks');
import padutils, {randomString} from "../../static/js/pad_utils"; import padutils, {randomString} from "../../static/js/pad_utils";
@ -131,6 +131,7 @@ const mapAuthorWithDBKey = async (mapperkey: string, mapper:string) => {
// there is an author with this mapper // there is an author with this mapper
// update the timestamp of this author // update the timestamp of this author
// @ts-ignore
await db.setSub(`globalAuthor:${author}`, ['timestamp'], Date.now()); await db.setSub(`globalAuthor:${author}`, ['timestamp'], Date.now());
// return the author // return the author
@ -222,6 +223,7 @@ exports.getAuthor = async (author: string) => await db.get(`globalAuthor:${autho
* Returns the color Id of the author * Returns the color Id of the author
* @param {String} author The id of the author * @param {String} author The id of the author
*/ */
// @ts-ignore
exports.getAuthorColorId = async (author: string) => await db.getSub(`globalAuthor:${author}`, ['colorId']); exports.getAuthorColorId = async (author: string) => await db.getSub(`globalAuthor:${author}`, ['colorId']);
/** /**
@ -230,12 +232,14 @@ exports.getAuthorColorId = async (author: string) => await db.getSub(`globalAuth
* @param {String} colorId The color id of the author * @param {String} colorId The color id of the author
*/ */
exports.setAuthorColorId = async (author: string, colorId: string) => await db.setSub( exports.setAuthorColorId = async (author: string, colorId: string) => await db.setSub(
`globalAuthor:${author}`, ['colorId'], colorId); // @ts-ignore
`globalAuthor:${author}`, ['colorId'], colorId);
/** /**
* Returns the name of the author * Returns the name of the author
* @param {String} author The id of the author * @param {String} author The id of the author
*/ */
// @ts-ignore
exports.getAuthorName = async (author: string) => await db.getSub(`globalAuthor:${author}`, ['name']); exports.getAuthorName = async (author: string) => await db.getSub(`globalAuthor:${author}`, ['name']);
/** /**
@ -244,7 +248,8 @@ exports.getAuthorName = async (author: string) => await db.getSub(`globalAuthor:
* @param {String} name The name of the author * @param {String} name The name of the author
*/ */
exports.setAuthorName = async (author: string, name: string) => await db.setSub( exports.setAuthorName = async (author: string, name: string) => await db.setSub(
`globalAuthor:${author}`, ['name'], name); // @ts-ignore
`globalAuthor:${author}`, ['name'], name);
/** /**
* Returns an array of all pads this author contributed to * Returns an array of all pads this author contributed to

View file

@ -24,37 +24,55 @@
import {Database} from 'ueberdb2'; import {Database} from 'ueberdb2';
import settings from '../utils/Settings'; import settings from '../utils/Settings';
import log4js from 'log4js'; import log4js from 'log4js';
const stats = require('../stats') import stats from '../stats';
const logger = log4js.getLogger('ueberDB'); const logger = log4js.getLogger('ueberDB');
/** /**
* The UeberDB Object that provides the database functions * The UeberDB Object that provides the database functions
*/ */
exports.db = null; export let db:Database|null = null;
/** /**
* Initializes the database with the settings provided by the settings module * Initializes the database with the settings provided by the settings module
*/ */
exports.init = async () => { export const init = async () => {
exports.db = new Database(settings.dbType, settings.dbSettings, null, logger); db = new Database(settings.dbType, settings.dbSettings, null, logger);
await exports.db.init(); await db.init();
if (exports.db.metrics != null) { if (db.metrics != null) {
for (const [metric, value] of Object.entries(exports.db.metrics)) { for (const [metric, value] of Object.entries(db.metrics)) {
if (typeof value !== 'number') continue; if (typeof value !== 'number') continue;
stats.gauge(`ueberdb_${metric}`, () => exports.db.metrics[metric]); stats.gauge(`ueberdb_${metric}`, () => db!.metrics[metric]);
} }
} }
for (const fn of ['get', 'set', 'findKeys', 'getSub', 'setSub', 'remove']) { for (const fn of ['get', 'set', 'findKeys', 'getSub', 'setSub', 'remove']) {
const f = exports.db[fn]; // @ts-ignore
exports[fn] = async (...args:string[]) => await f.call(exports.db, ...args); const f = db[fn];
Object.setPrototypeOf(exports[fn], Object.getPrototypeOf(f)); // @ts-ignore
Object.defineProperties(exports[fn], Object.getOwnPropertyDescriptors(f)); dbInstance[fn] = async (...args:string[]) => await f.call(db, ...args);
// @ts-ignore
Object.setPrototypeOf(dbInstance[fn], Object.getPrototypeOf(f));
// @ts-ignore
Object.defineProperties(dbInstance[fn], Object.getOwnPropertyDescriptors(f));
} }
}; };
exports.shutdown = async (hookName: string, context:any) => { export const shutdown = async (hookName: string, context:any) => {
if (exports.db != null) await exports.db.close(); if (db != null) await db.close();
exports.db = null; db = null;
logger.log('Database closed'); logger.log('Database closed');
}; };
let dbInstance = {} as {
get: (key:string) => any;
set: (key:string, value:any) => void;
findKeys: (key:string) => string[];
getSub: (key:string, subkey:string) => any;
setSub: (key:string, subkey:string, value:any) => void;
remove: (key:string) => void;
init: () => Promise<void>;
}
dbInstance.init = init
export default dbInstance

View file

@ -21,7 +21,7 @@
const CustomError = require('../utils/customError'); const CustomError = require('../utils/customError');
import {randomString} from "../../static/js/pad_utils"; import {randomString} from "../../static/js/pad_utils";
const db = require('./DB'); import db from './DB';
const padManager = require('./PadManager'); const padManager = require('./PadManager');
const sessionManager = require('./SessionManager'); const sessionManager = require('./SessionManager');
@ -69,6 +69,7 @@ exports.deleteGroup = async (groupID: string): Promise<void> => {
// UeberDB's setSub() method atomically reads the record, updates the appropriate property, and // UeberDB's setSub() method atomically reads the record, updates the appropriate property, and
// writes the result. Setting a property to `undefined` deletes that property (JSON.stringify() // writes the result. Setting a property to `undefined` deletes that property (JSON.stringify()
// ignores such properties). // ignores such properties).
// @ts-ignore
db.setSub('groups', [groupID], undefined), db.setSub('groups', [groupID], undefined),
...Object.keys(group.mappings || {}).map(async (m) => await db.remove(`mapper2group:${m}`)), ...Object.keys(group.mappings || {}).map(async (m) => await db.remove(`mapper2group:${m}`)),
]); ]);
@ -99,6 +100,7 @@ exports.createGroup = async () => {
// Add the group to the `groups` record after the group's individual record is created so that // Add the group to the `groups` record after the group's individual record is created so that
// the state is consistent. Note: UeberDB's setSub() method atomically reads the record, updates // the state is consistent. Note: UeberDB's setSub() method atomically reads the record, updates
// the appropriate property, and writes the result. // the appropriate property, and writes the result.
// @ts-ignore
await db.setSub('groups', [groupID], 1); await db.setSub('groups', [groupID], 1);
return {groupID}; return {groupID};
}; };
@ -121,6 +123,7 @@ exports.createGroupIfNotExistsFor = async (groupMapper: string|object) => {
// deleted. Although the core Etherpad API does not support multiple mappings for the same // deleted. Although the core Etherpad API does not support multiple mappings for the same
// group, the database record does support multiple mappings in case a plugin decides to extend // group, the database record does support multiple mappings in case a plugin decides to extend
// the core Etherpad functionality. (It's also easy to implement it this way.) // the core Etherpad functionality. (It's also easy to implement it this way.)
// @ts-ignore
db.setSub(`group:${result.groupID}`, ['mappings', groupMapper], 1), db.setSub(`group:${result.groupID}`, ['mappings', groupMapper], 1),
]); ]);
return result; return result;
@ -157,6 +160,7 @@ exports.createGroupPad = async (groupID: string, padName: string, text: string,
await padManager.getPad(padID, text, authorId); await padManager.getPad(padID, text, authorId);
// create an entry in the group for this pad // create an entry in the group for this pad
// @ts-ignore
await db.setSub(`group:${groupID}`, ['pads', padID], 1); await db.setSub(`group:${groupID}`, ['pads', padID], 1);
return {padID}; return {padID};
@ -176,6 +180,7 @@ exports.listPads = async (groupID: string): Promise<{ padIDs: string[]; }> => {
} }
// group exists, let's get the pads // group exists, let's get the pads
// @ts-ignore
const result = await db.getSub(`group:${groupID}`, ['pads']); const result = await db.getSub(`group:${groupID}`, ['pads']);
const padIDs = Object.keys(result); const padIDs = Object.keys(result);

View file

@ -13,7 +13,7 @@ import ChatMessage from '../../static/js/ChatMessage';
import AttributePool from '../../static/js/AttributePool'; import AttributePool from '../../static/js/AttributePool';
const Stream = require('../utils/Stream'); const Stream = require('../utils/Stream');
const assert = require('assert').strict; const assert = require('assert').strict;
const db = require('./DB'); import db from './DB';
import settings from '../utils/Settings'; import settings from '../utils/Settings';
const authorManager = require('./AuthorManager'); const authorManager = require('./AuthorManager');
const padManager = require('./PadManager'); const padManager = require('./PadManager');
@ -56,6 +56,7 @@ class Pad {
* own database table, or to validate imported pad data before it is written to the database. * own database table, or to validate imported pad data before it is written to the database.
*/ */
constructor(id:string, database = db) { constructor(id:string, database = db) {
// @ts-ignore
this.db = database; this.db = database;
this.atext = makeAText('\n'); this.atext = makeAText('\n');
this.pool = new AttributePool(); this.pool = new AttributePool();
@ -428,6 +429,7 @@ class Pad {
yield* Stream.range(0, this.chatHead + 1).map((i) => copyRecord(`:chat:${i}`)); yield* Stream.range(0, this.chatHead + 1).map((i) => copyRecord(`:chat:${i}`));
// @ts-ignore // @ts-ignore
yield this.copyAuthorInfoToDestinationPad(destinationID); yield this.copyAuthorInfoToDestinationPad(destinationID);
// @ts-ignore
if (destGroupID) yield db.setSub(`group:${destGroupID}`, ['pads', destinationID], 1); if (destGroupID) yield db.setSub(`group:${destGroupID}`, ['pads', destinationID], 1);
}).call(this); }).call(this);
for (const p of new Stream(promises).batch(100).buffer(99)) await p; for (const p of new Stream(promises).batch(100).buffer(99)) await p;
@ -511,6 +513,7 @@ class Pad {
// Group pad? Add it to the group's list // Group pad? Add it to the group's list
if (destGroupID) { if (destGroupID) {
// @ts-ignore
await db.setSub(`group:${destGroupID}`, ['pads', destinationID], 1); await db.setSub(`group:${destGroupID}`, ['pads', destinationID], 1);
} }

View file

@ -24,7 +24,7 @@ import {PadType} from "../types/PadType";
const CustomError = require('../utils/customError'); const CustomError = require('../utils/customError');
const Pad = require('../db/Pad'); const Pad = require('../db/Pad');
const db = require('./DB'); import db from './DB';
import settings from '../utils/Settings'; import settings from '../utils/Settings';
/** /**
@ -74,6 +74,7 @@ const padList = new class {
async getPads() { async getPads() {
if (!this._loaded) { if (!this._loaded) {
this._loaded = (async () => { this._loaded = (async () => {
// @ts-ignore
const dbData = await db.findKeys('pad:*', '*:*:*'); const dbData = await db.findKeys('pad:*', '*:*:*');
if (dbData == null) return; if (dbData == null) return;
for (const val of dbData) this.addPad(val.replace(/^pad:/, '')); for (const val of dbData) this.addPad(val.replace(/^pad:/, ''));

View file

@ -20,8 +20,8 @@
*/ */
const db = require('./DB'); import db from './DB';
const randomString = require('../utils/randomstring'); import randomString from '../utils/randomstring';
/** /**

View file

@ -23,7 +23,7 @@
const CustomError = require('../utils/customError'); const CustomError = require('../utils/customError');
const promises = require('../utils/promises'); const promises = require('../utils/promises');
const randomString = require('../utils/randomstring'); const randomString = require('../utils/randomstring');
const db = require('./DB'); import db from './DB';
const groupManager = require('./GroupManager'); const groupManager = require('./GroupManager');
const authorManager = require('./AuthorManager'); const authorManager = require('./AuthorManager');
@ -151,7 +151,9 @@ exports.createSession = async (groupID: string, authorID: string, validUntil: nu
await Promise.all([ await Promise.all([
// UeberDB's setSub() method atomically reads the record, updates the appropriate (sub)object // UeberDB's setSub() method atomically reads the record, updates the appropriate (sub)object
// property, and writes the result. // property, and writes the result.
// @ts-ignore
db.setSub(`group2sessions:${groupID}`, ['sessionIDs', sessionID], 1), db.setSub(`group2sessions:${groupID}`, ['sessionIDs', sessionID], 1),
// @ts-ignore
db.setSub(`author2sessions:${authorID}`, ['sessionIDs', sessionID], 1), db.setSub(`author2sessions:${authorID}`, ['sessionIDs', sessionID], 1),
]); ]);
@ -196,7 +198,9 @@ exports.deleteSession = async (sessionID:string) => {
// UeberDB's setSub() method atomically reads the record, updates the appropriate (sub)object // UeberDB's setSub() method atomically reads the record, updates the appropriate (sub)object
// property, and writes the result. Setting a property to `undefined` deletes that property // property, and writes the result. Setting a property to `undefined` deletes that property
// (JSON.stringify() ignores such properties). // (JSON.stringify() ignores such properties).
// @ts-ignore
db.setSub(`group2sessions:${groupID}`, ['sessionIDs', sessionID], undefined), db.setSub(`group2sessions:${groupID}`, ['sessionIDs', sessionID], undefined),
// @ts-ignore
db.setSub(`author2sessions:${authorID}`, ['sessionIDs', sessionID], undefined), db.setSub(`author2sessions:${authorID}`, ['sessionIDs', sessionID], undefined),
]); ]);

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
const DB = require('./DB'); import DB from './DB';
const Store = require('@etherpad/express-session').Store; const Store = require('@etherpad/express-session').Store;
const log4js = require('log4js'); const log4js = require('log4js');
const util = require('util'); const util = require('util');
@ -19,7 +19,7 @@ class SessionStore extends Store {
* Etherpad is restarted. Use `null` to prevent `touch()` from ever updating the record. * Etherpad is restarted. Use `null` to prevent `touch()` from ever updating the record.
* Ignored if the cookie does not expire. * Ignored if the cookie does not expire.
*/ */
constructor(refresh = null) { constructor(refresh:number|null = null) {
super(); super();
this._refresh = refresh; this._refresh = refresh;
// Maps session ID to an object with the following properties: // Maps session ID to an object with the following properties:
@ -111,4 +111,4 @@ for (const m of ['get', 'set', 'destroy', 'touch']) {
SessionStore.prototype[m] = util.callbackify(SessionStore.prototype[`_${m}`]); SessionStore.prototype[m] = util.callbackify(SessionStore.prototype[`_${m}`]);
} }
module.exports = SessionStore; export default SessionStore

View file

@ -36,8 +36,8 @@ const plugins = require('../../static/js/pluginfw/plugin_defs');
import log4js from 'log4js'; import log4js from 'log4js';
const messageLogger = log4js.getLogger('message'); const messageLogger = log4js.getLogger('message');
const accessLogger = log4js.getLogger('access'); const accessLogger = log4js.getLogger('access');
const hooks = require('../../static/js/pluginfw/hooks'); const hooks = require('../../static/js/pluginfw/hooks.js');
const stats = require('../stats') import stats from '../stats';
const assert = require('assert').strict; const assert = require('assert').strict;
import {RateLimiterMemory} from 'rate-limiter-flexible'; import {RateLimiterMemory} from 'rate-limiter-flexible';
import {ChangesetRequest, PadUserInfo, SocketClientRequest} from "../types/SocketClientRequest"; import {ChangesetRequest, PadUserInfo, SocketClientRequest} from "../types/SocketClientRequest";

View file

@ -22,9 +22,9 @@
import {MapArrayType} from "../types/MapType"; import {MapArrayType} from "../types/MapType";
import {SocketModule} from "../types/SocketModule"; import {SocketModule} from "../types/SocketModule";
const log4js = require('log4js'); import log4js from 'log4js';
import settings from '../utils/Settings'; import settings from '../utils/Settings';
const stats = require('../../node/stats') import stats from '../../node/stats';
const logger = log4js.getLogger('socket.io'); const logger = log4js.getLogger('socket.io');

View file

@ -13,9 +13,9 @@ import expressSession from '@etherpad/express-session';
import fs from 'fs'; import fs from 'fs';
const hooks = require('../../static/js/pluginfw/hooks'); const hooks = require('../../static/js/pluginfw/hooks');
import log4js from 'log4js'; import log4js from 'log4js';
const SessionStore = require('../db/SessionStore'); import SessionStore from '../db/SessionStore';
import settings from '../utils/Settings'; import settings from '../utils/Settings';
const stats = require('../stats') import stats from '../stats';
import util from 'util'; import util from 'util';
const webaccess = require('./express/webaccess'); const webaccess = require('./express/webaccess');

View file

@ -3,7 +3,7 @@
import {ArgsExpressType} from "../../types/ArgsExpressType"; import {ArgsExpressType} from "../../types/ArgsExpressType";
import {ErrorCaused} from "../../types/ErrorCaused"; import {ErrorCaused} from "../../types/ErrorCaused";
const stats = require('../../stats') import stats from '../../stats';
exports.expressCreateServer = (hook_name:string, args: ArgsExpressType, cb:Function) => { exports.expressCreateServer = (hook_name:string, args: ArgsExpressType, cb:Function) => {
exports.app = args.app; exports.app = args.app;

View file

@ -5,7 +5,7 @@ import {LegacyParams} from "../types/LegacyParams";
const {Buffer} = require('buffer'); const {Buffer} = require('buffer');
const crypto = require('./crypto'); const crypto = require('./crypto');
const db = require('../db/DB'); import db from '../db/DB';
const log4js = require('log4js'); const log4js = require('log4js');
class Kdf { class Kdf {
@ -173,6 +173,7 @@ export class SecretRotator {
// TODO: This is racy. If two instances start up at the same time and there are no existing // TODO: This is racy. If two instances start up at the same time and there are no existing
// matching publications, each will generate and publish their own paramters. In practice this // matching publications, each will generate and publish their own paramters. In practice this
// is unlikely to happen, and if it does it can be fixed by restarting both Etherpad instances. // is unlikely to happen, and if it does it can be fixed by restarting both Etherpad instances.
// @ts-ignore
const dbKeys:string[] = await db.findKeys(`${this._dbPrefix}:*`, null) || []; const dbKeys:string[] = await db.findKeys(`${this._dbPrefix}:*`, null) || [];
let currentParams:any = null; let currentParams:any = null;
let currentId = null; let currentId = null;

View file

@ -69,13 +69,13 @@ NodeVersion.enforceMinNodeVersion(pkg.engines.node.replace(">=", ""));
NodeVersion.checkDeprecationStatus(pkg.engines.node.replace(">=", ""), '2.1.0'); NodeVersion.checkDeprecationStatus(pkg.engines.node.replace(">=", ""), '2.1.0');
const UpdateCheck = require('./utils/UpdateCheck'); const UpdateCheck = require('./utils/UpdateCheck');
const db = require('./db/DB'); import db from './db/DB';
const express = require('./hooks/express'); const express = require('./hooks/express');
const hooks = require('../static/js/pluginfw/hooks'); const hooks = require('../static/js/pluginfw/hooks');
const pluginDefs = require('../static/js/pluginfw/plugin_defs'); const pluginDefs = require('../static/js/pluginfw/plugin_defs');
const plugins = require('../static/js/pluginfw/plugins'); const plugins = require('../static/js/pluginfw/plugins');
const {Gate} = require('./utils/promises'); const {Gate} = require('./utils/promises');
const stats = require('./stats') import stats from './stats';
const logger = log4js.getLogger('server'); const logger = log4js.getLogger('server');

View file

@ -1,10 +1,13 @@
'use strict'; 'use strict';
const measured = require('measured-core'); // @ts-ignore
import measured from 'measured-core';
module.exports = measured.createCollection(); const coll = measured.createCollection()
export default coll;
// @ts-ignore // @ts-ignore
module.exports.shutdown = async (hookName, context) => { export const shutdown = async (hookName, context) => {
module.exports.end(); coll.end();
}; };

View file

@ -22,7 +22,7 @@ import AttributePool from '../../static/js/AttributePool';
const {Pad} = require('../db/Pad'); const {Pad} = require('../db/Pad');
const Stream = require('./Stream'); const Stream = require('./Stream');
const authorManager = require('../db/AuthorManager'); const authorManager = require('../db/AuthorManager');
const db = require('../db/DB'); import db from '../db/DB';
const hooks = require('../../static/js/pluginfw/hooks'); const hooks = require('../../static/js/pluginfw/hooks');
import log4js from 'log4js'; import log4js from 'log4js';
const supportedElems = require('../../static/js/contentcollector').supportedElems; const supportedElems = require('../../static/js/contentcollector').supportedElems;

View file

@ -779,7 +779,7 @@ class Settings {
* *
* The isSettings variable only controls the error logging. * The isSettings variable only controls the error logging.
*/ */
private parseSettings = (settingsFilename: string, isSettings: boolean) => { parseSettings = (settingsFilename: string, isSettings: boolean) => {
let settingsStr = ''; let settingsStr = '';
let settingsType, notFoundMessage, notFoundFunction; let settingsType, notFoundMessage, notFoundFunction;
@ -964,3 +964,4 @@ export default settings

View file

@ -1,5 +1,5 @@
'use strict'; import {cleanComments, minify} from "admin/src/utils/utils";
import {expect, describe, it, beforeAll} from 'vitest'
import {strict as assert} from "assert"; import {strict as assert} from "assert";
import {cleanComments, minify} from "admin/src/utils/utils"; import {cleanComments, minify} from "admin/src/utils/utils";

View file

@ -0,0 +1,39 @@
// line comment
/*
* block comment
*/
{
"trailing commas": {
"lists": {
"multiple lines": [
"",
]
},
"objects": {
"multiple lines": {
"key": "",
}
}
},
"environment variable substitution": {
"set": {
"true": "${SET_VAR_TRUE}",
"false": "${SET_VAR_FALSE}",
"null": "${SET_VAR_NULL}",
"undefined": "${SET_VAR_UNDEFINED}",
"number": "${SET_VAR_NUMBER}",
"string": "${SET_VAR_STRING}",
"empty string": "${SET_VAR_EMPTY_STRING}"
},
"unset": {
"no default": "${UNSET_VAR}",
"true": "${UNSET_VAR:true}",
"false": "${UNSET_VAR:false}",
"null": "${UNSET_VAR:null}",
"undefined": "${UNSET_VAR:undefined}",
"number": "${UNSET_VAR:123}",
"string": "${UNSET_VAR:foo}",
"empty string": "${UNSET_VAR:}"
}
}
}

View file

@ -1,9 +1,8 @@
'use strict'; import settingsMod from '../../../node/utils/Settings';
const assert = require('assert').strict;
const {parseSettings} = require('../../../node/utils/Settings').exportedForTestingOnly;
import path from 'path'; import path from 'path';
import process from 'process'; import process from 'process';
import {expect, describe, it, beforeAll} from 'vitest'
describe(__filename, function () { describe(__filename, function () {
describe('parseSettings', function () { describe('parseSettings', function () {
@ -18,11 +17,11 @@ describe(__filename, function () {
{name: 'empty string', val: '', var: 'SET_VAR_EMPTY_STRING', want: ''}, {name: 'empty string', val: '', var: 'SET_VAR_EMPTY_STRING', want: ''},
]; ];
before(async function () { beforeAll(async function () {
for (const tc of envVarSubstTestCases) process.env[tc.var] = tc.val; for (const tc of envVarSubstTestCases) process.env[tc.var] = tc.val;
delete process.env.UNSET_VAR; delete process.env.UNSET_VAR;
settings = parseSettings(path.join(__dirname, 'settings.json'), true); settings = settingsMod.parseSettings(path.join(__dirname, 'settings.json'), true);
assert(settings != null); expect(settings).not.toBe(null);
}); });
describe('environment variable substitution', function () { describe('environment variable substitution', function () {
@ -31,9 +30,9 @@ describe(__filename, function () {
it(tc.name, async function () { it(tc.name, async function () {
const obj = settings['environment variable substitution'].set; const obj = settings['environment variable substitution'].set;
if (tc.name === 'undefined') { if (tc.name === 'undefined') {
assert(!(tc.name in obj)); expect(obj[tc.name]).toBe(undefined);
} else { } else {
assert.equal(obj[tc.name], tc.want); expect(obj[tc.name]).toBe(tc.want);
} }
}); });
} }
@ -42,16 +41,16 @@ describe(__filename, function () {
describe('unset', function () { describe('unset', function () {
it('no default', async function () { it('no default', async function () {
const obj = settings['environment variable substitution'].unset; const obj = settings['environment variable substitution'].unset;
assert.equal(obj['no default'], null); expect(obj['no default']).toBe(null);
}); });
for (const tc of envVarSubstTestCases) { for (const tc of envVarSubstTestCases) {
it(tc.name, async function () { it(tc.name, async function () {
const obj = settings['environment variable substitution'].unset; const obj = settings['environment variable substitution'].unset;
if (tc.name === 'undefined') { if (tc.name === 'undefined') {
assert(!(tc.name in obj)); expect(obj[tc.name]).toBe(undefined);
} else { } else {
assert.equal(obj[tc.name], tc.want); expect(obj[tc.name]).toBe(tc.want);
} }
}); });
} }
@ -62,31 +61,31 @@ describe(__filename, function () {
describe("Parse plugin settings", function () { describe("Parse plugin settings", function () {
before(async function () { beforeAll(async function () {
process.env["EP__ADMIN__PASSWORD"] = "test" process.env["EP__ADMIN__PASSWORD"] = "test"
}) })
it('should parse plugin settings', async function () { it('should parse plugin settings', async function () {
let settings = parseSettings(path.join(__dirname, 'settings.json'), true); let settings = settingsMod.parseSettings(path.join(__dirname, 'settings.json'), true);
assert.equal(settings.ADMIN.PASSWORD, "test"); expect(settings!.ADMIN.PASSWORD).toBe("test");
}) })
it('should bundle settings with same path', async function () { it('should bundle settings with same path', async function () {
process.env["EP__ADMIN__USERNAME"] = "test" process.env["EP__ADMIN__USERNAME"] = "test"
let settings = parseSettings(path.join(__dirname, 'settings.json'), true); let settings = settingsMod.parseSettings(path.join(__dirname, 'settings.json'), true);
assert.deepEqual(settings.ADMIN, {PASSWORD: "test", USERNAME: "test"}); expect(settings!.ADMIN).toEqual({PASSWORD: "test", USERNAME: "test"});
}) })
it("Can set the ep themes", async function () { it("Can set the ep themes", async function () {
process.env["EP__ep_themes__default_theme"] = "hacker" process.env["EP__ep_themes__default_theme"] = "hacker"
let settings = parseSettings(path.join(__dirname, 'settings.json'), true); let settings = settingsMod.parseSettings(path.join(__dirname, 'settings.json'), true);
assert.deepEqual(settings.ep_themes, {"default_theme": "hacker"}); expect(settings!.ep_themes.default_theme).toBe("hacker");
}) })
it("can set the ep_webrtc settings", async function () { it("can set the ep_webrtc settings", async function () {
process.env["EP__ep_webrtc__enabled"] = "true" process.env["EP__ep_webrtc__enabled"] = "true"
let settings = parseSettings(path.join(__dirname, 'settings.json'), true); let settings = settingsMod.parseSettings(path.join(__dirname, 'settings.json'), true);
assert.deepEqual(settings.ep_webrtc, {"enabled": true}); expect(settings!.ep_webrtc.enabled).toBe(true);
}) })
}) })
}); });

View file

@ -8,7 +8,7 @@ const io = require('socket.io-client');
const log4js = require('log4js'); const log4js = require('log4js');
import padutils from '../../static/js/pad_utils'; import padutils from '../../static/js/pad_utils';
const process = require('process'); const process = require('process');
const server = require('../../node/server'); const server = require('../../node/server')
const setCookieParser = require('set-cookie-parser'); const setCookieParser = require('set-cookie-parser');
import settings from '../../node/utils/Settings'; import settings from '../../node/utils/Settings';
import supertest from 'supertest'; import supertest from 'supertest';

View file

@ -4,7 +4,7 @@ import {MapArrayType} from "../../../node/types/MapType";
const assert = require('assert').strict; const assert = require('assert').strict;
const authorManager = require('../../../node/db/AuthorManager'); const authorManager = require('../../../node/db/AuthorManager');
const db = require('../../../node/db/DB'); import db from '../../../node/db/DB';
const importEtherpad = require('../../../node/utils/ImportEtherpad'); const importEtherpad = require('../../../node/utils/ImportEtherpad');
const padManager = require('../../../node/db/PadManager'); const padManager = require('../../../node/db/PadManager');
const plugins = require('../../../static/js/pluginfw/plugin_defs'); const plugins = require('../../../static/js/pluginfw/plugin_defs');

View file

@ -3,7 +3,7 @@
import {strict} from "assert"; import {strict} from "assert";
const common = require('../common'); const common = require('../common');
const crypto = require('../../../node/security/crypto'); const crypto = require('../../../node/security/crypto');
const db = require('../../../node/db/DB'); import db from '../../../node/db/DB';
const SecretRotator = require("../../../node/security/SecretRotator").SecretRotator; const SecretRotator = require("../../../node/security/SecretRotator").SecretRotator;
const logger = common.logger; const logger = common.logger;
@ -121,7 +121,8 @@ describe(__filename, function () {
if (sr != null) sr.stop(); if (sr != null) sr.stop();
sr = null; sr = null;
await Promise.all( await Promise.all(
(await db.findKeys(`${dbPrefix}:*`, null)).map(async (dbKey: string) => await db.remove(dbKey))); // @ts-ignore
(await db.findKeys(`${dbPrefix}:*`, null)).map(async (dbKey: string) => await db.remove(dbKey)));
}); });
describe('constructor', function () { describe('constructor', function () {
@ -163,6 +164,7 @@ describe(__filename, function () {
sr = newRotator(); sr = newRotator();
const fc = setFakeClock(sr); const fc = setFakeClock(sr);
await sr.start(); await sr.start();
// @ts-ignore
const dbKeys = await db.findKeys(`${dbPrefix}:*`, null); const dbKeys = await db.findKeys(`${dbPrefix}:*`, null);
strict.equal(dbKeys.length, 1); strict.equal(dbKeys.length, 1);
const [id] = dbKeys; const [id] = dbKeys;
@ -196,12 +198,14 @@ describe(__filename, function () {
const fc = setFakeClock(sr); const fc = setFakeClock(sr);
await sr.start(); await sr.start();
const {secrets} = sr; const {secrets} = sr;
// @ts-ignore
const dbKeys = await db.findKeys(`${dbPrefix}:*`, null); const dbKeys = await db.findKeys(`${dbPrefix}:*`, null);
sr.stop(); sr.stop();
sr = newRotator(); sr = newRotator();
setFakeClock(sr, fc); setFakeClock(sr, fc);
await sr.start(); await sr.start();
strict.deepEqual(sr.secrets, secrets); strict.deepEqual(sr.secrets, secrets);
// @ts-ignore
strict.deepEqual(await db.findKeys(`${dbPrefix}:*`, null), dbKeys); strict.deepEqual(await db.findKeys(`${dbPrefix}:*`, null), dbKeys);
}); });
@ -209,6 +213,7 @@ describe(__filename, function () {
sr = newRotator(); sr = newRotator();
const fc = setFakeClock(sr); const fc = setFakeClock(sr);
await sr.start(); await sr.start();
// @ts-ignore
const [oldId] = await db.findKeys(`${dbPrefix}:*`, null); const [oldId] = await db.findKeys(`${dbPrefix}:*`, null);
strict(oldId != null); strict(oldId != null);
sr.stop(); sr.stop();
@ -217,6 +222,7 @@ describe(__filename, function () {
sr = newRotator(); sr = newRotator();
setFakeClock(sr, fc); setFakeClock(sr, fc);
await sr.start(); await sr.start();
// @ts-ignore
const ids = await db.findKeys(`${dbPrefix}:*`, null); const ids = await db.findKeys(`${dbPrefix}:*`, null);
strict.equal(ids.length, 1); strict.equal(ids.length, 1);
const [newId] = ids; const [newId] = ids;
@ -229,6 +235,7 @@ describe(__filename, function () {
await sr.start(); await sr.start();
const [, , future] = sr.secrets; const [, , future] = sr.secrets;
sr.stop(); sr.stop();
// @ts-ignore
const [origId] = await db.findKeys(`${dbPrefix}:*`, null); const [origId] = await db.findKeys(`${dbPrefix}:*`, null);
const p = await db.get(origId); const p = await db.get(origId);
await fc.advance(p.end + p.lifetime + p.interval - 1); await fc.advance(p.end + p.lifetime + p.interval - 1);
@ -237,6 +244,7 @@ describe(__filename, function () {
await sr.start(); await sr.start();
strict(sr.secrets.slice(1).includes(future)); strict(sr.secrets.slice(1).includes(future));
// It should have created a new publication, not extended the life of the old publication. // It should have created a new publication, not extended the life of the old publication.
// @ts-ignore
strict.equal((await db.findKeys(`${dbPrefix}:*`, null)).length, 2); strict.equal((await db.findKeys(`${dbPrefix}:*`, null)).length, 2);
strict.deepEqual(await db.get(origId), p); strict.deepEqual(await db.get(origId), p);
}); });
@ -247,10 +255,12 @@ describe(__filename, function () {
await sr.start(); await sr.start();
strict.equal(fc.timeouts.size, 1); strict.equal(fc.timeouts.size, 1);
const secrets = [...sr.secrets]; const secrets = [...sr.secrets];
// @ts-ignore
const dbKeys = await db.findKeys(`${dbPrefix}:*`, null); const dbKeys = await db.findKeys(`${dbPrefix}:*`, null);
await sr.start(); await sr.start();
strict.equal(fc.timeouts.size, 1); strict.equal(fc.timeouts.size, 1);
strict.deepEqual(sr.secrets, secrets); strict.deepEqual(sr.secrets, secrets);
// @ts-ignore
strict.deepEqual(await db.findKeys(`${dbPrefix}:*`, null), dbKeys); strict.deepEqual(await db.findKeys(`${dbPrefix}:*`, null), dbKeys);
}); });
@ -335,6 +345,7 @@ describe(__filename, function () {
await sr.start(); await sr.start();
strict.equal(sr.secrets.length, 4); // 1 for the legacy secret, 3 for past, current, future strict.equal(sr.secrets.length, 4); // 1 for the legacy secret, 3 for past, current, future
strict(sr.secrets.slice(1).includes('legacy')); // Should not be the current secret. strict(sr.secrets.slice(1).includes('legacy')); // Should not be the current secret.
// @ts-ignore
const ids = await db.findKeys(`${dbPrefix}:*`, null); const ids = await db.findKeys(`${dbPrefix}:*`, null);
const params = (await Promise.all(ids.map(async (id:string) => await db.get(id)))) const params = (await Promise.all(ids.map(async (id:string) => await db.get(id))))
.sort((a, b) => a.algId - b.algId); .sort((a, b) => a.algId - b.algId);
@ -380,6 +391,7 @@ describe(__filename, function () {
await sr.start(); await sr.start();
strict.equal(sr.secrets.length, 5); // s0 through s3 and the legacy secret. strict.equal(sr.secrets.length, 5); // s0 through s3 and the legacy secret.
strict.deepEqual(sr.secrets, [s2, s1, s0, sr.secrets[3], 'legacy']); strict.deepEqual(sr.secrets, [s2, s1, s0, sr.secrets[3], 'legacy']);
// @ts-ignore
const ids = await db.findKeys(`${dbPrefix}:*`, null); const ids = await db.findKeys(`${dbPrefix}:*`, null);
const params = (await Promise.all(ids.map(async (id:string) => await db.get(id)))) const params = (await Promise.all(ids.map(async (id:string) => await db.get(id))))
.sort((a, b) => a.algId - b.algId); .sort((a, b) => a.algId - b.algId);
@ -425,6 +437,7 @@ describe(__filename, function () {
await sr.start(); await sr.start();
strict.deepEqual(sr.secrets, [...new Set(sr.secrets)]); strict.deepEqual(sr.secrets, [...new Set(sr.secrets)]);
// There shouldn't be multiple publications for the same legacy secret. // There shouldn't be multiple publications for the same legacy secret.
// @ts-ignore
strict.equal((await db.findKeys(`${dbPrefix}:*`, null)).length, 2); strict.equal((await db.findKeys(`${dbPrefix}:*`, null)).length, 2);
}); });
@ -511,8 +524,10 @@ describe(__filename, function () {
sr = newRotator(); sr = newRotator();
setFakeClock(sr, fc); setFakeClock(sr, fc);
await sr.start(); await sr.start();
// @ts-ignore
strict.equal((await db.findKeys(`${dbPrefix}:*`, null)).length, 2); strict.equal((await db.findKeys(`${dbPrefix}:*`, null)).length, 2);
await fc.advance(lifetime + (3 * origInterval)); await fc.advance(lifetime + (3 * origInterval));
// @ts-ignore
strict.equal((await db.findKeys(`${dbPrefix}:*`, null)).length, 1); strict.equal((await db.findKeys(`${dbPrefix}:*`, null)).length, 1);
}); });

View file

@ -1,9 +1,9 @@
'use strict'; 'use strict';
const SessionStore = require('../../../node/db/SessionStore'); import SessionStore from '../../../node/db/SessionStore';
import {strict as assert} from 'assert'; import {strict as assert} from 'assert';
const common = require('../common'); const common = require('../common');
const db = require('../../../node/db/DB'); import db from '../../../node/db/DB';
import util from 'util'; import util from 'util';
type Session = { type Session = {
@ -15,7 +15,7 @@ type Session = {
} }
describe(__filename, function () { describe(__filename, function () {
let ss: Session|null; let ss: SessionStore|null;
let sid: string|null; let sid: string|null;
const set = async (sess: string|null) => await util.promisify(ss!.set).call(ss, sid, sess); const set = async (sess: string|null) => await util.promisify(ss!.set).call(ss, sid, sess);

View file

@ -5,7 +5,7 @@ import {agent, generateJWTToken, init, logger} from "../../common";
import TestAgent from "supertest/lib/agent"; import TestAgent from "supertest/lib/agent";
import supertest from "supertest"; import supertest from "supertest";
const assert = require('assert').strict; const assert = require('assert').strict;
const db = require('../../../../node/db/DB'); import db from '../../../../node/db/DB';
let apiVersion = 1; let apiVersion = 1;
let groupID = ''; let groupID = '';

View file

@ -2,14 +2,14 @@
const AuthorManager = require('../../../node/db/AuthorManager'); const AuthorManager = require('../../../node/db/AuthorManager');
import {strict as assert} from "assert"; import {strict as assert} from "assert";
const common = require('../common'); import {init} from '../common';
const db = require('../../../node/db/DB'); import db from '../../../node/db/DB';
describe(__filename, function () { describe(__filename, function () {
let setBackup: Function; let setBackup: Function;
before(async function () { before(async function () {
await common.init(); await init();
setBackup = db.set; setBackup = db.set;
db.set = async (...args:any) => { db.set = async (...args:any) => {
@ -20,7 +20,7 @@ describe(__filename, function () {
}); });
after(async function () { after(async function () {
db.set = setBackup; db.set = setBackup as any;
}); });
it('regression test for missing await in createAuthor (#5000)', async function () { it('regression test for missing await in createAuthor (#5000)', async function () {