Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
rosshinkley committed May 22, 2016
0 parents commit 8b27874
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
.DS_Store
test/tmp
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# nightmare-upload
Grants the ability to add files to file inputs for Nightmare 2.x, just like the good ol' days of Nightmare 1.x.

## Usage
Require the library, passing Nightmare as a reference to add the plugin actions:

```js
var Nightmare = require('nightmare');
require('nightmare-upload')(Nightmare);
```
### .upload(selector, files)
Specify the `files` to add to a `selector` file input. The `files` parameter can be a single string (for a single file) or an array of strings (for multiple files).

## Important note about setting file upload inputs
This plugin will not work if the Chromium devtools panel is open as Chromium allows only one attachment to the debugger at a time.

## Example

```js
var Nightmare = require('nightmare');
require('nightmare-upload')(Nightmare);
var nightmare = Nightmare();
nightmare
.goto('http://some-url.tld')
.upload('#some_file_input', '/path/to/my/upload.ext')
.click('#button_that_submits_form_for_upload')
...
```
53 changes: 53 additions & 0 deletions nightmare-upload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
var debug = require('debug')('nightmare:upload');

module.exports = exports = function(Nightmare) {
Nightmare.action('upload',
function(ns, options, parent, win, renderer, done) {
parent.respondTo('upload', function(selector, pathsToUpload, done) {
parent.emit('log', 'paths', pathsToUpload);
try {
//attach the debugger
//NOTE: this will fail if devtools is open
win.webContents.debugger.attach('1.1');
} catch (e) {
parent.emit('log', 'problem attaching', e);
return done(e);
}

win.webContents.debugger.sendCommand('DOM.getDocument', {}, function(err, domDocument) {
win.webContents.debugger.sendCommand('DOM.querySelector', {
nodeId: domDocument.root.nodeId,
selector: selector
}, function(err, queryResult) {
//HACK: chromium errors appear to be unpopulated objects?
if (Object.keys(err)
.length > 0) {
parent.emit('log', 'problem selecting', err);
return done(err);
}
win.webContents.debugger.sendCommand('DOM.setFileInputFiles', {
nodeId: queryResult.nodeId,
files: pathsToUpload
}, function(err, setFileResult) {
if (Object.keys(err)
.length > 0) {
parent.emit('log', 'problem setting input', err);
return done(err);
}
win.webContents.debugger.detach();
done(null, pathsToUpload);
});
});
});
});
done();
},
function(selector, pathsToUpload, done) {
if(!Array.isArray(pathsToUpload)){
pathsToUpload = [pathsToUpload];
}
this.child.call('upload', selector, pathsToUpload, (err, stuff) => {
done(err, stuff);
});
})
}
37 changes: 37 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "nightmare-upload",
"version": "0.1.0",
"license": "MIT",
"main": "./nightmare-upload.js",
"description":"upload files using NightmareJS",
"scripts": {
"test": "mocha test"
},
"repository": {
"type": "git",
"url": "https://github.com/rosshinkley/nightmare-upload.git"
},
"author": "Ross Hinkley",
"keywords": [
"nightmare",
"upload"
],
"peerDependencies":{
"nightmare": "^2.3.0"
},
"dependencies": {
"debug": "^2.2.0"
},
"devDependencies": {
"rimraf": "^2.4.3",
"mkdirp": "^0.5.1",
"basic-auth": "^1.0.3",
"basic-auth-connect": "^1.0.0",
"chai": "^3.4.1",
"express": "^4.13.3",
"mocha-generators": "^1.2.0",
"mocha": "^2.3.0",
"multer": "1.1.0",
"serve-static": "^1.10.0"
}
}
1 change: 1 addition & 0 deletions test/files/upload-again.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
this is an upload test! again!
1 change: 1 addition & 0 deletions test/files/upload.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
this is an upload test!
12 changes: 12 additions & 0 deletions test/fixtures/upload/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>Uploade</title>
</head>
<body>
<form method="post" action="/upload" enctype="multipart/form-data">
<input type="file" name="file">
<button type="submit">Upload</button>
</form>
</body>
</html>
102 changes: 102 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/**
* Module dependencies.
*/

require('mocha-generators')
.install();

var Nightmare = require('nightmare');
var should = require('chai')
.should();
var url = require('url');
var server = require('./server');
var fs = require('fs');
var mkdirp = require('mkdirp');
var path = require('path');
var rimraf = require('rimraf');

/**
* Temporary directory
*/

var tmp_dir = path.join(__dirname, 'tmp')

/**
* Get rid of a warning.
*/

process.setMaxListeners(0);

/**
* Locals.
*/

var base = 'http://localhost:7500/';

describe('Nightmare Upload', function() {
before(function(done) {
require('../nightmare-upload')(Nightmare);
server.listen(7500, done);
});

it('should be constructable', function * () {
var nightmare = Nightmare();
nightmare.should.be.ok;
yield nightmare.end();
});

describe('upload', function() {
it('should upload a single file', function * () {
var nightmare = new Nightmare();
var files = yield nightmare.goto(fixture('upload'))
.upload('input[type=file]', path.resolve(__dirname, 'files', 'upload.txt'))
.click('button[type=submit]')
.wait(1000)
.evaluate(function() {
return JSON.parse(document.body.querySelector('pre')
.innerHTML)
});
files[0].originalname.should.equal('upload.txt');
yield nightmare.end();
});

it('should upload more than one file', function * () {
var nightmare = new Nightmare();
var files = yield nightmare.goto(fixture('upload'))
.upload('input[type=file]', [
path.resolve(__dirname, 'files', 'upload.txt'),
path.resolve(__dirname, 'files', 'upload-again.txt')
])
.click('button[type=submit]')
.wait(1000)
.evaluate(function() {
return JSON.parse(document.body.querySelector('pre')
.innerHTML)
});
files.length.should.equal(2);
files[0].originalname.should.equal('upload.txt');
files[1].originalname.should.equal('upload-again.txt');
yield nightmare.end();
});

it('should verify a file exists before upload', function(done) {
new Nightmare()
.goto(fixture('upload'))
.upload('#uploaded_file', 'nope.jpg')
.run(function(err) {
err.should.exist;
done();
});
});
});
});

/**
* Generate a URL to a specific fixture.
* @param {String} path
* @returns {String}
*/

function fixture(path) {
return url.resolve(base, path);
}
2 changes: 2 additions & 0 deletions test/mocha.opts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--slow 3s
--timeout 10s
18 changes: 18 additions & 0 deletions test/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
var express = require('express');
var multer = require('multer');
var path = require('path');
var serve = require('serve-static');
var debug= require('debug')('nightmare:server');

var app = module.exports = express();

app.use(multer({ inMemory: true }).any());

app.post('/upload', function (req, res) {
debug('uploading', req.files);
res.send(req.files);
});

app.use(serve(path.resolve(__dirname, 'fixtures')));

if (!module.parent) app.listen(7500);

0 comments on commit 8b27874

Please sign in to comment.