Skip to content

Commit

Permalink
feat: accept onStderrData callback
Browse files Browse the repository at this point in the history
* chore: use cypress eslint dev rules

* feat: expose onStderrData callback

* fix: handle when xvfb closes with non zero exit code

* fix: eslint

* chore: add tests

* fix: link to circle
  • Loading branch information
brian-mann authored Dec 24, 2017
1 parent 199fe62 commit 174b2d7
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 36 deletions.
10 changes: 10 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": [
"plugin:cypress-dev/general",
"plugin:cypress-dev/tests"
],
"env": {
"es6": true,
"node": true
}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@cypress/xvfb: easily start and stop an X Virtual Frame Buffer from your node apps.
-----

[![CircleCI](https://circleci.com/gh/cypress-io/node-xvfb.svg?style=svg)](https://circleci.com/gh/cypress-io/node-xvfb)
[![CircleCI](https://circleci.com/gh/cypress-io/xvfb.svg?style=svg)](https://circleci.com/gh/cypress-io/xvfb)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)

### Usage
Expand Down
76 changes: 48 additions & 28 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
/* eslint-disable node/no-deprecated-api */
var fs = require('fs')
var path = require('path')
var spawn = require('child_process').spawn
const once = require('lodash.once')
const fs = require('fs')
const path = require('path')
const spawn = require('child_process').spawn
fs.exists = fs.exists || path.exists
fs.existsSync = fs.existsSync || path.existsSync

function Xvfb (options) {
options = options || {}
this._display = (options.displayNum ? ':' + options.displayNum : null)
this._display = (options.displayNum ? `:${options.displayNum}` : null)
this._reuse = options.reuse
this._timeout = options.timeout || 500
this._silent = options.silent
this._onStderrData = options.onStderrData || (() => {})
this._xvfb_args = options.xvfb_args || []
}

Xvfb.prototype = {
start: function (cb) {
start (cb) {
if (!this._process) {
var lockFile = this._lockFile()
let lockFile = this._lockFile()

this._setDisplayEnvVariable()

fs.exists(lockFile, function (exists) {
var didSpawnFail = false
let didSpawnFail = false
try {
this._spawnProcess(exists, function (e) {
didSpawnFail = true
Expand All @@ -32,7 +34,7 @@ Xvfb.prototype = {
return cb && cb(e)
}

var totalTime = 0;
let totalTime = 0;
(function checkIfStarted () {
fs.exists(lockFile, function (exists) {
if (didSpawnFail) {
Expand All @@ -56,13 +58,13 @@ Xvfb.prototype = {
}
},

stop: function (cb) {
stop (cb) {
if (this._process) {
this._killProcess()
this._restoreDisplayEnvVariable()

var lockFile = this._lockFile()
var totalTime = 0;
let lockFile = this._lockFile()
let totalTime = 0;
(function checkIfStopped () {
fs.exists(lockFile, function (exists) {
if (!exists) {
Expand All @@ -82,25 +84,26 @@ Xvfb.prototype = {
}
},

display: function () {
display () {
if (!this._display) {
var displayNum = 98
var lockFile
let displayNum = 98
let lockFile
do {
displayNum++
lockFile = this._lockFile(displayNum)
} while (!this._reuse && fs.existsSync(lockFile))
this._display = ':' + displayNum
this._display = `:${displayNum}`
}

return this._display
},

_setDisplayEnvVariable: function () {
_setDisplayEnvVariable () {
this._oldDisplay = process.env.DISPLAY
process.env.DISPLAY = this.display()
},

_restoreDisplayEnvVariable: function () {
_restoreDisplayEnvVariable () {
// https://github.com/cypress-io/xvfb/issues/1
// only reset truthy backed' up values
if (this._oldDisplay) {
Expand All @@ -112,35 +115,52 @@ Xvfb.prototype = {
}
},

_spawnProcess: function (lockFileExists, onAsyncSpawnError) {
var display = this.display()
_spawnProcess (lockFileExists, onAsyncSpawnError) {
const onError = once(onAsyncSpawnError)

let display = this.display()
if (lockFileExists) {
if (!this._reuse) {
throw new Error('Display ' + display + ' is already in use and the "reuse" option is false.')
throw new Error(`Display ${display} is already in use and the "reuse" option is false.`)
}
} else {
this._process = spawn('Xvfb', [ display ].concat(this._xvfb_args))
const stderr = []

this._process = spawn('Xvfb', [display].concat(this._xvfb_args))
this._process.stderr.on('data', function (data) {
if (!this._silent) {
process.stderr.write(data)
stderr.push(data.toString())

if (this._silent) {
return
}

this._onStderrData(data)
}.bind(this))

this._process.on('close', (code) => {
if (code !== 0) {
const err = new Error(`${stderr.join('\n')}`)
err.nonZeroExitCode = true
onError(err)
}
})

// Bind an error listener to prevent an error from crashing node.
this._process.once('error', function (e) {
onAsyncSpawnError(e)
onError(e)
})
}
},

_killProcess: function () {
_killProcess () {
this._process.kill()
this._process = null
},

_lockFile: function (displayNum) {
_lockFile (displayNum) {
displayNum = displayNum || this.display().toString().replace(/^:/, '')
return '/tmp/.X' + displayNum + '-lock'
}
return `/tmp/.X${displayNum}-lock`
},
}

module.exports = Xvfb
10 changes: 8 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,22 @@
"repository": {
"url": "https://github.com/cypress-io/xvfb"
},
"dependencies": {},
"dependencies": {
"lodash.once": "^4.1.1"
},
"license": "MIT",
"scripts": {
"test": "standard --fix --verbose *.js && mocha",
"test": "eslint **/*.js && mocha",
"test-watch": "mocha watch",
"semantic-release": "semantic-release pre && npm publish --access public && semantic-release post",
"commit": "commit-wizard"
},
"devDependencies": {
"chai": "^4.1.2",
"condition-circle": "^1.5.0",
"eslint": "^4.13.1",
"eslint-plugin-cypress-dev": "^1.1.2",
"eslint-plugin-mocha": "^4.11.0",
"mocha": "^3.5.0",
"pre-git": "^3.15.0",
"semantic-release": "^6.3.6",
Expand Down
28 changes: 23 additions & 5 deletions test/xvfb_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,31 @@ const { expect } = require('chai')

const Xvfb = require('../')

describe('xvfb', function(){
beforeEach(function(){
this.xvfb = new Xvfb()
describe('xvfb', function () {
context('onStderrData', function () {
it('accepts callback function', function () {
const cb = () => {}

const xvfb = new Xvfb({
onStderrData: cb,
})

expect(xvfb._onStderrData).to.eq(cb)
})

it('sets default function otherwise', function () {
const xvfb = new Xvfb()

expect(xvfb._onStderrData).to.be.a('function')
})
})

context('issue: #1', function(){
it('issue #1: does not mutate process.env.DISPLAY', function(){
context('issue: #1', function () {
beforeEach(function () {
this.xvfb = new Xvfb()
})

it('issue #1: does not mutate process.env.DISPLAY', function () {
delete process.env.DISPLAY

expect(process.env.DISPLAY).to.be.undefined
Expand Down

0 comments on commit 174b2d7

Please sign in to comment.