Skip to content

Commit

Permalink
refactor: refactor and test requiring user-provided module
Browse files Browse the repository at this point in the history
  • Loading branch information
honzajavorek committed Apr 3, 2019
1 parent d87f34f commit 2ed04d9
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 51 deletions.
12 changes: 4 additions & 8 deletions lib/Dredd.js
@@ -1,7 +1,6 @@
const async = require('async');
const clone = require('clone');
const fs = require('fs');
const path = require('path');
const request = require('request');
const url = require('url');
const parse = require('dredd-transactions/parse');
Expand All @@ -10,6 +9,7 @@ const compile = require('dredd-transactions/compile');
const configureReporters = require('./configureReporters');
const handleRuntimeProblems = require('./handleRuntimeProblems');
const resolveLocations = require('./resolveLocations');
const resolveModule = require('./resolveModule');
const logger = require('./logger');
const Runner = require('./TransactionRunner');
const { applyConfiguration } = require('./configuration');
Expand Down Expand Up @@ -43,16 +43,12 @@ class Dredd {

this.logger.debug('Resolving --require');
if (this.configuration.options.require) {
let mod = this.configuration.options.require;
const abs = fs.existsSync(mod) || fs.existsSync(`${mod}.js`);
if (abs) {
mod = path.resolve(mod);
}
const requirePath = resolveModule(this.configuration.custom.cwd, this.configuration.options.require);
try {
// eslint-disable-next-line global-require, import/no-dynamic-require
require(mod);
require(requirePath);
} catch (err) {
this.logger.error(`Error requiring module '${mod}':`, err.message);
this.logger.error(`Error requiring module '${requirePath}':`, err.message);
callback(err, this.stats);
return;
}
Expand Down
10 changes: 10 additions & 0 deletions lib/resolveModule.js
@@ -0,0 +1,10 @@
const fs = require('fs');
const path = require('path');


module.exports = function resolveModule(workingDirectory, moduleName) {
const absolutePath = path.resolve(workingDirectory, moduleName);
return fs.existsSync(absolutePath) || fs.existsSync(`${absolutePath}.js`)
? path.resolve(absolutePath)
: moduleName;
};
1 change: 1 addition & 0 deletions test/fixtures/requiredModule.js
@@ -0,0 +1 @@
global.__requiredModule = true;
107 changes: 64 additions & 43 deletions test/integration/require-test.js
@@ -1,64 +1,85 @@
const { assert } = require('chai');
const Dredd = require('../../lib/Dredd');

const {
createServer, DEFAULT_SERVER_PORT, runDredd,
} = require('./helpers');

const APIARY_PORT = DEFAULT_SERVER_PORT + 1;

const API_DESCRIPTION = './test/fixtures/single-get.apib';
const Dredd = require('../../lib/Dredd');
const { runDredd } = require('./helpers');

describe('Dredd requiring language compilers', () => {
let apiary;

before((done) => {
const app = createServer();
describe('Requiring user-provided modules (e.g. language compilers)', () => {
describe('when provided with a local module', () => {
let dreddRuntimeInfo;

app.post('/apis/*', (req, res) => res.json({
_id: '1234_id',
testRunId: '6789_testRunId',
reportUrl: 'http://example.com/test/run/1234_id',
}));
before((done) => {
delete global.__requiredModule;

app.all('*', (req, res) => res.json({}));
const dredd = new Dredd({
options: {
path: './test/fixtures/single-get.apib',
require: './test/fixtures/requiredModule',
},
});
runDredd(dredd, (err, info) => {
dreddRuntimeInfo = info;
done(err);
});
});

apiary = app.listen(APIARY_PORT, (err) => {
done(err);
it('passes no error to the callback', () => {
assert.isNotOk(dreddRuntimeInfo.err);
});
it('requires the module', () => {
assert.isTrue(global.__requiredModule);
});
});

after(done => apiary.close(done));
describe('when provided with an installed module', () => {
let dreddRuntimeInfo;

it('should work with CoffeScript', (done) => {
const dredd = new Dredd({
options: {
path: [API_DESCRIPTION],
hookfiles: ['./test/fixtures/hooks-log.coffee'],
require: 'coffeescript/register',
},
before((done) => {
const dredd = new Dredd({
options: {
path: './test/fixtures/single-get.apib',
hookfiles: './test/fixtures/hooks-log.coffee',
require: 'coffeescript/register',
},
});
runDredd(dredd, (err, info) => {
dreddRuntimeInfo = info;
done(err);
});
});

runDredd(dredd, APIARY_PORT, (error, info) => {
assert.include(info.logging, 'using hooks.log to debug');
done();
it('passes no error to the callback', () => {
assert.isNotOk(dreddRuntimeInfo.err);
});
it('requires the module', () => {
assert.include(dreddRuntimeInfo.logging, 'using hooks.log to debug');
});
});

it('should handle non-existing modules', (done) => {
const dredd = new Dredd({
options: {
path: [API_DESCRIPTION],
hookfiles: ['./test/fixtures/hooks-log.coffee'],
require: 'no-such-module',
},
describe('when provided with a non-existing module', () => {
let dreddRuntimeInfo;

before((done) => {
const dredd = new Dredd({
options: {
path: './test/fixtures/single-get.apib',
require: 'no-such-module',
},
});
runDredd(dredd, (err, info) => {
dreddRuntimeInfo = info;
done(err);
});
});

runDredd(dredd, APIARY_PORT, (error, info) => {
assert.equal(info.err.code, 'MODULE_NOT_FOUND');
assert.equal(info.err.message, 'Cannot find module \'no-such-module\'');
assert.equal(info.logging, 'error: Error requiring module \'no-such-module\': Cannot find module \'no-such-module\'\n');
done();
it('passes error to the callback', () => {
assert.instanceOf(dreddRuntimeInfo.err, Error);
});
it('the error is a native MODULE_NOT_FOUND error', () => {
assert.equal(dreddRuntimeInfo.err.code, 'MODULE_NOT_FOUND');
});
it('the error message is descriptive', () => {
assert.equal(dreddRuntimeInfo.err.message, 'Cannot find module \'no-such-module\'');
});
});
});
30 changes: 30 additions & 0 deletions test/unit/resolveModule-test.js
@@ -0,0 +1,30 @@
const path = require('path');
const { assert } = require('chai');

const resolveModule = require('../../lib/resolveModule');


describe('resolveModule()', () => {
const workingDirectory = path.join(__dirname, '..', 'fixtures');

it('resolves a local module name', () => {
assert.equal(
resolveModule(workingDirectory, 'requiredModule'),
path.join(workingDirectory, 'requiredModule')
);
});

it('resolves a local module name with .js extension', () => {
assert.equal(
resolveModule(workingDirectory, 'requiredModule.js'),
path.join(workingDirectory, 'requiredModule.js')
);
});

it('resolves an installed module name', () => {
assert.equal(
resolveModule(workingDirectory, 'coffeescript/register'),
'coffeescript/register'
);
});
});

0 comments on commit 2ed04d9

Please sign in to comment.