'How to fetch copied to clipboard content in cypress

How to get the 'clipboard' content in cypress. I have a button in my web application, on click of button system will perform 'copy to clipboard' and a message will get displayed. Below is an example of the url content that is copy to clipboard ( this url content is different from web site url)

https://someurl.net/machines/0c459829-a5b1-4d4b-b3c3-18b03c1c969a/attachments/a30ceca7-198e-4d87-a550-04c97fbb9231/download

I have double check that there is no href attribute in that button tag. So I have use a plugin called clipboardy and I have added plugins/index.js file

 const clipboardy = require('clipboardy');
    module.exports = ( on ) => {
        on('task', {
            getClipboard () {
                return clipboardy.readSync();
            }
        });
    };

In my test I have used cy.task() to get the clipboard content, but this is not printing the actual url content

cy.get('td').find('div').find('span').find('button').find('i').eq(0).click().then(()=>{
          cy.task('getClipboard').then((data)=>{
          console.log("Helloooo:"+data);
      })
    })

<td class="sc-hgRTRy duUdhJ">
<div>
<span class="sc-bYwvMP jTmLTC">
<span class="sc-jzJRlG iVpVVy">
<span role="button" aria-expanded="true" aria-haspopup="true" aria-owns="5aa03785-1370-455e-a838-4154f7481a7b">
<button class="sc-feJyhm cJOKrG">
<i class="icon fas fa-link sc-htpNat cQABgO" aria-hidden="true" data-component-type="icon">
</i>
</button>
</span>
</span>
</span>
</div>
</td>

enter image description here



Solution 1:[1]

If you don't want to use clipboardy package you can also use this:

cy.window().then((win) => {
    win.navigator.clipboard.readText().then((text) => {
      expect(text).to.eq('your copied text');
    });
  });

in your case, it turns to something like

   cy.get('td').find('div').find('span').find('button').find('i').eq(0).click().then(()=>{
    cy.window().then((win) => {
      win.navigator.clipboard.readText().then((text) => {
        console.log("Helloooo:"+text);
      });
    });
   })

Solution 2:[2]

Accessing clipboard can be worked around, but the main issue is that the document.execCommand('copy') doesn't work (as stated above), which I reckon is the primary (and only?) way for your app to programmatically put a text to user's clipboard.

Assuming it happens somehow (or is fixed upstream), the checking the clipboard's contents can be done e.g. by using clipboardy:

npm i -D clipboardy

plugins/index.js:

const clipboardy = require('clipboardy');
module.exports = ( on ) => {
    on('task', {
        getClipboard () {
            return clipboardy.readSync();
        }
    });
};

In your specification:

describe('test', () => {
    it('test', () => {
        cy.document().then( doc => {
            doc.body.innerHTML = '<input id="inp">';
        });
        cy.get('#inp').type('test{selectall}');
        cy.document().then( doc => {
            doc.execCommand('copy');
        });
        cy.task('getClipboard').should('contain', 'test');
    });
});

I hope this code will be usefull for you. Thank you.

Solution 3:[3]

I have found this nice and simple solution of testing the clipboard content in Gleb Bahmutov's video Access the clipboard from Cypress test using Electron browser.

cy.window().its('navigator.clipboard')
  .invoke('readText').should('equal', 'copied text')

It uses the new Clipboard API (Chrome, FF and Opera: 2018; Safari and Edge: 2020; IE: no)

In the video, Gleb also suggets to test a case for browsers not supporting the Clipboard API, using an old (and deprecated) method of document.execCommand('copy').

It expects the page to have an input field or textarea to paste the content. Let's assume it's textarea#paste-here.

// delete navigator.clipboard to force the app to use execCommand
cy.visit('index.html', {
  onBeforeLoad(window) {
    delete window.navigator.__proto__.clipboard
  }
})
cy.document().then(document => cy.spy(document, 'execCommand').as('exec'))

/* trigger the copy action here... cy.get(...).click() */

cy.get('@exec').should('have.been.calledOnceWith', 'copy')

cy.get('#paste-here').focus()
cy.document().invoke('execCommand', 'paste')

cy.get('#paste-here').should('have.value', 'copied text')

Due to the clipboard permissions dialog, this test can be automated (CI) only in Electron browser. To make it running in Chrome, take a look at another Gleb's video Give Chrome Browser Clipboard Permissions from Cypress Test. Otherwise, you can limit the test to be run only in Electron using Test configuration object:

describe('Clipboard', {browser: 'electron'}, () => {
...

Solution 4:[4]

I managed to get the copied link by printing out the yielded value after clicking the button and then searched the object in the console in order to find the link. I found the link in [object]._vClipboard.clipboardAction.text, as you can see below:

cy.get('[data-test=copy-link-button]').click().then(($clipboard) => {
   const copiedLink = $clipboard[0]._vClipboard.clipboardAction.text;
   cy.visit(copiedLink);
});

I hope that this will help.

Solution 5:[5]

Reading this really helped me solve my own issue, I had to use a mixture from the OP and the first comment. This is what worked for me:

     cy.get(':nth-child(2) > .mat-card > .row > .col-sm-3 > .mat-focus-indicator').click().then(() => {
        cy.task('getClipboard').then(($clip) => {
             const url = $clip;
             cy.log('this is what was in clipboard', url);
             cy.visit(url);
         });
     });

This gave me the URL i wanted from the button I clicked. I then just passed that right into cy.visit to visit the url i just copied. Worked great.

Solution 6:[6]

Code at https://stackoverflow.com/a/61653634/2742007 should be adapted to call clipboardy functions supported by browsers, as commented by "opike": mind the async and read() instead of readSync().

const clipboardy = require('clipboardy');
module.exports = (on, config) => {
  on('task', {
    async getClipboard() {
      return clipboardy.read();
    }
  });
}

Solution 7:[7]

Note: Above usage of window.navigator https://stackoverflow.com/a/68871590/5667941 , only works for Electron. For Chrome user permisson would be required

User permission request

Solution 8:[8]

Try using cy.window() and you can use the navigator.clipboard as normal for pasting and copying.

it("Paste cliboard numbers", () => {
  cy.window()
    .then((win) => {
      return win.navigator.clipboard.writeText("234");
    `})`
    .then(() => {
      cy.get("[data-test=paste]").click();
      cy.get("[data-test=calc-input]").should("have.text", 234);
    });
});

Solution 9:[9]

None of the other answares worked for me so far with the cypress ui but I managedto find a solution without any additional libs or plugins by using the Cypress.Promises and the window.navigator directly ... and here it is:

cy.window().then(win =>
  new Cypress.Promise((resolve, reject) =>
    win.navigator
      .clipboard
      .readText()
      .then(resolve)
      .catch(reject))
).should('eq', '`myExpectedClipboardValue')

Solution 10:[10]

For me, none of the answers helped me taking de data from the clipboard. The next code worked:

First we will allow the access to the clipboard:

cy.window().its('navigator.permissions')
                .invoke('query', { name: 'clipboard-read' })
                .its('state').then(cy.log)

Then we access the clipboard

cy.window().its('navigator.clipboard')
                .invoke('readText')
                .then((text) => {
                    cy.log(text)
                })

Hope this works for anyone here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 marzzy
Solution 2 Reza
Solution 3
Solution 4 Realdinho
Solution 5 Daniel
Solution 6 Fred Klein
Solution 7 doktordirk
Solution 8 Weam Adel
Solution 9 Mariano
Solution 10 SrArkaitz