是否可以使用Electron进行复制/粘贴?

时间:2017-04-24 09:48:17

标签: javascript unit-testing electron nightmare

我正在使用Electron + Nightmare.js进行单元测试。

我需要将字符串复制到clibboard>聚焦元素>粘贴内容。然后测试是关于我的JavaScript处理行为是否正常。

我在关于clipboard api的电子文档中读到,  和copy/paste in webview,但不确定如何与Nightmare.js API集成,可能在.action suggested in this issue中。

一个例子是:

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');

有任何指示或经验吗?

从我从nightmare.action获得的参数是什么等同于<webview>所以我可以调用它的复制/粘贴方法?

3 个答案:

答案 0 :(得分:5)

好的,经过几个小时才开始工作!

诀窍是使用Nightmare.js可以模拟的click事件,并使用它来触发浏览器中的复制和粘贴。

复制/粘贴逻辑是:

.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将负责触发点击,然后我们会使用自己的文字进行复制/粘贴。

我的整个测试现在就像:

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);
});

答案 1 :(得分:3)

复制/粘贴不在Electron中工作。这是因为缺少应用程序的菜单,其中包含对本机剪贴板的键绑定。您可以使用此JS代码修复此问题。

你还应该检查这个GitHub存储库 - 它是一个干净的HowTo来解决这个问题。

<强> 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));
});

答案 2 :(得分:1)

使用普通的旧JavaScript来处理按键事件。

摘要:

if (
  process.env.NODE_ENV === 'development' ||
  process.env.DEBUG_PROD === 'true'
) {
  mainWindow.webContents.on('context-menu', (e, props) => {
    const { x, y } = props;

    Menu.buildFromTemplate([
      {
        label: 'Inspect element',
        click: () => {
          mainWindow.inspectElement(x, y);
        }
      }
    ]).popup(mainWindow);
  });

  mainWindow.webContents.on('devtools-opened', () => {
    mainWindow.webContents.devToolsWebContents.executeJavaScript(`
            window.addEventListener('keydown', function (e) {
              if (e.keyCode === 88 && e.metaKey) {
                document.execCommand('cut');
              }
              else if (e.keyCode === 67 && e.metaKey) {
                document.execCommand('copy');
              }
              else if (e.keyCode === 86 && e.metaKey) {
                document.execCommand('paste');
              }
              else if (e.keyCode === 65 && e.metaKey) {
                document.execCommand('selectAll');
              }
              else if (e.keyCode === 90 && e.metaKey) {
                document.execCommand('undo');
              }
              else if (e.keyCode === 89 && e.metaKey) {
                document.execCommand('redo');
              }
            });
        `);
  });

  mainWindow.openDevTools();
}