Coder Social home page Coder Social logo

electron-userland / spectron Goto Github PK

View Code? Open in Web Editor NEW
1.7K 50.0 229.0 3.19 MB

DEPRECATED: ๐Ÿ”Ž Test Electron apps using ChromeDriver

Home Page: http://electronjs.org/spectron

License: MIT License

JavaScript 99.85% Batchfile 0.15%
spectron chromedriver electron

spectron's People

Contributors

adrianoferrari avatar avivahl avatar codebytere avatar darxriggs avatar dependabot-preview[bot] avatar durran avatar etiennejcharles avatar kevinsawicki avatar magne4000 avatar malept avatar marshallofsound avatar mceachen avatar michelkaporin avatar mquevill avatar mtgto avatar nic-bor avatar npezza93 avatar rhysd avatar russellbradley avatar scottrippey avatar sindresorhus avatar teameh avatar timfish avatar toromyx avatar vanessayuenn avatar vertedinde avatar vhashimotoo avatar wenjunche avatar yuya-oc avatar zeke avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spectron's Issues

Basic Test doesn't work

Hi,

I am trying to get a basic test working as per the documentation. I've copied/pasted from the README and adjusted my path to point to the Electron executable but I get a test failure. Here's my test code:

/**
 * Created by Clifton Craig on 4/30/16.
 */
describe('Initial spec', function () {
    it('Should be easy to test.');
});

var Application = require('spectron').Application;
var assert = require('assert');

describe('application launch', function () {
    this.timeout(10000);

    beforeEach(function () {
        this.app = new Application({
            path: '/Applications/Electron.app/Contents/MacOS/Electron'
        });
        return this.app.start()
    });

    afterEach(function () {
        if (this.app && this.app.isRunning()) {
            return this.app.stop()
        }
    });

    it('shows an initial window', function () {
        return this.app.client.getWindowCount().then(function (count) {
            assert.equal(count, 1)
        })
    })
});

And here's the output:

SFO1212474815A:nightmare 212474815$ npm test

> [email protected] test /Users/212474815/dev/nightmare
> mocha



  Initial spec
    - Should be easy to test.

  application launch
    1) "before each" hook for "shows an initial window"


  0 passing (5s)
  1 pending
  1 failing

  1) application launch "before each" hook for "shows an initial window":
     Error: ChromeDriver did not start within 5000ms
      at Error (native)
      at node_modules/spectron/lib/chrome-driver.js:58:25
      at Request._callback (node_modules/spectron/lib/chrome-driver.js:116:45)
      at Request.self.callback (node_modules/request/request.js:200:22)
      at Request.<anonymous> (node_modules/request/request.js:1067:10)
      at IncomingMessage.<anonymous> (node_modules/request/request.js:988:12)
      at endReadableNT (_stream_readable.js:905:12)



npm ERR! Test failed.  See above for more details.

Is there something I've missed from the documentation? Do I need to start ChromeDriver separately? I've never used ChromeDrive or WebDriver before. This is my 1st take at automated Electron testing. Thanks for any/all clarification!

Help getting started

I'm trying to use spectron with mocha. In my beforeEach, I have:
this.app = new Application({path: "bin/package/pluginContainer.html"});
return this.appstart();
This times out after 2000ms. What am I doing wrong? Am I passing the wrong path to Application? I didn't see a description anywhere of what that path is supposed to point to.

Thanks,
-Josh

Setting debuggerAddress

Hello

Is it possible to set chromeOptions.debuggerAddress ? We need to launch our app outside of ChromeDriver so we can set custom Chromium command options.

Thanks for the great tool

Possibility to configure require name

Hello,

I'm currently trying to make use of spectron for my angular2 app. My index.html contains the following lines:

    window.electronRequire = require;
    delete window.require;
    delete window.exports;
    delete window.module;

This is needed because some of the code I load otherwise hook these symbols and that messes with the code loading. However, api.js seems to fail because the require symbol is deleted. Manually patching up api.js to use electronRequire makes things work fine, but this is obviously less than ideal

Any suggestions for dealing with this?

The app.stop() do not fail when the electron app canceled the quit with a beforeunload

If the electron app has a beforeunload that cancel the app quit like this

// index.html
window.onbeforeunload = function(e) {
  console.log('app quit canceled')
  return false
};

