diff --git a/lib/helpers/child-process.js b/lib/helpers/child-process.js new file mode 100644 index 0000000..a3bf89c --- /dev/null +++ b/lib/helpers/child-process.js @@ -0,0 +1,19 @@ +"use strict"; +var async = require("async"); + +process.on('message', function(task) { + var hydrate = require(task.functionPath); + async.waterfall([ + function startHydration(cb) { + cb.urlCallback = task.options.urlCallback; + cb.apiUrl = task.options.apiUrl; + hydrate(task.path, task.document, task.changes, cb); + } + ], + function(err, changes) { + process.send({ + err: err, + changes: changes + }); + }); +}); diff --git a/lib/helpers/hydrater.js b/lib/helpers/hydrater.js index e259690..43280fc 100644 --- a/lib/helpers/hydrater.js +++ b/lib/helpers/hydrater.js @@ -8,7 +8,7 @@ */ var async = require('async'); -var nodeDomain = require('domain'); +var shellFork = require('child_process').fork; var request = require('supertest'); var crypto = require('crypto'); var restify = require('restify'); @@ -44,38 +44,35 @@ module.exports = function(hydraterFunction, logger, errLogger) { /** * Download the file from task.file_path, store it in a temporary file if there is file_path */ - function initHydration(cb) { + function downloadFile(cb) { if(task.file_path) { - // Download the file - var stream = fs.createWriteStream(path); - - // Store error if statusCode !== 200 - var err; - stream.on("finish", function() { - cb(err); - }); - var apiUrl = url.parse(task.file_path, false, true); - var req = request(apiUrl.protocol + "//" + apiUrl.host) - .get(apiUrl.path); - - req.end().req.once('response', function(res) { - if(res.statusCode !== 200) { - err = new restify.BadGatewayError('Error when downloading file ' + task.file_path + ': ' + res.statusCode); - stream.end(); - this.abort(); - } - }); - - req.pipe(stream); + request(apiUrl.protocol + "//" + apiUrl.host) + .get(apiUrl.path) + .expect(200) + .end(function(err, res) { + if(err) { + err = new restify.BadGatewayError('Error when downloading file ' + task.file_path + ': ' + err); + } + cb(err, res && res.text); + }); } else { cb(null); } }, + function saveFile(res, cb) { + if(res) { + fs.writeFile(path, res, cb); + } + else { + cb(); + } + }, function performHydration(cb) { - var domain = nodeDomain.create(); - + var child = shellFork(__dirname + '/child-process.js', {silent: true}); + var stderr = ""; + var stdout = ""; var timeout; /** * Function to call, either on domain error, on hydration error or successful hydration. @@ -84,46 +81,65 @@ module.exports = function(hydraterFunction, logger, errLogger) { var cleaner = function(err, changes) { if(!cleaner.called) { cleaner.called = true; - domain.exit(); - domain.dispose(); cb(err, changes); } + clearTimeout(timeout); }; cleaner.called = false; - domain.on('error', cleaner); - - // Run in a domain to prevent memory leak on crash - domain.run(function() { - async.waterfall([ - function callHydrationFunction(cb) { - // Give user access to the final URL callback and the API url (which can be staging, prod or anything) - // In case he wants to bypass us and send the changes himself - cb.urlCallback = task.callback; - cb.apiUrl = ''; - if(task.callback) { - var parsed = url.parse(task.callback); - cb.apiUrl = parsed.protocol + "//" + parsed.host; - } + child.on('error', function(exitCode) { + cleaner(new HydrationError("Wild error appeared while spawning child. Exit code:" + exitCode)); + }); - // Call the real function for hydration. - hydraterFunction((task.file_path) ? path : null, task.document, lib.defaultChanges(), cb); - } - ], function cleanHydration(err, changes) { - // If the function replied with an "HydrationError", we'll wrap this in a nicely formatted document - // and stop the error from bubbling up. - if(err instanceof HydrationError) { - changes = {}; - changes.hydration_errored = true; - changes.hydration_error = err.message; - err = null; - } + child.stderr.on('readable', function() { + var chunk; + while (null !== (chunk = child.stderr.read())) { + stderr += chunk; + } + }); + + child.stdout.on('readable', function() { + var chunk; + while (null !== (chunk = child.stdout.read())) { + stdout += chunk; + } + }); + + child.on('exit', function(errCode) { + if(errCode !== 0) { + cleaner(new HydrationError("Child exiting with err code: " + errCode + stdout + stderr)); + } + }); + + // Build objects to send to child + var options = {}; + options.urlCallback = task.callback; + options.apiUrl = ''; + if(task.callback) { + var parsed = url.parse(task.callback); + options.apiUrl = parsed.protocol + "//" + parsed.host; + } + + child.send({ + functionPath: hydraterFunction, + path: (task.file_path) ? path : null, + document: task.document, + changes: lib.defaultChanges(), + options: options, + }); + + child.on('message', function(res) { + var err = res.err + // If the function replied with an "HydrationError", we'll wrap this in a nicely formatted document + // and stop the error from bubbling up. + if(err && err._hydrationError) { + res.changes = {}; + res.changes.hydration_errored = true; + res.changes.hydration_error = res.err.message; + err = null; + } + cleaner(err, res.changes); - // Wait for nexttick, to end this function and be able to properly GC it on domain.dispose(). - process.nextTick(function() { - cleaner(err, changes); - }); - }); }); timeout = setTimeout(function() { @@ -131,6 +147,7 @@ module.exports = function(hydraterFunction, logger, errLogger) { var changes = {}; changes.hydration_errored = true; changes.hydration_error = "Task took too long."; + child.kill('SIGKILL'); cleaner(null, changes); } }, process.env.TIMEOUT || 60 * 1000); @@ -183,6 +200,7 @@ module.exports = function(hydraterFunction, logger, errLogger) { } var apiUrl = url.parse(task.callback, false, true); + request(apiUrl.protocol + "//" + apiUrl.host) .patch(apiUrl.path) .send(changes) diff --git a/lib/index.js b/lib/index.js index 6450397..0aee920 100644 --- a/lib/index.js +++ b/lib/index.js @@ -62,5 +62,6 @@ module.exports.defaultChanges = function() { module.exports.HydrationError = function(message) { this.name = 'HydrationError'; this.message = (message || "").toString(); + this._hydrationError = true; }; util.inherits(module.exports.HydrationError, Error); diff --git a/test/errors.js b/test/errors.js index 47d8fdd..d8e1589 100644 --- a/test/errors.js +++ b/test/errors.js @@ -2,20 +2,11 @@ require('should'); var request = require('supertest'); -var restify = require('restify'); - var anyfetchFileHydrater = require('../lib/'); -var buggyHydrater = function() { - // Fake async stuff - process.nextTick(function() { - throw new Error("I'm buggy"); - }); -}; - describe('Errors', function() { var config = { - hydrater_function: buggyHydrater, + hydrater_function: __dirname + '/hydraters/buggy-hydrater.js', logger: function() {// Will be pinged with error. We don't care. }, errLogger: function() {// Will be pinged with error. We don't care. @@ -23,122 +14,122 @@ describe('Errors', function() { }; var hydrationServer = anyfetchFileHydrater.createServer(config); - it('should be handled gracefully while hydrating', function(done) { - this.timeout(10000); - request(hydrationServer).post('/hydrate') - .send({ - file_path: 'http://anyfetch.com', - callback: 'http://anyfetch.com/result', - document: { - metadata: { - "foo": "bar" - } - } - }) - .expect(204) - .end(function() {}); - - hydrationServer.queue.drain = function(err) { - hydrationServer.queue.drain = null; - done(err); - }; - }); - it('should be handled gracefully with long_poll option while hydrating', function(done) { - this.timeout(10000); + describe('in lib', function() { + var fakeApi = require('./helpers/fake-api.js')(); + before(function() { + fakeApi.get('/notafile', function(req, res, next) { + res.send(404); + next(); + }); + fakeApi.listen(4243); + }); - request(hydrationServer).post('/hydrate') - .send({ - file_path: 'http://anyfetch.com', - callback: 'http://anyfetch.com/result', - document: { - metadata: { - "foo": "bar" - }, - }, - 'long_poll': true - }) - .expect(400) - .expect(/err/i) - .expect(/buggy/i) - .expect(400) - .end(done); - }); + after(function() { + fakeApi.close(); + }); - it('should be handled gracefully if file does not exists', function(done) { - this.timeout(10000); + it('should be handled gracefully while hydrating', function(done) { + this.timeout(10000); + request(hydrationServer).post('/hydrate') + .send({ + file_path: 'http://127.0.0.1:4243/afile', + callback: 'http://127.0.0.1:4243/result', + document: { + metadata: { + "foo": "bar" + } + } + }) + .expect(204) + .end(function() {}); + + hydrationServer.queue.drain = function(err) { + hydrationServer.queue.drain = null; + done(err); + }; + }); - request(hydrationServer).post('/hydrate') - .send({ - file_path: 'http://anyfetch.com/NOPE?some_query', - callback: 'http://anyfetch.com/result?some_query', - document: { - metadata: { - "foo": "bar" + it('should be handled gracefully with long_poll option while hydrating', function(done) { + request(hydrationServer).post('/hydrate') + .send({ + file_path: 'http://127.0.0.1:4243/afile', + callback: 'http://127.0.0.1:4243/result', + document: { + metadata: { + "foo": "bar" + }, }, - }, - 'long_poll': true - }) - .expect(400) - .expect(/err/i) - .expect(/downloading file/i) - .expect(/404/i) - .end(done); - }); -}); + 'long_poll': true + }) + .expect(400) + .expect(/err/i) + .expect(/buggy/i) + .end(done); + }); -describe('hydrationErrors', function() { - var erroredHydrater = function(path, document, changes, cb) { - // Fake async stuff - process.nextTick(function() { - cb(new anyfetchFileHydrater.HydrationError("hydrater errored")); + it('should be handled gracefully if file does not exists', function(done) { + this.timeout(10000); + request(hydrationServer).post('/hydrate') + .send({ + file_path: 'http://127.0.0.1:4243/notafile', + callback: 'http://127.0.0.1:4243/result', + document: { + metadata: { + "foo": "bar" + }, + }, + 'long_poll': true + }) + .expect(400) + .expect(/err/i) + .expect(/downloading file/i) + .end(done); }); - }; + }); - var config = { - hydrater_function: erroredHydrater, - logger: function() {// Will be pinged with error. We don't care. - } - }; - var hydrationErrorServer = anyfetchFileHydrater.createServer(config); + describe('in hydrators', function() { + var config = { + hydrater_function: __dirname + '/hydraters/errored-hydrater.js', + logger: function() {// Will be pinged with error. We don't care. + } + }; + var hydrationErrorServer = anyfetchFileHydrater.createServer(config); - it('should be handled gracefully while hydrating', function(done) { - this.timeout(10000); + it('should be handled gracefully while hydrating', function(done) { + var fakeApi = require('./helpers/fake-api.js')(); + fakeApi.patch('/result', function(req, res, next) { + res.send(204); + next(); - var fakeApi = restify.createServer(); - fakeApi.use(restify.queryParser()); - fakeApi.use(restify.bodyParser()); + if(req.params.hydration_errored && req.params.hydration_error === "hydrater errored") { + done(); + } + else { + done(new Error("Invalid call")); + } + fakeApi.close(); - fakeApi.patch('/result', function(req, res, next) { - //should - res.send(204); - next(); + }); - if(req.params.hydration_errored && req.params.hydration_error === "hydrater errored") { - done(); - } - else { - done(new Error("Invalid call")); - } - fakeApi.close(); - }); - fakeApi.listen(4242); + fakeApi.listen(4243); - request(hydrationErrorServer).post('/hydrate') - .send({ - file_path: 'http://anyfetch.com/', - callback: 'http://127.0.0.1:4242/result', - document: { - metadata: { - "foo": "bar" + request(hydrationErrorServer).post('/hydrate') + .send({ + file_path: 'http://127.0.0.1:4243/afile', + callback: 'http://127.0.0.1:4243/result', + document: { + metadata: { + "foo": "bar" + } } - } - }) - .expect(202) - .end(function(err) { - if(err) { - throw err; - } - }); + }) + .expect(202) + .end(function(err) { + if(err) { + throw err; + } + }); + }); }); }); diff --git a/test/helpers/fake-api.js b/test/helpers/fake-api.js new file mode 100644 index 0000000..187914e --- /dev/null +++ b/test/helpers/fake-api.js @@ -0,0 +1,17 @@ +"use strict"; + +var restify = require('restify'); +var fs = require('fs'); + +module.exports = function() { + var fakeApi = restify.createServer(); + fakeApi.use(restify.queryParser()); + fakeApi.use(restify.bodyParser()); + fakeApi.use(restify.acceptParser(fakeApi.acceptable)); + + fakeApi.get('/afile', function(req, res, next) { + fs.createReadStream(__filename).pipe(res); + next(); + }); + return fakeApi; +}; diff --git a/test/helpers/hydrater.js b/test/helpers/hydrater.js index f7d981a..ddc70ae 100644 --- a/test/helpers/hydrater.js +++ b/test/helpers/hydrater.js @@ -1,106 +1,98 @@ 'use strict'; require('should'); +var path = require("path"); +var createFakeApi = require('./fake-api.js'); +describe("hydrate()", function() { + var fakeApi = createFakeApi(); + before(function() { + fakeApi.listen(4243); + }); + after(function() { + fakeApi.close(); + }); -describe("Hydrated document", function() { - it("should have only updated changes", function(done) { - - var dummyHydrater = function(path, document, changes, cb) { - changes.metadata.hydrated = true; - - cb(null, changes); - }; - - var config = { - hydrater_function: dummyHydrater, - logger: function(str, err) { - if(err) { - throw err; + describe("Hydrated document", function() { + it("should have only updated changes", function(done) { + var config = { + hydrater_function: path.resolve(__dirname, '../hydraters/dummy-hydrater.js'), + logger: function(str, err) { + if(err) { + throw err; + } } - } - }; - var hydrate = require('../../lib/helpers/hydrater')(config.hydrater_function, config.logger); - - var task = { - callback: "http://wedontcare.com", - filepath: "/tmp/anyfetch-hydrater.test", - document: { - id: "azerty" - } - }; + }; + var hydrate = require('../../lib/helpers/hydrater')(config.hydrater_function, config.logger); + + var task = { + file_path: "http://127.0.0.1:4243/afile", + callback: "http://127.0.0.1:4243", + document: { + id: "azerty" + } + }; - hydrate(task, function(changes) { - changes.should.have.keys(["metadata"]); - done(); + hydrate(task, function(err, changes) { + changes.should.have.keys(["metadata"]); + done(); + }); }); - }); - - it("should keep Dates", function(done) { - var dummyHydrater = function(path, document, changes, cb) { - changes.creation_date = new Date(); - cb(null, changes); - }; - - var config = { - hydrater_function: dummyHydrater, - logger: function(str, err) { - if(err) { - throw err; + it("should keep Dates", function(done) { + var config = { + hydrater_function: path.resolve(__dirname, '../hydraters/update-date-hydrater.js'), + logger: function(str, err) { + if(err) { + throw err; + } + } + }; + var hydrate = require('../../lib/helpers/hydrater')(config.hydrater_function, config.logger); + var task = { + file_path: "http://127.0.0.1:4243/afile", + callback: "http://127.0.0.1:4243", + document: { + id: "azerty" } - } - }; - var hydrate = require('../../lib/helpers/hydrater')(config.hydrater_function, config.logger); - var task = { - callback: "http://wedontcare.com", - filepath: "/tmp/anyfetch-hydrater.test", - document: { - id: "azerty" - } - }; + }; - hydrate(task, function(changes) { - changes.should.have.keys(["creation_date"]); - done(); + hydrate(task, function(err, changes) { + changes.should.have.keys(["creation_date"]); + done(); + }); }); }); -}); - -describe('Timeout', function() { - it('should send an error', function(done) { - process.env.TIMEOUT = 20; + describe('Timeout', function() { + it('should send an error', function(done) { + process.env.TIMEOUT = 20; - var tooLongHydrater = function(path, document, changes, cb) { - setTimeout(function() { - cb(null, changes); - }, 1000); - }; - - var config = { - hydrater_function: tooLongHydrater, - logger: function(str, err) { - if(err) { - throw err; + var config = { + hydrater_function: path.resolve(__dirname, '../hydraters/too-long-hydrater.js'), + logger: function(str, err) { + if(err) { + throw err; + } } - } - }; - var hydrate = require('../../lib/helpers/hydrater.js')(config.hydrater_function, config.logger); - - var task = { - callback: "http://wedontcare.com", - filepath: "/tmp/anyfetch-hydrater.test", - document: { - id: "azerty" - } - }; - - hydrate(task, function(changes) { - changes.should.have.property('hydration_errored', true); - process.env.TIMEOUT = 60 * 1000; - done(); + }; + var hydrate = require('../../lib/helpers/hydrater.js')(config.hydrater_function, config.logger); + + var task = { + file_path: "http://127.0.0.1:4243/afile", + callback: "http://127.0.0.1:4243", + document: { + id: "azerty" + } + }; + + hydrate(task, function(err, changes) { + changes.should.have.property('hydration_errored', true); + changes.should.have.property('hydration_error', 'Task took too long.'); + process.env.TIMEOUT = 60 * 1000; + done(err); + }); }); }); }); diff --git a/test/hook.js b/test/hook.js index 6a1a7fe..75cd106 100644 --- a/test/hook.js +++ b/test/hook.js @@ -2,82 +2,49 @@ require('should'); var request = require('supertest'); -var restify = require('restify'); -var fs = require('fs'); - - +var fs = require("fs"); var anyfetchFileHydrater = require('../lib/'); +var createFakeApi = require('./helpers/fake-api.js'); describe('/hydrate webhooks', function() { - // Patch AnyFetch URL - // Avoid uselessly pinging anyfetch.com with invalid requests - process.env.ANYFETCH_API_URL = 'http://localhost'; - - var dummyHydrater; - var hydrationFunction = function(path, document, changes, cb) { - dummyHydrater(path, document, changes, cb); - }; - var config = { - hydrater_function: hydrationFunction, - logger: function(str, err) { - if(err) { - throw err; - } - } - }; - var hydrationServer = anyfetchFileHydrater.createServer(config); - - // Create a fake HTTP server to send a file and test results - var fileServer = restify.createServer(); - fileServer.use(restify.acceptParser(fileServer.acceptable)); - fileServer.use(restify.queryParser()); - fileServer.use(restify.bodyParser()); - - fileServer.get('/file', function(req, res, next) { - fs.createReadStream(__filename).pipe(res); - next(); - }); - fileServer.listen(1337); - - var patchFunction; - fileServer.patch('/result', function(req, res, next) { - patchFunction(req, res, next); - }); - it('should be pinged with hydrater result', function(done) { - dummyHydrater = function(path, document, changes, cb) { - if(document.replace) { - return cb(); + var config = { + hydrater_function: __dirname + '/hydraters/useful-hydrater.js', + logger: function(str, err) { + if(err) { + throw err; + } } - - changes.metadata.path = path; - changes.metadata.text = fs.readFileSync(path).toString(); - - cb(null, changes); }; + var hydrationServer = anyfetchFileHydrater.createServer(config); - patchFunction = function(req, res, next) { + var fakeApi = createFakeApi(); + fakeApi.patch('/result', function(req, res, next) { try { req.params.should.have.property('metadata'); req.params.metadata.should.not.have.property('foo'); req.params.metadata.should.have.property('path'); - req.params.metadata.should.have.property('text', fs.readFileSync(__filename).toString()); + req.params.metadata.should.have.property('text', fs.readFileSync(__dirname + '/helpers/fake-api.js').toString()); res.send(204); next(); done(); + fakeApi.close(); } catch(e) { // We need a try catch cause mocha is try-catching on main event loop, and the server create a new stack. done(e); + fakeApi.close(); } - }; + }); + + fakeApi.listen(4243); request(hydrationServer).post('/hydrate') .send({ - file_path: 'http://127.0.0.1:1337/file', - callback: 'http://127.0.0.1:1337/result', + file_path: 'http://127.0.0.1:4243/afile', + callback: 'http://127.0.0.1:4243/result', document: { metadata: { "foo": "bar" @@ -89,18 +56,29 @@ describe('/hydrate webhooks', function() { }); it('should not be pinged on skipped task', function(done) { - dummyHydrater = function(path, document, changes, cb) { - return cb(null, null); + var config = { + hydrater_function: __dirname + '/hydraters/skipper-hydrater.js', + logger: function(str, err) { + if(err) { + throw err; + } + } }; + var hydrationServer = anyfetchFileHydrater.createServer(config); - patchFunction = function() { + var fakeApi = createFakeApi(); + fakeApi.patch('/result', function(req, res, next) { done(new Error("should not be called")); - }; + next(); + fakeApi.close(); + }); + + fakeApi.listen(4243); request(hydrationServer).post('/hydrate') .send({ - file_path: 'http://127.0.0.1:1337/file', - callback: 'http://127.0.0.1:1337/result', + file_path: 'http://127.0.0.1:4243/afile', + callback: 'http://127.0.0.1:4243/result', document: { metadata: { "foo": "bar" @@ -113,13 +91,9 @@ describe('/hydrate webhooks', function() { var interval = setInterval(function() { if(hydrationServer.queue.length() === 0) { clearInterval(interval); + fakeApi.close(); done(); } }, 25); - - }); - - after(function() { - fileServer.close(); }); }); diff --git a/test/hydraters/buggy-hydrater.js b/test/hydraters/buggy-hydrater.js new file mode 100644 index 0000000..6d8f6be --- /dev/null +++ b/test/hydraters/buggy-hydrater.js @@ -0,0 +1,5 @@ +"use strict"; + +module.exports = function buggyHydrater() { + throw new Error("I'm buggy"); +}; diff --git a/test/hydraters/dummy-hydrater.js b/test/hydraters/dummy-hydrater.js new file mode 100644 index 0000000..41eab75 --- /dev/null +++ b/test/hydraters/dummy-hydrater.js @@ -0,0 +1,6 @@ +"use strict"; + +module.exports = function dummyHydrater(path, document, changes, cb) { + changes.metadata.hydrated = true; + cb(null, changes); +}; diff --git a/test/hydraters/errored-hydrater.js b/test/hydraters/errored-hydrater.js new file mode 100644 index 0000000..95c5dad --- /dev/null +++ b/test/hydraters/errored-hydrater.js @@ -0,0 +1,7 @@ +"use strict"; + +var anyfetchFileHydrater = require('../../lib/'); + +module.exports = function erroredHydrater(path, document, changes, cb) { + cb(new anyfetchFileHydrater.HydrationError("hydrater errored")); +}; diff --git a/test/hydraters/skipper-hydrater.js b/test/hydraters/skipper-hydrater.js new file mode 100644 index 0000000..1405f1d --- /dev/null +++ b/test/hydraters/skipper-hydrater.js @@ -0,0 +1,5 @@ +"use strict"; + +module.exports = function dummyHydrater(path, document, changes, cb) { + return cb(null, null); +}; diff --git a/test/hydraters/too-long-hydrater.js b/test/hydraters/too-long-hydrater.js new file mode 100644 index 0000000..41f8a3d --- /dev/null +++ b/test/hydraters/too-long-hydrater.js @@ -0,0 +1,8 @@ +"use strict"; + +module.exports = function tooLongHydrater(path, document, changes, cb) { + setTimeout(function() { + changes.changed = true; + cb(null, changes); + }, 1000); +}; diff --git a/test/hydraters/update-date-hydrater.js b/test/hydraters/update-date-hydrater.js new file mode 100644 index 0000000..e80decd --- /dev/null +++ b/test/hydraters/update-date-hydrater.js @@ -0,0 +1,6 @@ +"use strict"; + +module.exports = function updateDateHydrater(path, document, changes, cb) { + changes.creation_date = new Date(); + cb(null, changes); +}; diff --git a/test/hydraters/useful-hydrater.js b/test/hydraters/useful-hydrater.js new file mode 100644 index 0000000..9cbf514 --- /dev/null +++ b/test/hydraters/useful-hydrater.js @@ -0,0 +1,9 @@ +"use strict"; + +var fs = require("fs"); + +module.exports = function usefulHydrater(path, document, changes, cb) { + changes.metadata.path = path; + changes.metadata.text = fs.readFileSync(path).toString(); + cb(null, changes); +}; diff --git a/test/index.js b/test/index.js index fdb51c9..917392d 100644 --- a/test/index.js +++ b/test/index.js @@ -5,15 +5,8 @@ var request = require('supertest'); var async = require('async'); var anyfetchFileHydrater = require('../lib/'); - -var dummyHydrater = function(path, document, changes, cb) { - changes.metadata.hydrated = true; - - cb(null, changes); -}; - var config = { - hydrater_function: dummyHydrater, + hydrater_function: __dirname + '/hydraters/dummy-hydrater.js', logger: function(str, err) { if(err) { throw err; @@ -22,13 +15,26 @@ var config = { }; describe('POST /hydrate', function() { + var fakeApi = require('./helpers/fake-api.js')(); + before(function() { + + fakeApi.patch('/callback', function(req, res, next) { + res.send(204); + next(); + }); + fakeApi.listen(4243); + }); + + after(function() { + fakeApi.close(); + }); var server = anyfetchFileHydrater.createServer(config); it('should refuse request without callback', function(done) { request(server).post('/hydrate') .send({ - 'file_path': 'http://anyfetch.com/file', + 'file_path': 'http://127.0.0.1:4243/afile', 'document': { 'metadata': {}, } @@ -40,7 +46,7 @@ describe('POST /hydrate', function() { it('should accept request without callback when long_polling', function(done) { request(server).post('/hydrate') .send({ - 'file_path': 'http://anyfetch.com', + 'file_path': 'http://127.0.0.1:4243/afile', 'long_poll': true, 'document': { 'metadata': {}, @@ -55,8 +61,8 @@ describe('POST /hydrate', function() { request(server) .post('/hydrate') .send({ - 'file_path': 'http://anyfetch.com/', - 'callback': 'http://anyfetch.com/callback', + 'file_path': 'http://127.0.0.1:4243/afile', + 'callback': 'http://127.0.0.1:4243/callback', 'document': { 'metadata': {}, } @@ -71,8 +77,8 @@ describe('POST /hydrate', function() { request(server) .post('/hydrate') .send({ - 'file_path': 'http://anyfetch.com/', - 'callback': 'http://anyfetch.com/callback', + 'file_path': 'http://127.0.0.1:4243/afile', + 'callback': 'http://127.0.0.1:4243/callback', 'long_poll': true, 'document': { 'metadata': {},