1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-10 22:11:50 +02:00

All: Resolves #12157: Add information about failing tests of OneNote importer inside test names (#12159)

Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
This commit is contained in:
pedr
2025-05-19 19:03:15 -03:00
committed by GitHub
parent d5830dd3a1
commit 60e27924ae
5 changed files with 78 additions and 44 deletions

View File

@@ -11,6 +11,9 @@ module.exports = {
testEnvironment: 'node',
setupFilesAfterEnv: [`${__dirname}/jest.setup.js`],
setupFilesAfterEnv: [
'jest-expect-message',
`${__dirname}/jest.setup.js`,
],
slowTestThreshold: 40,
};

View File

@@ -20,6 +20,7 @@
"@types/adm-zip": "0.5.7",
"@types/fs-extra": "11.0.4",
"@types/jest": "29.5.12",
"@types/jest-expect-message": "1.1.0",
"@types/js-yaml": "4.0.9",
"@types/jsdom": "21.1.7",
"@types/markdown-it": "13.0.9",
@@ -31,6 +32,7 @@
"canvas": "2.11.2",
"clean-html": "1.5.0",
"jest": "29.7.0",
"jest-expect-message": "1.1.3",
"jsdom": "23.2.0",
"pdfjs-dist": "3.11.174",
"react": "18.3.1",

View File

