文件
mynode/packages/lib/services/interop/InteropService_Importer_EnexToMd.test.ts
chen 301194963b
一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
feat: Initial clean release of CHM
2026-11-04 11:29:39 +08:00

77 行
2.8 KiB
TypeScript

import Note from '../../models/Note';
import { setupDatabaseAndSynchronizer, supportDir, switchClient } from '../../testing/test-utils';
import { ImportModuleOutputFormat, ImportOptions } from './types';
import InteropService from './InteropService';
import Folder from '../../models/Folder';
import { isRecoverableError } from '../../import-enex';
const importFolder = async (path: string, onError: ImportOptions['onError'] = null) => {
const importOptions: ImportOptions = {
path: path,
format: 'enex',
outputFormat: ImportModuleOutputFormat.Markdown,
onError,
};
await InteropService.instance().import(importOptions);
};
const importTestFile = async (name: string, onError: ImportOptions['onError'] = null) => {
const enexSampleBaseDir = `${supportDir}/../enex_to_md`;
await importFolder(`${enexSampleBaseDir}/${name}`, onError);
};
describe('InteropService_Importer_EnexToMd', () => {
beforeEach(async () => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
});
it('should resolve cross-notebook links', async () => {
await importTestFile('links/');
const folders = await Folder.all({ order: [{ by: 'title', dir: 'ASC' }] });
expect(folders).toMatchObject([
{ title: 'notebook1', parent_id: '' },
{ title: 'notebook2', parent_id: '' },
]);
const notes = await Note.all({ order: [{ by: 'title', dir: 'ASC' }] });
expect(notes).toMatchObject([
{ title: 'Example note', parent_id: folders[0].id },
{ title: 'Note 2', parent_id: folders[0].id },
{ title: 'Test', parent_id: folders[1].id },
{ title: 'Test note', parent_id: folders[1].id },
{ title: 'Testing', parent_id: folders[1].id },
]);
// Same-folder link (https:// link)
expect(notes[1].body).toContain(`[Example note](:/${notes[0].id})`);
// Cross-folder link (https:// link)
expect(notes[1].body).toContain(`[Test](:/${notes[2].id})`);
// Cross-folder link (https:// link)
expect(notes[2].body).toContain(`[Example note](:/${notes[0].id})`);
// Same-folder link (evernote:// link)
expect(notes[2].body).toContain(`[Test note](:/${notes[3].id})`);
expect(notes[4].body).toContain(`[Test](:/${notes[2].id})`);
});
it('should import notes even if the file contains unescaped ampersands', async () => {
const errors: Error[] = [];
await importTestFile('unescaped_ampersand.enex', error => errors.push(error));
const notes = await Note.all({ order: [{ by: 'title', dir: 'ASC' }] });
expect(notes.map(n => n.title)).toEqual([
'Note after the bad one',
'Unescaped ampersand',
]);
expect(notes[0].body).toContain('This note must still be imported');
expect(notes[1].body).toContain('Mobilize & Measure');
// Reported, but flagged so it's not presented as a failed import.
expect(errors.length).toBe(1);
expect(isRecoverableError(errors[0])).toBe(true);
});
});