Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix up regex, fails test for #79(!) #94

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 41 additions & 30 deletions lib/canned.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,41 +108,52 @@ function isContentTypeJson(request) {
return isJson;
}

/**
* _parseOptions takes a single line from a file and extracts
* JSON data if possible. Returns an object.
*/
Canned.prototype._parseOptions = function(line) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this does not need to be on the prototype as it is only used inside the file as far as I can see.

try {
line = line.replace("//!", '')
var content = line.split(',').map(function (s) {
var parts = s.split(':');
parts[0] = '"' + parts[0].trim() + '"'
return parts.join(':')
}).join(',')

return JSON.parse('{' + content + '}')
} catch(e) {
that._log('Invalid file header format try //! statusCode: 201')
return {};
}
}

Canned.prototype.parseMetaData = function(response) {
var metaData = {}
var metaData = {},
lines,
that = this,
optionsMatch = new RegExp(/\/\/!.*(?:statusCode|contentType|customHeaders)/),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/g is important as otherwise only the first match will be processed.

requestMatch = new RegExp(/\/\/!.*(?:body|params|header):\s+([\w {}":\[\]\-\+\%,@.\/]*)/)

// convert CR+LF => LF+LF, CR => LF, fixes line breaks causing issues in windows
response = response.replace("\r", "\n");
var lines = response.split("\n")
var that = this

var optionsMatch = new RegExp(/\/\/!.*[statusCode|contentType|customHeaders]/g)
var requestMatch = new RegExp(/\/\/! [body|params|header]+: ([\w {}":\[\]\-\+\%,@.\/]*)/g)
// we only care about special comment lines
lines = response.split("\n").filter(function(line) {
return line.indexOf("//!") === 0;
})

lines.forEach(function(line) {
if(line.indexOf("//!") === 0) { // special comment line
var matchedRequest = requestMatch.exec(line)
if(matchedRequest) {
metaData.request = JSON.parse(matchedRequest[1])
stringifyValues(metaData.request);
return
}
var matchedOptions = optionsMatch.exec(line)
if(matchedOptions) {
try {
line = line.replace("//!", '')
var content = line.split(',').map(function (s) {
var parts = s.split(':');
parts[0] = '"' + parts[0].trim() + '"'
return parts.join(':')
}).join(',')
var opts = JSON.parse('{' + content + '}')
cannedUtils.extend(metaData, opts)
} catch(e) {
that._log('Invalid file header format try //! statusCode: 201')
}
return
}
var matchedRequest = requestMatch.exec(line)
if (matchedRequest) {
metaData.request = JSON.parse(matchedRequest[1])
stringifyValues(metaData.request);
return
}

var matchedOptions = optionsMatch.exec(line)
if (matchedOptions) {
cannedUtils.extend(metaData, that._parseOptions(line))
}
})

Expand Down Expand Up @@ -314,7 +325,7 @@ Canned.prototype.responder = function(body, req, res) {
}
}
}

var paths = lookup(httpObj.pathname.join('/'), that.wildcard);
paths.splice(0,1); // The first path is the default
responseHandler = function (err, resp) {
Expand Down Expand Up @@ -397,4 +408,4 @@ Canned.prototype.responseFilter = function (req, res) {
}
}

module.exports = Canned;
module.exports = Canned;
91 changes: 91 additions & 0 deletions spec/canned.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,97 @@ describe('canned', function () {
})
})

describe("parsing metadata", function() {
it("Should accept statusCode", function(done) {
var Canned = require('../lib/canned')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't need to require in the scope here I think, we can require once and reuse.

var can = new Canned('./spec/test_responses', {});
var mock_text = '//! statusCode: 418';
var parsedMeta = can.parseMetaData(mock_text);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the tests, should we maybe create a ResponseFileParser which contains all thoses methods? This also makes the tests much easier as you would just need to require and use the ResponseFileParser here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had intended to move the parsing code out into a module in future, I think it'll help hide away some of the gnarly stuff and also let us test it in isolation more neatly.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that is what I was thinking, what I think is that all the fileParsing canned does kind of belongs together that is why I was thinking of a ResponseFileParser... but feel free to experiment.


expect(parsedMeta).toEqual({
statusCode: 418
});
done();
})

it("Should accept customHeaders", function(done) {
var Canned = require('../lib/canned')
var can = new Canned('./spec/test_responses', {});
var mock_text = '//! statusCode: 418\n' +
'//! customHeaders: {"Authorization": "Bearer xyz"}';
var parsedMeta = can.parseMetaData(mock_text);

expect(parsedMeta).toEqual({
statusCode: 418,
customHeaders: {
Authorization: 'Bearer xyz'
}
});
done();
})

it("Should accept request body", function(done) {
var Canned = require('../lib/canned')
var can = new Canned('./spec/test_responses', {});
var mock_text = '//! statusCode: 418\n' +
'//! customHeaders: {"Authorization": "Bearer xyz"}\n' +
'//! body: {"colour": "green"}';
var parsedMeta = can.parseMetaData(mock_text);

expect(parsedMeta).toEqual({
statusCode: 418,
customHeaders: {
Authorization: 'Bearer xyz'
},
request: {
colour: 'green'
}
});
done();
})

it("Should accept request body", function(done) {
var Canned = require('../lib/canned')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to require in the function, just require once and use it.

var can = new Canned('./spec/test_responses', {});
var mock_text = '//! statusCode: 418\n' +
'//! customHeaders: {"Authorization": "Bearer xyz"}\n' +
'//! body: {"colour": "green"}';
var parsedMeta = can.parseMetaData(mock_text);

expect(parsedMeta).toEqual({
statusCode: 418,
customHeaders: {
Authorization: 'Bearer xyz'
},
request: {
colour: 'green'
}
});
done();
})

it("Should apply the latest request params, body or header specified", function(done) {
var Canned = require('../lib/canned')
var can = new Canned('./spec/test_responses', {});
var mock_text = '//! statusCode: 418\n' +
'//! customHeaders: {"Authorization": "Bearer xyz"}\n' +
'//! body: {"colour": "green"}\n' +
'//! params: {"count": 126}';
var parsedMeta = can.parseMetaData(mock_text);

expect(parsedMeta).toEqual({
statusCode: 418,
customHeaders: {
Authorization: 'Bearer xyz'
},
request: {
count: '126',
}
});
done();
})
})

describe("variable POST responses", function() {
var req, data
beforeEach(function() {
Expand Down