mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-24 07:09:50 +08:00
- 恢复批量表和批量库按钮到原批量操作弹窗\n- 补回批量删除表和删除库的危险确认与执行逻辑\n- 删除表仅处理 table 对象,避免视图误走 DropTable\n- 补齐多语言文案与入口/删除回归测试
190 lines
6.9 KiB
TypeScript
190 lines
6.9 KiB
TypeScript
import { readFileSync } from 'node:fs';
|
|
import { describe, expect, it } from 'vitest';
|
|
|
|
const sidebarSource = readFileSync(new URL('./Sidebar.tsx', import.meta.url), 'utf8');
|
|
const batchModalSource = readFileSync(new URL('./sidebar/SidebarBatchExportModals.tsx', import.meta.url), 'utf8');
|
|
const batchHookSource = readFileSync(new URL('./sidebar/useSidebarBatchExport.ts', import.meta.url), 'utf8');
|
|
const batchTabSource = readFileSync(new URL('../utils/tableExportTab.ts', import.meta.url), 'utf8');
|
|
const locales = ['zh-CN', 'zh-TW', 'en-US', 'ja-JP', 'de-DE', 'ru-RU'] as const;
|
|
|
|
const requiredKeys = [
|
|
'sidebar.action.batch_tables',
|
|
'sidebar.action.batch_databases',
|
|
'sidebar.action.clear_tables',
|
|
'sidebar.action.delete_tables',
|
|
'sidebar.action.delete_database_count',
|
|
'sidebar.action.export_schema',
|
|
'sidebar.action.export_data_only',
|
|
'sidebar.action.backup_schema_data',
|
|
'sidebar.action.select_all',
|
|
'sidebar.action.clear_selection',
|
|
'sidebar.action.invert_selection',
|
|
'sidebar.action.export_database_schema_count',
|
|
'sidebar.action.backup_database_count',
|
|
'sidebar.field.select_connection',
|
|
'sidebar.field.select_database',
|
|
'sidebar.placeholder.select_connection',
|
|
'sidebar.placeholder.select_connection_first',
|
|
'sidebar.placeholder.filter_table_view',
|
|
'sidebar.filter.all_objects',
|
|
'sidebar.filter.tables_only',
|
|
'sidebar.filter.views_only',
|
|
'sidebar.filter.scope_filtered',
|
|
'sidebar.filter.scope_all',
|
|
'sidebar.modal.batch_tables.title',
|
|
'sidebar.modal.batch_tables.description',
|
|
'sidebar.modal.batch_tables.selection_hint',
|
|
'sidebar.modal.batch_databases.title',
|
|
'sidebar.modal.batch_databases.description',
|
|
'sidebar.modal.batch_databases.selection_hint',
|
|
'sidebar.batch.filtered_count',
|
|
'sidebar.batch.selected_objects',
|
|
'sidebar.batch.selected_databases',
|
|
'sidebar.batch.group.tables',
|
|
'sidebar.batch.group.views',
|
|
'sidebar.batch.no_matching_objects',
|
|
'sidebar.tab.batch_export_objects',
|
|
'sidebar.tab.batch_export_objects_database',
|
|
'sidebar.tab.batch_export_databases',
|
|
] as const;
|
|
|
|
const placeholders = (value: string): string[] => [...value.matchAll(/\{\{(\w+)\}\}/g)]
|
|
.map((match) => match[1])
|
|
.sort();
|
|
|
|
describe('Sidebar batch actions i18n', () => {
|
|
it('localizes batch table and database action copy', () => {
|
|
[
|
|
'批量操作表',
|
|
'批量操作库',
|
|
'按对象批量导出结构、数据或完整备份。',
|
|
'按数据库批量导出结构,或生成结构加数据的备份。',
|
|
].forEach((rawSnippet) => {
|
|
expect(sidebarSource).not.toContain(rawSnippet);
|
|
});
|
|
|
|
[
|
|
'清空表',
|
|
'删除表',
|
|
'导出结构',
|
|
'仅数据(INSERT)',
|
|
'备份(结构+数据)',
|
|
'取消',
|
|
'选择连接:',
|
|
'选择数据库:',
|
|
'请选择连接',
|
|
'请先选择连接',
|
|
'先选择连接与数据库,再决定导出范围和目标对象。',
|
|
'筛选表/视图名称',
|
|
"label: '全部对象'",
|
|
"label: '仅表'",
|
|
"label: '仅视图'",
|
|
'勾选作用于:当前筛选结果',
|
|
'勾选作用于:全部对象',
|
|
'当前筛选命中',
|
|
'取消全选',
|
|
'反选',
|
|
'个对象',
|
|
'无匹配对象',
|
|
'备份库',
|
|
'连接选定后会加载当前连接下可批量导出的数据库列表。',
|
|
'个库',
|
|
].forEach((rawSnippet) => {
|
|
expect(batchModalSource).not.toContain(rawSnippet);
|
|
});
|
|
|
|
[
|
|
'`批量导出 ${dbName} 对象`',
|
|
"'批量导出对象'",
|
|
"title: '批量导出库'",
|
|
].forEach((rawSnippet) => {
|
|
expect(batchHookSource).not.toContain(rawSnippet);
|
|
});
|
|
|
|
[
|
|
"title: String(input.title || '批量导出对象').trim() || '批量导出对象'",
|
|
"title: String(input.title || '批量导出库').trim() || '批量导出库'",
|
|
].forEach((rawSnippet) => {
|
|
expect(batchTabSource).not.toContain(rawSnippet);
|
|
});
|
|
|
|
[
|
|
'sidebar.action.batch_tables',
|
|
'sidebar.action.batch_databases',
|
|
'sidebar.modal.batch_tables.title',
|
|
'sidebar.modal.batch_tables.description',
|
|
'sidebar.modal.batch_databases.title',
|
|
'sidebar.modal.batch_databases.description',
|
|
].forEach((key) => {
|
|
expect(sidebarSource, key).toContain(`t('${key}'`);
|
|
});
|
|
|
|
[
|
|
'sidebar.action.clear_tables',
|
|
'sidebar.action.delete_tables',
|
|
'sidebar.action.delete_database_count',
|
|
'sidebar.action.export_schema',
|
|
'sidebar.action.export_data_only',
|
|
'sidebar.action.backup_schema_data',
|
|
'sidebar.action.select_all',
|
|
'sidebar.action.clear_selection',
|
|
'sidebar.action.invert_selection',
|
|
'sidebar.action.export_database_schema_count',
|
|
'sidebar.action.backup_database_count',
|
|
'sidebar.field.select_connection',
|
|
'sidebar.field.select_database',
|
|
'sidebar.placeholder.select_connection',
|
|
'sidebar.placeholder.select_connection_first',
|
|
'sidebar.placeholder.filter_table_view',
|
|
'sidebar.filter.all_objects',
|
|
'sidebar.filter.tables_only',
|
|
'sidebar.filter.views_only',
|
|
'sidebar.filter.scope_filtered',
|
|
'sidebar.filter.scope_all',
|
|
'sidebar.modal.batch_tables.selection_hint',
|
|
'sidebar.modal.batch_databases.selection_hint',
|
|
'sidebar.batch.filtered_count',
|
|
'sidebar.batch.selected_objects',
|
|
'sidebar.batch.selected_databases',
|
|
'sidebar.batch.group.tables',
|
|
'sidebar.batch.group.views',
|
|
'sidebar.batch.no_matching_objects',
|
|
].forEach((key) => {
|
|
expect(batchModalSource, key).toContain(`t('${key}'`);
|
|
});
|
|
|
|
expect(batchModalSource).toContain('handleBatchDeleteTables');
|
|
expect(batchModalSource).toContain('handleBatchDbDelete');
|
|
expect(batchModalSource).toContain("item.objectType === 'table'");
|
|
|
|
[
|
|
'sidebar.tab.batch_export_objects',
|
|
'sidebar.tab.batch_export_objects_database',
|
|
'sidebar.tab.batch_export_databases',
|
|
].forEach((key) => {
|
|
expect(batchHookSource, key).toContain(`t('${key}'`);
|
|
});
|
|
|
|
[
|
|
'sidebar.tab.batch_export_objects',
|
|
'sidebar.tab.batch_export_databases',
|
|
].forEach((key) => {
|
|
expect(batchTabSource, key).toContain(`t('${key}'`);
|
|
});
|
|
});
|
|
|
|
it('keeps batch action catalog entries available in every locale', () => {
|
|
locales.forEach((locale) => {
|
|
const catalog = JSON.parse(readFileSync(new URL(`../../../shared/i18n/${locale}.json`, import.meta.url), 'utf8')) as Record<string, string>;
|
|
requiredKeys.forEach((key) => {
|
|
expect(catalog[key], `${locale}:${key}`).toBeTruthy();
|
|
});
|
|
expect(placeholders(catalog['sidebar.action.delete_database_count'])).toEqual(['count']);
|
|
expect(placeholders(catalog['sidebar.action.delete_tables'])).toEqual([]);
|
|
expect(placeholders(catalog['sidebar.tab.batch_export_objects'])).toEqual([]);
|
|
expect(placeholders(catalog['sidebar.tab.batch_export_objects_database'])).toEqual(['database']);
|
|
expect(placeholders(catalog['sidebar.tab.batch_export_databases'])).toEqual([]);
|
|
});
|
|
});
|
|
});
|