RealTimeRedisManagerTests.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /* eslint-disable
  2. camelcase,
  3. no-return-assign,
  4. no-unused-vars,
  5. */
  6. // TODO: This file was created by bulk-decaffeinate.
  7. // Fix any style issues and re-enable lint.
  8. /*
  9. * decaffeinate suggestions:
  10. * DS102: Remove unnecessary code created because of implicit returns
  11. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  12. */
  13. const sinon = require('sinon');
  14. const chai = require('chai');
  15. const should = chai.should();
  16. const modulePath = "../../../../app/js/RealTimeRedisManager.js";
  17. const SandboxedModule = require('sandboxed-module');
  18. const Errors = require("../../../../app/js/Errors");
  19. describe("RealTimeRedisManager", function() {
  20. beforeEach(function() {
  21. this.rclient = {
  22. auth() {},
  23. exec: sinon.stub()
  24. };
  25. this.rclient.multi = () => this.rclient;
  26. this.pubsubClient =
  27. {publish: sinon.stub()};
  28. this.RealTimeRedisManager = SandboxedModule.require(modulePath, { requires: {
  29. "redis-sharelatex": { createClient: config => (config.name === 'pubsub') ? this.pubsubClient : this.rclient
  30. },
  31. "settings-sharelatex": {
  32. redis: {
  33. documentupdater: (this.settings = {
  34. key_schema: {
  35. pendingUpdates({doc_id}) { return `PendingUpdates:${doc_id}`; }
  36. }
  37. }),
  38. pubsub: {
  39. name: "pubsub"
  40. }
  41. }
  42. },
  43. "logger-sharelatex": { log() {} },
  44. "crypto": (this.crypto = { randomBytes: sinon.stub().withArgs(4).returns(Buffer.from([0x1, 0x2, 0x3, 0x4])) }),
  45. "os": (this.os = {hostname: sinon.stub().returns("somehost")}),
  46. "./Metrics": (this.metrics = { summary: sinon.stub()})
  47. }
  48. });
  49. this.doc_id = "doc-id-123";
  50. this.project_id = "project-id-123";
  51. return this.callback = sinon.stub();
  52. });
  53. describe("getPendingUpdatesForDoc", function() {
  54. beforeEach(function() {
  55. this.rclient.lrange = sinon.stub();
  56. return this.rclient.ltrim = sinon.stub();
  57. });
  58. describe("successfully", function() {
  59. beforeEach(function() {
  60. this.updates = [
  61. { op: [{ i: "foo", p: 4 }] },
  62. { op: [{ i: "foo", p: 4 }] }
  63. ];
  64. this.jsonUpdates = this.updates.map(update => JSON.stringify(update));
  65. this.rclient.exec = sinon.stub().callsArgWith(0, null, [this.jsonUpdates]);
  66. return this.RealTimeRedisManager.getPendingUpdatesForDoc(this.doc_id, this.callback);
  67. });
  68. it("should get the pending updates", function() {
  69. return this.rclient.lrange
  70. .calledWith(`PendingUpdates:${this.doc_id}`, 0, 7)
  71. .should.equal(true);
  72. });
  73. it("should delete the pending updates", function() {
  74. return this.rclient.ltrim
  75. .calledWith(`PendingUpdates:${this.doc_id}`, 8, -1)
  76. .should.equal(true);
  77. });
  78. return it("should call the callback with the updates", function() {
  79. return this.callback.calledWith(null, this.updates).should.equal(true);
  80. });
  81. });
  82. return describe("when the JSON doesn't parse", function() {
  83. beforeEach(function() {
  84. this.jsonUpdates = [
  85. JSON.stringify({ op: [{ i: "foo", p: 4 }] }),
  86. "broken json"
  87. ];
  88. this.rclient.exec = sinon.stub().callsArgWith(0, null, [this.jsonUpdates]);
  89. return this.RealTimeRedisManager.getPendingUpdatesForDoc(this.doc_id, this.callback);
  90. });
  91. return it("should return an error to the callback", function() {
  92. return this.callback.calledWith(new Error("JSON parse error")).should.equal(true);
  93. });
  94. });
  95. });
  96. describe("getUpdatesLength", function() {
  97. beforeEach(function() {
  98. this.rclient.llen = sinon.stub().yields(null, (this.length = 3));
  99. return this.RealTimeRedisManager.getUpdatesLength(this.doc_id, this.callback);
  100. });
  101. it("should look up the length", function() {
  102. return this.rclient.llen.calledWith(`PendingUpdates:${this.doc_id}`).should.equal(true);
  103. });
  104. return it("should return the length", function() {
  105. return this.callback.calledWith(null, this.length).should.equal(true);
  106. });
  107. });
  108. return describe("sendData", function() {
  109. beforeEach(function() {
  110. this.message_id = "doc:somehost:01020304-0";
  111. return this.RealTimeRedisManager.sendData({op: "thisop"});
  112. });
  113. it("should send the op with a message id", function() {
  114. return this.pubsubClient.publish.calledWith("applied-ops", JSON.stringify({op:"thisop",_id:this.message_id})).should.equal(true);
  115. });
  116. return it("should track the payload size", function() {
  117. return this.metrics.summary.calledWith("redis.publish.applied-ops", JSON.stringify({op:"thisop",_id:this.message_id}).length).should.equal(true);
  118. });
  119. });
  120. });