/* eslint-disable camelcase, handle-callback-err, no-return-assign, no-unused-vars, */ // TODO: This file was created by bulk-decaffeinate. // Fix any style issues and re-enable lint. /* * decaffeinate suggestions: * DS102: Remove unnecessary code created because of implicit returns * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ const should = require('chai').should(); const SandboxedModule = require('sandboxed-module'); const assert = require('assert'); const path = require('path'); const sinon = require('sinon'); const modulePath = path.join(__dirname, "../../../app/js/ConnectedUsersManager"); const { expect } = require("chai"); const tk = require("timekeeper"); describe("ConnectedUsersManager", function() { beforeEach(function() { this.settings = { redis: { realtime: { key_schema: { clientsInProject({project_id}) { return `clients_in_project:${project_id}`; }, connectedUser({project_id, client_id}){ return `connected_user:${project_id}:${client_id}`; } } } } }; this.rClient = { auth() {}, setex:sinon.stub(), sadd:sinon.stub(), get: sinon.stub(), srem:sinon.stub(), del:sinon.stub(), smembers:sinon.stub(), expire:sinon.stub(), hset:sinon.stub(), hgetall:sinon.stub(), exec:sinon.stub(), multi: () => { return this.rClient; } }; tk.freeze(new Date()); this.ConnectedUsersManager = SandboxedModule.require(modulePath, { requires: { "settings-sharelatex":this.settings, "logger-sharelatex": { log() {} }, "redis-sharelatex": { createClient:() => { return this.rClient; } } } } ); this.client_id = "32132132"; this.project_id = "dskjh2u21321"; this.user = { _id: "user-id-123", first_name: "Joe", last_name: "Bloggs", email: "joe@example.com" }; return this.cursorData = { row: 12, column: 9, doc_id: '53c3b8c85fee64000023dc6e' };}); afterEach(function() { return tk.reset(); }); describe("updateUserPosition", function() { beforeEach(function() { return this.rClient.exec.callsArgWith(0); }); it("should set a key with the date and give it a ttl", function(done){ return this.ConnectedUsersManager.updateUserPosition(this.project_id, this.client_id, this.user, null, err=> { this.rClient.hset.calledWith(`connected_user:${this.project_id}:${this.client_id}`, "last_updated_at", Date.now()).should.equal(true); return done(); }); }); it("should set a key with the user_id", function(done){ return this.ConnectedUsersManager.updateUserPosition(this.project_id, this.client_id, this.user, null, err=> { this.rClient.hset.calledWith(`connected_user:${this.project_id}:${this.client_id}`, "user_id", this.user._id).should.equal(true); return done(); }); }); it("should set a key with the first_name", function(done){ return this.ConnectedUsersManager.updateUserPosition(this.project_id, this.client_id, this.user, null, err=> { this.rClient.hset.calledWith(`connected_user:${this.project_id}:${this.client_id}`, "first_name", this.user.first_name).should.equal(true); return done(); }); }); it("should set a key with the last_name", function(done){ return this.ConnectedUsersManager.updateUserPosition(this.project_id, this.client_id, this.user, null, err=> { this.rClient.hset.calledWith(`connected_user:${this.project_id}:${this.client_id}`, "last_name", this.user.last_name).should.equal(true); return done(); }); }); it("should set a key with the email", function(done){ return this.ConnectedUsersManager.updateUserPosition(this.project_id, this.client_id, this.user, null, err=> { this.rClient.hset.calledWith(`connected_user:${this.project_id}:${this.client_id}`, "email", this.user.email).should.equal(true); return done(); }); }); it("should push the client_id on to the project list", function(done){ return this.ConnectedUsersManager.updateUserPosition(this.project_id, this.client_id, this.user, null, err=> { this.rClient.sadd.calledWith(`clients_in_project:${this.project_id}`, this.client_id).should.equal(true); return done(); }); }); it("should add a ttl to the project set so it stays clean", function(done){ return this.ConnectedUsersManager.updateUserPosition(this.project_id, this.client_id, this.user, null, err=> { this.rClient.expire.calledWith(`clients_in_project:${this.project_id}`, 24 * 4 * 60 * 60).should.equal(true); return done(); }); }); it("should add a ttl to the connected user so it stays clean", function(done) { return this.ConnectedUsersManager.updateUserPosition(this.project_id, this.client_id, this.user, null, err=> { this.rClient.expire.calledWith(`connected_user:${this.project_id}:${this.client_id}`, 60 * 15).should.equal(true); return done(); }); }); return it("should set the cursor position when provided", function(done){ return this.ConnectedUsersManager.updateUserPosition(this.project_id, this.client_id, this.user, this.cursorData, err=> { this.rClient.hset.calledWith(`connected_user:${this.project_id}:${this.client_id}`, "cursorData", JSON.stringify(this.cursorData)).should.equal(true); return done(); }); }); }); describe("markUserAsDisconnected", function() { beforeEach(function() { return this.rClient.exec.callsArgWith(0); }); it("should remove the user from the set", function(done){ return this.ConnectedUsersManager.markUserAsDisconnected(this.project_id, this.client_id, err=> { this.rClient.srem.calledWith(`clients_in_project:${this.project_id}`, this.client_id).should.equal(true); return done(); }); }); it("should delete the connected_user string", function(done){ return this.ConnectedUsersManager.markUserAsDisconnected(this.project_id, this.client_id, err=> { this.rClient.del.calledWith(`connected_user:${this.project_id}:${this.client_id}`).should.equal(true); return done(); }); }); return it("should add a ttl to the connected user set so it stays clean", function(done){ return this.ConnectedUsersManager.markUserAsDisconnected(this.project_id, this.client_id, err=> { this.rClient.expire.calledWith(`clients_in_project:${this.project_id}`, 24 * 4 * 60 * 60).should.equal(true); return done(); }); }); }); describe("_getConnectedUser", function() { it("should return a connected user if there is a user object", function(done){ const cursorData = JSON.stringify({cursorData:{row:1}}); this.rClient.hgetall.callsArgWith(1, null, {connected_at:new Date(), user_id: this.user._id, last_updated_at: `${Date.now()}`, cursorData}); return this.ConnectedUsersManager._getConnectedUser(this.project_id, this.client_id, (err, result)=> { result.connected.should.equal(true); result.client_id.should.equal(this.client_id); return done(); }); }); it("should return a not connected user if there is no object", function(done){ this.rClient.hgetall.callsArgWith(1, null, null); return this.ConnectedUsersManager._getConnectedUser(this.project_id, this.client_id, (err, result)=> { result.connected.should.equal(false); result.client_id.should.equal(this.client_id); return done(); }); }); return it("should return a not connected user if there is an empty object", function(done){ this.rClient.hgetall.callsArgWith(1, null, {}); return this.ConnectedUsersManager._getConnectedUser(this.project_id, this.client_id, (err, result)=> { result.connected.should.equal(false); result.client_id.should.equal(this.client_id); return done(); }); }); }); return describe("getConnectedUsers", function() { beforeEach(function() { this.users = ["1234", "5678", "9123", "8234"]; this.rClient.smembers.callsArgWith(1, null, this.users); this.ConnectedUsersManager._getConnectedUser = sinon.stub(); this.ConnectedUsersManager._getConnectedUser.withArgs(this.project_id, this.users[0]).callsArgWith(2, null, {connected:true, client_age: 2, client_id:this.users[0]}); this.ConnectedUsersManager._getConnectedUser.withArgs(this.project_id, this.users[1]).callsArgWith(2, null, {connected:false, client_age: 1, client_id:this.users[1]}); this.ConnectedUsersManager._getConnectedUser.withArgs(this.project_id, this.users[2]).callsArgWith(2, null, {connected:true, client_age: 3, client_id:this.users[2]}); return this.ConnectedUsersManager._getConnectedUser.withArgs(this.project_id, this.users[3]).callsArgWith(2, null, {connected:true, client_age: 11, client_id:this.users[3]}); }); // connected but old return it("should only return the users in the list which are still in redis and recently updated", function(done){ return this.ConnectedUsersManager.getConnectedUsers(this.project_id, (err, users)=> { users.length.should.equal(2); users[0].should.deep.equal({client_id:this.users[0], client_age: 2, connected:true}); users[1].should.deep.equal({client_id:this.users[2], client_age: 3, connected:true}); return done(); }); }); }); });