Hi there,
I'm curious as to why a document.execCommand("copy")
fails when being run during a cypress test (as a side effect to a cy.get().click()
). Curiously it works fine once I'm manually clicking the same element after the test has run.
The failing test in question can be reproduced by running the following code:
describe("menuBar", function() {
beforeEach(() => {
cy.visit("http://teselagen.github.io/openVectorEditor/#/Editor");
});
it("select range, copy, cut works", function() {
cy.clock()
cy.get('.tg-menu-bar').contains("Edit").click()
cy.get('.tg-menu-bar-popover').contains("Select").click()
cy.get(`[label="From:"]`).clear().type("10")
cy.get(`[label="To:"]`).clear().type("20")
cy.get(`.dialog-buttons`).contains("OK").click()
cy.get(".veStatusBar").contains(`10 to 20`)
cy.get(".veStatusBar").contains(`5299`)
cy.get('.tg-menu-bar').contains("Edit").click().tick(200)
cy.get('.tg-menu-bar-popover').contains("Copy").click()
cy.contains("Selection Copied")
cy.get('.tg-menu-bar').contains("Edit").click()
cy.get('.tg-menu-bar-popover').contains("Cut").click()
cy.contains("Selection Cut")
cy.get(".veStatusBar").contains(`5288`)
});
});
If you run the above example, the test will fail to find "Selection Copied". This is because
const worked = document.execCommand(type);
evaluates to false
so the "Selection Copied" popover is not shown.
You can add a breakpoint manually to the commands/index.js
file and see it not working.
Strangely, after the test has run if you manually click "File > Edit > Copy" then the document.execCommand("copy")
works just fine. Not sure what is going on here to stop it from working when cypress is running its tests.
Thanks!
I thought this piece of info from MDN docs looks interesting concerning the return value of document.execCommand()
Note: Only returns
true
if part of a user interaction. Don't try using the return value to verify browser support before calling a command.
Since Cypress programmatically triggers the 'click' event, the document.execCommand()
will always return true in this case. This looks like another reason we are implementing native events. https://github.com/cypress-io/cypress/issues/311
@jennifer-shehane so in the future I should be able to do cy.get().click({native:true}) to have the test pass as expected? Is there an expected date the native
events feature will land?
Thanks!
@tnrich Keep up with the checklist in the main comment of the https://github.com/cypress-io/cypress/issues/311 thread - it is being kept up to date.
@tnrich can you see if passing a true/false value to the showDefaultUI (second arg) of document.execCommand
makes a difference?
document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)
@Bkucera passing true/false as the second arg doesn't seem to have any effect on the copy command getting triggered from the cypress click.
@jennifer-shehane is correct, the copy command can only happen in response to a _trusted_ user event, which can only be done with native events.
I'll add this to the native events issue
Related to
@jennifer-shehane Any news on copy/pasting feature in Cypress?
@jennifer-shehane we're also looking for an update on this. Thanks
agreed with @bhellema really hoping this eventually will work. I might be able to offer some help. The biggest barrier that I can see is how cypress sends key combinations(not sure how it works). I came from webdriver.io background so there is .keys cmd there. But I didn't have any luck with cmd-c, cmd-v via that tool. Therefore I'm looking into cypress now. I know an npm module that could copy paste the content from current clipboard: https://www.npmjs.com/package/copy-paste maybe we can incorporate that into cypress. I only have experience using the paste functionality of it. maybe I can look into copy more now.
@xcao-riffyn copying to/from clipboard in cypress isn't a problem. This issue is about document.execCommand("copy")
not working and using a lib to manipulate OS clipboard isn't gonna solve it because we need to test AUT behavior --- our app itself uses document.execCommand("copy")
so that's why we need to make that DOM command work properly.
There is a way we can make this testable. We can overwrite document.execCommand
and store the copied text in a "fake" clipboard object that exists during the lifetime of the test. That way you could do something like:
cy.get('button').click().then(()=>{
expect(cy.clipboard()).to.contain('sometext')
})
This is just one possible version of the API. I would appreciate feedback
@Bkucera problem with mocking is you won't know if document.execCommand
will succeed in real conditions. As an interim solution, sounds good.
@dwelle I believe we can check the stack for a cypress click command, using rules that mimic the rules that the browser follows for user interaction. So when execCommand is called we can return true/false and push to clipboard conditionally
Is there any update on this?
@Bkucera ship it! I'd love to use your suggested
cy.get('button').click().then(()=>{
expect(cy.clipboard()).to.contain('sometext')
})
any update on this?
This issue is still in the 'ready for work' stage, which means no work has been done on this issue as of today, so we do not have an estimate on when this will be delivered.
Most helpful comment
@Bkucera ship it! I'd love to use your suggested