mirror of
https://github.com/whyour/qinglong.git
synced 2026-11-06 17:34:34 +08:00
Use MikroORM's official Node SQLite dialect with bounded database isolation, preserve legacy schema and data for rollback, and require Node 22.17 or newer. Update Debian runtimes and retain ARMv6 musl compatibility without a SQLite addon. Complete short archive writes, stop orphaned SQL workers after owner death, preserve buffered startup requests, and prestart the archived backend on every platform. Cover real package installation, migration, failure recovery, and legacy database compatibility. Keep authentication storage failures distinct from expired sessions with a pinned Keyv runtime, propagated cache errors, and retryable HTTP 503 responses. Preserve genuine 401 failures and verify legacy cache bytes, initialization safety, and session recovery.
165 lines
4.4 KiB
JavaScript
165 lines
4.4 KiB
JavaScript
const { DatabaseClient } = require('../../back/data/databaseClient');
|
|
const { repository, initialize } = require('../helpers/repository-fixture.cjs');
|
|
const { orderBy } = require('../../back/data/queries');
|
|
require('ts-node/register/transpile-only');
|
|
const assert = require('node:assert/strict');
|
|
const { test } = require('node:test');
|
|
const { Sequelize, DataTypes } = require('sequelize');
|
|
const dayjs = require('dayjs');
|
|
const express = require('express');
|
|
test('today result lists include mixed and deleted tasks and exclude other dates', async (t) => {
|
|
const db = new DatabaseClient(':memory:');
|
|
t.after(() => db.close());
|
|
const crons = repository(db, 'Crontab');
|
|
const stats = repository(db, 'CrontabStat');
|
|
const replacements = {
|
|
'../../back/data': { database: db },
|
|
'../../back/data/cron': { CrontabModel: crons },
|
|
'../../back/data/cronStats': { CrontabStatModel: stats },
|
|
'../../back/data/runningInstance': {},
|
|
'../../back/shared/i18n': { tf: (format, id) => format.replace('%s', id) },
|
|
};
|
|
for (const [modulePath, exports] of Object.entries(replacements)) {
|
|
const resolved = require.resolve(modulePath);
|
|
const original = require.cache[resolved];
|
|
require.cache[resolved] = {
|
|
id: resolved,
|
|
filename: resolved,
|
|
loaded: true,
|
|
exports,
|
|
};
|
|
t.after(() => {
|
|
if (original) require.cache[resolved] = original;
|
|
else delete require.cache[resolved];
|
|
});
|
|
}
|
|
await initialize(db);
|
|
await crons.insertMany([
|
|
{ id: 1, name: 'Recovered task', command: 'task recovered.js' },
|
|
{ id: 2, name: '', command: 'task unnamed.js' },
|
|
{ id: 3, name: 'Successful task', command: 'task success.js' },
|
|
]);
|
|
const today = dayjs().format('YYYY-MM-DD');
|
|
await stats.insertMany([
|
|
{ ref_id: 1, date: today, fail_count: 2, success_count: 1 },
|
|
{ ref_id: 2, date: today, fail_count: 1, success_count: 0 },
|
|
{ ref_id: 3, date: today, fail_count: 0, success_count: 4 },
|
|
{ ref_id: 4, date: today, fail_count: 3, success_count: 2 },
|
|
{
|
|
ref_id: 3,
|
|
date: dayjs().subtract(1, 'day').format('YYYY-MM-DD'),
|
|
fail_count: 10,
|
|
success_count: 20,
|
|
},
|
|
]);
|
|
const router = express.Router();
|
|
require('../../back/api/dashboard').default(router);
|
|
const dashboard = router.stack.find(
|
|
(layer) => layer.name === 'router',
|
|
).handle;
|
|
const handler = dashboard.stack.find(
|
|
(layer) => layer.route?.path === '/failures',
|
|
).route.stack[0].handle;
|
|
const successHandler = dashboard.stack.find(
|
|
(layer) => layer.route?.path === '/successes',
|
|
).route.stack[0].handle;
|
|
let response;
|
|
await handler(
|
|
{},
|
|
{
|
|
send: (value) => {
|
|
response = value;
|
|
},
|
|
},
|
|
(error) => {
|
|
throw error;
|
|
},
|
|
);
|
|
assert.deepEqual(response, {
|
|
code: 200,
|
|
data: [
|
|
{ id: 4, name: '任务#4', command: '', failCount: 3, deleted: true },
|
|
{
|
|
id: 1,
|
|
name: 'Recovered task',
|
|
command: 'task recovered.js',
|
|
failCount: 2,
|
|
deleted: false,
|
|
},
|
|
{
|
|
id: 2,
|
|
name: 'task unnamed.js',
|
|
command: 'task unnamed.js',
|
|
failCount: 1,
|
|
deleted: false,
|
|
},
|
|
],
|
|
});
|
|
await successHandler(
|
|
{},
|
|
{
|
|
send: (value) => {
|
|
response = value;
|
|
},
|
|
},
|
|
(error) => {
|
|
throw error;
|
|
},
|
|
);
|
|
assert.deepEqual(response, {
|
|
code: 200,
|
|
data: [
|
|
{
|
|
id: 3,
|
|
name: 'Successful task',
|
|
command: 'task success.js',
|
|
successCount: 4,
|
|
deleted: false,
|
|
},
|
|
{ id: 4, name: '任务#4', command: '', successCount: 2, deleted: true },
|
|
{
|
|
id: 1,
|
|
name: 'Recovered task',
|
|
command: 'task recovered.js',
|
|
successCount: 1,
|
|
deleted: false,
|
|
},
|
|
],
|
|
});
|
|
await stats.nativeDelete({});
|
|
await successHandler(
|
|
{},
|
|
{
|
|
send: (value) => {
|
|
response = value;
|
|
},
|
|
},
|
|
(error) => {
|
|
throw error;
|
|
},
|
|
);
|
|
assert.deepEqual(response, { code: 200, data: [] });
|
|
await handler(
|
|
{},
|
|
{
|
|
send: (value) => {
|
|
response = value;
|
|
},
|
|
},
|
|
(error) => {
|
|
throw error;
|
|
},
|
|
);
|
|
assert.deepEqual(response, { code: 200, data: [] });
|
|
await db.query('DROP TABLE CrontabStats');
|
|
let forwarded;
|
|
await handler(
|
|
{},
|
|
{ send: () => assert.fail('must forward database errors') },
|
|
(error) => {
|
|
forwarded = error;
|
|
},
|
|
);
|
|
assert.ok(forwarded instanceof Error);
|
|
});
|