98 lines
4.8 KiB
TypeScript
98 lines
4.8 KiB
TypeScript
import { readFileSync } from 'fs';
|
|
import { resolve } from 'path';
|
|
|
|
const tables = [
|
|
'qqbot_message_subscription',
|
|
'qqbot_message_template',
|
|
'qqbot_message_publish_binding',
|
|
'qqbot_message_publish_target',
|
|
'qqbot_message_event',
|
|
'qqbot_message_delivery',
|
|
] as const;
|
|
|
|
const menuEntries = [
|
|
['2041700000000100413', 'QqBotMessageSubscription', 'QqBot:MessageSubscription:List'],
|
|
['2041700000000100414', 'QqBotMessageTemplate', 'QqBot:MessageTemplate:List'],
|
|
['2041700000000120461', 'QqBotMessageSubscriptionList', 'QqBot:MessageSubscription:List'],
|
|
['2041700000000120462', 'QqBotMessageSubscriptionCreate', 'QqBot:MessageSubscription:Create'],
|
|
['2041700000000120463', 'QqBotMessageSubscriptionUpdate', 'QqBot:MessageSubscription:Update'],
|
|
['2041700000000120464', 'QqBotMessageSubscriptionDelete', 'QqBot:MessageSubscription:Delete'],
|
|
['2041700000000120465', 'QqBotMessageSubscriptionToggle', 'QqBot:MessageSubscription:Toggle'],
|
|
['2041700000000120471', 'QqBotMessageTemplateList', 'QqBot:MessageTemplate:List'],
|
|
['2041700000000120472', 'QqBotMessageTemplateCreate', 'QqBot:MessageTemplate:Create'],
|
|
['2041700000000120473', 'QqBotMessageTemplateUpdate', 'QqBot:MessageTemplate:Update'],
|
|
['2041700000000120474', 'QqBotMessageTemplateDelete', 'QqBot:MessageTemplate:Delete'],
|
|
['2041700000000120475', 'QqBotMessageTemplateToggle', 'QqBot:MessageTemplate:Toggle'],
|
|
['2041700000000120476', 'QqBotMessageTemplatePreview', 'QqBot:MessageTemplate:Preview'],
|
|
['2041700000000120481', 'QqBotAccountMessagePushList', 'QqBot:Account:MessagePush:List'],
|
|
['2041700000000120482', 'QqBotAccountMessagePushCreate', 'QqBot:Account:MessagePush:Create'],
|
|
['2041700000000120483', 'QqBotAccountMessagePushUpdate', 'QqBot:Account:MessagePush:Update'],
|
|
['2041700000000120484', 'QqBotAccountMessagePushDelete', 'QqBot:Account:MessagePush:Delete'],
|
|
['2041700000000120485', 'QqBotAccountMessagePushToggle', 'QqBot:Account:MessagePush:Toggle'],
|
|
] as const;
|
|
|
|
/** Reads SQL with case and quote differences removed for contract assertions. */
|
|
const readNormalizedSql = (relativePath: string) =>
|
|
readFileSync(resolve(process.cwd(), relativePath), 'utf8')
|
|
.toLowerCase()
|
|
.replace(/`/g, '')
|
|
.replace(/\s+/g, ' ');
|
|
|
|
describe('QQBot message-push SQL contract', () => {
|
|
const bootstrapSql = readNormalizedSql('sql/qqbot-init.sql');
|
|
const schemaSql = readNormalizedSql('sql/refactor-v3/00-full-schema.sql');
|
|
const seedSql = readNormalizedSql('sql/refactor-v3/01-seed-core.sql');
|
|
const verifySql = readNormalizedSql('sql/refactor-v3/99-verify.sql');
|
|
const vbenSql = readNormalizedSql('sql/vben-admin-init.sql');
|
|
|
|
it.each(tables)('declares %s in current and bootstrap schema SQL', (table) => {
|
|
expect(bootstrapSql).toContain(`create table if not exists ${table}`);
|
|
expect(schemaSql).toContain(`create table if not exists ${table}`);
|
|
});
|
|
|
|
it('keeps six-table indexes, datetime precision, and JSON fields aligned', () => {
|
|
for (const sql of [bootstrapSql, schemaSql]) {
|
|
expect(sql).toContain('uk_qqbot_message_subscription_active_key');
|
|
expect(sql).toContain('uk_qqbot_message_publish_binding_active_key');
|
|
expect(sql).toContain('uk_qqbot_message_publish_target_active_key');
|
|
expect(sql).toContain('uk_qqbot_message_event_event_id');
|
|
expect(sql).toContain('uk_qqbot_message_delivery_event_target');
|
|
expect(sql).toContain('idx_qqbot_message_event_dispatch');
|
|
expect(sql).toContain('idx_qqbot_message_event_lease');
|
|
expect(sql).toContain('idx_qqbot_message_delivery_dispatch');
|
|
expect(sql).toContain('idx_qqbot_message_delivery_lease');
|
|
expect(sql).toContain('idx_qqbot_message_delivery_history');
|
|
expect(sql).toContain('source_config json');
|
|
expect(sql).toContain('payload json');
|
|
expect(sql).toContain('variable_snapshot json');
|
|
expect(sql).toContain('datetime(6)');
|
|
}
|
|
});
|
|
|
|
it('seeds the default template and every stable menu node idempotently', () => {
|
|
for (const sql of [bootstrapSql, seedSql]) {
|
|
expect(sql).toContain('2041700000000200601');
|
|
expect(sql).toContain('network.stun.mapping-port-changed');
|
|
expect(sql).toContain('当前stun的端口已变更为${{endpoint}}');
|
|
expect(sql).toContain('where not exists');
|
|
}
|
|
|
|
for (const [id, name, authCode] of menuEntries) {
|
|
for (const sql of [bootstrapSql, seedSql, vbenSql]) {
|
|
expect(sql).toContain(id);
|
|
expect(sql).toContain(name.toLowerCase());
|
|
expect(sql).toContain(authCode.toLowerCase());
|
|
}
|
|
}
|
|
});
|
|
|
|
it('verifies every persisted message-push table and seeded menu contract', () => {
|
|
for (const table of tables) {
|
|
expect(verifySql).toContain(table);
|
|
}
|
|
expect(verifySql).toContain('2041700000000200601');
|
|
expect(verifySql).toContain('qqbot:messagesubscription:list');
|
|
expect(verifySql).toContain('qqbot:account:messagepush:toggle');
|
|
});
|
|
});
|