Skip to content

Commit

Permalink
test/unit: match real querystring processing (#1243)
Browse files Browse the repository at this point in the history
odk-central-backend uses express's default querystring parser (qs), whereas node-mocks-http uses querystring.

See: eugef/node-mocks-http#299
  • Loading branch information
alxndrsn authored Oct 29, 2024
1 parent 8caa8c3 commit 5eef273
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 3 deletions.
2 changes: 1 addition & 1 deletion test/unit/http/endpoint.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const should = require('should');
const { EventEmitter } = require('events');
const { Transform } = require('stream');
const { createRequest, createResponse } = require('node-mocks-http');
const { createRequest, createResponse } = require('../../util/node-mocks-http');
const streamTest = require('streamtest').v2;
const { always } = require('ramda');

Expand Down
2 changes: 1 addition & 1 deletion test/unit/http/middleware.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const { createRequest } = require('node-mocks-http');
const { createRequest } = require('../../util/node-mocks-http');

const appRoot = require('app-root-path');
const middleware = require(appRoot + '/lib/http/middleware');
Expand Down
2 changes: 1 addition & 1 deletion test/unit/http/preprocessors.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const should = require('should');
const { createRequest } = require('node-mocks-http');
const { createRequest } = require('../../util/node-mocks-http');

const appRoot = require('app-root-path');
const preprocessors = require(appRoot + '/lib/http/preprocessors');
Expand Down
41 changes: 41 additions & 0 deletions test/util/node-mocks-http.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Safe wrapper for node-mocks-http - ensure that query string parsing matches
// what is happening in production. N.B. if express's `query parser` option is
// set, this wrapper will need to change too.
//
// See: https://expressjs.com/en/api.html#app.settings.table
// See: https://github.com/eugef/node-mocks-http/issues/299

const wrapped = require('node-mocks-http');

const qs = (() => {
try {
// In case express has its own version of qs, try loading that first:
return require('../../node_modules/express/node_modules/qs'); // eslint-disable-line import/extensions,import/no-unresolved
} catch (err) {
// Try loading the global qs. This is not written as `require('qs')` to avoid loading of the qs module from a surprising place.
try {
return require('../../node_modules/qs'); // eslint-disable-line import/extensions,import/no-unresolved
} catch (err) { // eslint-disable-line no-shadow
// node_modules layout may change in future (e.g. using yarn with different nodeLinker config)
throw new Error('Unexpected missing module: qs. Please confirm node_modules directory is initialised, and dependency resolution has not changed recently.');
}
}
})();

const createRequest = options => {
if (!options?.url) return wrapped.createRequest(options);

const { search } = new URL(options.url, 'http://example.test');
const { query } = options;

if (!search) return wrapped.createRequest(options);

if (query != null) throw new Error('Unsupported: .query option and query string in .url simultaneously.');

return wrapped.createRequest({ ...options, query: qs.parse(search.substr(1)) });
};

module.exports = {
createRequest,
createResponse: wrapped.createResponse,
};

0 comments on commit 5eef273

Please sign in to comment.