test.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. /*
  2. * decaffeinate suggestions:
  3. * DS102: Remove unnecessary code created because of implicit returns
  4. * DS206: Consider reworking classes to avoid initClass
  5. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  6. */
  7. const should = require('chai').should()
  8. const SandboxedModule = require('sandboxed-module')
  9. const assert = require('assert')
  10. const path = require('path')
  11. const sinon = require('sinon')
  12. const modulePath = path.join(__dirname, './../../../index.js')
  13. const { expect } = require('chai')
  14. describe('index', function () {
  15. beforeEach(function () {
  16. let Cluster, IoRedis, ioredisConstructor
  17. this.settings = {}
  18. this.ioredisConstructor = ioredisConstructor = sinon.stub()
  19. this.ioredis = IoRedis = (function () {
  20. let createIoRedis
  21. IoRedis = class IoRedis {
  22. static initClass() {
  23. this.prototype.on = sinon.stub()
  24. createIoRedis = ioredisConstructor
  25. }
  26. constructor() {
  27. return createIoRedis.apply(this, arguments)
  28. }
  29. }
  30. IoRedis.initClass()
  31. return IoRedis
  32. })()
  33. this.ioredis.Cluster = Cluster = (function () {
  34. Cluster = class Cluster {
  35. static initClass() {
  36. this.prototype.on = sinon.stub()
  37. }
  38. constructor(config, options) {
  39. this.config = config
  40. this.options = options
  41. }
  42. }
  43. Cluster.initClass()
  44. return Cluster
  45. })()
  46. this.redis = SandboxedModule.require(modulePath, {
  47. requires: {
  48. ioredis: this.ioredis,
  49. },
  50. globals: {
  51. process: process,
  52. },
  53. })
  54. return (this.auth_pass = '1234 pass')
  55. })
  56. describe('redis-sentinel', function () {
  57. it('should throw an error when creating a client', function () {
  58. const redisSentinelOptions = {
  59. endpoints: ['127.0.0.1:1234', '127.0.0.1:2345', '127.0.0.1:3456'],
  60. }
  61. const createNewClient = () => {
  62. this.redis.createClient(redisSentinelOptions)
  63. }
  64. expect(createNewClient).to.throw(
  65. '@overleaf/redis-wrapper: redis-sentinel is no longer supported'
  66. )
  67. })
  68. })
  69. describe('single node redis', function () {
  70. beforeEach(function () {
  71. return (this.standardOpts = {
  72. auth_pass: this.auth_pass,
  73. port: 1234,
  74. host: 'redis.mysite.env',
  75. })
  76. })
  77. it('should work without opts', function () {
  78. this.redis.createClient()
  79. })
  80. it('should use the ioredis driver in single-instance mode if a non array is passed', function () {
  81. const client = this.redis.createClient(this.standardOpts)
  82. return assert.equal(client.constructor, this.ioredis)
  83. })
  84. return it('should call createClient for the ioredis driver in single-instance mode if a non array is passed', function () {
  85. const client = this.redis.createClient(this.standardOpts)
  86. return this.ioredisConstructor
  87. .calledWith(sinon.match(this.standardOpts))
  88. .should.equal(true)
  89. })
  90. })
  91. describe('cluster', function () {
  92. beforeEach(function () {
  93. this.cluster = [{ mock: 'cluster' }, { mock: 'cluster2' }]
  94. this.extraOptions = { keepAlive: 100 }
  95. return (this.settings = {
  96. cluster: this.cluster,
  97. redisOptions: this.extraOptions,
  98. key_schema: {
  99. foo(x) {
  100. return `${x}`
  101. },
  102. },
  103. })
  104. })
  105. it('should pass the options correctly though with no options', function () {
  106. const client = this.redis.createClient({ cluster: this.cluster })
  107. assert(client instanceof this.ioredis.Cluster)
  108. return client.config.should.deep.equal(this.cluster)
  109. })
  110. it('should not pass the key_schema through to the driver', function () {
  111. const client = this.redis.createClient({
  112. cluster: this.cluster,
  113. key_schema: 'foobar',
  114. })
  115. assert(client instanceof this.ioredis.Cluster)
  116. client.config.should.deep.equal(this.cluster)
  117. return expect(client.options).to.deep.equal({ retry_max_delay: 5000 })
  118. })
  119. return it('should pass the options correctly though with additional options', function () {
  120. const client = this.redis.createClient(this.settings)
  121. assert(client instanceof this.ioredis.Cluster)
  122. client.config.should.deep.equal(this.cluster)
  123. // need to use expect here because of _.clone in sandbox
  124. return expect(client.options).to.deep.equal({
  125. redisOptions: this.extraOptions,
  126. retry_max_delay: 5000,
  127. })
  128. })
  129. })
  130. return describe('monkey patch ioredis exec', function () {
  131. beforeEach(function () {
  132. this.callback = sinon.stub()
  133. this.results = []
  134. this.multiOrig = { exec: sinon.stub().yields(null, this.results) }
  135. this.client = { multi: sinon.stub().returns(this.multiOrig) }
  136. this.ioredisConstructor.returns(this.client)
  137. this.redis.createClient(this.client)
  138. return (this.multi = this.client.multi())
  139. })
  140. it('should return the old redis format for an array', function () {
  141. this.results[0] = [null, 42]
  142. this.results[1] = [null, 'foo']
  143. this.multi.exec(this.callback)
  144. return this.callback.calledWith(null, [42, 'foo']).should.equal(true)
  145. })
  146. return it('should return the old redis format when there is an error', function () {
  147. this.results[0] = [null, 42]
  148. this.results[1] = ['error', 'foo']
  149. this.multi.exec(this.callback)
  150. return this.callback.calledWith('error').should.equal(true)
  151. })
  152. })
  153. })