Files
NodeBB/test/mocks/databasemock.js
Barış Soner Uşaklı d20b07cfea Webpack5 (#10311)
* feat: webpack 5 part 1

* fix: gruntfile fixes

* fix: fix taskbar warning

add app.importScript
copy public/src/modules to build folder

* refactor: remove commented old code

* feat: reenable admin

* fix: acp settings pages, fix sortable on manage categories

embedded require in html not allowed

* fix: bundle serialize/deserizeli so plugins dont break

* test: fixe util tests

* test: fix require path

* test: more test fixes

* test: require correct utils module

* test: require correct utils

* test: log stack

* test: fix db require blowing up tests

* test: move and disable bundle test

* refactor: add aliases

* test: disable testing route

* fix: move webpack modules necessary for build, into `dependencies`

* test: fix one more test

remove 500-embed.tpl

* fix: restore use of assets/nodebb.min.js, at least for now

* fix: remove unnecessary line break

* fix: point to proper ACP bundle

* test: maybe fix build test

* test: composer

* refactor: dont need dist

* refactor: more cleanup

use everything from build/public folder

* get rid of conditional import in app.js

* fix: ace

* refactor: cropper alias

* test: lint and test fixes

* lint: fix

* refactor: rename function to app.require

* refactor: go back to using app.require

* chore: use github branch

* chore: use webpack branch

* feat: webpack webinstaller

* feat: add chunkFile name with contenthash

* refactor: move hooks to top

* refactor: get rid of template500Function

* fix(deps): use webpack5 branch of 2factor plugin

* chore: tagging v2.0.0-beta.0 pre-release version 💥 :shipit: 🎉 🚀

* refactor: disable cache on templates

loadTemplate is called once by benchpress and the result is cache internally

* refactor: add server side helpers.js

* feat: deprecate /plugins shorthand route, closes #10343

* refactor: use build/public for webpack

* test: fix filename

* fix: more specific selector

* lint: ignore

* refactor: fix comments

* test: add debug for random failing test

* refactor: cleanup

remove test page, remove dupe functions in utils.common

* lint: use relative path  for now

* chore: bump prerelease version

* feat: add translateKeys

* fix: optional params

* fix: get rid of extra timeago files

* refactor: cleanup, require timeago locale earlier

remove translator.prepareDOM, it is in header.tpl html tag

* refactor: privileges system to use a Map in the backend instead of separate objects for keys and labels (#10378)

* refactor: privileges system to use a Map in the backend instead of separate objects for keys and labels

- Existing hooks are preserved (to be deprecated at a later date, possibly)
- New init hooks are called on NodeBB start, and provide a one-stop shop to add new privileges, instead of having to add to four different hooks

* docs: fix typo in comment

* test: spec changes

* refactor: privileges system to use a Map in the backend instead of separate objects for keys and labels (#10378)

* refactor: privileges system to use a Map in the backend instead of separate objects for keys and labels

- Existing hooks are preserved (to be deprecated at a later date, possibly)
- New init hooks are called on NodeBB start, and provide a one-stop shop to add new privileges, instead of having to add to four different hooks

* docs: fix typo in comment

* test: spec changes

* feat: allow app.require('bootbox'/'benchpressjs')

* refactor: require server side utils

* test: jquery ready

* change istaller to use build/public

* test: use document.addEventListener

* refactor: closes #10301

* refactor: generateTopicClass

* fix: column counts for other privileges

* fix: #10443, regression where sorted-list items did not render into the DOM in the predicted order [breaking]

* fix: typo in hook name

* refactor: introduce a generic autocomplete.init() method that can be called to add nodebb-style autocompletion but using different data sources (e.g. not user/groups/tags)

* fix: crash if `delay` not passed in (as it cannot be destructured)

* refactor: replace substr

* feat: set --panel-offset style in html element based on stored value in localStorage

* refactor: addDropupHandler() logic to be less naive

- Take into account height of the menu
- Don't apply dropUp logic if there's nothing in the dropdown
- Remove 'hidden' class (added by default in Persona for post tools) when menu items are added

closes #10423

* refactor: simplify utils.params [breaking]

Retrospective analysis of the usage of this method suggests that the options passed in are superfluous, and that only `url` is required. Using a browser built-in makes more sense to accomplish what this method sets out to do.

* feat: add support for returning full URLSearchParams for utils.params

* fix: utils.params() fallback handling

* fix: default empty obj for params()

* fix: remove \'loggedin\' and \'register\' qs parameters once they have been used, delay invocation of messages until ajaxify.end

* fix: utils.params() not allowing relative paths to be passed in

* refactor(DRY): new assertPasswordValidity utils method

* fix: incorrect error message returned on insufficient privilege on flag edit

* fix: read/update/delete access to flags API should be limited for moderators to only post flags in categories they moderate

- added failing tests and patched up middleware.assert.flags to fix

* refactor: flag api v3 tests to create new post and flags on every round

* fix: missing error:no-flag language key

* refactor: flags.canView to check flag existence, simplify middleware.assert.flag

* feat: flag deletion API endpoint, #10426

* feat: UI for flag deletion, closes #10426

* chore: update plugin versions

* chore: up emoji

* chore: update markdown

* chore: up emoji-android

* fix: regression caused by utils.params() refactor, supports arrays and pipes all values through utils.toType, adjusts tests to type check

Co-authored-by: Julian Lam <julian@nodebb.org>
2022-04-29 21:39:33 -04:00

262 lines
8.1 KiB
JavaScript

'use strict';
/**
* Database Mock - wrapper for database.js, makes system use separate test db, instead of production
* ATTENTION: testing db is flushed before every use!
*/
require('../../require-main');
const path = require('path');
const nconf = require('nconf');
const url = require('url');
const util = require('util');
process.env.NODE_ENV = process.env.TEST_ENV || 'production';
global.env = process.env.NODE_ENV || 'production';
const winston = require('winston');
const packageInfo = require('../../package.json');
winston.add(new winston.transports.Console({
format: winston.format.combine(
winston.format.splat(),
winston.format.simple()
),
}));
try {
const fs = require('fs');
const configJSON = fs.readFileSync(path.join(__dirname, '../../config.json'), 'utf-8');
winston.info('configJSON');
winston.info(configJSON);
} catch (err) {
console.error(err.stack);
throw err;
}
nconf.file({ file: path.join(__dirname, '../../config.json') });
nconf.defaults({
base_dir: path.join(__dirname, '../..'),
themes_path: path.join(__dirname, '../../node_modules'),
upload_path: 'test/uploads',
views_dir: path.join(__dirname, '../../build/public/templates'),
relative_path: '',
});
const urlObject = url.parse(nconf.get('url'));
const relativePath = urlObject.pathname !== '/' ? urlObject.pathname : '';
nconf.set('relative_path', relativePath);
nconf.set('asset_base_url', `${relativePath}/assets`);
nconf.set('upload_path', path.join(nconf.get('base_dir'), nconf.get('upload_path')));
nconf.set('upload_url', '/assets/uploads');
nconf.set('url_parsed', urlObject);
nconf.set('base_url', `${urlObject.protocol}//${urlObject.host}`);
nconf.set('secure', urlObject.protocol === 'https:');
nconf.set('use_port', !!urlObject.port);
nconf.set('port', urlObject.port || nconf.get('port') || (nconf.get('PORT_ENV_VAR') ? nconf.get(nconf.get('PORT_ENV_VAR')) : false) || 4567);
// cookies don't provide isolation by port: http://stackoverflow.com/a/16328399/122353
const domain = nconf.get('cookieDomain') || urlObject.hostname;
const origins = nconf.get('socket.io:origins') || `${urlObject.protocol}//${domain}:*`;
nconf.set('socket.io:origins', origins);
if (nconf.get('isCluster') === undefined) {
nconf.set('isPrimary', true);
nconf.set('isCluster', false);
nconf.set('singleHostCluster', false);
}
const dbType = nconf.get('database');
const testDbConfig = nconf.get('test_database');
const productionDbConfig = nconf.get(dbType);
if (!testDbConfig) {
const errorText = 'test_database is not defined';
winston.info(
'\n===========================================================\n' +
'Please, add parameters for test database in config.json\n' +
'For example (redis):\n' +
'"test_database": {\n' +
' "host": "127.0.0.1",\n' +
' "port": "6379",\n' +
' "password": "",\n' +
' "database": "1"\n' +
'}\n' +
' or (mongo):\n' +
'"test_database": {\n' +
' "host": "127.0.0.1",\n' +
' "port": "27017",\n' +
' "password": "",\n' +
' "database": "1"\n' +
'}\n' +
' or (mongo) in a replicaset\n' +
'"test_database": {\n' +
' "host": "127.0.0.1,127.0.0.1,127.0.0.1",\n' +
' "port": "27017,27018,27019",\n' +
' "username": "",\n' +
' "password": "",\n' +
' "database": "nodebb_test"\n' +
'}\n' +
' or (postgres):\n' +
'"test_database": {\n' +
' "host": "127.0.0.1",\n' +
' "port": "5432",\n' +
' "username": "postgres",\n' +
' "password": "",\n' +
' "database": "nodebb_test"\n' +
'}\n' +
'==========================================================='
);
winston.error(errorText);
throw new Error(errorText);
}
if (testDbConfig.database === productionDbConfig.database &&
testDbConfig.host === productionDbConfig.host &&
testDbConfig.port === productionDbConfig.port) {
const errorText = 'test_database has the same config as production db';
winston.error(errorText);
throw new Error(errorText);
}
nconf.set(dbType, testDbConfig);
winston.info('database config %s', dbType, testDbConfig);
winston.info(`environment ${global.env}`);
const db = require('../../src/database');
module.exports = db;
before(async function () {
this.timeout(30000);
// Parse out the relative_url and other goodies from the configured URL
const urlObject = url.parse(nconf.get('url'));
nconf.set('core_templates_path', path.join(__dirname, '../../src/views'));
nconf.set('base_templates_path', path.join(nconf.get('themes_path'), 'nodebb-theme-persona/templates'));
nconf.set('theme_config', path.join(nconf.get('themes_path'), 'nodebb-theme-persona', 'theme.json'));
nconf.set('bcrypt_rounds', 1);
nconf.set('socket.io:origins', '*:*');
nconf.set('version', packageInfo.version);
nconf.set('runJobs', false);
nconf.set('jobsDisabled', false);
await db.init();
if (db.hasOwnProperty('createIndices')) {
await db.createIndices();
}
await setupMockDefaults();
await db.initSessionStore();
const meta = require('../../src/meta');
nconf.set('theme_templates_path', meta.config['theme:templates'] ? path.join(nconf.get('themes_path'), meta.config['theme:id'], meta.config['theme:templates']) : nconf.get('base_templates_path'));
// nconf defaults, if not set in config
if (!nconf.get('sessionKey')) {
nconf.set('sessionKey', 'express.sid');
}
await meta.dependencies.check();
const webserver = require('../../src/webserver');
const sockets = require('../../src/socket.io');
await sockets.init(webserver.server);
require('../../src/notifications').startJobs();
require('../../src/user').startJobs();
await webserver.listen();
// Iterate over all of the test suites/contexts
this.test.parent.suites.forEach((suite) => {
// Attach an afterAll listener that resets the defaults
suite.afterAll(async () => {
await setupMockDefaults();
});
});
});
async function setupMockDefaults() {
const meta = require('../../src/meta');
await db.emptydb();
require('../../src/groups').cache.reset();
require('../../src/posts/cache').reset();
require('../../src/cache').reset();
require('../../src/middleware/uploads').clearCache();
winston.info('test_database flushed');
await setupDefaultConfigs(meta);
await giveDefaultGlobalPrivileges();
await meta.configs.init();
meta.config.postDelay = 0;
meta.config.initialPostDelay = 0;
meta.config.newbiePostDelay = 0;
meta.config.autoDetectLang = 0;
await enableDefaultPlugins();
await meta.themes.set({
type: 'local',
id: 'nodebb-theme-persona',
});
const rimraf = util.promisify(require('rimraf'));
await rimraf('test/uploads');
const mkdirp = require('mkdirp');
const folders = [
'test/uploads',
'test/uploads/category',
'test/uploads/files',
'test/uploads/system',
'test/uploads/profile',
];
for (const folder of folders) {
/* eslint-disable no-await-in-loop */
await mkdirp(folder);
}
}
db.setupMockDefaults = setupMockDefaults;
async function setupDefaultConfigs(meta) {
winston.info('Populating database with default configs, if not already set...\n');
const defaults = require(path.join(nconf.get('base_dir'), 'install/data/defaults.json'));
defaults.eventLoopCheckEnabled = 0;
defaults.minimumPasswordStrength = 0;
await meta.configs.setOnEmpty(defaults);
}
async function giveDefaultGlobalPrivileges() {
winston.info('Giving default global privileges...\n');
const privileges = require('../../src/privileges');
await privileges.global.give([
'groups:chat', 'groups:upload:post:image', 'groups:signature', 'groups:search:content',
'groups:search:users', 'groups:search:tags', 'groups:local:login', 'groups:view:users',
'groups:view:tags', 'groups:view:groups',
], 'registered-users');
await privileges.global.give([
'groups:view:users', 'groups:view:tags', 'groups:view:groups',
], 'guests');
}
async function enableDefaultPlugins() {
winston.info('Enabling default plugins\n');
const testPlugins = Array.isArray(nconf.get('test_plugins')) ? nconf.get('test_plugins') : [];
const defaultEnabled = [
'nodebb-plugin-dbsearch',
'nodebb-widget-essentials',
'nodebb-plugin-composer-default',
].concat(testPlugins);
winston.info('[install/enableDefaultPlugins] activating default plugins', defaultEnabled);
await db.sortedSetAdd('plugins:active', Object.keys(defaultEnabled), defaultEnabled);
}