PageRenderTime 61ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/test/transformer.base.js

https://github.com/eiriklv/primus
JavaScript | 1251 lines | 981 code | 256 blank | 14 comment | 31 complexity | be18decee85895f8ef1cc9ff1fa1de86 MD5 | raw file
  1. 'use strict';
  2. module.exports = function base(transformer, pathname, transformer_name) {
  3. transformer_name = transformer_name || '';
  4. var EventEmitter = require('events').EventEmitter;
  5. var emitter = {
  6. server: function (primus) {
  7. primus.transform('incoming', function (packet) {
  8. var data = packet.data;
  9. if (!('object' === typeof data && 'event' in data && 'args' in data)) return;
  10. this.emit.apply(this, [data.event].concat(data.args));
  11. return false;
  12. });
  13. },
  14. client: function (primus) {
  15. primus.$emit = function trigger(event) {
  16. return this.write({
  17. event: event,
  18. args: Array.prototype.slice.call(arguments, 1)
  19. });
  20. };
  21. }
  22. };
  23. describe('Transformer: '+ (transformer_name || transformer), function () {
  24. var common = require('./common')
  25. , request = common.request
  26. , Primus = common.Primus
  27. , expect = common.expect
  28. , create = common.create
  29. , destroy
  30. , Socket
  31. , server
  32. , primus;
  33. beforeEach(function beforeEach(done) {
  34. var services = create(transformer, done, pathname);
  35. destroy = services.destroy;
  36. Socket = services.Socket;
  37. server = services.server;
  38. primus = services.primus;
  39. });
  40. afterEach(function afterEach(done) {
  41. primus.destroy(done);
  42. });
  43. describe('.Socket', function () {
  44. it('exposes a compatible socket', function () {
  45. expect(Socket).to.be.a('function');
  46. });
  47. it('emits an `open` event when its connected', function (done) {
  48. var socket = new Socket(server.addr);
  49. socket.on('open', function () {
  50. socket.end();
  51. done();
  52. });
  53. });
  54. it('exposes a .socket property', function (done) {
  55. var socket = new Socket(server.addr);
  56. socket.on('open', function () {
  57. expect(!!socket.socket).to.equal(true);
  58. socket.end();
  59. done();
  60. });
  61. });
  62. it('initialises without `new`', function (done) {
  63. var socket = Socket(server.addr, {
  64. timeout: 50000
  65. });
  66. expect(socket.options.timeout).to.equal(50000);
  67. socket.on('open', function () {
  68. socket.end();
  69. done();
  70. });
  71. });
  72. it('should not throw an error when we connect to a dead server', function (done) {
  73. var socket = new Socket('http://localhost:1024');
  74. socket.on('error', function () {
  75. done();
  76. });
  77. });
  78. it('should not open the socket if we set out state to manual', function (done) {
  79. var socket = new Socket(server.addr, {
  80. manual: true
  81. });
  82. socket.on('open', function () {
  83. throw new Error('I should be closed');
  84. });
  85. setTimeout(function () {
  86. socket.end();
  87. done();
  88. }, 100);
  89. });
  90. it('allows disabling of the reconnect functionality', function () {
  91. var socket = new Socket(server.addr, {
  92. strategy: false,
  93. manual: true
  94. });
  95. expect(socket.options.strategy).to.equal('');
  96. });
  97. it('sets reconnection strategies by default', function () {
  98. var socket = new Socket(server.addr, {
  99. manual: true
  100. });
  101. expect(socket.options.strategy).to.contain('disconnect');
  102. expect(socket.options.strategy).to.contain('timeout');
  103. expect(socket.options.strategy).to.contain('online');
  104. expect(socket.options.strategy).to.contain(',');
  105. });
  106. it('emits errors for incorrect context when theres a listener', function () {
  107. var socket = new Socket(server.addr, {
  108. manual: true
  109. }), calls = 0;
  110. try {
  111. socket.open.call(new EventEmitter());
  112. } catch (err) {
  113. expect(Object.prototype.toString.call(err)).to.equal('[object Error]');
  114. expect(err.message).to.contain('Primus#open');
  115. expect(err.message).to.contain('context');
  116. calls++;
  117. }
  118. expect(calls).to.equal(1);
  119. });
  120. it('should change readyStates', function (done) {
  121. var socket = new Socket(server.addr);
  122. expect(socket.readyState).to.equal(Socket.CLOSED);
  123. setTimeout(function () {
  124. expect(socket.readyState).to.equal(Socket.OPENING);
  125. }, 0);
  126. socket.on('open', function () {
  127. expect(socket.readyState).to.equal(Socket.OPEN);
  128. socket.end();
  129. }).on('end', function () {
  130. expect(socket.readyState).to.equal(Socket.CLOSED);
  131. done();
  132. });
  133. });
  134. it('should set the correct read/writable states', function (done) {
  135. var socket = new Socket(server.addr);
  136. expect(socket.readable).to.equal(true);
  137. expect(socket.writable).to.equal(true);
  138. socket.once('open', function () {
  139. expect(socket.readable).to.equal(true);
  140. expect(socket.writable).to.equal(true);
  141. socket.once('end', function () {
  142. expect(socket.readable).to.equal(false);
  143. expect(socket.writable).to.equal(false);
  144. socket.once('open', function () {
  145. expect(socket.readable).to.equal(true);
  146. expect(socket.writable).to.equal(true);
  147. socket.once('end', done).end();
  148. }).open();
  149. }).end();
  150. });
  151. });
  152. it('can be open and closed', function (done) {
  153. primus.on('connection', function (spark) {
  154. setTimeout(function () {
  155. spark.end();
  156. }, 10);
  157. });
  158. var socket = new Socket(server.addr);
  159. socket.once('open', function () {
  160. socket.once('end', function () {
  161. socket.open();
  162. socket.once('open', function () {
  163. socket.once('end', done);
  164. });
  165. });
  166. });
  167. });
  168. it('emits a readyStateChange event', function (done) {
  169. var socket = new Socket(server.addr)
  170. , state = socket.readyState
  171. , calls = 0;
  172. socket.on('readyStateChange', function () {
  173. expect(state).to.not.equal(socket.readyState);
  174. state = socket.readyState;
  175. calls++;
  176. });
  177. socket.on('open', function () {
  178. expect(!!socket.socket).to.equal(true);
  179. socket.end();
  180. }).on('end', function () {
  181. expect(calls).to.equal(3);
  182. done();
  183. });
  184. });
  185. it('emits an `end` event when its closed', function (done) {
  186. var socket = new Socket(server.addr);
  187. socket.on('open', function () {
  188. socket.end();
  189. }).on('end', done);
  190. });
  191. it('emits an `close` event when its closed', function (done) {
  192. var socket = new Socket(server.addr);
  193. socket.on('open', function () {
  194. socket.end();
  195. }).on('close', done);
  196. });
  197. it('only emits `end` once', function (done) {
  198. var socket = new Socket(server.addr);
  199. socket.on('open', function () {
  200. socket.end();
  201. socket.end();
  202. socket.end();
  203. socket.end();
  204. socket.end();
  205. socket.end();
  206. }).on('end', done);
  207. });
  208. it('sends & receives messages', function (done) {
  209. var socket = new Socket(server.addr);
  210. socket.on('data', function (message) {
  211. expect(message).to.equal('pong');
  212. socket.end();
  213. done();
  214. });
  215. socket.on('open', function () {
  216. socket.write({ echo: 'pong' });
  217. });
  218. });
  219. it('receives the raw packet data', function (done) {
  220. var socket = new Socket(server.addr);
  221. socket.on('data', function (message, raw) {
  222. var data = JSON.stringify(message);
  223. expect(message).to.equal('pong');
  224. expect(raw).to.not.equal(message);
  225. expect(data).to.equal(raw);
  226. socket.end();
  227. done();
  228. });
  229. socket.on('open', function () {
  230. socket.write({ echo: 'pong' });
  231. });
  232. });
  233. it('emits an `error` event when it cannot encode the data', function (done) {
  234. var socket = new Socket(server.addr);
  235. socket.on('open', function () {
  236. var data = { foo: 'bar' };
  237. data.recusrive = data;
  238. socket.write(data);
  239. }).on('error', function (err) {
  240. expect(err).to.not.be.instanceOf(String);
  241. expect(err.message).to.contain('JSON');
  242. socket.end();
  243. done();
  244. });
  245. });
  246. it('buffers messages before it connected', function (done) {
  247. var socket = new Socket(server.addr)
  248. , messages = 10
  249. , received = 0;
  250. for (var i = 0; i <= messages; i++) {
  251. socket.write({ echo: i });
  252. }
  253. socket.on('data', function (message) {
  254. expect(message).to.be.a('number');
  255. if (++received === messages) {
  256. socket.end();
  257. done();
  258. }
  259. });
  260. });
  261. it('should not reconnect when we close the connection', function (done) {
  262. var socket = new Socket(server.addr);
  263. socket.on('open', function (message) {
  264. socket.end();
  265. done();
  266. });
  267. socket.on('reconnect', function () {
  268. throw new Error('fuck');
  269. });
  270. });
  271. it('should clean up timers', function (done) {
  272. primus.on('connection', function (spark) {
  273. if (!reconnected) {
  274. reconnected = true;
  275. return spark.end(null, { reconnect: true });
  276. }
  277. spark.end();
  278. });
  279. var socket = new Socket(server.addr)
  280. , reconnected = false
  281. , closed = 0
  282. , opened = 0;
  283. socket.on('open', function () {
  284. if (++opened === 1) {
  285. expect(Object.keys(socket.timers).length).to.be.above(0);
  286. return;
  287. }
  288. expect(Object.keys(socket.timers).length).to.be.equal(0);
  289. });
  290. socket.on('close', function () {
  291. closed++;
  292. expect(Object.keys(socket.timers).length).to.equal(0);
  293. });
  294. socket.on('end', function () {
  295. expect(closed).to.be.equal(2);
  296. done();
  297. });
  298. });
  299. it('should not reconnect when strategy is false', function (done) {
  300. primus.on('connection', function (spark) {
  301. //
  302. // Kill a connection to trigger a reconnect
  303. //
  304. spark.end(null, { reconnect: true });
  305. });
  306. var socket = new Socket(server.addr, { strategy: false });
  307. socket.on('reconnect', function (message) {
  308. throw new Error('bad');
  309. });
  310. socket.on('end', done);
  311. });
  312. //
  313. // This also tests the reconnection when the connection closes unexpectedly
  314. //
  315. it('should allow to trigger a client-side reconnect from server', function (done) {
  316. primus.on('connection', function (spark) {
  317. if (!reconnected) {
  318. reconnected = true;
  319. spark.end(null, { reconnect: true });
  320. }
  321. });
  322. var socket = new Socket(server.addr)
  323. , reconnected = false
  324. , reconnect = false
  325. , opened = 0;
  326. socket.on('reconnect', function (message) {
  327. reconnect = true;
  328. });
  329. socket.on('open', function () {
  330. if (++opened !== 2) return;
  331. expect(reconnect).to.equal(true);
  332. socket.end();
  333. });
  334. socket.on('end', done);
  335. });
  336. it('should allow to stop the reconnection procedure', function (done) {
  337. primus.on('connection', function (spark) {
  338. spark.end(null, { reconnect: true });
  339. });
  340. var socket = new Socket(server.addr);
  341. socket.on('reconnecting', socket.end);
  342. socket.on('reconnect', function (message) {
  343. throw new Error('bad');
  344. });
  345. socket.on('end', done);
  346. });
  347. it('should allow access to the original HTTP request', function (done) {
  348. primus.on('connection', function (spark) {
  349. expect(spark.request).to.not.equal(undefined);
  350. expect(spark.request.headers).to.be.a('object');
  351. //
  352. // Timeout is added to ensure that a request had time to get closed.
  353. // As closed requests could add a bunch of issues.
  354. //
  355. setTimeout(function () {
  356. expect(spark.request).to.not.equal(undefined);
  357. spark.end();
  358. done();
  359. }, 100);
  360. });
  361. var socket = new Socket(server.addr);
  362. });
  363. it('should not increment the attempt if a backoff is running', function (done) {
  364. var socket = new Socket(server.addr);
  365. var backoff = {}
  366. , result = socket.backoff(function () {
  367. socket.end();
  368. }, backoff);
  369. expect(backoff.attempt).to.equal(1);
  370. expect(result).to.equal(socket);
  371. result = socket.backoff(function () {
  372. throw new Error('I should not be called yo');
  373. }, backoff);
  374. expect(backoff.attempt).to.equal(1);
  375. expect(result).to.equal(socket);
  376. socket.on('end', done);
  377. });
  378. it('should reset the reconnect details after a succesful reconnect', function (done) {
  379. var socket = new Socket(server.addr, {
  380. reconnect: {
  381. minDelay: 100,
  382. maxDelay: 2000
  383. }
  384. }), closed = 0;
  385. expect(!socket.attempt).to.equal(true);
  386. this.timeout(5000);
  387. socket.once('reconnect', function () {
  388. expect(!!socket.attempt).to.equal(true);
  389. expect(socket.attempt.attempt).to.be.above(0);
  390. expect(socket.attempt.minDelay).to.equal(100);
  391. expect(socket.attempt.maxDelay).to.equal(2000);
  392. expect(socket.attempt.timeout).to.be.below(2000);
  393. expect(socket.attempt.timeout).to.be.above(99);
  394. });
  395. socket.once('open', function () {
  396. try { server.close(); destroy(); }
  397. catch (e) { return done(e); }
  398. setTimeout(function () {
  399. var services = create(transformer, function () {}, server.portnumber);
  400. destroy = services.destroy;
  401. Socket = services.Socket;
  402. server = services.server;
  403. primus = services.primus;
  404. }, 100);
  405. socket.once('open', function () {
  406. socket.removeAllListeners('end');
  407. socket.end();
  408. // once from the reconnect, and once from the .end above
  409. expect(closed).to.equal(2);
  410. done();
  411. });
  412. });
  413. socket.on('close', function () {
  414. closed++;
  415. });
  416. socket.on('end', function () {
  417. done(new Error('I shouldnt end'));
  418. });
  419. });
  420. it('can force websocket avoidance', function (done) {
  421. var socket = new Socket(server.addr, {
  422. websockets: false
  423. });
  424. expect(socket.AVOID_WEBSOCKETS).to.equal(true);
  425. // open is done in a setTimeout 0 so if we end it now then we'll
  426. // miss the connection
  427. socket.on('open', function () {
  428. socket.end();
  429. });
  430. done();
  431. });
  432. describe('#transform', function () {
  433. it('thrown an error if an invalid type is given', function (done) {
  434. var socket = new Socket(server.addr);
  435. primus.on('connection', function (spark) {
  436. spark.end();
  437. done();
  438. });
  439. try { socket.transform('cowsack', function () {}); }
  440. catch (e) {
  441. expect(e.message).to.contain('transformer');
  442. }
  443. });
  444. describe('outgoing', function () {
  445. it('rewrites the outgoing message', function (done) {
  446. var socket = new Socket(server.addr);
  447. primus.on('connection', function (spark) {
  448. spark.on('data', function (data) {
  449. expect(data).to.be.a('object');
  450. expect(data.meta).to.equal('meta');
  451. expect(data.message).to.equal('foo');
  452. spark.end();
  453. done();
  454. });
  455. });
  456. socket.transform('outgoing', function (data) {
  457. expect(data).to.be.a('object');
  458. expect(data.data).to.equal('foo');
  459. data.data = {
  460. message: 'foo',
  461. meta: 'meta'
  462. };
  463. });
  464. socket.write('foo');
  465. });
  466. it('prevents the message from being written', function (done) {
  467. var socket = new Socket(server.addr);
  468. socket.transform('outgoing', function (data) {
  469. setTimeout(function () {
  470. socket.end();
  471. done();
  472. }, 0);
  473. return false;
  474. });
  475. socket.on('outgoing::data', function () {
  476. throw new Error('return false should prevent this emit');
  477. }).write('foo');
  478. });
  479. });
  480. describe('incoming', function () {
  481. it('rewrites the incoming message', function (done) {
  482. var socket = new Socket(server.addr);
  483. primus.on('connection', function (spark) {
  484. spark.write('foo');
  485. });
  486. socket.transform('incoming', function (data) {
  487. expect(data).to.be.a('object');
  488. expect(data.data).to.equal('foo');
  489. data.data = {
  490. message: 'foo',
  491. meta: 'meta'
  492. };
  493. });
  494. socket.on('data', function (data) {
  495. expect(data).to.be.a('object');
  496. expect(data.meta).to.equal('meta');
  497. expect(data.message).to.equal('foo');
  498. socket.end();
  499. done();
  500. });
  501. });
  502. it('prevents the message from being emitted', function (done) {
  503. var socket = new Socket(server.addr);
  504. primus.on('connection', function (spark) {
  505. spark.write('foo');
  506. });
  507. socket.transform('incoming', function (data) {
  508. setTimeout(function () {
  509. socket.end();
  510. done();
  511. }, 0);
  512. return false;
  513. });
  514. socket.on('data', function () {
  515. throw new Error('return false should prevent this emit');
  516. });
  517. });
  518. });
  519. });
  520. });
  521. describe('.createSocket', function () {
  522. it('can connect to the server', function (done) {
  523. var PSocket = Primus.createSocket({
  524. transformer: transformer,
  525. pathname: server.pathname
  526. })
  527. , socket = new PSocket(server.addr);
  528. socket.on('open', function () {
  529. socket.end();
  530. done();
  531. });
  532. });
  533. it('should accept plugins', function (done) {
  534. var PSocket = Primus.createSocket({
  535. transformer: transformer,
  536. pathname: server.pathname,
  537. plugin: {
  538. emit: emitter
  539. }
  540. })
  541. , socket = new PSocket(server.addr);
  542. expect(socket.$emit).to.be.a('function');
  543. socket.on('open', function () {
  544. socket.end();
  545. done();
  546. });
  547. });
  548. });
  549. describe('Authorization', function () {
  550. it('support declined authorization', function (done) {
  551. primus.authorize(function auth(req, next) {
  552. expect(req.headers).to.be.a('object');
  553. next(new Error('I failed'));
  554. });
  555. primus.on('connection', function (spark) {
  556. throw new Error('Auth should be called');
  557. });
  558. var Socket = Primus.createSocket({
  559. transformer: transformer,
  560. pathname: server.pathname,
  561. authorization: true
  562. })
  563. , socket = new Socket(server.addr);
  564. socket.on('end', done);
  565. socket.on('reconnect', function () {
  566. throw new Error('fuck');
  567. });
  568. });
  569. it('support declined authorization with status code', function (done) {
  570. primus.authorize(function auth(req, next) {
  571. expect(req.headers).to.be.a('object');
  572. var err = new Error('I failed');
  573. err.statusCode = 404;
  574. next(err);
  575. });
  576. primus.on('connection', function (spark) {
  577. throw new Error('Auth should be called');
  578. });
  579. var Socket = Primus.createSocket({
  580. transformer: transformer,
  581. pathname: server.pathname,
  582. authorization: true
  583. })
  584. , socket = new Socket(server.addr);
  585. socket.on('end', done);
  586. socket.on('reconnect', function () {
  587. throw new Error('fuck');
  588. });
  589. });
  590. it('support declined authorization with message and www-authenticate header', function (done) {
  591. primus.authorize(function auth(req, next) {
  592. expect(req.headers).to.be.a('object');
  593. var err = new Error('I failed');
  594. err.authenticate = 'Basic realm="primus"';
  595. next(err);
  596. });
  597. primus.on('connection', function (spark) {
  598. throw new Error('Auth should be called');
  599. });
  600. var Socket = Primus.createSocket({
  601. transformer: transformer,
  602. pathname: server.pathname,
  603. authorization: true
  604. })
  605. , socket = new Socket(server.addr);
  606. socket.on('outgoing::open', function () {
  607. if (socket.socket.on) {
  608. socket.socket.on('unexpected-response', function (req, res) {
  609. expect(res.statusCode).to.equal(401);
  610. expect(res.headers['www-authenticate']).to.equal('Basic realm="primus"');
  611. var data = '';
  612. res.on('data', function (v) {
  613. data += v;
  614. });
  615. res.on('end', function () {
  616. var obj = JSON.parse(data);
  617. expect(obj).to.eql({error: 'I failed'});
  618. socket.socket.emit('error', new Error(obj.error));
  619. });
  620. });
  621. }
  622. });
  623. socket.on('end', done);
  624. socket.on('reconnect', function () {
  625. throw new Error('reconnect should not be called');
  626. });
  627. });
  628. it('support accepted authorization', function (done) {
  629. primus.authorize(function auth(req, next) {
  630. expect(req.headers).to.be.a('object');
  631. next();
  632. });
  633. primus.on('connection', function (spark) {
  634. spark.end();
  635. });
  636. var socket = new Socket(server.addr);
  637. socket.on('end', done);
  638. socket.on('reconnect', function () {
  639. throw new Error('fuck');
  640. });
  641. });
  642. it('communicates over an authorized connection', function (done) {
  643. primus.authorize(function auth(req, next) {
  644. expect(req.headers).to.be.a('object');
  645. setTimeout(next, 20);
  646. });
  647. primus.on('connection', function (spark) {
  648. spark.on('data', function (data) {
  649. expect(data).to.equal('balls');
  650. spark.end();
  651. });
  652. });
  653. var socket = new Socket(server.addr);
  654. socket.on('end', done);
  655. socket.write('balls');
  656. });
  657. if (transformer.toLowerCase() === 'websockets')
  658. it('should connect using basic auth', function (done) {
  659. primus.on('connection', function (spark) {
  660. expect(spark.headers.authorization).to.equal('Basic dXNyOnBhc3M=');
  661. socket.end();
  662. });
  663. var socket = new Socket(server.make_addr('usr:pass', '?foo=bar'));
  664. socket.on('end', done);
  665. });
  666. it('should emit a timeout event if it cannot connect in a timely manner', function (done) {
  667. primus.authorize(function (req, next) {
  668. setTimeout(next, 1000);
  669. });
  670. var socket = new Socket(server.make_addr('usr:pass', '?foo=bar'), {
  671. timeout: 500
  672. });
  673. socket.on('timeout', done);
  674. });
  675. it('should reconnect after the timeout', function (done) {
  676. primus.authorize(function (req, next) {
  677. setTimeout(next, 1000);
  678. });
  679. var socket = new Socket(server.addr, { timeout: 10 })
  680. , pattern = [];
  681. socket.on('timeout', function () {
  682. pattern.push('timeout');
  683. });
  684. socket.once('reconnecting', function () {
  685. pattern.push('reconnecting');
  686. });
  687. socket.once('reconnect', function () {
  688. pattern.push('reconnect');
  689. expect(pattern.join(',')).to.equal('timeout,reconnecting,reconnect');
  690. socket.end();
  691. // outgoing::reconnect is emitted after reconnect whatever we do
  692. socket.removeAllListeners('outgoing::reconnect');
  693. done();
  694. });
  695. });
  696. });
  697. describe('Server', function () {
  698. it('emits a `connection` event before any `data` event', function (done) {
  699. var create = 10
  700. , foo = 0;
  701. primus.on('connection', function (spark) {
  702. spark.on('data', function (data) {
  703. if ('foo' === data) {
  704. if (++foo === create) done();
  705. }
  706. });
  707. });
  708. for (var i = 0; i < create; i++) {
  709. (new Socket(server.addr)).write('foo');
  710. }
  711. });
  712. it('emits `end` when the connection is closed', function (done) {
  713. primus.on('connection', function (spark) {
  714. spark.on('end', done);
  715. });
  716. var socket = new Socket(server.addr);
  717. socket.on('open', function () {
  718. socket.end();
  719. });
  720. });
  721. it('should emit an `error` when it fails to encode the data', function (done) {
  722. primus.on('connection', function (spark) {
  723. var data = { foo: 'bar' };
  724. data.recusrive = data;
  725. spark.on('error', function (err) {
  726. expect(err).to.not.be.a('string');
  727. expect(err.message).to.include('JSON');
  728. socket.end();
  729. done();
  730. });
  731. spark.write(data);
  732. });
  733. var socket = new Socket(server.addr);
  734. });
  735. it('should receive querystrings', function (done) {
  736. primus.on('connection', function (spark) {
  737. expect(spark.query).to.be.a('object');
  738. if (
  739. (transformer.toLowerCase() !== 'sockjs') &&
  740. (transformer_name.toLowerCase() !== 'unixdomainwebsockets')
  741. ) {
  742. expect(spark.query.foo).to.equal('bar');
  743. }
  744. socket.end();
  745. });
  746. var socket = new Socket(server.make_addr(null, '?foo=bar'));
  747. socket.on('end', done);
  748. });
  749. it('should receive all headers', function (done) {
  750. primus.on('connection', function (spark) {
  751. expect(spark.headers).to.be.a('object');
  752. expect(spark.headers).to.have.property('connection');
  753. socket.end();
  754. });
  755. var socket = new Socket(server.make_addr(null, '?foo=bar'));
  756. socket.on('end', done);
  757. });
  758. it('should not trigger a reconnect when we end the connection', function (done) {
  759. primus.on('connection', function (spark) {
  760. spark.end();
  761. });
  762. var socket = new Socket(server.addr);
  763. socket.on('end', done);
  764. socket.on('reconnect', function () {
  765. throw new Error('fuck');
  766. });
  767. });
  768. if (transformer_name.toLowerCase() !== 'unixdomainwebsockets') {
  769. it('should still allow requests to the original listener', function (done) {
  770. request(
  771. server.addr +'/nothrow',
  772. function (err, res, body) {
  773. if (err) return done(err);
  774. expect(body).to.equal('original listener');
  775. done();
  776. }
  777. );
  778. });
  779. it('responds to library requests', function (done) {
  780. request(
  781. server.addr + '/primus/primus.js',
  782. function (err, res, body) {
  783. if (err) return done(err);
  784. expect(res.statusCode).to.equal(200);
  785. expect(res.headers['content-type']).to.equal('text/javascript; charset=utf-8');
  786. expect(body).to.equal(primus.library());
  787. done();
  788. }
  789. );
  790. });
  791. it('handles requests to non existing routes captured by primus', function (done) {
  792. this.timeout(100);
  793. request(
  794. server.addr + '/primus.js',
  795. function (err, res, body) {
  796. if (err) return done(err);
  797. done();
  798. }
  799. );
  800. });
  801. it('correctly handles requests when a middleware returns an error', function (done) {
  802. primus.before('foo', function foo(req, res, next) {
  803. next(new Error('foo failed'));
  804. });
  805. primus.on('connection', function (spark) {
  806. throw new Error('connection should not be triggered');
  807. });
  808. var socket = new Socket(server.addr, { strategy: false });
  809. socket.on('end', done);
  810. });
  811. it('correctly parses the ip address', function (done) {
  812. primus.on('connection', function (spark) {
  813. var address = spark.address;
  814. expect(address.port).to.not.equal(0);
  815. expect(address.port).to.not.equal(server.portnumber);
  816. spark.end();
  817. done();
  818. });
  819. var socket = new Socket(server.addr);
  820. });
  821. } // !unixdomainwebsockets
  822. it('uses x-forwarded headers over the connection ip address', function (done) {
  823. primus.on('connection', function (spark) {
  824. spark.headers['x-forwarded-for'] = '13.3.37.1,12.12.12.12';
  825. spark.headers['x-forwarded-port'] = '9083,1334';
  826. expect(spark.address.ip).to.equal('13.3.37.1');
  827. expect(spark.address.port).to.equal(9083);
  828. spark.end();
  829. done();
  830. });
  831. var socket = new Socket(server.addr);
  832. });
  833. if (transformer_name.toLowerCase() !== 'unixdomainwebsockets') {
  834. it('exposes a spec file with the correct transformer', function (done) {
  835. request(
  836. server.addr +'/primus/spec',
  837. function (err, res, body) {
  838. if (err) return done(err);
  839. body = JSON.parse(body);
  840. expect(body.transformer).to.equal(transformer.toLowerCase());
  841. expect(body.version).to.equal(primus.version);
  842. expect(body.pathname).to.equal('/primus');
  843. expect(body.parser).to.equal('json');
  844. done();
  845. }
  846. );
  847. });
  848. } // !unixdomainwebsockets
  849. it('doesnt crash when we write to a closed connection', function (done) {
  850. primus.on('connection', function (spark) {
  851. spark.on('end', function () {
  852. spark.write('I should not crash');
  853. setTimeout(function () {
  854. spark.write('the server should ignore me');
  855. setTimeout(done, 10);
  856. }, 10);
  857. });
  858. });
  859. var socket = new Socket(server.addr);
  860. socket.on('open', function () {
  861. socket.end();
  862. });
  863. });
  864. it('should make the spark available to the parser', function (done) {
  865. var rnd = Math.random(),
  866. parser = primus.parser;
  867. primus.parsers({
  868. decoder: function (data, fn) {
  869. expect(this.foobar).to.equal(rnd);
  870. parser.decoder.call(this, data, function (err, decoded) {
  871. expect(err).not.to.exist;
  872. expect(decoded).to.eql({ echo: 'pong' });
  873. fn(null, decoded);
  874. });
  875. },
  876. encoder: function (data, fn) {
  877. expect(this.foobar).to.equal(rnd);
  878. parser.encoder.call(this, data, fn);
  879. if (data === 'pong') {
  880. done();
  881. }
  882. }
  883. });
  884. primus.on('connection', function (spark) {
  885. spark.foobar = rnd;
  886. });
  887. var socket = new Socket(server.addr);
  888. socket.on('open', function () {
  889. socket.write({ echo: 'pong' });
  890. });
  891. });
  892. describe('#transform', function () {
  893. it('thrown an error if an invalid type is given', function (done) {
  894. try { primus.transform('cowsack', function () {}); }
  895. catch (e) {
  896. expect(e.message).to.contain('transformer');
  897. done();
  898. }
  899. });
  900. describe('outgoing', function () {
  901. it('rewrites the outgoing message', function (done) {
  902. primus.transform('outgoing', function (data) {
  903. expect(data).to.be.a('object');
  904. expect(data.data).to.equal('foo');
  905. data.data = {
  906. message: 'foo',
  907. meta: 'meta'
  908. };
  909. });
  910. primus.on('connection', function (spark) {
  911. setTimeout(function () {
  912. spark.write('foo');
  913. }, 10);
  914. });
  915. var socket = new Socket(server.addr);
  916. socket.on('data', function (data) {
  917. expect(data).to.be.a('object');
  918. expect(data.meta).to.equal('meta');
  919. expect(data.message).to.equal('foo');
  920. socket.end();
  921. done();
  922. });
  923. });
  924. it('prevents the message from being written', function (done) {
  925. primus.transform('outgoing', function () {
  926. setTimeout(function () {
  927. socket.end();
  928. done();
  929. }, 0);
  930. return false;
  931. });
  932. primus.on('connection', function (spark) {
  933. spark.on('outgoing::data', function (data) {
  934. if (~data.indexOf('foo')) throw new Error('return false should prevent this emit');
  935. });
  936. spark.write('foo');
  937. });
  938. var socket = new Socket(server.addr);
  939. });
  940. });
  941. describe('incoming', function () {
  942. it('rewrites the incoming message', function (done) {
  943. primus.transform('incoming', function (data) {
  944. expect(data).to.be.a('object');
  945. expect(data.data).to.equal('foo');
  946. data.data = {
  947. message: 'foo',
  948. meta: 'meta'
  949. };
  950. });
  951. primus.on('connection', function (spark) {
  952. spark.on('data', function (data) {
  953. expect(data).to.be.a('object');
  954. expect(data.meta).to.equal('meta');
  955. expect(data.message).to.equal('foo');
  956. spark.end();
  957. done();
  958. });
  959. });
  960. var socket = new Socket(server.addr);
  961. socket.write('foo');
  962. });
  963. it('prevents the message from being emitted', function (done) {
  964. primus.transform('incoming', function (data) {
  965. setTimeout(function () {
  966. socket.end();
  967. done();
  968. }, 0);
  969. return false;
  970. });
  971. primus.on('connection', function (spark) {
  972. spark.on('data', function () {
  973. throw new Error('return false should prevent this emit');
  974. });
  975. });
  976. var socket = new Socket(server.addr);
  977. socket.write('foo');
  978. });
  979. });
  980. });
  981. describe('#id', function () {
  982. it('should receive the id', function (done) {
  983. primus.on('connection', function (spark) {
  984. socket.id(function (id) {
  985. expect(id).to.equal(spark.id);
  986. spark.end();
  987. done();
  988. });
  989. });
  990. var socket = new Socket(server.addr);
  991. });
  992. });
  993. });
  994. });
  995. };