Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests(storybook): adding selection commands for text #313

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions packages/storybook/cypress/storybook/markdownEditorMarks.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// https://www.cypress.io/blog/2020/02/12/working-with-iframes-in-cypress/
const getIframeDocument = () =>
cy.get("#storybook-preview-iframe").its("0.contentDocument").should("exist");

const getIframeBody = () =>
getIframeDocument().its("body").should("not.be.undefined").then(cy.wrap);

describe('Marks', () => {
describe('Bold', () => {
it('should visit markdown editor', () => {
cy.visit("/");
cy.get("#markdown-editor").click();
})

it('should make paragraph text bold', () => {
getIframeBody().setSelection("#ap-rich-text-editor > p:nth-child(3)",'This','.');
})
})
})
76 changes: 76 additions & 0 deletions packages/storybook/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,79 @@
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })

Cypress.Commands.add('selection', { prevSubject: true }, (subject, fn) => {
cy.wrap(subject)
.trigger('mousedown')
.then(fn)
.trigger('mouseup');

cy.document().trigger('selectionchange');
return cy.wrap(subject);
});

Cypress.Commands.add('setSelection', { prevSubject: true }, (subject, query, endQuery) => {
return cy.wrap(subject)
.selection($el => {
Comment on lines +27 to +39
Copy link
Contributor Author

@Cronus1007 Cronus1007 Apr 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@irmerk Yes you are on the right path.Here the $el should identify the text as node although I have wrapped a node here in selection custom command.But still it is taking up the text rather than the element.
Here I want to refer to this as well since Slate follows nested and recursive structure but still it is unable to capture node.A problem may be there in selection Custom Command.
Plus @sanketshevkar PR #311 would also fail until we found a way to select the text.

Copy link
Member

@sanketshevkar sanketshevkar Apr 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#311 does not require the text to be selected, its about placing the cursor in a para and then changing the headings.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm not following after all. Why do we need these custom commands when Slate has built in functions for this?

Copy link
Contributor Author

@Cronus1007 Cronus1007 Apr 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@irmerk I guess you are not on the right track.Since slate has no connection with the selection of text.The Cypress automates that work which a user has to do.The selection of text must be done by Cypress.

if (typeof query === 'string') {
const anchorNode = getTextNode($el, query);
const focusNode = endQuery ? getTextNode($el, endQuery) : anchorNode;
const anchorOffset = anchorNode.wholeText.indexOf(query);
const focusOffset = endQuery ?
focusNode.wholeText.indexOf(endQuery) + endQuery.length :
anchorOffset + query.length;
setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
} else if (typeof query === 'object') {
const el = $el[0];
const anchorNode = getTextNode(el.querySelector(query.anchorQuery));
const anchorOffset = query.anchorOffset || 0;
const focusNode = query.focusQuery ? getTextNode(el.querySelector(query.focusQuery)) : anchorNode;
const focusOffset = query.focusOffset || 0;
setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset);
}
});
});

// Low level command reused by `setCursorBefore` and `setCursorAfter`, equal to `setCursorAfter`
Cypress.Commands.add('setCursor', { prevSubject: true }, (subject, query, atStart) => {
return cy.wrap(subject)
.selection($el => {
const node = getTextNode($el[0], query);
const offset = node.wholeText.indexOf(query) + (atStart ? 0 : query.length);
const document = node.ownerDocument;
document.getSelection().removeAllRanges();
document.getSelection().collapse(node, offset);
})
// Depending on what you're testing, you may need to chain a `.click()` here to ensure
// further commands are picked up by whatever you're testing (this was required for Slate, for example).
});

Cypress.Commands.add('setCursorBefore', { prevSubject: true }, (subject, query) => {
cy.wrap(subject).setCursor(query, true);
});

Cypress.Commands.add('setCursorAfter', { prevSubject: true }, (subject, query) => {
cy.wrap(subject).setCursor(query);
});

// Helper functions
function getTextNode(el, match){
const walk = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, null, false);
if (!match) {
return walk.nextNode();
}

const nodes = [];
let node;
while(node = walk.nextNode()) {
if (node.wholeText.includes(match)) {
return node;
}
}
}

function setBaseAndExtent(...args) {
const document = args[0].ownerDocument;
document.getSelection().removeAllRanges();
document.getSelection().setBaseAndExtent(...args);
}