Add some tests, and fix the one for subtitles

Relates to MS-899 #complete
This commit is contained in:
Ramon Wenger 2024-03-10 21:56:50 +01:00
parent f5b44cdf37
commit 0c95117832
2 changed files with 149 additions and 14 deletions

View File

@ -59,6 +59,16 @@ const contentListContents = [
}, },
]; ];
const subTitleContents = [
{
id: 'c4eaf571-de75-436b-b4d7-9178f2a86979',
type: 'subtitle',
value: {
text: 'Wozu dienen Visualisierungen?',
},
},
];
const getAddHighlight = (pageType: string = 'ModuleNode') => { const getAddHighlight = (pageType: string = 'ModuleNode') => {
log.debug(`adding highlight for page ${pageType}`); log.debug(`adding highlight for page ${pageType}`);
let page: { id: string; __typename: string; slug?: string }; let page: { id: string; __typename: string; slug?: string };
@ -166,13 +176,15 @@ const selectText = (elm: Node, start: number, end: number) => {
cy.window().then((win) => win.getSelection().addRange(range)); cy.window().then((win) => win.getSelection().addRange(range));
}; };
const markText = (dataCy = 'text-block') => { const makeSelection = (dataCy, tag = null) => {
/*
* Mark the text (programmatically, as Cypress has no API for this)
*/
cy.getByDataCy(dataCy).then(($elm) => { cy.getByDataCy(dataCy).then(($elm) => {
const textBlock = $elm[0]; const textBlock = $elm[0];
const paragraph = textBlock.querySelector('p'); let paragraph;
if (tag) {
paragraph = textBlock.querySelector(tag);
} else {
paragraph = textBlock;
}
selectText(paragraph.childNodes[0], 2, 12); selectText(paragraph.childNodes[0], 2, 12);
/* /*
* Also trigger the events manually * Also trigger the events manually
@ -180,19 +192,30 @@ const markText = (dataCy = 'text-block') => {
cy.document().trigger('selectionchange'); cy.document().trigger('selectionchange');
cy.wrap(paragraph.parentNode).trigger('mouseup'); cy.wrap(paragraph.parentNode).trigger('mouseup');
}); });
cy.getByDataCy('highlight-popover').should('be.visible'); };
cy.getByDataCy('highlight-popover').should('have.length', 1); // there should only be one popover
/* const removeSelection = () => {
* manually remove the selection, because cypress does not do that on a click, unlike a real browser
*/
cy.window().then((win) => { cy.window().then((win) => {
const selection = win.getSelection(); const selection = win.getSelection();
selection.removeAllRanges(); selection.removeAllRanges();
}); });
}; };
const createHighlight = (text: string, content = false) => { const markText = (dataCy = 'text-block', tag = 'p') => {
/*
* Mark the text (programmatically, as Cypress has no API for this)
*/
makeSelection(dataCy, tag);
cy.getByDataCy('highlight-popover').should('be.visible');
cy.getByDataCy('highlight-popover').should('have.length', 1); // there should only be one popover
/*
* manually remove the selection, because cypress does not do that on a click, unlike a real browser
*/
removeSelection();
};
const createHighlight = (text: string, content = false, numHighlights = 1) => {
// delete doesn't make sense before the highlight exists // delete doesn't make sense before the highlight exists
cy.getByDataCy('highlight-delete').should('not.exist'); cy.getByDataCy('highlight-delete').should('not.exist');
// mark the text with yellow and check the text // mark the text with yellow and check the text
@ -206,7 +229,7 @@ const createHighlight = (text: string, content = false) => {
// we only want to have one of each element and not accidentally create multiple // we only want to have one of each element and not accidentally create multiple
cy.getByDataCy('highlight-popover').should('have.length', 1); // there should only be one popover cy.getByDataCy('highlight-popover').should('have.length', 1); // there should only be one popover
cy.getByDataCy('highlight-mark').should('have.length', 1); cy.getByDataCy('highlight-mark').should('have.length', numHighlights);
}; };
const updateHighlight = (text, color = 'beta') => { const updateHighlight = (text, color = 'beta') => {
@ -507,4 +530,114 @@ describe('Highlights', () => {
addNote(); addNote();
deleteHighlight(); deleteHighlight();
}); });
it('visits an instrument with a subtitle and does not display the popover', () => {
cy.mockGraphqlOps({
operations: {
...operations,
InstrumentQuery: {
instrument: {
title: 'some instrument',
id: instrumentId,
slug: instrumentSlug,
contents: subTitleContents,
},
},
},
});
cy.visit(`/instrument/${instrumentSlug}`);
cy.wait('@InstrumentQuery');
// markText('subtitle-block');
cy.getByDataCy('subtitle-block').should('have.text', 'Wozu dienen Visualisierungen?');
makeSelection('subtitle-block');
cy.getByDataCy('highlight-popover').should('not.exist');
});
describe.skip('with paragraphs and lists', () => {
beforeEach(() => {
const contents = [
{
id: 'eaf8016b-ba47-4690-8e3b-21296cc095fa',
type: 'assignment',
value: {
title: 'A LF1 A8: Ziele',
assignment:
'<p data-block-key="hed7c">Ihr Produkt und Ihre Erkenntnisse aus dem folgenden Lernauftrag können Sie in Ihr persönliches Portfolio aufnehmen.</p><p data-block-key="d739u">Formulieren Sie je drei bis fünf persönliche Ziele …</p><ul><li data-block-key="9ske7">für den schulischen Bereich.</li><li data-block-key="71vi0">für den Bereich des Lehrbetriebs.</li></ul><p data-block-key="849i"></p><p data-block-key="6qgb7">Wenden Sie dabei Ihre Kenntnisse aus dem Studium des Sachtextes an. Tauschen Sie sich in Gruppen über Ihre Ziele aus. Wer hat gleiche oder ähnliche Ziele? Wo gibt es Unterschiede? Was möchte ich von wem noch wissen?</p>',
id: 'QXNzaWdubWVudE5vZGU6MzU=',
},
},
];
// const contents = [
// {
// type: 'text_block',
// id: 'some-other-content-component-id',
// value: {
// text: `
// <p>First, there is a paragraph</p>
// <ul>
// <li>Then, there is a list</li>
// <li>With multiple list items</li>
// </ul>
// <p>Then, there is another paragrah</p>
// `,
// },
// },
// ];
cy.mockGraphqlOps({
operations: {
...operations,
AddHighlight: getAddHighlight('InstrumentNode'),
ModuleDetailsQuery: {
module: getModule(contents),
},
AssignmentQuery: {
assignment: {
id: 'QXNzaWdubWVudE5vZGU6Mzk=',
title: 'A LF1 A13: Ziele und Vorhaben',
assignment:
'<p data-block-key="6fgwz">Ihr Produkt und Ihre Erkenntnisse aus dem folgenden Lernauftrag können Sie in Ihr persönliches Portfolio aufnehmen.</p><p data-block-key="1l7np">Notieren Sie Ihre Ziele und Vorhaben für Ihre berufliche und private Zukunft. Gestalten Sie anschliessend ein Vision Board als Plakat oder in digitaler Form.</p><p data-block-key="a0fqk">Zusätzliche Möglichkeit: Sie wählen Ziele und Vorhaben für ein gesellschaftliches Thema wie zum Beispiel Zusammenleben, Weltfrieden, Naturschutz usw.</p><p data-block-key="6kj6a">Hinweis: Im Internet finden Sie zahlreiche Anleitungen zum Erstellen eines Vision Boards. Lassen Sie sich dadurch inspirieren, doch verwenden Sie keine Vorlagen. Vertrauen Sie auf Ihre eigene Kreativität und kreieren Sie Ihr ganz persönliches Vision Board.</p>',
solution: null,
},
},
},
});
cy.visit(`/module/${moduleSlug}`);
cy.wait('@ModuleDetailsQuery');
cy.wait('@AssignmentQuery');
});
it('highlights a paragraph', () => {
markText('assignment-main-text');
const highlightedText = 'rst, there';
createHighlight(highlightedText, true);
updateHighlight(highlightedText);
addNote();
deleteHighlight();
});
it('highlights a list item', () => {
markText('assignment-main-text', 'li');
const highlightedText = 'en, there';
createHighlight(highlightedText, true);
updateHighlight(highlightedText);
addNote();
deleteHighlight();
});
it('highlights a paragraph and a list item', () => {
const highlightedText = 'rst, there';
markText('assignment-main-text', 'p');
createHighlight(highlightedText, true);
// click outside the created components to make them disappear
cy.getByDataCy('module-title').click();
const secondHighlightedText = 'en, there';
markText('text-block', 'li');
createHighlight(secondHighlightedText, true, 2);
updateHighlight(secondHighlightedText);
addNote();
deleteHighlight();
});
});
}); });

View File

@ -61,7 +61,7 @@ const findClosestAncestorWithTag = (node: Node, tags: string | string[]): HTMLEl
) { ) {
currentNode = currentNode.parentNode; currentNode = currentNode.parentNode;
} }
if (currentNode) { if (currentNode && currentNode.nodeName.toLowerCase() !== 'body') {
return currentNode as HTMLElement; return currentNode as HTMLElement;
} }
return null; return null;
@ -164,7 +164,9 @@ export const getSelectionHandler =
const startAncestor = findClosestAncestorWithTag(startContainer, ['p', 'li']); const startAncestor = findClosestAncestorWithTag(startContainer, ['p', 'li']);
// const endAncestor = findClosestAncestorWithTag(endContainer, 'p'); // const endAncestor = findClosestAncestorWithTag(endContainer, 'p');
if (!startAncestor) { if (!startAncestor) {
throw Error('This should not be happening, but there was no paragraph or list item'); // there was no ancestor found, but this can be the case when there's a subtitle or something similar
// selected
return;
} }
// should have the same tag as the start item // should have the same tag as the start item
const endAncestor = findClosestAncestorWithTag(endContainer, startAncestor.tagName.toLowerCase()); const endAncestor = findClosestAncestorWithTag(endContainer, startAncestor.tagName.toLowerCase());