diff --git a/lib/index.js b/lib/index.js index 5287e4ead0..461cb54379 100644 --- a/lib/index.js +++ b/lib/index.js @@ -106,11 +106,9 @@ Server.prototype.serveClient = function(v){ if (!arguments.length) return this._serveClient; this._serveClient = v; var resolvePath = function(file){ - var filepath = path.resolve(__dirname, './../../', file); - if (exists(filepath)) { - return filepath; - } - return require.resolve(file); + // resolve the client dep. The resulting string ends with `lib/index.js` + var clientPath = require.resolve('socket.io-client'); + return path.normalize(path.join(path.dirname(clientPath), '..', '..', file)); }; if (v && !clientSource) { clientSource = read(resolvePath( 'socket.io-client/dist/socket.io.js'), 'utf-8'); @@ -123,6 +121,15 @@ Server.prototype.serveClient = function(v){ return this; }; +/** + * Empties cache of client code. + * @api public + */ +Server.prototype.clearClientCodeCache = function(){ + clientSource = undefined; + clientSourceMap = undefined; +} + /** * Old settings for backwards compatibility */ diff --git a/test/fixtures/create-fake-socket.io-client-module.js b/test/fixtures/create-fake-socket.io-client-module.js new file mode 100644 index 0000000000..573d2fbddc --- /dev/null +++ b/test/fixtures/create-fake-socket.io-client-module.js @@ -0,0 +1,65 @@ +var fs = require('fs'); +var join = require('path').join; +var io = require('../../lib'); + +var testHadToCreateFakeModule = false +var fakeModuleLocation = '../socket.io-client' +var socketIOClientMainFilePath = fakeModuleLocation + '/dist/socket.io.js' + +before(function(){ + // set up at fake socket.io-client module sitting at ../.. (sibling to socket.io folder). Emulates being on the same level inside a node_modules folder + // http.Server should ignore the fake module, and use the one in socket.io/node_modules/socket.io-client + try { + fs.mkdirSync(fakeModuleLocation); + testHadToCreateFakeModule = true; + } catch (_) {} + + // load fake package.json + var fakePackageFixture = fs.readFileSync('./test/fixtures/package.json'); + // place fake package.json, if necessary + try { + fs.writeFileSync(fakeModuleLocation + '/package.json', fakePackageFixture, { flag: 'wx' }); + // 'wx' mode fails if the file exists + } catch (_) {} + + try { + fs.mkdirSync(fakeModuleLocation + '/dist'); + } catch (_) {} + + // temporarily put away the real main file, if it exists + try { + fs.renameSync(socketIOClientMainFilePath, socketIOClientMainFilePath + '.temp') + } catch (_) {} + // write in the fake main file + fs.writeFileSync(socketIOClientMainFilePath, '\'im a fake socket.io-client\''); + + io().clearClientCodeCache(); +}) + +after(function(){ + // put the temp file back into place, if it exists + try { + fs.renameSync(socketIOClientMainFilePath + '.temp', socketIOClientMainFilePath) + } catch (_) {} + + if (testHadToCreateFakeModule) { + // delete whole folder + var deleteFolderRecursive = function(path) { + if (fs.existsSync(path)) { + fs.readdirSync(path).forEach((file, index) => { + var curPath = join(path, file); + if (fs.lstatSync(curPath).isDirectory()) { // recurse + deleteFolderRecursive(curPath); + } else { // delete file + fs.unlinkSync(curPath); + } + }); + fs.rmdirSync(path); + } + }; + + deleteFolderRecursive(fakeModuleLocation); + } + + io().clearClientCodeCache(); +}); \ No newline at end of file diff --git a/test/fixtures/package.json b/test/fixtures/package.json new file mode 100644 index 0000000000..32e41892e9 --- /dev/null +++ b/test/fixtures/package.json @@ -0,0 +1,8 @@ +{ + "name": "socket.io-client", + "version": "2.3.0", + "keywords": [ + "this package.json is a fixture for a socket.io test" + ], + "main": "./lib/index" + } \ No newline at end of file diff --git a/test/socket.io.js b/test/socket.io.js index 337f2ebd4a..870d38385e 100644 --- a/test/socket.io.js +++ b/test/socket.io.js @@ -205,6 +205,23 @@ describe('socket.io', function(){ done(); }); }); + + describe('when serving the socket.io-client lib', function(){ + require('./fixtures/create-fake-socket.io-client-module.js') + + it('should serve the closest socket.io-client module it can find', function(done){ + var srv = http(); + io(srv); + request(srv) + .get('/socket.io/socket.io.js') + .buffer(true) + .end(function(err, res){ + if (err) return done(err); + expect(res.text).to.not.match(/im a fake socket\.io-client/); + done(); + }) + }); + }); }); describe('port', function(done){