{"id":13432767,"url":"https://github.com/electron-userland/spectron","last_synced_at":"2026-01-12T00:42:27.075Z","repository":{"id":1758333,"uuid":"44138456","full_name":"electron-userland/spectron","owner":"electron-userland","description":"DEPRECATED: 🔎 Test Electron apps using ChromeDriver","archived":false,"fork":false,"pushed_at":"2024-02-29T13:12:23.000Z","size":3262,"stargazers_count":1681,"open_issues_count":265,"forks_count":228,"subscribers_count":48,"default_branch":"master","last_synced_at":"2025-04-30T17:47:39.335Z","etag":null,"topics":["chromedriver","electron","spectron"],"latest_commit_sha":null,"homepage":"http://electronjs.org/spectron","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/electron-userland.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-10-12T22:50:37.000Z","updated_at":"2025-04-26T15:36:51.000Z","dependencies_parsed_at":"2024-05-05T10:49:01.862Z","dependency_job_id":null,"html_url":"https://github.com/electron-userland/spectron","commit_stats":{"total_commits":658,"total_committers":62,"mean_commits":"10.612903225806452","dds":"0.27963525835866265","last_synced_commit":"7f7004f1de5e081684e4b151bb7579df5036be5d"},"previous_names":["electron/spectron","kevinsawicki/spectron"],"tags_count":64,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/electron-userland%2Fspectron","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/electron-userland%2Fspectron/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/electron-userland%2Fspectron/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/electron-userland%2Fspectron/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/electron-userland","download_url":"https://codeload.github.com/electron-userland/spectron/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251972615,"owners_count":21673635,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chromedriver","electron","spectron"],"created_at":"2024-07-31T02:01:16.324Z","updated_at":"2026-01-12T00:42:27.035Z","avatar_url":"https://github.com/electron-userland.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","Library"],"sub_categories":["Testing"],"readme":"# \u003cimg src=\"https://cloud.githubusercontent.com/assets/378023/15063284/cf544f2c-1383-11e6-9336-e13bd64b1694.png\" width=\"60px\" align=\"center\" alt=\"Spectron icon\"\u003e Spectron\n\n[![CI](https://github.com/electron-userland/spectron/workflows/CI/badge.svg)](https://github.com/electron-userland/spectron/actions) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](http://standardjs.com/)\n[![dependencies](https://img.shields.io/david/electron/spectron.svg)](https://david-dm.org/electron/spectron) [![license:mit](https://img.shields.io/badge/license-mit-blue.svg)](https://opensource.org/licenses/MIT) [![npm:](https://img.shields.io/npm/v/spectron.svg)](https://www.npmjs.com/package/spectron) [![downloads](https://img.shields.io/npm/dm/spectron.svg)](https://www.npmjs.com/package/spectron)\n\n### 🚨 Spectron is officially deprecated as of February 1, 2022.\n\nEasily test your [Electron](http://electron.atom.io) apps using\n[ChromeDriver](https://sites.google.com/chromium.org/driver) and\n[WebdriverIO](http://webdriver.io).\n\n## Version Map\n\nFor given versions of Electron you must depend on a very specific version range of Spectron.  Below is a version mapping table between Spectron version and Electron version.\n\n| Electron Version | Spectron Version |\n|------------------|------------------|\n| `~1.0.0` | `~3.0.0` |\n| `~1.1.0` | `~3.1.0` |\n| `~1.2.0` | `~3.2.0` |\n| `~1.3.0` | `~3.3.0` |\n| `~1.4.0` | `~3.4.0` |\n| `~1.5.0` | `~3.5.0` |\n| `~1.6.0` | `~3.6.0` |\n| `~1.7.0` | `~3.7.0` |\n| `~1.8.0` | `~3.8.0` |\n| `^2.0.0` | `^4.0.0` |\n| `^3.0.0` | `^5.0.0` |\n| `^4.0.0` | `^6.0.0` |\n| `^5.0.0` | `^7.0.0` |\n| `^6.0.0` | `^8.0.0` |\n| `^7.0.0` | `^9.0.0` |\n| `^8.0.0` | `^10.0.0`|\n| `^9.0.0` | `^11.0.0`|\n| `^10.0.0` | `^12.0.0`|\n| `^11.0.0` | `^13.0.0`|\n| `^12.0.0` | `^14.0.0`|\n| `^13.0.0` | `^15.0.0`|\n| `^14.0.0` | `^16.0.0`|\n| `^15.0.0` | `^17.0.0`|\n| `^16.0.0` | `^18.0.0`|\n| `^17.0.0` | `^19.0.0`|\n\nLearn more from [this presentation](https://speakerdeck.com/kevinsawicki/testing-your-electron-apps-with-chromedriver).\n\n:rotating_light: Upgrading from `1.x` to `2.x`/`3.x`? Read the [changelog](https://github.com/electron/spectron/blob/master/CHANGELOG.md).\n\n## Installation\n\n```sh\nnpm install --save-dev spectron\n```\n\n## Usage\n\nSpectron works with any testing framework but the following example uses\n[mocha](https://mochajs.org):\n\nTo get up and running from your command line:\n```sh\n# Install mocha locally as a dev dependency.\nnpm i mocha -D\n\n# From the project root, create a folder called test, in that directory, create a file called 'spec.js'\ntouch test/spec.js\n\n# Change directory to test\ncd test\n```\n\nThen simply include the following in your first `spec.js`.\n\n```js\nconst { Application } = require('spectron')\nconst assert = require('assert')\nconst electronPath = require('electron') // Require Electron from the binaries included in node_modules.\nconst path = require('path')\n\ndescribe('Application launch', function () {\n  this.timeout(10000)\n\n  beforeEach(async function () {\n    this.app = new Application({\n      // Your electron path can be any binary\n      // i.e for OSX an example path could be '/Applications/MyApp.app/Contents/MacOS/MyApp'\n      // But for the sake of the example we fetch it from our node_modules.\n      path: electronPath,\n\n      // Assuming you have the following directory structure\n\n      //  |__ my project\n      //     |__ ...\n      //     |__ main.js\n      //     |__ package.json\n      //     |__ index.html\n      //     |__ ...\n      //     |__ test\n      //        |__ spec.js  \u003c- You are here! ~ Well you should be.\n\n      // The following line tells spectron to look and use the main.js file\n      // and the package.json located 1 level above.\n      args: [path.join(__dirname, '..')]\n    })\n    await this.app.start()\n  })\n\n  afterEach(async function () {\n    if (this.app \u0026\u0026 this.app.isRunning()) {\n      await this.app.stop()\n    }\n  })\n\n  it('shows an initial window', async function () {\n    const count = await this.app.client.getWindowCount()\n    assert.equal(count, 1)\n    // Please note that getWindowCount() will return 2 if `dev tools` are opened.\n    // assert.equal(count, 2)\n  })\n})\n```\n\nCreate an npm task in your package.json file\n```sh\n\"scripts\": {\n  \"test\": \"mocha\"\n}\n```\n\nAnd from the root of your project, in your command-line simply run:\n```sh\nnpm test\n```\n\nBy default, mocha searches for a folder with the name `test` ( which we created before ).\nFor more information on how to configure mocha, please visit [mocha](https://mochajs.org).\n\n#### Limitations\n\nAs stated in [issue #19](https://github.com/electron/spectron/issues/19), Spectron will not be able to start if your Electron app is launched using the `remote-debugging-port` command-line switch (i.e. `app.commandLine.appendSwitch('remote-debugging-port', \u003cdebugging-port-number\u003e);`). Please make sure to include the necessary logic in your app's code to disable the switch during tests.\n\nAs mentioned in [issue #202](https://github.com/electron-userland/spectron/issues/202#issuecomment-632223955),\n`app.start()` promise won't resolve if the electron application calls\n`setPath('userData', path)`. Webdriver places a port file into the `userData`\ndirectory and needs to know where to look for it. The workaround is to pass\n`chromeDriverArgs: ['user-data-dir=/custom/userData/path']` to the `Application`\nconstructor.\n\n## Application API\n\nSpectron exports an `Application` class that when configured, can start and\nstop your Electron application.\n\n### new Application(options)\n\nCreate a new application with the following options:\n\n* `path` -  **Required.** String path to the Electron application executable to\n  launch.\n  **Note:** If you want to invoke `electron` directly with your app's main\n  script then you should specify `path` as  `electron` via `electron-prebuilt`\n  and specify your app's main script path as the first argument in the `args`\n  array.\n* `args` - Array of arguments to pass to the Electron application.\n* `chromeDriverArgs` - Array of arguments to pass to ChromeDriver.\n  See [here](https://sites.google.com/chromium.org/driver/capabilities) for details on the Chrome arguments.\n* `cwd`- String path to the working directory to use for the launched\n  application. Defaults to `process.cwd()`.\n* `env` - Object of additional environment variables to set in the launched\n  application.\n* `host` - String host name of the launched `chromedriver` process.\n  Defaults to `'localhost'`.\n* `port` - Number port of the launched `chromedriver` process.\n  Defaults to `9515`.\n* `nodePath` - String path to a `node` executable to launch ChromeDriver with.\n  Defaults to `process.execPath`.\n* `connectionRetryCount` - Number of retry attempts to make when connecting\n  to ChromeDriver. Defaults to `10` attempts.\n* `connectionRetryTimeout` - Number in milliseconds to wait for connections\n  to ChromeDriver to be made. Defaults to `30000` milliseconds.\n* `quitTimeout` - Number in milliseconds to wait for application quitting.\n  Defaults to `1000` milliseconds.\n* `requireName` - Custom property name to use when requiring modules. Defaults\n  to `require`. This should only be used if your application deletes the main\n  `window.require` function and assigns it to another property name on `window`.\n* `startTimeout` - Number in milliseconds to wait for ChromeDriver to start.\n  Defaults to `5000` milliseconds.\n* `waitTimeout` - Number in milliseconds to wait for calls like\n  `waitUntilTextExists` and `waitUntilWindowLoaded` to complete.\n  Defaults to `5000` milliseconds.\n* `debuggerAddress` - String address of a Chrome debugger server to connect to.\n* `chromeDriverLogPath` - String path to file to store ChromeDriver logs in.\n  Setting this option enables `--verbose` logging when starting ChromeDriver.\n* `webdriverLogPath` - String path to a directory where Webdriver will write\n  logs to. Setting this option enables `verbose` logging from Webdriver.\n* `webdriverOptions` - Object of additional options for Webdriver\n\n### Node Integration\n\nThe Electron helpers provided by Spectron require accessing the core Electron\nAPIs in the renderer processes of your application. So, either your Electron\napplication has `nodeIntegration` set to `true` or you'll need to expose a\n`require` window global to Spectron so it can access the core Electron APIs.\n\nYou can do this by adding a [`preload`][preload] script that does the following:\n\n```js\nif (process.env.NODE_ENV === 'test') {\n  window.electronRequire = require\n}\n```\n\nThen create the Spectron `Application` with the `requireName` option set to\n`'electronRequire'` and then runs your tests via `NODE_ENV=test npm test`.\n\n**Note:** This is only required if your tests are accessing any Electron APIs.\nYou don't need to do this if you are only accessing the helpers on the `client`\nproperty which do not require Node integration.\n\n### Properties\n\n#### client\n\nSpectron uses [WebdriverIO](https://webdriver.io) and exposes the managed\n`client` property on the created `Application` instances.\n\nThe `client` API is WebdriverIO's `browser` object. Documentation can be found\n[here](https://webdriver.io/docs/browserobject/).\n\nSeveral additional commands are provided specific to Electron.\n\nAll the commands return a `Promise`.\n\nSo if you wanted to get the text of an element you would do:\n\n```js\nconst element = await app.client.$('#error-alert')\nconst errorText = await element.getText()\nconsole.log('The #error-alert text content is ' + errorText)\n```\n\n#### electron\n\nThe `electron` property is your gateway to accessing the full Electron API.\n\nEach Electron module is exposed as a property on the `electron` property\nso you can think of it as an alias for `require('electron')` from within your\napp.\n\nSo if you wanted to access the [clipboard](http://electron.atom.io/docs/latest/api/clipboard)\nAPI in your tests you would do:\n\n```js\napp.electron.clipboard.writeText('pasta')\nconst clipboardText = app.electron.clipboard.readText()\nconsole.log('The clipboard text is ' + clipboardText)\n```\n\n#### browserWindow\n\nThe `browserWindow` property is an alias for `require('electron').remote.getCurrentWindow()`.\n\nIt provides you access to the current [BrowserWindow](http://electron.atom.io/docs/latest/api/browser-window/)\nand contains all the APIs.\n\nSo if you wanted to check if the current window is visible in your tests you\nwould do:\n\n```js\nconst visible = await app.browserWindow.isVisible()\nconsole.log('window is visible? ' + visible)\n```\n\nIt is named `browserWindow` instead of `window` so that it doesn't collide\nwith the WebDriver command of that name.\n\n##### capturePage\n\nThe async `capturePage` API is supported but instead of taking a callback it\nreturns a `Promise` that resolves to a `Buffer` that is the image data of\nscreenshot.\n\n```js\nconst imageBuffer = await app.browserWindow.capturePage()\nfs.writeFile('page.png', imageBuffer)\n```\n\n#### webContents\n\nThe `webContents` property is an alias for `require('electron').remote.getCurrentWebContents()`.\n\nIt provides you access to the [WebContents](http://electron.atom.io/docs/latest/api/web-contents/)\nfor the current window and contains all the APIs.\n\nSo if you wanted to check if the current window is loading in your tests you\nwould do:\n\n```js\napp.webContents.isLoading().then(function (visible) {\n  console.log('window is loading? ' + visible)\n})\n```\n\n##### savePage\n\nThe async `savePage` API is supported but instead of taking a callback it\nreturns a `Promise` that will raise any errors and resolve to `undefined` when\ncomplete.\n\n```js\ntry {\n  await app.webContents.savePage('/Users/kevin/page.html', 'HTMLComplete')\n  console.log('page saved')\ncatch (error) {\n  console.error('saving page failed', error.message)\n}\n```\n\n##### executeJavaScript\nThe async `executeJavaScript` API is supported but instead of taking a callback it\nreturns a `Promise` that will resolve with the result of the last statement of the\nscript.\n\n```js\nconst result = await app.webContents.executeJavaScript('1 + 2')\nconsole.log(result) // prints 3\n```\n\n#### mainProcess\n\nThe `mainProcess` property is an alias for `require('electron').remote.process`.\n\nIt provides you access to the main process's [process](https://nodejs.org/api/process.html)\nglobal.\n\nSo if you wanted to get the `argv` for the main process in your tests you would\ndo:\n\n```js\nconst argv = await app.mainProcess.argv()\nconsole.log('main process args: ' + argv)\n```\n\nProperties on the `process` are exposed as functions that return promises so\nmake sure to call `mainProcess.env().then(...)` instead of\n`mainProcess.env.then(...)`.\n\n#### rendererProcess\n\nThe `rendererProcess` property is an alias for `global.process`.\n\nIt provides you access to the renderer process's [process](https://nodejs.org/api/process.html)\nglobal.\n\nSo if you wanted to get the environment variables for the renderer process in\nyour tests you would do:\n\n```js\nconst env = await app.rendererProcess.env()\nconsole.log('renderer process env variables: ' + env)\n```\n\n### Methods\n\n#### start()\n\nStarts the application. Returns a `Promise` that will be resolved when the\napplication is ready to use. You should always wait for start to complete\nbefore running any commands.\n\n#### stop()\n\nStops the application. Returns a `Promise` that will be resolved once the\napplication has stopped.\n\n#### restart()\n\nStops the application and then starts it. Returns a `Promise` that will be\nresolved once the application has started again.\n\n#### isRunning()\n\nChecks to determine if the application is running or not.\n\nReturns a `Boolean`.\n\n#### getSettings()\n\nGet all the configured options passed to the `new Application()` constructor.\nThis will include the default options values currently being used.\n\nReturns an `Object`.\n\n#### client.getMainProcessLogs()\n\nGets the `console` log output from the main process. The logs are cleared\nafter they are returned.\n\nReturns a `Promise` that resolves to an array of string log messages\n\n```js\nconst logs = await app.client.getMainProcessLogs()\nlogs.forEach(function (log) {\n  console.log(log)\n})\n```\n\n#### client.getRenderProcessLogs()\n\nGets the `console` log output from the render process. The logs are cleared\nafter they are returned.\n\nReturns a `Promise` that resolves to an array of log objects.\n\n```js\nconst logs = await app.client.getRenderProcessLogs()\nlogs.forEach(function (log) {\n  console.log(log.message)\n  console.log(log.source)\n  console.log(log.level)\n})\n```\n\n#### client.getSelectedText()\n\nGet the selected text in the current window.\n\n```js\nconst selectedText = await app.client.getSelectedText()\nconsole.log(selectedText)\n```\n\n#### client.getWindowCount()\n\nGets the number of open windows.\n`\u003cwebview\u003e` tags are also counted as separate windows.\n\n```js\nconst count = await app.client.getWindowCount()\nconsole.log(count)\n```\n\n#### client.waitUntilTextExists(selector, text, [timeout])\n\nWaits until the element matching the given selector contains the given\ntext. Takes an optional timeout in milliseconds that defaults to `5000`.\n\n```js\napp.client.waitUntilTextExists('#message', 'Success', 10000)\n```\n\n#### client.waitUntilWindowLoaded([timeout])\n\nWait until the window is no longer loading. Takes an optional timeout\nin milliseconds that defaults to `5000`.\n\n```js\napp.client.waitUntilWindowLoaded(10000)\n```\n\n#### client.windowByIndex(index)\n\nFocus a window using its index from the `windowHandles()` array.\n`\u003cwebview\u003e` tags can also be focused as a separate window.\n\n```js\napp.client.windowByIndex(1)\n```\n\n#### client.switchWindow(urlOrTitleToMatch)\n\nFocus a window using its URL or title.\n\n```js\n// switch via url match\napp.client.switchWindow('google.com')\n\n// switch via title match\napp.client.switchWindow('Next-gen WebDriver test framework')\n```\n\n### Accessibility Testing\n\nSpectron bundles the [Accessibility Developer Tools](https://github.com/GoogleChrome/accessibility-developer-tools)\nprovided by Google and adds support for auditing each window and `\u003cwebview\u003e`\ntag in your application.\n\n#### client.auditAccessibility(options)\n\nRun an accessibility audit in the focused window with the specified options.\n\n* `options` - An optional Object with the following keys:\n  * `ignoreWarnings` - `true` to ignore failures with a severity of `'Warning'`\n    and only include failures with a severity of `'Severe'`. Defaults to `false`.\n  * `ignoreRules` - Array of String rule code values such as `AX_COLOR_01` to\n    ignore failures for. The full list is available [here](https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules).\n\nReturns an `audit` Object with the following properties:\n\n* `message` - A detailed String message about the results\n* `failed` - A Boolean, `false` when the audit has failures\n* `results` - An array of detail objects for each failed rule. Each object\n  in the array has the following properties:\n  * `code` - A unique String accessibility rule identifier\n  * `elements` - An Array of Strings representing the selector path of each\n    HTML element that failed the rule\n  * `message` - A String message about the failed rule\n  * `severity` - `'Warning'` or `'Severe'`\n  * `url` - A String URL providing more details about the failed rule\n\n```js\nconst audit = await app.client.auditAccessibility()\nif (audit.failed) {\n  console.error(audit.message)\n}\n```\n\nSee https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules\nfor more details about the audit rules.\n\nIf you are using a `\u003cwebview\u003e` tag in your app and want to audit both the outer\npage and the `\u003cwebview\u003e`'s page then you will need to do the following:\n\n```js\n// Focus main page and audit it\nawait app.client.windowByIndex(0)\nconst audit = await app.client.auditAccessibility()\nif (audit.failed) {\n  console.error('Main page failed audit')\n  console.error(audit.message)\n}\n\n//Focus \u003cwebview\u003e tag and audit it\nawait app.client.windowByIndex(1)\nconst audit = await app.client.auditAccessibility()\nif (audit.failed) {\n  console.error('\u003cwebview\u003e page failed audit')\n  console.error(audit.message)\n}\n```\n\n## Continuous Integration\n\n### On Travis CI\n\nYou will want to add the following to your `.travis.yml` file when building on\nLinux:\n\n```yml\nbefore_script:\n  - \"export DISPLAY=:99.0\"\n  - \"sh -e /etc/init.d/xvfb start\"\n  - sleep 3 # give xvfb some time to start\n```\n\nCheck out Spectron's [.travis.yml](https://github.com/electron/spectron/blob/master/.travis.yml)\nfile for a production example.\n\n### On AppVeyor\n\nYou will want to add the following to your `appveyor.yml` file:\n\n```yml\nos: unstable\n```\n\nCheck out Spectron's [appveyor.yml](https://github.com/electron/spectron/blob/master/appveyor.yml)\nfile for a production example.\n\n\n## Test Library Examples\n\n### With Chai As Promised\n\nWebdriverIO is promise-based and so it pairs really well with the\n[Chai as Promised](https://github.com/domenic/chai-as-promised) library that\nbuilds on top of [Chai](http://chaijs.com).\n\nUsing these together allows you to chain assertions together and have fewer\ncallback blocks. See below for a simple example:\n\n```sh\nnpm install --save-dev chai\nnpm install --save-dev chai-as-promised\n```\n\n```js\nconst Application = require('spectron').Application\nconst chai = require('chai')\nconst chaiAsPromised = require('chai-as-promised')\nconst electronPath = require('electron')\nconst path = require('path')\n\nchai.should()\nchai.use(chaiAsPromised)\n\ndescribe('Application launch', function () {\n  this.timeout(10000);\n\n  beforeEach(function () {\n    this.app = new Application({\n      path: electronPath,\n      args: [path.join(__dirname, '..')]\n    })\n    return this.app.start()\n  })\n\n  beforeEach(function () {\n    chaiAsPromised.transferPromiseness = this.app.transferPromiseness\n  })\n\n  afterEach(function () {\n    if (this.app \u0026\u0026 this.app.isRunning()) {\n      return this.app.stop()\n    }\n  })\n\n  it('opens a window', function () {\n    return this.app.client.waitUntilWindowLoaded()\n      .getWindowCount().should.eventually.have.at.least(1)\n      .browserWindow.isMinimized().should.eventually.be.false\n      .browserWindow.isVisible().should.eventually.be.true\n      .browserWindow.isFocused().should.eventually.be.true\n      .browserWindow.getBounds().should.eventually.have.property('width').and.be.above(0)\n      .browserWindow.getBounds().should.eventually.have.property('height').and.be.above(0)\n  })\n})\n```\n\n### With AVA\n\nSpectron works with [AVA](https://github.com/avajs/ava), which allows you\nto write your tests in ES2015+ without doing any extra work.\n\n```js\nimport test from 'ava';\nimport {Application} from 'spectron';\n\ntest.beforeEach(t =\u003e {\n  t.context.app = new Application({\n    path: '/Applications/MyApp.app/Contents/MacOS/MyApp'\n  });\n\n  return t.context.app.start();\n});\n\ntest.afterEach(t =\u003e {\n  return t.context.app.stop();\n});\n\ntest('opens a window', t =\u003e {\n  return t.context.app.client.waitUntilWindowLoaded()\n    .getWindowCount().then(count =\u003e {\n      t.is(count, 1);\n    }).browserWindow.isMinimized().then(min =\u003e {\n      t.false(min);\n    }).browserWindow.isDevToolsOpened().then(opened =\u003e {\n      t.false(opened);\n    }).browserWindow.isVisible().then(visible =\u003e {\n      t.true(visible);\n    }).browserWindow.isFocused().then(focused =\u003e {\n      t.true(focused);\n    }).browserWindow.getBounds().then(bounds =\u003e {\n      t.true(bounds.width \u003e 0);\n      t.true(bounds.height \u003e 0);\n    });\n});\n```\n\nAVA has built-in support for [async functions](https://github.com/avajs/ava#async-function-support), which simplifies async operations:\n\n```js\nimport test from 'ava';\nimport {Application} from 'spectron';\n\ntest.beforeEach(async t =\u003e {\n  t.context.app = new Application({\n    path: '/Applications/MyApp.app/Contents/MacOS/MyApp'\n  });\n\n  await t.context.app.start();\n});\n\ntest.afterEach.always(async t =\u003e {\n  await t.context.app.stop();\n});\n\ntest('example', async t =\u003e {\n  const app = t.context.app;\n  await app.client.waitUntilWindowLoaded();\n\n  const win = app.browserWindow;\n  t.is(await app.client.getWindowCount(), 1);\n  t.false(await win.isMinimized());\n  t.false(await win.isDevToolsOpened());\n  t.true(await win.isVisible());\n  t.true(await win.isFocused());\n\n  const {width, height} = await win.getBounds();\n  t.true(width \u003e 0);\n  t.true(height \u003e 0);\n});\n```\n\n[preload]: http://electron.atom.io/docs/api/browser-window/#new-browserwindowoptions\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felectron-userland%2Fspectron","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felectron-userland%2Fspectron","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felectron-userland%2Fspectron/lists"}