Repository: node-nock/nock (js)

Issue:
allowUnmocked causes no requests to match when query is specified
``` javascript
var nock=require('nock'),
request=require('request');

nock('https://www.google.com', 
    { allowUnmocked: true })
    .log(console.log)
    .get("/abc")
    .query({'user':'fred'})
    .reply(200, "Match!")

request('https://www.google.com/abc?user=fred', function (error, response, body) {
    if (!error && response.statusCode == 200) {
        console.log(body);
    } else{
        console.log(error ? "error: " + error : "response.statusCode: "+ response.statusCode);
    }
});
```

With the code above, my request does NOT match and goes to google.com.
$ node nockTest.js 
response.statusCode: 404

By changing allowUnmocked to false, I get:

$ node nockTest.js 
matching https://www.google.com:443?user=fred to GET https://www.google.com:443/abc with query({"user":"fred"}): true
Match!

I am able to work around this and keep allowUnmocked=true by using a filteringPath to remove the query. Is this a bug or am I missing something here? Thanks!


Pull request:
Fix #490
fixes #490

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 25ed21a..c87af73 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,15 @@
+9.0.22 / 2017-09-27
+===================
+
+  * fix: query string recording where value is an array ([#917](https://github.com/node-nock/nock/issues/917))
+  * docs(README): link to license file, link to contributors, update Copyright years
+  * chore(LICENSE): MIT
+  * chore(CHANGELOG): v9.0.21
+
 9.0.21 / 2017-09-25
 ===================
 
+  * 9.0.21
   * fix: compare falsy header values & numbers correctly
   * test: match number header values
   * multiple interceptors override headers from unrelated requests
@@ -190,9 +199,3 @@
   * 9.0.7: Fix for [#610](https://github.com/node-nock/nock/issues/610)
   * Merge pull request [#829](https://github.com/node-nock/nock/issues/829) from yodeyer/fixQs
     Fix interceptor if query have no query strings
-  * chore(package): update superagent to version 3.5.0
-    https://greenkeeper.io/
-  * fix for the "fix matchBody for multipart requests [#425](https://github.com/node-nock/nock/issues/425)"
-  * Test against request 2.79.0, with which timeout issue occured.
-  * Add Visual Studio Code folder into gitignore
-  * Update the failed test case
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..ccfa6f7
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 Pedro Teixeira and other contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index 55bcc0e..6cb7bff 100644
--- a/README.md
+++ b/README.md
@@ -1392,12 +1392,6 @@ $ npm test
 
 # License
 
-(The MIT License)
+[MIT](LICENSE)
 
-Copyright (c) 2011-2015 Pedro Teixeira. http://about.me/pedroteixeira
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+Copyright (c) 2011-2017 [Pedro Teixeira](http://about.me/pedroteixeira) and other [contributors](https://github.com/node-nock/nock/graphs/contributors).
diff --git a/lib/interceptor.js b/lib/interceptor.js
index a29c1f3..d7f7376 100755
--- a/lib/interceptor.js
+++ b/lib/interceptor.js
@@ -316,10 +316,10 @@ Interceptor.prototype.match = function match(options, body, hostNameOnly) {
 
     // special logger for query()
     if (queryIndex !== -1) {
-        this.scope.logger('matching ' + matchKey + '?' + queryString + ' to ' + this._key +
+        this.scope.logger('matching ' + matchKey + path + '?' + queryString + ' to ' + this._key +
             ' with query(' + stringify(this.queries) + '): ' + matches);
     } else {
-        this.scope.logger('matching ' + matchKey + ' to ' + this._key + ': ' + matches);
+        this.scope.logger('matching ' + matchKey + path + ' to ' + this._key + ': ' + matches);
     }
 
     if (matches) {
@@ -339,6 +339,8 @@ Interceptor.prototype.matchIndependentOfBody = function matchIndependentOfBody(o
         , path = options.path
         , proto = options.proto;
 
+    path = path.split('?')[0];
+
     if (this.scope.transformPathFunction) {
         path = this.scope.transformPathFunction(path);
     }
diff --git a/lib/recorder.js b/lib/recorder.js
index 9881d3d..e98474d 100644
--- a/lib/recorder.js
+++ b/lib/recorder.js
@@ -8,6 +8,7 @@ var debug = require('debug')('nock.recorder');
 var _ = require('lodash');
 var URL = require('url');
 var semver = require('semver')
+var qs = require('qs');
 
 var SEPARATOR = '\n<<<<<<-- cut here -->>>>>>\n';
 var recordingInProgress = false;
@@ -110,15 +111,12 @@ function generateRequestAndResponse(req, bodyChunks, options, res, dataChunks) {
   var queryIndex = 0;
   var queryObj = {};
   if ((queryIndex = req.path.indexOf('?')) !== -1) {
+    // Remove the query from the path
     path = path.substring(0, queryIndex);
 
     // Create the query() object
-    var queries = req.path.slice(queryIndex + 1).split('&');
-
-    for (var i = 0; i < queries.length; i++) {
-      var query = queries[i].split('=');
-      queryObj[query[0]] = query[1];
-    }
+    var queryStr = req.path.slice(queryIndex + 1);
+    queryObj = qs.parse(queryStr);
   }
 
   var ret = [];
diff --git a/package.json b/package.json
index 364379c..6956f36 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,7 @@
     "testing",
     "isolation"
   ],
-  "version": "9.0.21",
+  "version": "9.0.22",
   "author": "Pedro Teixeira <pedro.teixeira@gmail.com>",
   "contributors": [
     {


Test patch:
diff --git a/tests/test_intercept.js b/tests/test_intercept.js
index 962cf8f..1050545 100644
--- a/tests/test_intercept.js
+++ b/tests/test_intercept.js
@@ -5098,7 +5098,7 @@ test('match multiple paths to domain using regexp with allowUnmocked (#835)', fu
     .reply(200, imgResponse);
 
   var scope2 = nock(/google/, nockOpts)
-    .get(/search\?/)
+    .get(/search/)
     .reply(200, searchResponse);
 
 
@@ -5171,6 +5171,32 @@ test('multiple interceptors override headers from unrelated request', function (
   });
 });
 
+test('match when query is specified with allowUnmocked (#490)', function (t) {
+  nock.cleanAll();
+
+  var nockOpts = { allowUnmocked: true };
+  var searchResponse = 'Matched body';
+
+  var scope = nock('http://www.google.com/', nockOpts)
+    .get('/search')
+    .query({q: 'js'})
+    .reply(200, searchResponse);
+
+
+  mikealRequest.get('http://www.google.com', function (err, res, body) {
+    t.type(err, 'null');
+    t.equal(res.statusCode, 200);
+
+    mikealRequest.get('http://www.google.com/search?q=js', function (err, res, body) {
+      scope.done();
+      t.type(err, 'null');
+      t.equal(res.statusCode, 200);
+      t.equal(body, searchResponse);
+      t.end();
+    });
+  });
+});
+
 test("teardown", function(t) {
   var leaks = Object.keys(global)
     .splice(globalCount, Number.MAX_VALUE);
diff --git a/tests/test_recorder.js b/tests/test_recorder.js
index 1030c70..9f8ddc6 100644
--- a/tests/test_recorder.js
+++ b/tests/test_recorder.js
@@ -810,6 +810,34 @@ test('outputs query string parameters using query()', {skip: process.env.AIRPLAN
   });
 });
 
+test('outputs query string arrays correctly', {skip: process.env.AIRPLANE}, function(t) {
+  nock.restore();
+  nock.recorder.clear();
+  t.equal(nock.recorder.play().length, 0);
+
+  nock.recorder.rec(true);
+
+  var makeRequest = function(callback) {
+    superagent
+      .get('https://example.com/')
+      .query({'foo':['bar', 'baz']})
+      .end(callback);
+  };
+
+  makeRequest(function(err, resp) {
+    t.ok(!err, err && err.message || 'no error');
+    t.ok(resp, 'have response');
+    t.ok(resp.headers, 'have headers');
+
+    var ret = nock.recorder.play();
+    t.equal(ret.length, 1);
+    t.type(ret[0], 'string');
+    var match = "\nnock('https://example.com:443', {\"encodedQueryParams\":true})\n  .get('/')\n  .query({\"foo\":[\"bar\",\"baz\"]})\n  .reply(";
+    t.equal(ret[0].substring(0, match.length), match);
+    t.end();
+  });
+});
+
 test('removes query params from from that path and puts them in query()', {skip: process.env.AIRPLANE}, function(t) {
   nock.restore();
   nock.recorder.clear();