fix backup import preview and refresh race (#167)
This commit is contained in:
@@ -121,6 +121,64 @@ const allApiHubV2Payload = JSON.stringify({
|
||||
},
|
||||
});
|
||||
|
||||
const nativeMetapiPayload = JSON.stringify({
|
||||
version: '2.0',
|
||||
timestamp: 1735689600000,
|
||||
accounts: {
|
||||
sites: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Native Site',
|
||||
url: 'https://native.example.com',
|
||||
platform: 'new-api',
|
||||
},
|
||||
],
|
||||
accounts: [
|
||||
{
|
||||
id: 1,
|
||||
siteId: 1,
|
||||
username: 'native-user',
|
||||
accessToken: 'session-token',
|
||||
apiToken: 'api-token',
|
||||
status: 'active',
|
||||
},
|
||||
],
|
||||
accountTokens: [
|
||||
{
|
||||
id: 1,
|
||||
accountId: 1,
|
||||
name: 'default',
|
||||
token: 'sk-native',
|
||||
enabled: true,
|
||||
isDefault: true,
|
||||
},
|
||||
],
|
||||
tokenRoutes: [
|
||||
{
|
||||
id: 1,
|
||||
modelPattern: 'gpt-5-nano',
|
||||
enabled: true,
|
||||
},
|
||||
],
|
||||
routeChannels: [
|
||||
{
|
||||
id: 1,
|
||||
routeId: 1,
|
||||
accountId: 1,
|
||||
tokenId: 1,
|
||||
enabled: true,
|
||||
manualOverride: false,
|
||||
},
|
||||
],
|
||||
routeGroupSources: [],
|
||||
},
|
||||
preferences: {
|
||||
settings: [
|
||||
{ key: 'locale', value: 'zh-CN' },
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
describe('ImportExport', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
@@ -178,6 +236,31 @@ describe('ImportExport', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('does not label native metapi backups as ALL-API-Hub V2', async () => {
|
||||
let root: ReturnType<typeof create> | null = null;
|
||||
try {
|
||||
await act(async () => {
|
||||
root = create(
|
||||
<MemoryRouter>
|
||||
<ImportExport />
|
||||
</MemoryRouter>,
|
||||
);
|
||||
});
|
||||
|
||||
const textarea = root!.root.findByType('textarea');
|
||||
await act(async () => {
|
||||
textarea.props.onChange({ target: { value: nativeMetapiPayload } });
|
||||
});
|
||||
await flushMicrotasks();
|
||||
|
||||
const rendered = collectText(root!.root);
|
||||
expect(rendered).not.toContain('ALL-API-Hub V2');
|
||||
expect(rendered).toContain('统计:站点 1 / 账号 1 / 令牌 1 / 路由 1 / 通道 1 / 设置 1');
|
||||
} finally {
|
||||
root?.unmount();
|
||||
}
|
||||
});
|
||||
|
||||
it('uses backend import summary in the completion toast', async () => {
|
||||
const confirmSpy = vi.mocked((window as { confirm: (...args: unknown[]) => boolean }).confirm);
|
||||
let root: ReturnType<typeof create> | null = null;
|
||||
|
||||
@@ -75,8 +75,26 @@ function parseImportSummary(raw: string): ParsedSummary | null {
|
||||
const legacyPrefs = Boolean(data.data?.preferences);
|
||||
const profilesCount = Array.isArray(data.apiCredentialProfiles?.profiles) ? data.apiCredentialProfiles.profiles.length : 0;
|
||||
const bookmarksCount = Array.isArray(accountsSection?.bookmarks) ? accountsSection.bookmarks.length : 0;
|
||||
const isNativeMetapiBackup = Boolean(
|
||||
accountsSection
|
||||
&& Array.isArray(accountsSection.sites)
|
||||
&& Array.isArray(accountsSection.accountTokens)
|
||||
&& Array.isArray(accountsSection.tokenRoutes)
|
||||
&& Array.isArray(accountsSection.routeChannels)
|
||||
);
|
||||
const hasLegacyAccountRows = Array.isArray(accountsSection?.accounts)
|
||||
&& accountsSection.accounts.some((row: any) => row && typeof row === 'object' && !Array.isArray(row) && (
|
||||
'site_url' in row
|
||||
|| 'site_type' in row
|
||||
|| 'account_info' in row
|
||||
|| 'cookieAuth' in row
|
||||
|| 'authType' in row
|
||||
|| 'sub2apiAuth' in row
|
||||
));
|
||||
const isAllApiHubV2 = Boolean(
|
||||
accountsSection
|
||||
&& !isNativeMetapiBackup
|
||||
&& hasLegacyAccountRows
|
||||
&& Array.isArray(accountsSection.accounts)
|
||||
&& (
|
||||
(typeof data.version === 'string' && data.version.startsWith('2'))
|
||||
|
||||
Reference in New Issue
Block a user