@@ -10,6 +10,18 @@ import InteropService_Importer_OneNote from './InteropService_Importer_OneNote';
import { JSDOM } from 'jsdom';
import { ImportModuleOutputFormat } from './types';
const instructionMessage = `
--------------------------------------
IF THIS IS FAILING IN THE CI
you can test it locally
Check packages/onenote-converter/README.md for more instructions
--------------------------------------
`;
const expectWithInstructions = <T>(value: T) => {
return expect(value, instructionMessage);
};
// We don't require all developers to have Rust to run the project, so we skip this test if not running in CI
const skipIfNotCI = process.env.IS_CONTINUOUS_INTEGRATION ? it : it.skip;
@@ -44,17 +56,17 @@ describe('InteropService_Importer_OneNote', () => {
const notes = await importNote(`${supportDir}/onenote/simple_notebook.zip`);
const folders = await Folder.all();
expect(notes.length).toBe(2);
expectWithInstructions(notes.length).toBe(2);
const mainNote = notes[0];
expect(folders.length).toBe(3);
expectWithInstructions(folders.length).toBe(3);
const parentFolder = folders.find(f => f.id === mainNote.parent_id);
expect(parentFolder.title).toBe('Section title');
expect(folders.find(f => f.id === parentFolder.parent_id).title).toBe('Simple notebook');
expectWithInstructions(parentFolder.title).toBe('Section title');
expectWithInstructions(folders.find(f => f.id === parentFolder.parent_id).title).toBe('Simple notebook');
expect(mainNote.title).toBe('Page title');
expect(mainNote.markup_language).toBe(MarkupToHtml.MARKUP_LANGUAGE_HTML);
expect(mainNote.body).toMatchSnapshot(mainNote.title);
expectWithInstructions(mainNote.title).toBe('Page title');
expectWithInstructions(mainNote.markup_language).toBe(MarkupToHtml.MARKUP_LANGUAGE_HTML);
expectWithInstructions(mainNote.body).toMatchSnapshot(mainNote.title);
});
skipIfNotCI('should preserve indentation of subpages in Section page', async () => {
@@ -65,16 +77,16 @@ describe('InteropService_Importer_OneNote', () => {
const menuLines = menuHtml.split('</li>');
const pageTwo = notes.find(n => n.title === 'Page 2');
expect(menuLines[3].trim()).toBe(`<li class="l1"><a href=":/${pageTwo.id}" target="content" title="Page 2">${pageTwo.title}</a>`);
expectWithInstructions(menuLines[3].trim()).toBe(`<li class="l1"><a href=":/${pageTwo.id}" target="content" title="Page 2">${pageTwo.title}</a>`);
const pageTwoA = notes.find(n => n.title === 'Page 2-a');
expect(menuLines[4].trim()).toBe(`<li class="l2"><a href=":/${pageTwoA.id}" target="content" title="Page 2-a">${pageTwoA.title}</a>`);
expectWithInstructions(menuLines[4].trim()).toBe(`<li class="l2"><a href=":/${pageTwoA.id}" target="content" title="Page 2-a">${pageTwoA.title}</a>`);
const pageTwoAA = notes.find(n => n.title === 'Page 2-a-a');
expect(menuLines[5].trim()).toBe(`<li class="l3"><a href=":/${pageTwoAA.id}" target="content" title="Page 2-a-a">${pageTwoAA.title}</a>`);
expectWithInstructions(menuLines[5].trim()).toBe(`<li class="l3"><a href=":/${pageTwoAA.id}" target="content" title="Page 2-a-a">${pageTwoAA.title}</a>`);
const pageTwoB = notes.find(n => n.title === 'Page 2-b');
expect(menuLines[7].trim()).toBe(`<li class="l2"><a href=":/${pageTwoB.id}" target="content" title="Page 2-b">${pageTwoB.title}</a>`);
expectWithInstructions(menuLines[7].trim()).toBe(`<li class="l2"><a href=":/${pageTwoB.id}" target="content" title="Page 2-b">${pageTwoB.title}</a>`);
});
skipIfNotCI('should created subsections', async () => {
@@ -87,12 +99,12 @@ describe('InteropService_Importer_OneNote', () => {
const subSection2 = folders.find(f => f.title === 'Subsection 2');
const notesFromParentSection = notes.filter(n => n.parent_id === parentSection.id);
expect(parentSection.id).toBe(subSection1.parent_id);
expect(parentSection.id).toBe(subSection2.parent_id);
expect(parentSection.id).toBe(subSection.parent_id);
expect(folders.length).toBe(7);
expect(notes.length).toBe(6);
expect(notesFromParentSection.length).toBe(2);
expectWithInstructions(parentSection.id).toBe(subSection1.parent_id);
expectWithInstructions(parentSection.id).toBe(subSection2.parent_id);
expectWithInstructions(parentSection.id).toBe(subSection.parent_id);
expectWithInstructions(folders.length).toBe(7);
expectWithInstructions(notes.length).toBe(6);
expectWithInstructions(notesFromParentSection.length).toBe(2);
});
skipIfNotCI('should expect notes to be rendered the same', async () => {
@@ -102,12 +114,12 @@ describe('InteropService_Importer_OneNote', () => {
const folders = await Folder.all();
const parentSection = folders.find(f => f.title === 'Quick Notes');
expect(folders.length).toBe(3);
expect(notes.length).toBe(7);
expect(notes.filter(n => n.parent_id === parentSection.id).length).toBe(6);
expectWithInstructions(folders.length).toBe(3);
expectWithInstructions(notes.length).toBe(7);
expectWithInstructions(notes.filter(n => n.parent_id === parentSection.id).length).toBe(6);
for (const note of notes) {
expect(note.body).toMatchSnapshot(note.title);
expectWithInstructions(note.body).toMatchSnapshot(note.title);
}
BaseModel.setIdGenerator(originalIdGenerator);
});
@@ -125,19 +137,19 @@ describe('InteropService_Importer_OneNote', () => {
const sectionD1 = folders.find(f => f.title === 'Section D1');
const sectionD = folders.find(f => f.title === 'Section D');
expect(section.parent_id).toBe(mainFolder.id);
expect(sectionA.parent_id).toBe(mainFolder.id);
expect(sectionD.parent_id).toBe(mainFolder.id);
expectWithInstructions(section.parent_id).toBe(mainFolder.id);
expectWithInstructions(sectionA.parent_id).toBe(mainFolder.id);
expectWithInstructions(sectionD.parent_id).toBe(mainFolder.id);
expect(sectionA1.parent_id).toBe(sectionA.id);
expect(sectionB.parent_id).toBe(sectionA.id);
expectWithInstructions(sectionA1.parent_id).toBe(sectionA.id);
expectWithInstructions(sectionB.parent_id).toBe(sectionA.id);
expect(sectionB1.parent_id).toBe(sectionB.id);
expect(sectionD1.parent_id).toBe(sectionD.id);
expectWithInstructions(sectionB1.parent_id).toBe(sectionB.id);
expectWithInstructions(sectionD1.parent_id).toBe(sectionD.id);
expect(notes.filter(n => n.parent_id === sectionA1.id).length).toBe(2);
expect(notes.filter(n => n.parent_id === sectionB1.id).length).toBe(2);
expect(notes.filter(n => n.parent_id === sectionD1.id).length).toBe(1);
expectWithInstructions(notes.filter(n => n.parent_id === sectionA1.id).length).toBe(2);
expectWithInstructions(notes.filter(n => n.parent_id === sectionB1.id).length).toBe(2);
expectWithInstructions(notes.filter(n => n.parent_id === sectionD1.id).length).toBe(1);
});
skipIfNotCI.each([
@@ -164,7 +176,7 @@ describe('InteropService_Importer_OneNote', () => {
xmlSerializer: new jsdom.window.XMLSerializer(),
});
expect(importer.extractSvgs(content, titleGenerator())).toMatchSnapshot();
expectWithInstructions(importer.extractSvgs(content, titleGenerator())).toMatchSnapshot();
});
skipIfNotCI('should ignore broken characters at the start of paragraph', async () => {
@@ -172,7 +184,7 @@ describe('InteropService_Importer_OneNote', () => {
const originalIdGenerator = BaseModel.setIdGenerator(() => String(idx++));
const notes = await importNote(`${supportDir}/onenote/bug_broken_character.zip`);
expect(notes.find(n => n.title === 'Action research - Wikipedia').body).toMatchSnapshot();
expectWithInstructions(notes.find(n => n.title === 'Action research - Wikipedia').body).toMatchSnapshot();
BaseModel.setIdGenerator(originalIdGenerator);
});
@@ -183,7 +195,7 @@ describe('InteropService_Importer_OneNote', () => {
const notes = await importNote(`${supportDir}/onenote/remove_hyperlink_on_title.zip`);
for (const note of notes) {
expect(note.body).toMatchSnapshot(note.title);
expectWithInstructions(note.body).toMatchSnapshot(note.title);
}
BaseModel.setIdGenerator(originalIdGenerator);
});
@@ -193,8 +205,8 @@ describe('InteropService_Importer_OneNote', () => {
const noteToTest = notes.find(n => n.title === 'Tips from a Pro Using Trees for Dramatic Landscape Photography');
expect(noteToTest).toBeTruthy();
expect(noteToTest.body.includes('<a href="onenote:https://d.docs.live.net/c8d3bbab7f1acf3a/Documents/Photography/风景.one#Tips%20from%20a%20Pro%20Using%20Trees%20for%20Dramatic%20Landscape%20Photography&section-id={262ADDFB-A4DC-4453-A239-0024D6769962}&page-id={88D803A5-4F43-48D4-9B16-4C024F5787DC}&end" style="">Tips from a Pro: Using Trees for Dramatic Landscape Photography</a>')).toBe(true);
expectWithInstructions(noteToTest).toBeTruthy();
expectWithInstructions(noteToTest.body.includes('<a href="onenote:https://d.docs.live.net/c8d3bbab7f1acf3a/Documents/Photography/风景.one#Tips%20from%20a%20Pro%20Using%20Trees%20for%20Dramatic%20Landscape%20Photography&section-id={262ADDFB-A4DC-4453-A239-0024D6769962}&page-id={88D803A5-4F43-48D4-9B16-4C024F5787DC}&end" style="">Tips from a Pro: Using Trees for Dramatic Landscape Photography</a>')).toBe(true);
});
skipIfNotCI('should render links properly by ignoring wrongly set indices when the first character is a hyperlink marker', async () => {
@@ -203,7 +215,7 @@ describe('InteropService_Importer_OneNote', () => {
const notes = await importNote(`${supportDir}/onenote/hyperlink_marker_as_first_character.zip`);
for (const note of notes) {
expect(note.body).toMatchSnapshot(note.title);
expectWithInstructions(note.body).toMatchSnapshot(note.title);
}
BaseModel.setIdGenerator(originalIdGenerator);
});
@@ -213,10 +225,10 @@ describe('InteropService_Importer_OneNote', () => {
const originalIdGenerator = BaseModel.setIdGenerator(() => String(idx++));
const notes = await importNote(`${supportDir}/onenote/corrupted_attachment.zip`);
expect(notes.length).toBe(2);
expectWithInstructions(notes.length).toBe(2);
for (const note of notes) {
expect(note.body).toMatchSnapshot(note.title);
expectWithInstructions(note.body).toMatchSnapshot(note.title);
}
BaseModel.setIdGenerator(originalIdGenerator);
});
@@ -226,10 +238,10 @@ describe('InteropService_Importer_OneNote', () => {
const originalIdGenerator = BaseModel.setIdGenerator(() => String(idx++));
const notes = await importNote(`${supportDir}/onenote/note_with_audio_embedded.zip`);
expect(notes.length).toBe(2);
expectWithInstructions(notes.length).toBe(2);
for (const note of notes) {
expect(note.body).toMatchSnapshot(note.title);
expectWithInstructions(note.body).toMatchSnapshot(note.title);
}
BaseModel.setIdGenerator(originalIdGenerator);
});

View File

@@ -56,12 +56,27 @@ To work with the project you will need:
- Rust https://www.rust-lang.org/learn/get-started
### Running tests
Tests for the project are located in the `lib` packages, but to make it work it is necessary to build this project first:
`IS_CONTINUOUS_INTEGRATION=1 yarn build # for production build`
or
`IS_CONTINUOUS_INTEGRATION=1 yarn buildDev # for build with more logs and compiles faster`
After that you should navigate to `lib` package and run the tests of `InteropService_Importer_OneNote.test.` file
```
cd ../lib
IS_CONTINUOUS_INTEGRATION=1 yarn test services/interop/InteropService_Importer_OneNote.test.
```
### Developing
When working with the Rust code you will probably rather run `yarn buildDev` since it is faster and it has more logging messages (they can be disabled in the macro `log!()`)
During development, it will be easier to test it where this library is called. `InteropService_Importer_Onenote.ts` is the code that depends on this and already has some tests.
### Running tests and IS_CONTINUOUS_INTEGRATION
We don't require developers that won't work on this project to have Rust installed on their machine.
To make this work we:

View File

@@ -9046,6 +9046,7 @@ __metadata:
"@types/adm-zip": 0.5.7
"@types/fs-extra": 11.0.4
"@types/jest": 29.5.12
"@types/jest-expect-message": 1.1.0
"@types/js-yaml": 4.0.9
"@types/jsdom": 21.1.7
"@types/markdown-it": 13.0.9
@@ -9078,6 +9079,7 @@ __metadata:
image-data-uri: 2.0.1
immer: 9.0.21
jest: 29.7.0
jest-expect-message: 1.1.3
js-yaml: 4.1.0
jsdom: 23.2.0
markdown-it: 13.0.2