Files
qinglong/test/back/notification-audit.test.cjs
T

92 lines
3.0 KiB
JavaScript

const test = require('node:test'),
assert = require('node:assert/strict'),
{ Sequelize, DataTypes } = require('sequelize');
const load = require('../helpers/load-security-module.cjs');
const decorators = { Service: () => (x) => x, Inject: () => () => {} };
async function fixture(t) {
const db = new Sequelize({
dialect: 'sqlite',
storage: ':memory:',
logging: false,
});
t.after(() => db.close());
const rows = db.define('System', {
type: DataTypes.STRING,
info: DataTypes.JSON,
});
await db.sync();
const logger = { error() {} };
const S = load('back/services/system.ts', {
typedi: decorators,
'../config': {},
'../config/const': { NotificationModeStringMap: { 0: 'gotify' } },
'../config/util': {},
'../data/dependence': {},
'../data/system': {
SystemModel: rows,
AuthDataType: { notifyLog: 'notifyLog', notification: 'notification' },
NotifyStatus: { success: 0, fail: 1 },
},
'./schedule': class {},
'./sock': class {},
'./notify': class {},
'../shared/pLimit': {},
'../schedule/client': {},
'../config/index': {},
'../shared/store': {},
'../shared/i18n': { t: (s) => s },
}).default;
const service = Object.assign(Object.create(S.prototype), {
logger,
notificationService: { notify: async () => true },
});
service.getDb = async () => ({ info: { type: 'email' } });
return { rows, service };
}
test('writes cap logs without reading the page and preserve other system data', async (t) => {
const { rows, service } = await fixture(t);
await rows.create({ type: 'authConfig', info: { keep: true } });
for (let i = 0; i < 205; i++)
await service.notify({ title: String(i), content: 'body' });
assert.equal(await rows.count({ where: { type: 'notifyLog' } }), 200);
const logs = await service.getNotifyLog();
assert.equal(logs[0].title, '204');
assert.equal(logs.at(-1).title, '5');
assert.equal(logs[0].notifyType, 'email');
assert.equal(await rows.count({ where: { type: 'authConfig' } }), 1);
});
test('audit DB failure does not turn a successful notification into failure', async (t) => {
const { rows, service } = await fixture(t);
const create = rows.create;
rows.create = async () => {
throw Error('disk full');
};
try {
assert.equal(
(await service.notify({ title: 'ok', content: 'ok' })).code,
200,
);
} finally {
rows.create = create;
}
});
test('failed sends are recorded and message size is bounded', async (t) => {
const { service } = await fixture(t);
service.notificationService.notify = async () => false;
assert.equal(
(
await service.notify({
title: 'x'.repeat(1000),
content: 'y'.repeat(20000),
notificationInfo: { type: 0 },
})
).code,
400,
);
const [row] = await service.getNotifyLog();
assert.equal(row.status, 1);
assert.equal(row.title.length, 512);
assert.equal(row.content.length, 8192);
assert.equal(row.notifyType, 'gotify');
});