2017-04-24 4 views
2

J'utilise Electron + Nightmare.js pour faire des tests unitaires.Est-il possible de copier/coller avec Electron?

Je dois copier une chaîne dans le clibboard> focus un élément> coller le contenu. Ensuite, le test est sur le point de savoir si mon JavaScript gère correctement son comportement.

Je lis dans les documents électroniques sur le clipboard api, et copy/paste in webview, mais ne savez pas comment cela intègre avec l'API Nightmare.js, probablement dans un .action comme suggested in this issue.

Un exemple serait:

import nightmare from 'nightmare' 
nightmare.action('copyPaste', function(name, options, parent, win, renderer, done) { 
    // some magic here 
}); 

// and then 

let res = await page 
    .wait('.my-element-to-render') 
    .copyPaste(blob) 
    .evaluate(() => { 
     return document.querySelector('.my-element').value; 
    }).end(); 
expect(res).to.equal('my pasted string'); 

Tous les pointeurs ou de l'expérience avec cela?

D'après les arguments que je reçois de nightmare.action, quel est l'équivalent de <webview> pour que je puisse appeler sa méthode copier/coller?

Répondre

0

Copier/Coller ne fonctionne pas dans Electron. Cela est dû à l'absence du menu de l'application avec les raccourcis clavier dans le presse-papiers natif. Vous pouvez corriger cela avec ce code de JS.

Vous devriez également vérifier ce référentiel GitHub - c'est une solution Comment résoudre ce problème.

codesnippet

var app = require("app"); 
var BrowserWindow = require("browser-window"); 
var Menu = require("menu"); 
var mainWindow = null; 

app.on("window-all-closed", function(){ 
    app.quit(); 
}); 

app.on("ready", function() { 
    mainWindow = new BrowserWindow({ 
     width: 980, 
     height: 650, 
     "min-width": 980, 
     "min-height": 650 
    }); 
    mainWindow.openDevTools(); 
    mainWindow.loadUrl("file://" + __dirname + "/index.html"); 
    mainWindow.on("closed", function() { 
     mainWindow = null; 
    }); 

    // Create the Application's main menu 
    var template = [{ 
     label: "Application", 
     submenu: [ 
      { label: "About Application", selector: "orderFrontStandardAboutPanel:" }, 
      { type: "separator" }, 
      { label: "Quit", accelerator: "Command+Q", click: function() { app.quit(); }} 
     ]}, { 
     label: "Edit", 
     submenu: [ 
      { label: "Undo", accelerator: "CmdOrCtrl+Z", selector: "undo:" }, 
      { label: "Redo", accelerator: "Shift+CmdOrCtrl+Z", selector: "redo:" }, 
      { type: "separator" }, 
      { label: "Cut", accelerator: "CmdOrCtrl+X", selector: "cut:" }, 
      { label: "Copy", accelerator: "CmdOrCtrl+C", selector: "copy:" }, 
      { label: "Paste", accelerator: "CmdOrCtrl+V", selector: "paste:" }, 
      { label: "Select All", accelerator: "CmdOrCtrl+A", selector: "selectAll:" } 
     ]} 
    ]; 

    Menu.setApplicationMenu(Menu.buildFromTemplate(template)); 
}); 
+0

Merci pour vérifier cela! Pourriez-vous me montrer comment cela pourrait être intégré avec nightmare.js? qu'est-ce que 'app' regarde npm je trouve un vieux module qui est parti de Github. – Sergio

+0

Géré pour le faire fonctionner réellement. Et posté une réponse. Merci encore d'avoir vérifié cela! – Sergio

+0

ne fonctionne pas pour moi 'Erreur: Impossible de trouver le module 'menu'' –

4

Ok, après de nombreuses heures obtenu ce travail!

L'astuce consiste à utiliser l'événement click que Nightmare.js peut simuler et utiliser pour déclencher le copier-coller dans le navigateur.

La copie/logique de pâte est:

.evaluate((blob) => { 
    var editor = document.querySelector('.the-element-to-paste-to'); 
    editor.innerHTML = ''; // so we have a clean paste 
    window.addEventListener('copy', function (e){ // this will fire because of "document.execCommand('copy')" 
     e.clipboardData.setData('text/html', blob); 
     e.preventDefault(); 
     return false; 
    }); 
    var mockClick = document.createElement('button'); 
    mockClick.id = 'mockClick'; 
    mockClick.addEventListener('click', function(e){ // this will fire first 
     document.execCommand("copy"); 
     editor.focus(); 
     document.execCommand('paste'); 
    }); 
    document.body.appendChild(mockClick); 
}, myTextThatIWantToPaste) 

Nightmare.js prendra soin de déclencher le clic et nous obtenons un copier/coller avec notre propre texte.

Mon test entier est maintenant comme:

it('should handle pasted test', async function() { 
    let page = visit('/index.html'); 
    let res = await page 
     .wait('.the-element-to-paste-to') 
     .evaluate((blob) => { 
      var editor = document.querySelector('.the-element-to-paste-to'); 
      editor.innerHTML = ''; // so we have a clean paste 
      window.addEventListener('copy', function (e){ 
       e.clipboardData.setData('text/html', blob); 
       e.preventDefault(); 
       return false; 
      }); 
      var mockClick = document.createElement('button'); 
      mockClick.id = 'mockClick'; 
      mockClick.addEventListener('click', function(e){ 
       document.execCommand("copy"); 
       editor.focus(); 
       document.execCommand('paste'); 
      }); 
      document.body.appendChild(mockClick); 
     }, tableBlob) 
     .click('#mockClick') // <---- this is the trigger to the click 
     .wait(100) 
     .evaluate(() => { 
      var editor = document.querySelector('.the-element-to-paste-to'); 
      return { 
       someBold: editor.querySelector('strong').innerHTML, 
       someItalic: editor.querySelector('em').innerHTML, 
       someUnderlined: editor.querySelector('u').innerHTML, 
       someRows: editor.querySelectorAll('table tr').length, 
       someColumns: editor.querySelectorAll('table tr:first-child td').length, 
      } 
     }).end(); 
    expect(res.someBold).toEqual('Col1 Row 1'); 
    expect(res.someItalic).toEqual('Col2 Row 2'); 
    expect(res.someUnderlined).toEqual('Col3 Row 3'); 
    expect(res.someRows).toEqual(3); 
    expect(res.someColumns).toEqual(3); 
});