Then try to close the spectron app

// test.js
if (this.app && this.app.isRunning()) {
    return this.app.stop().then(function() {
        console.log('stopped')
    })
}

The output is "stopped" even if app is still running.
The expected behaviour is the this.app.stop() promise rejects

Electron 1.1.1
Spectron 3.1.1

Test on Windows

Might need to iron out a few things regarding the wrapper script

Cannot take screenshot

The saveScreenshot throw this error

RuntimeError: unknown error: cannot get automation extension from unknown error: page could not be found: chrome-extension://aapnijgdinlhnhlmodcfapnahmbfebeb/_generated_background_page.html

Spectron v.3.2.4
Electron v.1.2.5

app.browserWindow is not available when node integration is set to false

FYI to others that might hit on this issue, when note integration is set to false, like this:

app.on('ready', function () {
    mainWindow = new BrowserWindow({
        show      : false,
        x         : 1200,
        y         : -1000,
        width     : 500,
        height    : 400,
        webPreferences: {
            nodeIntegration: false }
    })

the app.browserWindow will not be available

I'm sure there is a good reason for that , but it caught me off guard and I spent a couple hours trying to figure out why my tests were failing and the browserWindow wasn't set

How to access Electron logs

I can't seem to access any logs from neither the browser process nor the render processes. Any ideas on how to do this?

Selenium has a /session/:sessionId/log and /session/:sessionId/log/types endpoint that I'm successfully able to access via the webdriver client.log() and client.logTypes() APIs. logTypes resolves to an array with ['browser', 'driver'].

Unfortunately, the value of the logs coming out of the browser type is always empty. I can see that the app boots, and I can open the inspector console and see logs and enter more console.log commands, but nothing ever comes back when you request the logs via client.log.

this.app.start().then(()=> {
  this.app.client.log("browser").then(({value}) => {
     console.log(value) // Always an empty []
  })
})

I've also tried putting that log polling function on an interval thinking that it wouldn't return anything until the app fully booted. It never returns any data.

On the flip side, polling app.client.log("driver") returns all of the Selenium driver log data properly.

Looking for help running spectron inside a Docker container

So I'm trying to get Spectron running headlessly inside a docker container using xvfb and it doesn't start Electron no matter what I try to do.

This is my docker file

FROM node:6.3

RUN apt-get update
RUN apt-get install g++-multilib lib32z1 lib32ncurses5 -y
RUN apt-get install rpm fakeroot dpkg libdbus-1-dev libx11-dev -y
RUN apt-get install libavahi-compat-libdnssd-dev g++ -y
RUN apt-get install gcc-4.8-multilib g++-4.8-multilib -y
RUN apt-get install libgtk2.0-0 libgtk2.0-dev xvfb -y
RUN apt-get install libxtst6 -y

WORKDIR /app

COPY package.json /app
RUN npm install

RUN apt-get install libxss1 libnss3 libasound2 libgconf-2-4 -y

RUN export ELECTRON_ENABLE_STACK_DUMPING=true
RUN export ELECTRON_ENABLE_LOGGING=true

ADD vendor/docker-entrypoint.sh /entrypoint.sh
RUN chmod 777 /entrypoint.sh
ENTRYPOINT ["/bin/sh", "/entrypoint.sh"]

COPY . /app

And this is my entrypoint.sh

#!/bin/bash

echo "Starting Xvfb"
Xvfb :99 -ac &
sleep 2

export DISPLAY=:99
echo "Executing command $@"

exec "$@"

This exact config works for electron-mocha which also launches electron processes so I can't tell why Electron isn't starting in this container. If I launch the container interactively I can launch the electron process and get logs indicating it is running successfully. Is there some dependency I am missing for the chromedriver or something?

Examples recommend using chaiAsPromised but it has problems with some promises.

chaiAsPromised doesn't properly handle rejections, and constantly reports true for some spectron methods when using some Promised methods. For example:

it("should be true", function() {
  let val = this.app.electron.remote.getGlobal("appConfig").then(v => { return v.val })
  assert.eventually.equal(
    val, true
  )
})

Always returns true for us, and never actually causes an assertion failure because there was a rejection with the object having an error. We could catch it, but then what is the point of chaiAsPromised at that point?


I propose the documentation also recommend a better way to deal with promises if they are using ES7.

it("should be true", async function() {
  let config = await this.app.electron.remote.getGlobal("appConfig")
  assert.equal(
    config.val, true
  )
})

If this is acceptable, I'm happy to send a pull request.

Getting userData path

How can you get the userData path that's available in electron via

app.getPath('userData')

Hangs on start with "DevTools request failed"

Ubuntu 14.04
Node.js 6.0.0
spectron 3.2.3
electron-prebuilt 1.2.2

Test file:

// test.js
var Application = require('spectron').Application;

const app = new Application({
  path: __dirname + '/app.js',
  chromeDriverLogPath: __dirname + '/chrome-driver.log'
});

app.start()
  .then(function() {
    console.log('started');
  })
  .catch((err) => {
    console.log(err);
  });

And binary I am passing to application as path, this is a JS file with "executable" permissions:

// app.js
var electron = require('electron');

electron.app.on('ready', function() {
  var window = new electron.BrowserWindow({
    width: 800,
    height: 600
  });
  window.loadURL('https://github.com');
});

When I run $ node test.js it just hangs, no any output in terminal.
After adding chromeDriverLogPath I've noticed that it infinitely tries to connect to DevTools, but fails. Here is the contents of chrome-driver.log:

// chrome-driver.log

[0.205][INFO]: COMMAND InitSession {
   "desiredCapabilities": {
      "browserName": "electron",
      "chromeOptions": {
         "args": [ "spectron-path=/var/www/github/hanshot/test/int-spectron/app.js" ],
         "binary": "/var/www/github/hanshot/node_modules/spectron/lib/launcher.js"
      },
      "handlesAlerts": true,
      "javascriptEnabled": true,
      "locationContextEnabled": true,
      "loggingPrefs": {
         "browser": "ALL",
         "driver": "ALL"
      },
      "requestOrigins": {
         "name": "webdriverio",
         "url": "http://webdriver.io",
         "version": "4.0.9"
      },
      "rotatable": true
   }
}
[0.205][INFO]: Populating Preferences file: {
   "alternate_error_pages": {
      "enabled": false
   },
   "autofill": {
      "enabled": false
   },
   "browser": {
      "check_default_browser": false
   },
   "distribution": {
      "import_bookmarks": false,
      "import_history": false,
      "import_search_engine": false,
      "make_chrome_default_for_user": false,
      "show_welcome_page": false,
      "skip_first_run_ui": true
   },
   "dns_prefetching": {
      "enabled": false
   },
   "profile": {
      "content_settings": {
         "pattern_pairs": {
            "https://*,*": {
               "media-stream": {
                  "audio": "Default",
                  "video": "Default"
               }
            }
         }
      },
      "default_content_setting_values": {
         "geolocation": 1
      },
      "default_content_settings": {
         "geolocation": 1,
         "mouselock": 1,
         "notifications": 1,
         "popups": 1,
         "ppapi-broker": 1
      },
      "password_manager_enabled": false
   },
   "safebrowsing": {
      "enabled": false
   },
   "search": {
      "suggest_enabled": false
   },
   "translate": {
      "enabled": false
   }
}
[0.205][INFO]: Populating Local State file: {
   "background_mode": {
      "enabled": false
   },
   "ssl": {
      "rev_checking": {
         "enabled": false
      }
   }
}
[0.206][INFO]: Launching chrome: /var/www/github/hanshot/node_modules/spectron/lib/launcher.js 
--disable-background-networking --disable-client-side-phishing-detection 
--disable-component-update --disable-default-apps --disable-hang-monitor 
--disable-popup-blocking --disable-prompt-on-repost --disable-sync --disable-web-resources 
--enable-logging --ignore-certificate-errors 
--load-extension=/tmp/.org.chromium.Chromium.mdUELY/internal --log-level=0 
--metrics-recording-only --no-first-run --password-store=basic 
--remote-debugging-port=12902 --safebrowsing-disable-auto-update 
--safebrowsing-disable-download-protection 
--spectron-path=/var/www/github/hanshot/test/int-spectron/app.js --test-type=webdriver 
--use-mock-keychain --user-data-dir=/tmp/.org.chromium.Chromium.KjuOCY data:,
[0.206][DEBUG]: DevTools request: http://localhost:12902/json/version
[0.246][DEBUG]: DevTools request failed
[0.296][DEBUG]: DevTools request: http://localhost:12902/json/version
[0.297][DEBUG]: DevTools request failed
[0.347][DEBUG]: DevTools request: http://localhost:12902/json/version
[0.347][DEBUG]: DevTools request failed
[0.397][DEBUG]: DevTools request: http://localhost:12902/json/version
[0.397][DEBUG]: DevTools request failed
[0.448][DEBUG]: DevTools request: http://localhost:12902/json/version
[0.448][DEBUG]: DevTools request failed
[0.498][DEBUG]: DevTools request: http://localhost:12902/json/version
[0.498][DEBUG]: DevTools request failed
[0.549][DEBUG]: DevTools request: http://localhost:12902/json/version
[0.549][DEBUG]: DevTools request failed
[0.599][DEBUG]: DevTools request: http://localhost:12902/json/version
[0.600][DEBUG]: DevTools request failed
[0.650][DEBUG]: DevTools request: http://localhost:12902/json/version
[0.650][DEBUG]: DevTools request failed
[0.700][DEBUG]: DevTools request: http://localhost:12902/json/version
[0.701][DEBUG]: DevTools request failed
[0.751][DEBUG]: DevTools request: http://localhost:12902/json/version
[0.751][DEBUG]: DevTools request failed
[0.801][DEBUG]: DevTools request: http://localhost:12902/json/version
[0.802][DEBUG]: DevTools request failed
[0.852][DEBUG]: DevTools request: http://localhost:12902/json/version
[0.852][DEBUG]: DevTools request failed
[0.903][DEBUG]: DevTools request: http://localhost:12902/json/version
[0.903][DEBUG]: DevTools request failed
[0.953][DEBUG]: DevTools request: http://localhost:12902/json/version
[0.953][DEBUG]: DevTools request failed
[1.003][DEBUG]: DevTools request: http://localhost:12902/json/version
[1.004][DEBUG]: DevTools request failed
[1.054][DEBUG]: DevTools request: http://localhost:12902/json/version
[1.054][DEBUG]: DevTools request failed
[1.104][DEBUG]: DevTools request: http://localhost:12902/json/version
[1.104][DEBUG]: DevTools request failed
[1.155][DEBUG]: DevTools request: http://localhost:12902/json/version
[1.155][DEBUG]: DevTools request failed
[1.205][DEBUG]: DevTools request: http://localhost:12902/json/version
[1.205][DEBUG]: DevTools request failed
[1.256][DEBUG]: DevTools request: http://localhost:12902/json/version
[1.256][DEBUG]: DevTools request failed
[1.306][DEBUG]: DevTools request: http://localhost:12902/json/version
[1.307][DEBUG]: DevTools request failed
...

Even though there are some bugs with same message in the web, I was not able to find any information what might cause this issue. I can only see that Chrome instance is started with flag --remote-debugging-port=12902, but I never set it.

Is it because of chrome-driver?
Seems like it was updated to 2.22 recently https://sites.google.com/a/chromium.org/chromedriver/ to support Chrome 49-52 and as I can see latest electron uses Chrome 51 and Spectron uses chrome-driver 2.21.

Thanks!

Help with WDIO Testrunner and Spectron

I am adapting an existing test suite (using mocha and chai/chai as promised) using WDIO Testrunner to use an electron version of the app the tests were originally written for. The example in the documentation of a test with chai as promised does not use a test runner file, just a standalone test, nor can I find an example of WDIO Testrunner being used elsewhere in the documentation. Is it possible to use WDIO Testrunner in conjunction with Spectron? When I try to configure the testrunner file to use the electron app instead of chrome (via chromeOptions: {binary: 'path'}), the app launches, but all tests timeout and fail.

The documentation indicates that Spectron exposes the client property of an Application instance. The current set of tests I have use the browser global object. How are these two objects related, and is there some straight-forward way of converting these objects? There also does not seem to be a clear cut way of exposing the client property from the test runner file itself, is this correct?

From a maintainability perspective, it would be really beneficial if I could simply write a different Testrunner file specific to the electron app that utilises the same underlying test files as the web app. Is this possible?

Here's my Testrunner file and an example of the tests I am trying to run:

wdio.conf.js

exports.config = {
    host: 'localhost',
    port: '4444',
    path: '/wd/hub',
    specs: [
        './ui/*.js'
    ],
    maxInstances: 1,
    capabilities: [{
        browserName: 'chrome',
        chromeOptions: {
        //  binary: 'path/to/electron/app' 
        }
    }],
    logLevel: 'silent',
    sync: false,
    coloredLogs: true,
    screenshotPath: './errorShots/',
    baseUrl: 'http://localhost:3000',
    waitforTimeout: 19500,
    framework: 'mocha',
    mochaOpts: {
      timeout: 20000
    },
    reporters: ['dot'],
    reporterOptions: {
      outputDir: './logs/'
    },    
    before: function() {
        var chai = require('../service/node_modules/chai/chai');
        var chaiAsPromised = require('../service/node_modules/chai-as-promised');
        expect = chai.expect;
        chai.Should();
        chai.use(chaiAsPromised);
        chaiAsPromised.transferPromiseness = browser.transferPromiseness;
        //File specifying ui actions -- defines custom commands
        require('./framework/app_extensions.js');
    }
};

Example test

describe("Menu tests", function() {
  console.log('\nMenu Tests:')
  // check Menu visibility
  describe("Menu visibility", function() {
    it("should be visible", function() {
      return browser
        .openApp() // contained in app_extensions.js
        .isVisible('.menu').should.eventually.be.true
        .isVisible('#dropdownModelsMenu').should.eventually.be.true;
    });
  });
  // check Model submenu
  describe("Models Menu", function(){
    var modelsMenuId = "#dropdownModelsMenu";
    var modelsSubMenu = ["#open-model", "#import-model", "#save-project", "#export-model", "#delete-project"];

    it("should open the submenu", function() {
      return browser
        .openApp()
        .waitForEnabled(modelsMenuId)
        .click(modelsMenuId)
        .waitForVisible(modelsSubMenu[0])
        .isVisible(modelsSubMenu[0]).should.eventually.be.true
        .isVisible(modelsSubMenu[1]).should.eventually.be.true
        .isVisible(modelsSubMenu[2]).should.eventually.be.true
        .isVisible(modelsSubMenu[3]).should.eventually.be.true
        .isVisible(modelsSubMenu[4]).should.eventually.be.true;
    });

    it("should disable submenu options when model not loaded", function() {
      return browser
        .openApp()
        .waitForEnabled(modelsMenuId)
        .click(modelsMenuId)
        .getAttribute(modelsSubMenu[2], 'class').should.eventually.contain('disabled')
        .getAttribute(modelsSubMenu[3], 'class').should.eventually.contain('disabled')
        .getAttribute(modelsSubMenu[4], 'class').should.eventually.contain('disabled');
    });
  });
});

I have been looking into this over the past few days haven't met much with success. Any help would be greatly appreciated. Thanks.

Start fails when using remote-debugging-port cmd line switch

@kevinsawicki thanks for working on this. It's awesome to directly test with electron app, Adding below lines to electron default app, is sufficient to reproduce this, thought of adding this as issue, in turn might help someone save time.

Ex : 
var app = require('app');
app.commandLine.appendSwitch('remote-debugging-port', '9222');

Add option to run tests on a hidden window (or innactive)

I find that when writing these type of UI tests, it makes a massive difference for the dev environment to hide the image so that it doesn't show in the screen and interrupt the dev's workflow (since the eyes are drawn to the newly created window).

There is also the .showInactive() which can be used to show the window but not give it focus. This means that we can continue to type the test as it executes (which is what happens when WallabyJS is used, see #35)

getGlobal returns basic object rather than class instance.

When we create our browser window we also initialize a Configuration object which is stored in the global and gotten again via getGlobal so that we don't have to constantly initialize. In Electron this works out great because we can do global.appConfig = new Config(app) and then pull it out with getGlobal later and store it for the entire browser to have access to.

However, spectron only returns the values that are initialized upon class creation and none of the getters, setters or other methods that are defined on the class. A basic example:

class Hello {
  constructor() {
    this.valueOne = "works"
    this.valueTwo = "works"
  }

  get world() {
    return "DoesntWork"
  }
}

global.appConfig = new Hello()
import { Application } from "spectron"
import { assert } from "chai"

describe("hello.js", function() {
  before(function() {
    this.app = new Application({
      path: "./node_modules/.bin/electron",
      chromeDriverLogPath: "./chrome.driver.log",
      args: ["./app/entry.js"]
    })

    return this.app.start(
      //
    )
  })

  after(function() {
    if (this.app && this.app.isRunning()) {
      this.app.stop(
        //
      )
    }
  })

  describe("#world", function() {
    it("should be a function", async function() {
      let config = await this.app.electron.remote.getGlobal("appConfig")
      assert.isFunction(config.world)
    })
  })
})

This ultimately fails because world is not even defined for some reason when getGlobal gets it, however... valueOne and valueTwo are there and ready to be tested/used.

Error when running demo - "self.client.init if not a function"

I'm trying to run the basic demo and am receiving this error
image

I tracked it to here where the self.client.init(). value is not defined (in https://github.com/electron/spectron/blob/db2d66733dbd79c3d8aeed5427e591ac579a89fc/lib/application.js#L153)

image

It is caused by the fact that the object returned from https://github.com/electron/spectron/blob/db2d66733dbd79c3d8aeed5427e591ac579a89fc/lib/application.js#L141 does not have an ```.init() function

Here is the code (which is based on the main example):

electron_Prebuild = require('electron-prebuilt')

electronPath = '/Users/diniscruz/GitHub_REPOS/BSIMM-Graphs/node_modules/electron-prebuilt/dist/Electron.app/Contents/MacOS/Electron'
appPath      = '/Users/diniscruz/GitHub_REPOS/BSIMM-Graphs/test-spectron/electron-apps/web-view'

var Application = require('spectron').Application
var assert = require('assert')

describe('application launch 2', function () {
    this.timeout(10000)

    beforeEach(function () {
        this.app = new Application({
            path: electronPath,
            args: [appPath]
        })
        return this.app.start()
    })

    afterEach(function () {
        if (this.app && this.app.isRunning()) {
            return this.app.stop()
        }
    })

    it('shows an initial window', function () {
        return this.app.client.getWindowCount().then(function (count) {
            assert.equal(count, 1)
        })
    })
})

Keep electron instance opened between tests

What is a good way to run multiple tests using the same electron window?

The test examples I have seen, tend to show the use of beforeEach and afterEach to start and stop the electron instance, but this has a 2 sec penalty per test

For example note how in the tests bellow the 'check Html' and 'check title' tool 2sec each

image

Ideally I would like to keep an instance of Electron opened which I can then use on demand to load pages in the browser window (or to create new ones).

And yes I know that there are cases where we want to have a pristine browser session, but in most browser automation cases that is not really needed

getWindowWidth and getWindowHeight have null response.value when using the Tape test framework

I've been playing around using spectron (-v 0.34.0) with tape (-v 4.2.2) and am running into difficulty using the getWindowWidth and getWindowHeight commands.

Here's the test I'm running:

    this.app.client.getWindowHeight().then(function(height) {
        t.equal(height, 600)
    })

It appears that the getWindowDimensions execution is passing a null response.value to getResponseValue.

{ sessionId: 'abe9c8387e2d12ea86fb59dfb4faebe7',
  status: 0,
  value: null }

An equivalent test using mocha and assert run without problems.

Note, using the getWindowDimensions command runs fine as such:

   this.app.client.getWindowDimensions().then(function(dimensions) {
        t.equal(dimensions.height, 600)
        t.equal(dimensions.width, 900)
    })

Any ideas?

electron.remote.require returns empty object

I'm trying to remote require a module from renderer process, the module itself is from the main process.

However it seems app.electron.remote.require('./main_proc_module') returns a promise that resolves to an empty object.

Can I use remote require with spectron?

Testing menu interaction

Love the framework! ๐Ÿ‘

Is there any way currently to test menu item functionality through spectron? I could test the code itself but that doesn't take into account menu item states like enabled and visible.

If not, is there a suggested strategy for testing menu items?

Thanks!

Add mocha example to main spectron page

Since Spectron is a framework to help with testing, then it would make sense to show a test on its main page :)

Namely at http://electron.atom.io/spectron/ where the example shown is:

image

Since we already have one on the README.md that would be a good one to use

image

If you are ok with this idea, I'm happy to send a PR (if you can point me to the code that is used at http://electron.atom.io/spectron/ )

Note: I usually tell devs to resist the temptation to experiment with APIs using simple apps. It is much better to write tests (which leave behind the learning path). For example see https://gist.github.com/DinisCruz/060b427139bc2dd747a214d77dd1f970 which shows the tests I did when understanding @wallabyjs Electron support

Remote BrowserWindow APIs with callback don't work

Hi, I'm considering to take a screenshot of app when test failed. I found BrowserWindow's capturePage method but it doesn't work from Spectron as below.

Repro

1. $ npm install spectron electron-prebuilt

2. $ node below-code.js

'use strict';
const Application = require('spectron').Application;
const electron = require('electron-prebuilt');

const app = new Application({path: electron});
app.start();

// Wait for app starting
setTimeout(() => {
    console.log('start');
    app.browserWindow
        .capturePage(img => {
            console.log(img);
            const fs = require('fs');
            fs.writeFile('screenshot.png', img.toPng());
        })
        .then(result => {
            console.log('RESULT:', result);
            app.stop();
        });
}, 3000);

3. screenshot.png is not generated and final log is not output

Environment

  • Spectron 3.1.0
  • Electron 1.1.3
  • OS X 10.11.4 (MacBook Pro)

Element could not be located

I am trying to find an element on the page with waitUntilTextExists, but it cannot be found. Not sure if this is the right place, but I've decided to open up an issue in case somebody spots anything wrong with what I am doing:

return myApp.client.waitForVisible('.btn-add').then(function(text) {
   console.log(text);
});

Code here and this is the element I am trying to find: .btn-add.

I have tried different ways, including one similar to the example here, but none of them worked. I've captured the full error with catch: An element could not be located on the page using the given search parameters.

Perhaps this belongs on the webdriver project?

Can't interact with webview

This is an issue and a request for help.

My app mostly relies on webviews for partitioning out 'plugins' that hold most of the app's functionality. I can't do anything with Webdriver to test these plugins besides sending and listening through ipc. Even when adding an ipc listener on the renderer through client.execute, I can't retrieve the value obtained by said listener. See below, especially the 6th to last line.

// Libraries required for testing
const Application = require('spectron').Application;
const Chai = require('chai');
const ChaiAsPromised = require('chai-as-promised');
const Path = require('path');
const Crypto = require('crypto');

// Chai's should syntax is executed to edit Object to have Object.should
var should = Chai.should();
// Chai's should syntax is extended to deal well with Promises
Chai.use(ChaiAsPromised);

describe('renderer process', function() {
    var app;
    var client;

    // Starts a new session and assigns spectron's Application instance to a
    // variable, app, available to all tests
    before('start electron', function() {
        app = new Application({
            path: Path.join(__dirname, '../node_modules/.bin/electron'),
            args: [Path.join(__dirname, '..')],
        });
        return app.start();
    });

    // Extends ChaiAsPromised's syntax with spectron's electron-specific
    // functions and assigns spectron's WebDriverIO properties to a variable,
    // client, available to all tests
    before('transfer spectron methods', function() {
        client = app.client;
        ChaiAsPromised.transferPromiseness = client.transferPromiseness;
    });

    // Close session after each test-suite
    after('stop electron', function() {
        if (app && app.isRunning()) {
            return app.stop();
        }
    });

    // Test basic startup properties
    describe('plugin', function() {
        // Helper to have the UI add an IPC listener
        function addIPCListener(channel, response) {
            client.execute(function(c, r) {
                IPCRenderer.on(channel, response);
            }, channel, response);
        }

        // Helper to have a plugin add an IPC listener
        function addPluginIPCListener(name, channel, response) {
            client.execute(function(n, c, r) {
                Plugins[n].execute('IPC.on(' + c + ', ' + r.toString());
            }, name, channel, response);
        }

        // Helper to send an IPC message to a plugin
        function sendPluginIPC(name, channel, args) {
            args.unshift(channel);
            client.execute(function(n, a) {
                Plugins[n].sendToView.apply(this, a);
            }, name, args);
        }

        // Helper to get a variable's value from the plugin via IPC
        function getPluginVariable(name, varName) {
            // Generate one-off IPC channel to transfer variable across on both ways
            var channel = Crypto.randomBytes(20).toString('hex');
            addPluginIPCListener(name, channel, function() {
                IPCRenderer.sendToHost(channel, varName);
            });
            addIPCListener(channel, function(event, varValue) {
// Is there anything I can do here to send a variable or value back to the Webdriver?
            });
            sendPluginIPC(name, channel, varName);
        }
    });
});

Sorry this is a long post, but I think the dilemma makes itself clear. Any ideas?

Sample app

I would like to unit testing my electron into headless (on remote server). There's a sample app somewhere to see how to write a basic test from a sample application ? Spectron looks good for that but I cant figure how to apply this to a project.

unknown error: window[requireName] is not a function

Hey,
I am trying to check the title of my second window. Is this a bug, or am I doing something wrong?

let handles = await app.client.windowHandles();
console.log(handles);
/*
{ sessionId: '0d66b5bac77357c36ea41fd298e55854',
  status: 0,
  value:
   [ 'CDwindow-97CD6BD5-C47A-45C1-9A66-7D0FF3B2F9DF',
     'CDwindow-946E9CE7-9A1C-458A-9DE2-00A975ACC5BD' ] }
*/
await app.client.windowByIndex(1);
console.log(await app.client.browserWindow.getTitle());

BTW windowHandles is missing in the readme. Also I saw on stackoverflow that somebody was doing windowByIndex(handles.values[1]) but this also fails for me.

What is also weird is that my second window actually has focus, but app.client.browserWindow.getTitle() will get me the title of the first window. How can I make app.client.browserWindow to point at currently focused window?

Can't interact with dialog

I am opening dialog in my app like this:

const path = dialog.showOpenDialog(remote.getCurrentWindow(), {
      title: i18n.t("Where do you want to save it?"),
      properties: ['openDirectory', 'createDirectory']
    });

And I cannot find way to select directory in tests. I tried using webdriverio's keys with no luck. I thought that maybe electron creates second window and that's why I can't interact with it but by using client.getWindowCount() it founds only 1 window. Any ideas?

Error: timeout exceeded

Hi @kevinsawicki,

I gave a try to the sample here. It successfully run the appp, but than it failed as follows:

application launch
    1) "before each" hook for "shows an initial window"


  0 passing (10s)
  1 failing

  1) application launch "before each" hook for "shows an initial window":
     Error: timeout of 10000ms exceeded. Ensure the done() callback is being called in this test.

My repo: https://github.com/vchimev/spectron-sample

Any help would be appreciated,
@vchimev

Navigation breaks all API's

In the following use case (waiting for a signin button, clicking it and then attempting to enter a password. The renderer process of the WebView crashes with this sample code. The WebView's devtools become completely empty and all other client methods fail.

This code fails and the click event is not fired.

app.client
    .waitUntilWindowLoaded()
    .windowByIndex(1)
    .waitForVisible('[data-action=signin]').should.eventually.be.true
    .leftClick('[data-action=signin]').should.eventually.be.ok
    .waitForVisible('#Passwd').should.eventually.be.true;

However, this code works and the click event is fired.

app.client
    .waitUntilWindowLoaded()
    .windowByIndex(1)
    .waitForVisible('[data-action=signin]').should.eventually.be.true
    .leftClick('[data-action=signin]').should.eventually.be.ok;

With my understanding of how this is supposed to work it makes no sense that adding a WebDriver call to the end can break a call that works before it. Do you have any idea what is going on here?

Getting started with Spectron

Having created an electron application with a main.js and an index.html,
And it runs with a GUI on the command:

   node_modules/.bin/electron .

or

   npm start

Using the Spectron "Get Started" example, saving "a sample test" as "testApp.js",
What should be the value of:

   var app = new Application({ path: ' ??? ' })

And what is the command to invoke this code, which runs the GUI app and performs the test?

Clearly it is not "node testApp.js", or I have not configured things correctly.

Thanks!

client.execute does not work if app closes initial window and opens another

I have an app whose startup sequence is as follows:

  1. Show splash window for 5 seconds...then close it
  2. Open and show main app window

I wait for 10 seconds in my tests before issuing commands via the APIs. However they don't work because client.execute() doesn't work - and I think this is because the webdriver client API gets initialized agains the splash window since that shows up first - am I right?

How can I make it so that I can issue commands agains the main app window?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.